diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/skfp/fplustm.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/net/skfp/fplustm.c')
-rw-r--r-- | drivers/net/skfp/fplustm.c | 1561 |
1 files changed, 1561 insertions, 0 deletions
diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c new file mode 100644 index 000000000000..76e78442fc24 --- /dev/null +++ b/drivers/net/skfp/fplustm.c | |||
@@ -0,0 +1,1561 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * (C)Copyright 1998,1999 SysKonnect, | ||
4 | * a business unit of Schneider & Koch & Co. Datensysteme GmbH. | ||
5 | * | ||
6 | * See the file "skfddi.c" for further information. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * The information in this file is provided "AS IS" without warranty. | ||
14 | * | ||
15 | ******************************************************************************/ | ||
16 | |||
17 | /* | ||
18 | * FORMAC+ Driver for tag mode | ||
19 | */ | ||
20 | |||
21 | #include "h/types.h" | ||
22 | #include "h/fddi.h" | ||
23 | #include "h/smc.h" | ||
24 | #include "h/supern_2.h" | ||
25 | #include "can.c" | ||
26 | |||
27 | #ifndef lint | ||
28 | static const char ID_sccs[] = "@(#)fplustm.c 1.32 99/02/23 (C) SK " ; | ||
29 | #endif | ||
30 | |||
31 | #ifndef UNUSED | ||
32 | #ifdef lint | ||
33 | #define UNUSED(x) (x) = (x) | ||
34 | #else | ||
35 | #define UNUSED(x) | ||
36 | #endif | ||
37 | #endif | ||
38 | |||
39 | #define FM_ADDRX (FM_ADDET|FM_EXGPA0|FM_EXGPA1) | ||
40 | #define MS2BCLK(x) ((x)*12500L) | ||
41 | #define US2BCLK(x) ((x)*1250L) | ||
42 | |||
43 | /* | ||
44 | * prototypes for static function | ||
45 | */ | ||
46 | static void build_claim_beacon(struct s_smc *smc, u_long t_request); | ||
47 | static int init_mac(struct s_smc *smc, int all); | ||
48 | static void rtm_init(struct s_smc *smc); | ||
49 | static void smt_split_up_fifo(struct s_smc *smc); | ||
50 | |||
51 | #if (!defined(NO_SMT_PANIC) || defined(DEBUG)) | ||
52 | static char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n"; | ||
53 | static char cam_warning [] = "E_SMT_004: CAM still busy\n"; | ||
54 | #endif | ||
55 | |||
56 | #define DUMMY_READ() smc->hw.mc_dummy = (u_short) inp(ADDR(B0_RAP)) | ||
57 | |||
58 | #define CHECK_NPP() { unsigned k = 10000 ;\ | ||
59 | while ((inpw(FM_A(FM_STMCHN)) & FM_SNPPND) && k) k--;\ | ||
60 | if (!k) { \ | ||
61 | SMT_PANIC(smc,SMT_E0130, SMT_E0130_MSG) ; \ | ||
62 | } \ | ||
63 | } | ||
64 | |||
65 | #define CHECK_CAM() { unsigned k = 10 ;\ | ||
66 | while (!(inpw(FM_A(FM_AFSTAT)) & FM_DONE) && k) k--;\ | ||
67 | if (!k) { \ | ||
68 | SMT_PANIC(smc,SMT_E0131, SMT_E0131_MSG) ; \ | ||
69 | } \ | ||
70 | } | ||
71 | |||
72 | const struct fddi_addr fddi_broadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; | ||
73 | static const struct fddi_addr null_addr = {{0,0,0,0,0,0}}; | ||
74 | static const struct fddi_addr dbeacon_multi = {{0x01,0x80,0xc2,0x00,0x01,0x00}}; | ||
75 | |||
76 | static const u_short my_said = 0xffff ; /* short address (n.u.) */ | ||
77 | static const u_short my_sagp = 0xffff ; /* short group address (n.u.) */ | ||
78 | |||
79 | /* | ||
80 | * define my address | ||
81 | */ | ||
82 | #ifdef USE_CAN_ADDR | ||
83 | #define MA smc->hw.fddi_canon_addr | ||
84 | #else | ||
85 | #define MA smc->hw.fddi_home_addr | ||
86 | #endif | ||
87 | |||
88 | |||
89 | /* | ||
90 | * useful interrupt bits | ||
91 | */ | ||
92 | static int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ; | ||
93 | static int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0| | ||
94 | FM_STBURS | FM_STBURA0 ; | ||
95 | |||
96 | /* delete FM_SRBFL after tests */ | ||
97 | static int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL | | ||
98 | FM_SMYCLM ; | ||
99 | static int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR | | ||
100 | FM_SERRCTR | FM_SLSTCTR | | ||
101 | FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ; | ||
102 | |||
103 | static int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ; | ||
104 | static int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ; | ||
105 | |||
106 | static int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC | | ||
107 | FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ; | ||
108 | |||
109 | |||
110 | static u_long mac_get_tneg(struct s_smc *smc) | ||
111 | { | ||
112 | u_long tneg ; | ||
113 | |||
114 | tneg = (u_long)((long)inpw(FM_A(FM_TNEG))<<5) ; | ||
115 | return((u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) | | ||
116 | 0xffe00000L)) ; | ||
117 | } | ||
118 | |||
119 | void mac_update_counter(struct s_smc *smc) | ||
120 | { | ||
121 | smc->mib.m[MAC0].fddiMACFrame_Ct = | ||
122 | (smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L) | ||
123 | + (u_short) inpw(FM_A(FM_FCNTR)) ; | ||
124 | smc->mib.m[MAC0].fddiMACLost_Ct = | ||
125 | (smc->mib.m[MAC0].fddiMACLost_Ct & 0xffff0000L) | ||
126 | + (u_short) inpw(FM_A(FM_LCNTR)) ; | ||
127 | smc->mib.m[MAC0].fddiMACError_Ct = | ||
128 | (smc->mib.m[MAC0].fddiMACError_Ct & 0xffff0000L) | ||
129 | + (u_short) inpw(FM_A(FM_ECNTR)) ; | ||
130 | smc->mib.m[MAC0].fddiMACT_Neg = mac_get_tneg(smc) ; | ||
131 | #ifdef SMT_REAL_TOKEN_CT | ||
132 | /* | ||
133 | * If the token counter is emulated it is updated in smt_event. | ||
134 | */ | ||
135 | TBD | ||
136 | #else | ||
137 | smt_emulate_token_ct( smc, MAC0 ); | ||
138 | #endif | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * write long value into buffer memory over memory data register (MDR), | ||
143 | */ | ||
144 | static void write_mdr(struct s_smc *smc, u_long val) | ||
145 | { | ||
146 | CHECK_NPP() ; | ||
147 | MDRW(val) ; | ||
148 | } | ||
149 | |||
150 | #if 0 | ||
151 | /* | ||
152 | * read long value from buffer memory over memory data register (MDR), | ||
153 | */ | ||
154 | static u_long read_mdr(struct s_smc *smc, unsigned int addr) | ||
155 | { | ||
156 | long p ; | ||
157 | CHECK_NPP() ; | ||
158 | MARR(addr) ; | ||
159 | outpw(FM_A(FM_CMDREG1),FM_IRMEMWO) ; | ||
160 | CHECK_NPP() ; /* needed for PCI to prevent from timeing violations */ | ||
161 | /* p = MDRR() ; */ /* bad read values if the workaround */ | ||
162 | /* smc->hw.mc_dummy = *((short volatile far *)(addr)))*/ | ||
163 | /* is used */ | ||
164 | p = (u_long)inpw(FM_A(FM_MDRU))<<16 ; | ||
165 | p += (u_long)inpw(FM_A(FM_MDRL)) ; | ||
166 | return(p) ; | ||
167 | } | ||
168 | #endif | ||
169 | |||
170 | /* | ||
171 | * clear buffer memory | ||
172 | */ | ||
173 | static void init_ram(struct s_smc *smc) | ||
174 | { | ||
175 | u_short i ; | ||
176 | |||
177 | smc->hw.fp.fifo.rbc_ram_start = 0 ; | ||
178 | smc->hw.fp.fifo.rbc_ram_end = | ||
179 | smc->hw.fp.fifo.rbc_ram_start + RBC_MEM_SIZE ; | ||
180 | CHECK_NPP() ; | ||
181 | MARW(smc->hw.fp.fifo.rbc_ram_start) ; | ||
182 | for (i = smc->hw.fp.fifo.rbc_ram_start; | ||
183 | i < (u_short) (smc->hw.fp.fifo.rbc_ram_end-1); i++) | ||
184 | write_mdr(smc,0L) ; | ||
185 | /* Erase the last byte too */ | ||
186 | write_mdr(smc,0L) ; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * set receive FIFO pointer | ||
191 | */ | ||
192 | static void set_recvptr(struct s_smc *smc) | ||
193 | { | ||
194 | /* | ||
195 | * initialize the pointer for receive queue 1 | ||
196 | */ | ||
197 | outpw(FM_A(FM_RPR1),smc->hw.fp.fifo.rx1_fifo_start) ; /* RPR1 */ | ||
198 | outpw(FM_A(FM_SWPR1),smc->hw.fp.fifo.rx1_fifo_start) ; /* SWPR1 */ | ||
199 | outpw(FM_A(FM_WPR1),smc->hw.fp.fifo.rx1_fifo_start) ; /* WPR1 */ | ||
200 | outpw(FM_A(FM_EARV1),smc->hw.fp.fifo.tx_s_start-1) ; /* EARV1 */ | ||
201 | |||
202 | /* | ||
203 | * initialize the pointer for receive queue 2 | ||
204 | */ | ||
205 | if (smc->hw.fp.fifo.rx2_fifo_size) { | ||
206 | outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rx2_fifo_start) ; | ||
207 | outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rx2_fifo_start) ; | ||
208 | outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rx2_fifo_start) ; | ||
209 | outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ; | ||
210 | } | ||
211 | else { | ||
212 | outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rbc_ram_end-1) ; | ||
213 | outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rbc_ram_end-1) ; | ||
214 | outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rbc_ram_end-1) ; | ||
215 | outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * set transmit FIFO pointer | ||
221 | */ | ||
222 | static void set_txptr(struct s_smc *smc) | ||
223 | { | ||
224 | outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ; /* reset transmit queues */ | ||
225 | |||
226 | /* | ||
227 | * initialize the pointer for asynchronous transmit queue | ||
228 | */ | ||
229 | outpw(FM_A(FM_RPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* RPXA0 */ | ||
230 | outpw(FM_A(FM_SWPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* SWPXA0 */ | ||
231 | outpw(FM_A(FM_WPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* WPXA0 */ | ||
232 | outpw(FM_A(FM_EAA0),smc->hw.fp.fifo.rx2_fifo_start-1) ; /* EAA0 */ | ||
233 | |||
234 | /* | ||
235 | * initialize the pointer for synchronous transmit queue | ||
236 | */ | ||
237 | if (smc->hw.fp.fifo.tx_s_size) { | ||
238 | outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_s_start) ; | ||
239 | outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_s_start) ; | ||
240 | outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_s_start) ; | ||
241 | outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ; | ||
242 | } | ||
243 | else { | ||
244 | outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_a0_start-1) ; | ||
245 | outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_a0_start-1) ; | ||
246 | outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_a0_start-1) ; | ||
247 | outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ; | ||
248 | } | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * init memory buffer management registers | ||
253 | */ | ||
254 | static void init_rbc(struct s_smc *smc) | ||
255 | { | ||
256 | u_short rbc_ram_addr ; | ||
257 | |||
258 | /* | ||
259 | * set unused pointers or permanent pointers | ||
260 | */ | ||
261 | rbc_ram_addr = smc->hw.fp.fifo.rx2_fifo_start - 1 ; | ||
262 | |||
263 | outpw(FM_A(FM_RPXA1),rbc_ram_addr) ; /* a1-send pointer */ | ||
264 | outpw(FM_A(FM_WPXA1),rbc_ram_addr) ; | ||
265 | outpw(FM_A(FM_SWPXA1),rbc_ram_addr) ; | ||
266 | outpw(FM_A(FM_EAA1),rbc_ram_addr) ; | ||
267 | |||
268 | set_recvptr(smc) ; | ||
269 | set_txptr(smc) ; | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * init rx pointer | ||
274 | */ | ||
275 | static void init_rx(struct s_smc *smc) | ||
276 | { | ||
277 | struct s_smt_rx_queue *queue ; | ||
278 | |||
279 | /* | ||
280 | * init all tx data structures for receive queue 1 | ||
281 | */ | ||
282 | smc->hw.fp.rx[QUEUE_R1] = queue = &smc->hw.fp.rx_q[QUEUE_R1] ; | ||
283 | queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R1_CSR) ; | ||
284 | queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R1_DA) ; | ||
285 | |||
286 | /* | ||
287 | * init all tx data structures for receive queue 2 | ||
288 | */ | ||
289 | smc->hw.fp.rx[QUEUE_R2] = queue = &smc->hw.fp.rx_q[QUEUE_R2] ; | ||
290 | queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R2_CSR) ; | ||
291 | queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R2_DA) ; | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * set the TSYNC register of the FORMAC to regulate synchronous transmission | ||
296 | */ | ||
297 | void set_formac_tsync(struct s_smc *smc, long sync_bw) | ||
298 | { | ||
299 | outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * init all tx data structures | ||
304 | */ | ||
305 | static void init_tx(struct s_smc *smc) | ||
306 | { | ||
307 | struct s_smt_tx_queue *queue ; | ||
308 | |||
309 | /* | ||
310 | * init all tx data structures for the synchronous queue | ||
311 | */ | ||
312 | smc->hw.fp.tx[QUEUE_S] = queue = &smc->hw.fp.tx_q[QUEUE_S] ; | ||
313 | queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XS_CSR) ; | ||
314 | queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XS_DA) ; | ||
315 | |||
316 | #ifdef ESS | ||
317 | set_formac_tsync(smc,smc->ess.sync_bw) ; | ||
318 | #endif | ||
319 | |||
320 | /* | ||
321 | * init all tx data structures for the asynchronous queue 0 | ||
322 | */ | ||
323 | smc->hw.fp.tx[QUEUE_A0] = queue = &smc->hw.fp.tx_q[QUEUE_A0] ; | ||
324 | queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XA_CSR) ; | ||
325 | queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XA_DA) ; | ||
326 | |||
327 | |||
328 | llc_recover_tx(smc) ; | ||
329 | } | ||
330 | |||
331 | static void mac_counter_init(struct s_smc *smc) | ||
332 | { | ||
333 | int i ; | ||
334 | u_long *ec ; | ||
335 | |||
336 | /* | ||
337 | * clear FORMAC+ frame-, lost- and error counter | ||
338 | */ | ||
339 | outpw(FM_A(FM_FCNTR),0) ; | ||
340 | outpw(FM_A(FM_LCNTR),0) ; | ||
341 | outpw(FM_A(FM_ECNTR),0) ; | ||
342 | /* | ||
343 | * clear internal error counter stucture | ||
344 | */ | ||
345 | ec = (u_long *)&smc->hw.fp.err_stats ; | ||
346 | for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--) | ||
347 | *ec++ = 0L ; | ||
348 | smc->mib.m[MAC0].fddiMACRingOp_Ct = 0 ; | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * set FORMAC address, and t_request | ||
353 | */ | ||
354 | static void set_formac_addr(struct s_smc *smc) | ||
355 | { | ||
356 | long t_requ = smc->mib.m[MAC0].fddiMACT_Req ; | ||
357 | |||
358 | outpw(FM_A(FM_SAID),my_said) ; /* set short address */ | ||
359 | outpw(FM_A(FM_LAIL),(unsigned)((smc->hw.fddi_home_addr.a[4]<<8) + | ||
360 | smc->hw.fddi_home_addr.a[5])) ; | ||
361 | outpw(FM_A(FM_LAIC),(unsigned)((smc->hw.fddi_home_addr.a[2]<<8) + | ||
362 | smc->hw.fddi_home_addr.a[3])) ; | ||
363 | outpw(FM_A(FM_LAIM),(unsigned)((smc->hw.fddi_home_addr.a[0]<<8) + | ||
364 | smc->hw.fddi_home_addr.a[1])) ; | ||
365 | |||
366 | outpw(FM_A(FM_SAGP),my_sagp) ; /* set short group address */ | ||
367 | |||
368 | outpw(FM_A(FM_LAGL),(unsigned)((smc->hw.fp.group_addr.a[4]<<8) + | ||
369 | smc->hw.fp.group_addr.a[5])) ; | ||
370 | outpw(FM_A(FM_LAGC),(unsigned)((smc->hw.fp.group_addr.a[2]<<8) + | ||
371 | smc->hw.fp.group_addr.a[3])) ; | ||
372 | outpw(FM_A(FM_LAGM),(unsigned)((smc->hw.fp.group_addr.a[0]<<8) + | ||
373 | smc->hw.fp.group_addr.a[1])) ; | ||
374 | |||
375 | /* set r_request regs. (MSW & LSW of TRT ) */ | ||
376 | outpw(FM_A(FM_TREQ1),(unsigned)(t_requ>>16)) ; | ||
377 | outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ; | ||
378 | } | ||
379 | |||
380 | static void set_int(char *p, int l) | ||
381 | { | ||
382 | p[0] = (char)(l >> 24) ; | ||
383 | p[1] = (char)(l >> 16) ; | ||
384 | p[2] = (char)(l >> 8) ; | ||
385 | p[3] = (char)(l >> 0) ; | ||
386 | } | ||
387 | |||
388 | /* | ||
389 | * copy TX descriptor to buffer mem | ||
390 | * append FC field and MAC frame | ||
391 | * if more bit is set in descr | ||
392 | * append pointer to descriptor (endless loop) | ||
393 | * else | ||
394 | * append 'end of chain' pointer | ||
395 | */ | ||
396 | static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac, | ||
397 | unsigned off, int len) | ||
398 | /* u_long td; transmit descriptor */ | ||
399 | /* struct fddi_mac *mac; mac frame pointer */ | ||
400 | /* unsigned off; start address within buffer memory */ | ||
401 | /* int len ; lenght of the frame including the FC */ | ||
402 | { | ||
403 | int i ; | ||
404 | u_int *p ; | ||
405 | |||
406 | CHECK_NPP() ; | ||
407 | MARW(off) ; /* set memory address reg for writes */ | ||
408 | |||
409 | p = (u_int *) mac ; | ||
410 | for (i = (len + 3)/4 ; i ; i--) { | ||
411 | if (i == 1) { | ||
412 | /* last word, set the tag bit */ | ||
413 | outpw(FM_A(FM_CMDREG2),FM_ISTTB) ; | ||
414 | } | ||
415 | write_mdr(smc,MDR_REVERSE(*p)) ; | ||
416 | p++ ; | ||
417 | } | ||
418 | |||
419 | outpw(FM_A(FM_CMDREG2),FM_ISTTB) ; /* set the tag bit */ | ||
420 | write_mdr(smc,td) ; /* write over memory data reg to buffer */ | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | BEGIN_MANUAL_ENTRY(module;tests;3) | ||
425 | How to test directed beacon frames | ||
426 | ---------------------------------------------------------------- | ||
427 | |||
428 | o Insert a break point in the function build_claim_beacon() | ||
429 | before calling copy_tx_mac() for building the claim frame. | ||
430 | o Modify the RM3_DETECT case so that the RM6_DETECT state | ||
431 | will always entered from the RM3_DETECT state (function rmt_fsm(), | ||
432 | rmt.c) | ||
433 | o Compile the driver. | ||
434 | o Set the parameter TREQ in the protocol.ini or net.cfg to a | ||
435 | small value to make sure your station will win the claim | ||
436 | process. | ||
437 | o Start the driver. | ||
438 | o When you reach the break point, modify the SA and DA address | ||
439 | of the claim frame (e.g. SA = DA = 10005affffff). | ||
440 | o When you see RM3_DETECT and RM6_DETECT, observe the direct | ||
441 | beacon frames on the UPPSLANA. | ||
442 | |||
443 | END_MANUAL_ENTRY | ||
444 | */ | ||
445 | static void directed_beacon(struct s_smc *smc) | ||
446 | { | ||
447 | SK_LOC_DECL(u_int,a[2]) ; | ||
448 | |||
449 | /* | ||
450 | * set UNA in frame | ||
451 | * enable FORMAC to send endless queue of directed beacon | ||
452 | * important: the UNA starts at byte 1 (not at byte 0) | ||
453 | */ | ||
454 | * (char *) a = (char) ((long)DBEACON_INFO<<24L) ; | ||
455 | a[1] = 0 ; | ||
456 | memcpy((char *)a+1,(char *) &smc->mib.m[MAC0].fddiMACUpstreamNbr,6) ; | ||
457 | |||
458 | CHECK_NPP() ; | ||
459 | /* set memory address reg for writes */ | ||
460 | MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ; | ||
461 | write_mdr(smc,MDR_REVERSE(a[0])) ; | ||
462 | outpw(FM_A(FM_CMDREG2),FM_ISTTB) ; /* set the tag bit */ | ||
463 | write_mdr(smc,MDR_REVERSE(a[1])) ; | ||
464 | |||
465 | outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ; | ||
466 | } | ||
467 | |||
468 | /* | ||
469 | setup claim & beacon pointer | ||
470 | NOTE : | ||
471 | special frame packets end with a pointer to their own | ||
472 | descriptor, and the MORE bit is set in the descriptor | ||
473 | */ | ||
474 | static void build_claim_beacon(struct s_smc *smc, u_long t_request) | ||
475 | { | ||
476 | u_int td ; | ||
477 | int len ; | ||
478 | struct fddi_mac_sf *mac ; | ||
479 | |||
480 | /* | ||
481 | * build claim packet | ||
482 | */ | ||
483 | len = 17 ; | ||
484 | td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ; | ||
485 | mac = &smc->hw.fp.mac_sfb ; | ||
486 | mac->mac_fc = FC_CLAIM ; | ||
487 | /* DA == SA in claim frame */ | ||
488 | mac->mac_source = mac->mac_dest = MA ; | ||
489 | /* 2's complement */ | ||
490 | set_int((char *)mac->mac_info,(int)t_request) ; | ||
491 | |||
492 | copy_tx_mac(smc,td,(struct fddi_mac *)mac, | ||
493 | smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ; | ||
494 | /* set CLAIM start pointer */ | ||
495 | outpw(FM_A(FM_SACL),smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF) ; | ||
496 | |||
497 | /* | ||
498 | * build beacon packet | ||
499 | */ | ||
500 | len = 17 ; | ||
501 | td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ; | ||
502 | mac->mac_fc = FC_BEACON ; | ||
503 | mac->mac_source = MA ; | ||
504 | mac->mac_dest = null_addr ; /* DA == 0 in beacon frame */ | ||
505 | set_int((char *) mac->mac_info,((int)BEACON_INFO<<24) + 0 ) ; | ||
506 | |||
507 | copy_tx_mac(smc,td,(struct fddi_mac *)mac, | ||
508 | smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ; | ||
509 | /* set beacon start pointer */ | ||
510 | outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF) ; | ||
511 | |||
512 | /* | ||
513 | * build directed beacon packet | ||
514 | * contains optional UNA | ||
515 | */ | ||
516 | len = 23 ; | ||
517 | td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ; | ||
518 | mac->mac_fc = FC_BEACON ; | ||
519 | mac->mac_source = MA ; | ||
520 | mac->mac_dest = dbeacon_multi ; /* multicast */ | ||
521 | set_int((char *) mac->mac_info,((int)DBEACON_INFO<<24) + 0 ) ; | ||
522 | set_int((char *) mac->mac_info+4,0) ; | ||
523 | set_int((char *) mac->mac_info+8,0) ; | ||
524 | |||
525 | copy_tx_mac(smc,td,(struct fddi_mac *)mac, | ||
526 | smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ; | ||
527 | |||
528 | /* end of claim/beacon queue */ | ||
529 | outpw(FM_A(FM_EACB),smc->hw.fp.fifo.rx1_fifo_start-1) ; | ||
530 | |||
531 | outpw(FM_A(FM_WPXSF),0) ; | ||
532 | outpw(FM_A(FM_RPXSF),0) ; | ||
533 | } | ||
534 | |||
535 | static void formac_rcv_restart(struct s_smc *smc) | ||
536 | { | ||
537 | /* enable receive function */ | ||
538 | SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ; | ||
539 | |||
540 | outpw(FM_A(FM_CMDREG1),FM_ICLLR) ; /* clear receive lock */ | ||
541 | } | ||
542 | |||
543 | void formac_tx_restart(struct s_smc *smc) | ||
544 | { | ||
545 | outpw(FM_A(FM_CMDREG1),FM_ICLLS) ; /* clear s-frame lock */ | ||
546 | outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */ | ||
547 | } | ||
548 | |||
549 | static void enable_formac(struct s_smc *smc) | ||
550 | { | ||
551 | /* set formac IMSK : 0 enables irq */ | ||
552 | outpw(FM_A(FM_IMSK1U),~mac_imsk1u) ; | ||
553 | outpw(FM_A(FM_IMSK1L),~mac_imsk1l) ; | ||
554 | outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ; | ||
555 | outpw(FM_A(FM_IMSK2L),~mac_imsk2l) ; | ||
556 | outpw(FM_A(FM_IMSK3U),~mac_imsk3u) ; | ||
557 | outpw(FM_A(FM_IMSK3L),~mac_imsk3l) ; | ||
558 | } | ||
559 | |||
560 | #if 0 /* Removed because the driver should use the ASICs TX complete IRQ. */ | ||
561 | /* The FORMACs tx complete IRQ should be used any longer */ | ||
562 | |||
563 | /* | ||
564 | BEGIN_MANUAL_ENTRY(if,func;others;4) | ||
565 | |||
566 | void enable_tx_irq(smc, queue) | ||
567 | struct s_smc *smc ; | ||
568 | u_short queue ; | ||
569 | |||
570 | Function DOWNCALL (SMT, fplustm.c) | ||
571 | enable_tx_irq() enables the FORMACs transmit complete | ||
572 | interrupt of the queue. | ||
573 | |||
574 | Para queue = QUEUE_S: synchronous queue | ||
575 | = QUEUE_A0: asynchronous queue | ||
576 | |||
577 | Note After any ring operational change the transmit complete | ||
578 | interrupts are disabled. | ||
579 | The operating system dependent module must enable | ||
580 | the transmit complete interrupt of a queue, | ||
581 | - when it queues the first frame, | ||
582 | because of no transmit resources are beeing | ||
583 | available and | ||
584 | - when it escapes from the function llc_restart_tx | ||
585 | while some frames are still queued. | ||
586 | |||
587 | END_MANUAL_ENTRY | ||
588 | */ | ||
589 | void enable_tx_irq(struct s_smc *smc, u_short queue) | ||
590 | /* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */ | ||
591 | { | ||
592 | u_short imask ; | ||
593 | |||
594 | imask = ~(inpw(FM_A(FM_IMSK1U))) ; | ||
595 | |||
596 | if (queue == 0) { | ||
597 | outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMS)) ; | ||
598 | } | ||
599 | if (queue == 1) { | ||
600 | outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMA0)) ; | ||
601 | } | ||
602 | } | ||
603 | |||
604 | /* | ||
605 | BEGIN_MANUAL_ENTRY(if,func;others;4) | ||
606 | |||
607 | void disable_tx_irq(smc, queue) | ||
608 | struct s_smc *smc ; | ||
609 | u_short queue ; | ||
610 | |||
611 | Function DOWNCALL (SMT, fplustm.c) | ||
612 | disable_tx_irq disables the FORMACs transmit complete | ||
613 | interrupt of the queue | ||
614 | |||
615 | Para queue = QUEUE_S: synchronous queue | ||
616 | = QUEUE_A0: asynchronous queue | ||
617 | |||
618 | Note The operating system dependent module should disable | ||
619 | the transmit complete interrupts if it escapes from the | ||
620 | function llc_restart_tx and no frames are queued. | ||
621 | |||
622 | END_MANUAL_ENTRY | ||
623 | */ | ||
624 | void disable_tx_irq(struct s_smc *smc, u_short queue) | ||
625 | /* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */ | ||
626 | { | ||
627 | u_short imask ; | ||
628 | |||
629 | imask = ~(inpw(FM_A(FM_IMSK1U))) ; | ||
630 | |||
631 | if (queue == 0) { | ||
632 | outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMS)) ; | ||
633 | } | ||
634 | if (queue == 1) { | ||
635 | outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMA0)) ; | ||
636 | } | ||
637 | } | ||
638 | #endif | ||
639 | |||
640 | static void disable_formac(struct s_smc *smc) | ||
641 | { | ||
642 | /* clear formac IMSK : 1 disables irq */ | ||
643 | outpw(FM_A(FM_IMSK1U),MW) ; | ||
644 | outpw(FM_A(FM_IMSK1L),MW) ; | ||
645 | outpw(FM_A(FM_IMSK2U),MW) ; | ||
646 | outpw(FM_A(FM_IMSK2L),MW) ; | ||
647 | outpw(FM_A(FM_IMSK3U),MW) ; | ||
648 | outpw(FM_A(FM_IMSK3L),MW) ; | ||
649 | } | ||
650 | |||
651 | |||
652 | static void mac_ring_up(struct s_smc *smc, int up) | ||
653 | { | ||
654 | if (up) { | ||
655 | formac_rcv_restart(smc) ; /* enable receive function */ | ||
656 | smc->hw.mac_ring_is_up = TRUE ; | ||
657 | llc_restart_tx(smc) ; /* TX queue */ | ||
658 | } | ||
659 | else { | ||
660 | /* disable receive function */ | ||
661 | SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ; | ||
662 | |||
663 | /* abort current transmit activity */ | ||
664 | outpw(FM_A(FM_CMDREG2),FM_IACTR) ; | ||
665 | |||
666 | smc->hw.mac_ring_is_up = FALSE ; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | /*--------------------------- ISR handling ----------------------------------*/ | ||
671 | /* | ||
672 | * mac1_irq is in drvfbi.c | ||
673 | */ | ||
674 | |||
675 | /* | ||
676 | * mac2_irq: status bits for the receive queue 1, and ring status | ||
677 | * ring status indication bits | ||
678 | */ | ||
679 | void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l) | ||
680 | { | ||
681 | u_short change_s2l ; | ||
682 | u_short change_s2u ; | ||
683 | |||
684 | /* (jd) 22-Feb-1999 | ||
685 | * Restart 2_DMax Timer after end of claiming or beaconing | ||
686 | */ | ||
687 | if (code_s2u & (FM_SCLM|FM_SHICLM|FM_SBEC|FM_SOTRBEC)) { | ||
688 | queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ; | ||
689 | } | ||
690 | else if (code_s2l & (FM_STKISS)) { | ||
691 | queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ; | ||
692 | } | ||
693 | |||
694 | /* | ||
695 | * XOR current st bits with the last to avoid useless RMT event queuing | ||
696 | */ | ||
697 | change_s2l = smc->hw.fp.s2l ^ code_s2l ; | ||
698 | change_s2u = smc->hw.fp.s2u ^ code_s2u ; | ||
699 | |||
700 | if ((change_s2l & FM_SRNGOP) || | ||
701 | (!smc->hw.mac_ring_is_up && ((code_s2l & FM_SRNGOP)))) { | ||
702 | if (code_s2l & FM_SRNGOP) { | ||
703 | mac_ring_up(smc,1) ; | ||
704 | queue_event(smc,EVENT_RMT,RM_RING_OP) ; | ||
705 | smc->mib.m[MAC0].fddiMACRingOp_Ct++ ; | ||
706 | } | ||
707 | else { | ||
708 | mac_ring_up(smc,0) ; | ||
709 | queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ; | ||
710 | } | ||
711 | goto mac2_end ; | ||
712 | } | ||
713 | if (code_s2l & FM_SMISFRM) { /* missed frame */ | ||
714 | smc->mib.m[MAC0].fddiMACNotCopied_Ct++ ; | ||
715 | } | ||
716 | if (code_s2u & (FM_SRCVOVR | /* recv. FIFO overflow */ | ||
717 | FM_SRBFL)) { /* recv. buffer full */ | ||
718 | smc->hw.mac_ct.mac_r_restart_counter++ ; | ||
719 | /* formac_rcv_restart(smc) ; */ | ||
720 | smt_stat_counter(smc,1) ; | ||
721 | /* goto mac2_end ; */ | ||
722 | } | ||
723 | if (code_s2u & FM_SOTRBEC) | ||
724 | queue_event(smc,EVENT_RMT,RM_OTHER_BEACON) ; | ||
725 | if (code_s2u & FM_SMYBEC) | ||
726 | queue_event(smc,EVENT_RMT,RM_MY_BEACON) ; | ||
727 | if (change_s2u & code_s2u & FM_SLOCLM) { | ||
728 | DB_RMTN(2,"RMT : lower claim received\n",0,0) ; | ||
729 | } | ||
730 | if ((code_s2u & FM_SMYCLM) && !(code_s2l & FM_SDUPCLM)) { | ||
731 | /* | ||
732 | * This is my claim and that claim is not detected as a | ||
733 | * duplicate one. | ||
734 | */ | ||
735 | queue_event(smc,EVENT_RMT,RM_MY_CLAIM) ; | ||
736 | } | ||
737 | if (code_s2l & FM_SDUPCLM) { | ||
738 | /* | ||
739 | * If a duplicate claim frame (same SA but T_Bid != T_Req) | ||
740 | * this flag will be set. | ||
741 | * In the RMT state machine we need a RM_VALID_CLAIM event | ||
742 | * to do the appropriate state change. | ||
743 | * RM(34c) | ||
744 | */ | ||
745 | queue_event(smc,EVENT_RMT,RM_VALID_CLAIM) ; | ||
746 | } | ||
747 | if (change_s2u & code_s2u & FM_SHICLM) { | ||
748 | DB_RMTN(2,"RMT : higher claim received\n",0,0) ; | ||
749 | } | ||
750 | if ( (code_s2l & FM_STRTEXP) || | ||
751 | (code_s2l & FM_STRTEXR) ) | ||
752 | queue_event(smc,EVENT_RMT,RM_TRT_EXP) ; | ||
753 | if (code_s2l & FM_SMULTDA) { | ||
754 | /* | ||
755 | * The MAC has found a 2. MAC with the same address. | ||
756 | * Signal dup_addr_test = failed to RMT state machine. | ||
757 | * RM(25) | ||
758 | */ | ||
759 | smc->r.dup_addr_test = DA_FAILED ; | ||
760 | queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ; | ||
761 | } | ||
762 | if (code_s2u & FM_SBEC) | ||
763 | smc->hw.fp.err_stats.err_bec_stat++ ; | ||
764 | if (code_s2u & FM_SCLM) | ||
765 | smc->hw.fp.err_stats.err_clm_stat++ ; | ||
766 | if (code_s2l & FM_STVXEXP) | ||
767 | smc->mib.m[MAC0].fddiMACTvxExpired_Ct++ ; | ||
768 | if ((code_s2u & (FM_SBEC|FM_SCLM))) { | ||
769 | if (!(change_s2l & FM_SRNGOP) && (smc->hw.fp.s2l & FM_SRNGOP)) { | ||
770 | mac_ring_up(smc,0) ; | ||
771 | queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ; | ||
772 | |||
773 | mac_ring_up(smc,1) ; | ||
774 | queue_event(smc,EVENT_RMT,RM_RING_OP) ; | ||
775 | smc->mib.m[MAC0].fddiMACRingOp_Ct++ ; | ||
776 | } | ||
777 | } | ||
778 | if (code_s2l & FM_SPHINV) | ||
779 | smc->hw.fp.err_stats.err_phinv++ ; | ||
780 | if (code_s2l & FM_SSIFG) | ||
781 | smc->hw.fp.err_stats.err_sifg_det++ ; | ||
782 | if (code_s2l & FM_STKISS) | ||
783 | smc->hw.fp.err_stats.err_tkiss++ ; | ||
784 | if (code_s2l & FM_STKERR) | ||
785 | smc->hw.fp.err_stats.err_tkerr++ ; | ||
786 | if (code_s2l & FM_SFRMCTR) | ||
787 | smc->mib.m[MAC0].fddiMACFrame_Ct += 0x10000L ; | ||
788 | if (code_s2l & FM_SERRCTR) | ||
789 | smc->mib.m[MAC0].fddiMACError_Ct += 0x10000L ; | ||
790 | if (code_s2l & FM_SLSTCTR) | ||
791 | smc->mib.m[MAC0].fddiMACLost_Ct += 0x10000L ; | ||
792 | if (code_s2u & FM_SERRSF) { | ||
793 | SMT_PANIC(smc,SMT_E0114, SMT_E0114_MSG) ; | ||
794 | } | ||
795 | mac2_end: | ||
796 | /* notice old status */ | ||
797 | smc->hw.fp.s2l = code_s2l ; | ||
798 | smc->hw.fp.s2u = code_s2u ; | ||
799 | outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ; | ||
800 | } | ||
801 | |||
802 | /* | ||
803 | * mac3_irq: receive queue 2 bits and address detection bits | ||
804 | */ | ||
805 | void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l) | ||
806 | { | ||
807 | UNUSED(code_s3l) ; | ||
808 | |||
809 | if (code_s3u & (FM_SRCVOVR2 | /* recv. FIFO overflow */ | ||
810 | FM_SRBFL2)) { /* recv. buffer full */ | ||
811 | smc->hw.mac_ct.mac_r_restart_counter++ ; | ||
812 | smt_stat_counter(smc,1); | ||
813 | } | ||
814 | |||
815 | |||
816 | if (code_s3u & FM_SRPERRQ2) { /* parity error receive queue 2 */ | ||
817 | SMT_PANIC(smc,SMT_E0115, SMT_E0115_MSG) ; | ||
818 | } | ||
819 | if (code_s3u & FM_SRPERRQ1) { /* parity error receive queue 2 */ | ||
820 | SMT_PANIC(smc,SMT_E0116, SMT_E0116_MSG) ; | ||
821 | } | ||
822 | } | ||
823 | |||
824 | |||
825 | /* | ||
826 | * take formac offline | ||
827 | */ | ||
828 | static void formac_offline(struct s_smc *smc) | ||
829 | { | ||
830 | outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */ | ||
831 | |||
832 | /* disable receive function */ | ||
833 | SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ; | ||
834 | |||
835 | /* FORMAC+ 'Initialize Mode' */ | ||
836 | SETMASK(FM_A(FM_MDREG1),FM_MINIT,FM_MMODE) ; | ||
837 | |||
838 | disable_formac(smc) ; | ||
839 | smc->hw.mac_ring_is_up = FALSE ; | ||
840 | smc->hw.hw_state = STOPPED ; | ||
841 | } | ||
842 | |||
843 | /* | ||
844 | * bring formac online | ||
845 | */ | ||
846 | static void formac_online(struct s_smc *smc) | ||
847 | { | ||
848 | enable_formac(smc) ; | ||
849 | SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT | | ||
850 | smc->hw.fp.rx_mode, FM_MMODE | FM_SELRA | FM_ADDRX) ; | ||
851 | } | ||
852 | |||
853 | /* | ||
854 | * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon) | ||
855 | */ | ||
856 | int init_fplus(struct s_smc *smc) | ||
857 | { | ||
858 | smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ; | ||
859 | smc->hw.fp.rx_mode = FM_MDAMA ; | ||
860 | smc->hw.fp.group_addr = fddi_broadcast ; | ||
861 | smc->hw.fp.func_addr = 0 ; | ||
862 | smc->hw.fp.frselreg_init = 0 ; | ||
863 | |||
864 | init_driver_fplus(smc) ; | ||
865 | if (smc->s.sas == SMT_DAS) | ||
866 | smc->hw.fp.mdr3init |= FM_MENDAS ; | ||
867 | |||
868 | smc->hw.mac_ct.mac_nobuf_counter = 0 ; | ||
869 | smc->hw.mac_ct.mac_r_restart_counter = 0 ; | ||
870 | |||
871 | smc->hw.fp.fm_st1u = (HW_PTR) ADDR(B0_ST1U) ; | ||
872 | smc->hw.fp.fm_st1l = (HW_PTR) ADDR(B0_ST1L) ; | ||
873 | smc->hw.fp.fm_st2u = (HW_PTR) ADDR(B0_ST2U) ; | ||
874 | smc->hw.fp.fm_st2l = (HW_PTR) ADDR(B0_ST2L) ; | ||
875 | smc->hw.fp.fm_st3u = (HW_PTR) ADDR(B0_ST3U) ; | ||
876 | smc->hw.fp.fm_st3l = (HW_PTR) ADDR(B0_ST3L) ; | ||
877 | |||
878 | smc->hw.fp.s2l = smc->hw.fp.s2u = 0 ; | ||
879 | smc->hw.mac_ring_is_up = 0 ; | ||
880 | |||
881 | mac_counter_init(smc) ; | ||
882 | |||
883 | /* convert BCKL units to symbol time */ | ||
884 | smc->hw.mac_pa.t_neg = (u_long)0 ; | ||
885 | smc->hw.mac_pa.t_pri = (u_long)0 ; | ||
886 | |||
887 | /* make sure all PCI settings are correct */ | ||
888 | mac_do_pci_fix(smc) ; | ||
889 | |||
890 | return(init_mac(smc,1)) ; | ||
891 | /* enable_formac(smc) ; */ | ||
892 | } | ||
893 | |||
894 | static int init_mac(struct s_smc *smc, int all) | ||
895 | { | ||
896 | u_short t_max,x ; | ||
897 | u_long time=0 ; | ||
898 | |||
899 | /* | ||
900 | * clear memory | ||
901 | */ | ||
902 | outpw(FM_A(FM_MDREG1),FM_MINIT) ; /* FORMAC+ init mode */ | ||
903 | set_formac_addr(smc) ; | ||
904 | outpw(FM_A(FM_MDREG1),FM_MMEMACT) ; /* FORMAC+ memory activ mode */ | ||
905 | /* Note: Mode register 2 is set here, incase parity is enabled. */ | ||
906 | outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ; | ||
907 | |||
908 | if (all) { | ||
909 | init_ram(smc) ; | ||
910 | } | ||
911 | else { | ||
912 | /* | ||
913 | * reset the HPI, the Master and the BMUs | ||
914 | */ | ||
915 | outp(ADDR(B0_CTRL), CTRL_HPI_SET) ; | ||
916 | time = hwt_quick_read(smc) ; | ||
917 | } | ||
918 | |||
919 | /* | ||
920 | * set all pointers, frames etc | ||
921 | */ | ||
922 | smt_split_up_fifo(smc) ; | ||
923 | |||
924 | init_tx(smc) ; | ||
925 | init_rx(smc) ; | ||
926 | init_rbc(smc) ; | ||
927 | |||
928 | build_claim_beacon(smc,smc->mib.m[MAC0].fddiMACT_Req) ; | ||
929 | |||
930 | /* set RX threshold */ | ||
931 | /* see Errata #SN2 Phantom receive overflow */ | ||
932 | outpw(FM_A(FM_FRMTHR),14<<12) ; /* switch on */ | ||
933 | |||
934 | /* set formac work mode */ | ||
935 | outpw(FM_A(FM_MDREG1),MDR1INIT | FM_SELRA | smc->hw.fp.rx_mode) ; | ||
936 | outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ; | ||
937 | outpw(FM_A(FM_MDREG3),smc->hw.fp.mdr3init) ; | ||
938 | outpw(FM_A(FM_FRSELREG),smc->hw.fp.frselreg_init) ; | ||
939 | |||
940 | /* set timer */ | ||
941 | /* | ||
942 | * errata #22 fplus: | ||
943 | * T_MAX must not be FFFE | ||
944 | * or one of FFDF, FFB8, FF91 (-0x27 etc..) | ||
945 | */ | ||
946 | t_max = (u_short)(smc->mib.m[MAC0].fddiMACT_Max/32) ; | ||
947 | x = t_max/0x27 ; | ||
948 | x *= 0x27 ; | ||
949 | if ((t_max == 0xfffe) || (t_max - x == 0x16)) | ||
950 | t_max-- ; | ||
951 | outpw(FM_A(FM_TMAX),(u_short)t_max) ; | ||
952 | |||
953 | /* BugFix for report #10204 */ | ||
954 | if (smc->mib.m[MAC0].fddiMACTvxValue < (u_long) (- US2BCLK(52))) { | ||
955 | outpw(FM_A(FM_TVX), (u_short) (- US2BCLK(52))/255 & MB) ; | ||
956 | } else { | ||
957 | outpw(FM_A(FM_TVX), | ||
958 | (u_short)((smc->mib.m[MAC0].fddiMACTvxValue/255) & MB)) ; | ||
959 | } | ||
960 | |||
961 | outpw(FM_A(FM_CMDREG1),FM_ICLLS) ; /* clear s-frame lock */ | ||
962 | outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */ | ||
963 | outpw(FM_A(FM_CMDREG1),FM_ICLLR); /* clear receive lock */ | ||
964 | |||
965 | /* Auto unlock receice threshold for receive queue 1 and 2 */ | ||
966 | outpw(FM_A(FM_UNLCKDLY),(0xff|(0xff<<8))) ; | ||
967 | |||
968 | rtm_init(smc) ; /* RT-Monitor */ | ||
969 | |||
970 | if (!all) { | ||
971 | /* | ||
972 | * after 10ms, reset the BMUs and repair the rings | ||
973 | */ | ||
974 | hwt_wait_time(smc,time,MS2BCLK(10)) ; | ||
975 | outpd(ADDR(B0_R1_CSR),CSR_SET_RESET) ; | ||
976 | outpd(ADDR(B0_XA_CSR),CSR_SET_RESET) ; | ||
977 | outpd(ADDR(B0_XS_CSR),CSR_SET_RESET) ; | ||
978 | outp(ADDR(B0_CTRL), CTRL_HPI_CLR) ; | ||
979 | outpd(ADDR(B0_R1_CSR),CSR_CLR_RESET) ; | ||
980 | outpd(ADDR(B0_XA_CSR),CSR_CLR_RESET) ; | ||
981 | outpd(ADDR(B0_XS_CSR),CSR_CLR_RESET) ; | ||
982 | if (!smc->hw.hw_is_64bit) { | ||
983 | outpd(ADDR(B4_R1_F), RX_WATERMARK) ; | ||
984 | outpd(ADDR(B5_XA_F), TX_WATERMARK) ; | ||
985 | outpd(ADDR(B5_XS_F), TX_WATERMARK) ; | ||
986 | } | ||
987 | smc->hw.hw_state = STOPPED ; | ||
988 | mac_drv_repair_descr(smc) ; | ||
989 | } | ||
990 | smc->hw.hw_state = STARTED ; | ||
991 | |||
992 | return(0) ; | ||
993 | } | ||
994 | |||
995 | |||
996 | /* | ||
997 | * called by CFM | ||
998 | */ | ||
999 | void config_mux(struct s_smc *smc, int mux) | ||
1000 | { | ||
1001 | plc_config_mux(smc,mux) ; | ||
1002 | |||
1003 | SETMASK(FM_A(FM_MDREG1),FM_SELRA,FM_SELRA) ; | ||
1004 | } | ||
1005 | |||
1006 | /* | ||
1007 | * called by RMT | ||
1008 | * enable CLAIM/BEACON interrupts | ||
1009 | * (only called if these events are of interest, e.g. in DETECT state | ||
1010 | * the interrupt must not be permanently enabled | ||
1011 | * RMT calls this function periodically (timer driven polling) | ||
1012 | */ | ||
1013 | void sm_mac_check_beacon_claim(struct s_smc *smc) | ||
1014 | { | ||
1015 | /* set formac IMSK : 0 enables irq */ | ||
1016 | outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ; | ||
1017 | /* the driver must receive the directed beacons */ | ||
1018 | formac_rcv_restart(smc) ; | ||
1019 | process_receive(smc) ; | ||
1020 | } | ||
1021 | |||
1022 | /*-------------------------- interface functions ----------------------------*/ | ||
1023 | /* | ||
1024 | * control MAC layer (called by RMT) | ||
1025 | */ | ||
1026 | void sm_ma_control(struct s_smc *smc, int mode) | ||
1027 | { | ||
1028 | switch(mode) { | ||
1029 | case MA_OFFLINE : | ||
1030 | /* Add to make the MAC offline in RM0_ISOLATED state */ | ||
1031 | formac_offline(smc) ; | ||
1032 | break ; | ||
1033 | case MA_RESET : | ||
1034 | (void)init_mac(smc,0) ; | ||
1035 | break ; | ||
1036 | case MA_BEACON : | ||
1037 | formac_online(smc) ; | ||
1038 | break ; | ||
1039 | case MA_DIRECTED : | ||
1040 | directed_beacon(smc) ; | ||
1041 | break ; | ||
1042 | case MA_TREQ : | ||
1043 | /* | ||
1044 | * no actions necessary, TREQ is already set | ||
1045 | */ | ||
1046 | break ; | ||
1047 | } | ||
1048 | } | ||
1049 | |||
1050 | int sm_mac_get_tx_state(struct s_smc *smc) | ||
1051 | { | ||
1052 | return((inpw(FM_A(FM_STMCHN))>>4)&7) ; | ||
1053 | } | ||
1054 | |||
1055 | /* | ||
1056 | * multicast functions | ||
1057 | */ | ||
1058 | |||
1059 | static struct s_fpmc* mac_get_mc_table(struct s_smc *smc, | ||
1060 | struct fddi_addr *user, | ||
1061 | struct fddi_addr *own, | ||
1062 | int del, int can) | ||
1063 | { | ||
1064 | struct s_fpmc *tb ; | ||
1065 | struct s_fpmc *slot ; | ||
1066 | u_char *p ; | ||
1067 | int i ; | ||
1068 | |||
1069 | /* | ||
1070 | * set own = can(user) | ||
1071 | */ | ||
1072 | *own = *user ; | ||
1073 | if (can) { | ||
1074 | p = own->a ; | ||
1075 | for (i = 0 ; i < 6 ; i++, p++) | ||
1076 | *p = canonical[*p] ; | ||
1077 | } | ||
1078 | slot = NULL; | ||
1079 | for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){ | ||
1080 | if (!tb->n) { /* not used */ | ||
1081 | if (!del && !slot) /* if !del save first free */ | ||
1082 | slot = tb ; | ||
1083 | continue ; | ||
1084 | } | ||
1085 | if (memcmp((char *)&tb->a,(char *)own,6)) | ||
1086 | continue ; | ||
1087 | return(tb) ; | ||
1088 | } | ||
1089 | return(slot) ; /* return first free or NULL */ | ||
1090 | } | ||
1091 | |||
1092 | /* | ||
1093 | BEGIN_MANUAL_ENTRY(if,func;others;2) | ||
1094 | |||
1095 | void mac_clear_multicast(smc) | ||
1096 | struct s_smc *smc ; | ||
1097 | |||
1098 | Function DOWNCALL (SMT, fplustm.c) | ||
1099 | Clear all multicast entries | ||
1100 | |||
1101 | END_MANUAL_ENTRY() | ||
1102 | */ | ||
1103 | void mac_clear_multicast(struct s_smc *smc) | ||
1104 | { | ||
1105 | struct s_fpmc *tb ; | ||
1106 | int i ; | ||
1107 | |||
1108 | smc->hw.fp.os_slots_used = 0 ; /* note the SMT addresses */ | ||
1109 | /* will not be deleted */ | ||
1110 | for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){ | ||
1111 | if (!tb->perm) { | ||
1112 | tb->n = 0 ; | ||
1113 | } | ||
1114 | } | ||
1115 | } | ||
1116 | |||
1117 | /* | ||
1118 | BEGIN_MANUAL_ENTRY(if,func;others;2) | ||
1119 | |||
1120 | int mac_set_func_addr(smc,f_addr) | ||
1121 | struct s_smc *smc ; | ||
1122 | u_long f_addr ; | ||
1123 | |||
1124 | Function DOWNCALL (SMT, fplustm.c) | ||
1125 | Set a Token-Ring functional address, the address will | ||
1126 | be activated after calling mac_update_multicast() | ||
1127 | |||
1128 | Para f_addr functional bits in non-canonical format | ||
1129 | |||
1130 | Returns 0: always success | ||
1131 | |||
1132 | END_MANUAL_ENTRY() | ||
1133 | */ | ||
1134 | int mac_set_func_addr(struct s_smc *smc, u_long f_addr) | ||
1135 | { | ||
1136 | smc->hw.fp.func_addr = f_addr ; | ||
1137 | return(0) ; | ||
1138 | } | ||
1139 | |||
1140 | |||
1141 | /* | ||
1142 | BEGIN_MANUAL_ENTRY(if,func;others;2) | ||
1143 | |||
1144 | int mac_add_multicast(smc,addr,can) | ||
1145 | struct s_smc *smc ; | ||
1146 | struct fddi_addr *addr ; | ||
1147 | int can ; | ||
1148 | |||
1149 | Function DOWNCALL (SMC, fplustm.c) | ||
1150 | Add an entry to the multicast table | ||
1151 | |||
1152 | Para addr pointer to a multicast address | ||
1153 | can = 0: the multicast address has the physical format | ||
1154 | = 1: the multicast address has the canonical format | ||
1155 | | 0x80 permanent | ||
1156 | |||
1157 | Returns 0: success | ||
1158 | 1: address table full | ||
1159 | |||
1160 | Note After a 'driver reset' or a 'station set address' all | ||
1161 | entries of the multicast table are cleared. | ||
1162 | In this case the driver has to fill the multicast table again. | ||
1163 | After the operating system dependent module filled | ||
1164 | the multicast table it must call mac_update_multicast | ||
1165 | to activate the new multicast addresses! | ||
1166 | |||
1167 | END_MANUAL_ENTRY() | ||
1168 | */ | ||
1169 | int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) | ||
1170 | { | ||
1171 | SK_LOC_DECL(struct fddi_addr,own) ; | ||
1172 | struct s_fpmc *tb ; | ||
1173 | |||
1174 | /* | ||
1175 | * check if there are free table entries | ||
1176 | */ | ||
1177 | if (can & 0x80) { | ||
1178 | if (smc->hw.fp.smt_slots_used >= SMT_MAX_MULTI) { | ||
1179 | return(1) ; | ||
1180 | } | ||
1181 | } | ||
1182 | else { | ||
1183 | if (smc->hw.fp.os_slots_used >= FPMAX_MULTICAST-SMT_MAX_MULTI) { | ||
1184 | return(1) ; | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | /* | ||
1189 | * find empty slot | ||
1190 | */ | ||
1191 | if (!(tb = mac_get_mc_table(smc,addr,&own,0,can & ~0x80))) | ||
1192 | return(1) ; | ||
1193 | tb->n++ ; | ||
1194 | tb->a = own ; | ||
1195 | tb->perm = (can & 0x80) ? 1 : 0 ; | ||
1196 | |||
1197 | if (can & 0x80) | ||
1198 | smc->hw.fp.smt_slots_used++ ; | ||
1199 | else | ||
1200 | smc->hw.fp.os_slots_used++ ; | ||
1201 | |||
1202 | return(0) ; | ||
1203 | } | ||
1204 | |||
1205 | /* | ||
1206 | BEGIN_MANUAL_ENTRY(if,func;others;2) | ||
1207 | |||
1208 | void mac_del_multicast(smc,addr,can) | ||
1209 | struct s_smc *smc ; | ||
1210 | struct fddi_addr *addr ; | ||
1211 | int can ; | ||
1212 | |||
1213 | Function DOWNCALL (SMT, fplustm.c) | ||
1214 | Delete an entry from the multicast table | ||
1215 | |||
1216 | Para addr pointer to a multicast address | ||
1217 | can = 0: the multicast address has the physical format | ||
1218 | = 1: the multicast address has the canonical format | ||
1219 | | 0x80 permanent | ||
1220 | |||
1221 | END_MANUAL_ENTRY() | ||
1222 | */ | ||
1223 | void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) | ||
1224 | { | ||
1225 | SK_LOC_DECL(struct fddi_addr,own) ; | ||
1226 | struct s_fpmc *tb ; | ||
1227 | |||
1228 | if (!(tb = mac_get_mc_table(smc,addr,&own,1,can & ~0x80))) | ||
1229 | return ; | ||
1230 | /* | ||
1231 | * permanent addresses must be deleted with perm bit | ||
1232 | * and vice versa | ||
1233 | */ | ||
1234 | if (( tb->perm && (can & 0x80)) || | ||
1235 | (!tb->perm && !(can & 0x80))) { | ||
1236 | /* | ||
1237 | * delete it | ||
1238 | */ | ||
1239 | if (tb->n) { | ||
1240 | tb->n-- ; | ||
1241 | if (tb->perm) { | ||
1242 | smc->hw.fp.smt_slots_used-- ; | ||
1243 | } | ||
1244 | else { | ||
1245 | smc->hw.fp.os_slots_used-- ; | ||
1246 | } | ||
1247 | } | ||
1248 | } | ||
1249 | } | ||
1250 | |||
1251 | /* | ||
1252 | * mode | ||
1253 | */ | ||
1254 | |||
1255 | #define RX_MODE_PROM 0x1 | ||
1256 | #define RX_MODE_ALL_MULTI 0x2 | ||
1257 | |||
1258 | /* | ||
1259 | BEGIN_MANUAL_ENTRY(if,func;others;2) | ||
1260 | |||
1261 | void mac_update_multicast(smc) | ||
1262 | struct s_smc *smc ; | ||
1263 | |||
1264 | Function DOWNCALL (SMT, fplustm.c) | ||
1265 | Update FORMAC multicast registers | ||
1266 | |||
1267 | END_MANUAL_ENTRY() | ||
1268 | */ | ||
1269 | void mac_update_multicast(struct s_smc *smc) | ||
1270 | { | ||
1271 | struct s_fpmc *tb ; | ||
1272 | u_char *fu ; | ||
1273 | int i ; | ||
1274 | |||
1275 | /* | ||
1276 | * invalidate the CAM | ||
1277 | */ | ||
1278 | outpw(FM_A(FM_AFCMD),FM_IINV_CAM) ; | ||
1279 | |||
1280 | /* | ||
1281 | * set the functional address | ||
1282 | */ | ||
1283 | if (smc->hw.fp.func_addr) { | ||
1284 | fu = (u_char *) &smc->hw.fp.func_addr ; | ||
1285 | outpw(FM_A(FM_AFMASK2),0xffff) ; | ||
1286 | outpw(FM_A(FM_AFMASK1),(u_short) ~((fu[0] << 8) + fu[1])) ; | ||
1287 | outpw(FM_A(FM_AFMASK0),(u_short) ~((fu[2] << 8) + fu[3])) ; | ||
1288 | outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ; | ||
1289 | outpw(FM_A(FM_AFCOMP2), 0xc000) ; | ||
1290 | outpw(FM_A(FM_AFCOMP1), 0x0000) ; | ||
1291 | outpw(FM_A(FM_AFCOMP0), 0x0000) ; | ||
1292 | outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ; | ||
1293 | } | ||
1294 | |||
1295 | /* | ||
1296 | * set the mask and the personality register(s) | ||
1297 | */ | ||
1298 | outpw(FM_A(FM_AFMASK0),0xffff) ; | ||
1299 | outpw(FM_A(FM_AFMASK1),0xffff) ; | ||
1300 | outpw(FM_A(FM_AFMASK2),0xffff) ; | ||
1301 | outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ; | ||
1302 | |||
1303 | for (i = 0, tb = smc->hw.fp.mc.table; i < FPMAX_MULTICAST; i++, tb++) { | ||
1304 | if (tb->n) { | ||
1305 | CHECK_CAM() ; | ||
1306 | |||
1307 | /* | ||
1308 | * write the multicast address into the CAM | ||
1309 | */ | ||
1310 | outpw(FM_A(FM_AFCOMP2), | ||
1311 | (u_short)((tb->a.a[0]<<8)+tb->a.a[1])) ; | ||
1312 | outpw(FM_A(FM_AFCOMP1), | ||
1313 | (u_short)((tb->a.a[2]<<8)+tb->a.a[3])) ; | ||
1314 | outpw(FM_A(FM_AFCOMP0), | ||
1315 | (u_short)((tb->a.a[4]<<8)+tb->a.a[5])) ; | ||
1316 | outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ; | ||
1317 | } | ||
1318 | } | ||
1319 | } | ||
1320 | |||
1321 | /* | ||
1322 | BEGIN_MANUAL_ENTRY(if,func;others;3) | ||
1323 | |||
1324 | void mac_set_rx_mode(smc,mode) | ||
1325 | struct s_smc *smc ; | ||
1326 | int mode ; | ||
1327 | |||
1328 | Function DOWNCALL/INTERN (SMT, fplustm.c) | ||
1329 | This function enables / disables the selected receive. | ||
1330 | Don't call this function if the hardware module is | ||
1331 | used -- use mac_drv_rx_mode() instead of. | ||
1332 | |||
1333 | Para mode = 1 RX_ENABLE_ALLMULTI enable all multicasts | ||
1334 | 2 RX_DISABLE_ALLMULTI disable "enable all multicasts" | ||
1335 | 3 RX_ENABLE_PROMISC enable promiscous | ||
1336 | 4 RX_DISABLE_PROMISC disable promiscous | ||
1337 | 5 RX_ENABLE_NSA enable reception of NSA frames | ||
1338 | 6 RX_DISABLE_NSA disable reception of NSA frames | ||
1339 | |||
1340 | Note The selected receive modes will be lost after 'driver reset' | ||
1341 | or 'set station address' | ||
1342 | |||
1343 | END_MANUAL_ENTRY | ||
1344 | */ | ||
1345 | void mac_set_rx_mode(struct s_smc *smc, int mode) | ||
1346 | { | ||
1347 | switch (mode) { | ||
1348 | case RX_ENABLE_ALLMULTI : | ||
1349 | smc->hw.fp.rx_prom |= RX_MODE_ALL_MULTI ; | ||
1350 | break ; | ||
1351 | case RX_DISABLE_ALLMULTI : | ||
1352 | smc->hw.fp.rx_prom &= ~RX_MODE_ALL_MULTI ; | ||
1353 | break ; | ||
1354 | case RX_ENABLE_PROMISC : | ||
1355 | smc->hw.fp.rx_prom |= RX_MODE_PROM ; | ||
1356 | break ; | ||
1357 | case RX_DISABLE_PROMISC : | ||
1358 | smc->hw.fp.rx_prom &= ~RX_MODE_PROM ; | ||
1359 | break ; | ||
1360 | case RX_ENABLE_NSA : | ||
1361 | smc->hw.fp.nsa_mode = FM_MDAMA ; | ||
1362 | smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) | | ||
1363 | smc->hw.fp.nsa_mode ; | ||
1364 | break ; | ||
1365 | case RX_DISABLE_NSA : | ||
1366 | smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ; | ||
1367 | smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) | | ||
1368 | smc->hw.fp.nsa_mode ; | ||
1369 | break ; | ||
1370 | } | ||
1371 | if (smc->hw.fp.rx_prom & RX_MODE_PROM) { | ||
1372 | smc->hw.fp.rx_mode = FM_MLIMPROM ; | ||
1373 | } | ||
1374 | else if (smc->hw.fp.rx_prom & RX_MODE_ALL_MULTI) { | ||
1375 | smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode | FM_EXGPA0 ; | ||
1376 | } | ||
1377 | else | ||
1378 | smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode ; | ||
1379 | SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ; | ||
1380 | mac_update_multicast(smc) ; | ||
1381 | } | ||
1382 | |||
1383 | /* | ||
1384 | BEGIN_MANUAL_ENTRY(module;tests;3) | ||
1385 | How to test the Restricted Token Monitor | ||
1386 | ---------------------------------------------------------------- | ||
1387 | |||
1388 | o Insert a break point in the function rtm_irq() | ||
1389 | o Remove all stations with a restricted token monitor from the | ||
1390 | network. | ||
1391 | o Connect a UPPS ISA or EISA station to the network. | ||
1392 | o Give the FORMAC of UPPS station the command to send | ||
1393 | restricted tokens until the ring becomes instable. | ||
1394 | o Now connect your test test client. | ||
1395 | o The restricted token monitor should detect the restricted token, | ||
1396 | and your break point will be reached. | ||
1397 | o You can ovserve how the station will clean the ring. | ||
1398 | |||
1399 | END_MANUAL_ENTRY | ||
1400 | */ | ||
1401 | void rtm_irq(struct s_smc *smc) | ||
1402 | { | ||
1403 | outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ; /* clear IRQ */ | ||
1404 | if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) { | ||
1405 | outpw(FM_A(FM_CMDREG1),FM_ICL) ; /* force claim */ | ||
1406 | DB_RMT("RMT: fddiPATHT_Rmode expired\n",0,0) ; | ||
1407 | AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, | ||
1408 | (u_long) FDDI_SMT_EVENT, | ||
1409 | (u_long) FDDI_RTT, smt_get_event_word(smc)); | ||
1410 | } | ||
1411 | outpw(ADDR(B2_RTM_CRTL),TIM_START) ; /* enable RTM monitoring */ | ||
1412 | } | ||
1413 | |||
1414 | static void rtm_init(struct s_smc *smc) | ||
1415 | { | ||
1416 | outpd(ADDR(B2_RTM_INI),0) ; /* timer = 0 */ | ||
1417 | outpw(ADDR(B2_RTM_CRTL),TIM_START) ; /* enable IRQ */ | ||
1418 | } | ||
1419 | |||
1420 | void rtm_set_timer(struct s_smc *smc) | ||
1421 | { | ||
1422 | /* | ||
1423 | * MIB timer and hardware timer have the same resolution of 80nS | ||
1424 | */ | ||
1425 | DB_RMT("RMT: setting new fddiPATHT_Rmode, t = %d ns \n", | ||
1426 | (int) smc->mib.a[PATH0].fddiPATHT_Rmode,0) ; | ||
1427 | outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ; | ||
1428 | } | ||
1429 | |||
1430 | static void smt_split_up_fifo(struct s_smc *smc) | ||
1431 | { | ||
1432 | |||
1433 | /* | ||
1434 | BEGIN_MANUAL_ENTRY(module;mem;1) | ||
1435 | ------------------------------------------------------------- | ||
1436 | RECEIVE BUFFER MEMORY DIVERSION | ||
1437 | ------------------------------------------------------------- | ||
1438 | |||
1439 | R1_RxD == SMT_R1_RXD_COUNT | ||
1440 | R2_RxD == SMT_R2_RXD_COUNT | ||
1441 | |||
1442 | SMT_R1_RXD_COUNT must be unequal zero | ||
1443 | |||
1444 | | R1_RxD R2_RxD |R1_RxD R2_RxD | R1_RxD R2_RxD | ||
1445 | | x 0 | x 1-3 | x < 3 | ||
1446 | ---------------------------------------------------------------------- | ||
1447 | | 63,75 kB | 54,75 | R1_RxD | ||
1448 | rx queue 1 | RX_FIFO_SPACE | RX_LARGE_FIFO| ------------- * 63,75 kB | ||
1449 | | | | R1_RxD+R2_RxD | ||
1450 | ---------------------------------------------------------------------- | ||
1451 | | | 9 kB | R2_RxD | ||
1452 | rx queue 2 | 0 kB | RX_SMALL_FIFO| ------------- * 63,75 kB | ||
1453 | | (not used) | | R1_RxD+R2_RxD | ||
1454 | |||
1455 | END_MANUAL_ENTRY | ||
1456 | */ | ||
1457 | |||
1458 | if (SMT_R1_RXD_COUNT == 0) { | ||
1459 | SMT_PANIC(smc,SMT_E0117, SMT_E0117_MSG) ; | ||
1460 | } | ||
1461 | |||
1462 | switch(SMT_R2_RXD_COUNT) { | ||
1463 | case 0: | ||
1464 | smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE ; | ||
1465 | smc->hw.fp.fifo.rx2_fifo_size = 0 ; | ||
1466 | break ; | ||
1467 | case 1: | ||
1468 | case 2: | ||
1469 | case 3: | ||
1470 | smc->hw.fp.fifo.rx1_fifo_size = RX_LARGE_FIFO ; | ||
1471 | smc->hw.fp.fifo.rx2_fifo_size = RX_SMALL_FIFO ; | ||
1472 | break ; | ||
1473 | default: /* this is not the real defaule */ | ||
1474 | smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE * | ||
1475 | SMT_R1_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ; | ||
1476 | smc->hw.fp.fifo.rx2_fifo_size = RX_FIFO_SPACE * | ||
1477 | SMT_R2_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ; | ||
1478 | break ; | ||
1479 | } | ||
1480 | |||
1481 | /* | ||
1482 | BEGIN_MANUAL_ENTRY(module;mem;1) | ||
1483 | ------------------------------------------------------------- | ||
1484 | TRANSMIT BUFFER MEMORY DIVERSION | ||
1485 | ------------------------------------------------------------- | ||
1486 | |||
1487 | |||
1488 | | no sync bw | sync bw available and | sync bw available and | ||
1489 | | available | SynchTxMode = SPLIT | SynchTxMode = ALL | ||
1490 | ----------------------------------------------------------------------- | ||
1491 | sync tx | 0 kB | 32 kB | 55 kB | ||
1492 | queue | | TX_MEDIUM_FIFO | TX_LARGE_FIFO | ||
1493 | ----------------------------------------------------------------------- | ||
1494 | async tx | 64 kB | 32 kB | 9 k | ||
1495 | queue | TX_FIFO_SPACE| TX_MEDIUM_FIFO | TX_SMALL_FIFO | ||
1496 | |||
1497 | END_MANUAL_ENTRY | ||
1498 | */ | ||
1499 | |||
1500 | /* | ||
1501 | * set the tx mode bits | ||
1502 | */ | ||
1503 | if (smc->mib.a[PATH0].fddiPATHSbaPayload) { | ||
1504 | #ifdef ESS | ||
1505 | smc->hw.fp.fifo.fifo_config_mode |= | ||
1506 | smc->mib.fddiESSSynchTxMode | SYNC_TRAFFIC_ON ; | ||
1507 | #endif | ||
1508 | } | ||
1509 | else { | ||
1510 | smc->hw.fp.fifo.fifo_config_mode &= | ||
1511 | ~(SEND_ASYNC_AS_SYNC|SYNC_TRAFFIC_ON) ; | ||
1512 | } | ||
1513 | |||
1514 | /* | ||
1515 | * split up the FIFO | ||
1516 | */ | ||
1517 | if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON) { | ||
1518 | if (smc->hw.fp.fifo.fifo_config_mode & SEND_ASYNC_AS_SYNC) { | ||
1519 | smc->hw.fp.fifo.tx_s_size = TX_LARGE_FIFO ; | ||
1520 | smc->hw.fp.fifo.tx_a0_size = TX_SMALL_FIFO ; | ||
1521 | } | ||
1522 | else { | ||
1523 | smc->hw.fp.fifo.tx_s_size = TX_MEDIUM_FIFO ; | ||
1524 | smc->hw.fp.fifo.tx_a0_size = TX_MEDIUM_FIFO ; | ||
1525 | } | ||
1526 | } | ||
1527 | else { | ||
1528 | smc->hw.fp.fifo.tx_s_size = 0 ; | ||
1529 | smc->hw.fp.fifo.tx_a0_size = TX_FIFO_SPACE ; | ||
1530 | } | ||
1531 | |||
1532 | smc->hw.fp.fifo.rx1_fifo_start = smc->hw.fp.fifo.rbc_ram_start + | ||
1533 | RX_FIFO_OFF ; | ||
1534 | smc->hw.fp.fifo.tx_s_start = smc->hw.fp.fifo.rx1_fifo_start + | ||
1535 | smc->hw.fp.fifo.rx1_fifo_size ; | ||
1536 | smc->hw.fp.fifo.tx_a0_start = smc->hw.fp.fifo.tx_s_start + | ||
1537 | smc->hw.fp.fifo.tx_s_size ; | ||
1538 | smc->hw.fp.fifo.rx2_fifo_start = smc->hw.fp.fifo.tx_a0_start + | ||
1539 | smc->hw.fp.fifo.tx_a0_size ; | ||
1540 | |||
1541 | DB_SMT("FIFO split: mode = %x\n",smc->hw.fp.fifo.fifo_config_mode,0) ; | ||
1542 | DB_SMT("rbc_ram_start = %x rbc_ram_end = %x\n", | ||
1543 | smc->hw.fp.fifo.rbc_ram_start, smc->hw.fp.fifo.rbc_ram_end) ; | ||
1544 | DB_SMT("rx1_fifo_start = %x tx_s_start = %x\n", | ||
1545 | smc->hw.fp.fifo.rx1_fifo_start, smc->hw.fp.fifo.tx_s_start) ; | ||
1546 | DB_SMT("tx_a0_start = %x rx2_fifo_start = %x\n", | ||
1547 | smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start) ; | ||
1548 | } | ||
1549 | |||
1550 | void formac_reinit_tx(struct s_smc *smc) | ||
1551 | { | ||
1552 | /* | ||
1553 | * Split up the FIFO and reinitialize the MAC if synchronous | ||
1554 | * bandwidth becomes available but no synchronous queue is | ||
1555 | * configured. | ||
1556 | */ | ||
1557 | if (!smc->hw.fp.fifo.tx_s_size && smc->mib.a[PATH0].fddiPATHSbaPayload){ | ||
1558 | (void)init_mac(smc,0) ; | ||
1559 | } | ||
1560 | } | ||
1561 | |||