GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / net / skfp / fplustm.c
blobad22d5ddb2c3caec1dad47847b333483948c257e
1 /******************************************************************************
3 * (C)Copyright 1998,1999 SysKonnect,
4 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
6 * See the file "skfddi.c" for further information.
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.
13 * The information in this file is provided "AS IS" without warranty.
15 ******************************************************************************/
18 * FORMAC+ Driver for tag mode
21 #include "h/types.h"
22 #include "h/fddi.h"
23 #include "h/smc.h"
24 #include "h/supern_2.h"
25 #include <linux/bitrev.h>
27 #ifndef lint
28 static const char ID_sccs[] = "@(#)fplustm.c 1.32 99/02/23 (C) SK " ;
29 #endif
31 #ifndef UNUSED
32 #ifdef lint
33 #define UNUSED(x) (x) = (x)
34 #else
35 #define UNUSED(x)
36 #endif
37 #endif
39 #define FM_ADDRX (FM_ADDET|FM_EXGPA0|FM_EXGPA1)
40 #define MS2BCLK(x) ((x)*12500L)
41 #define US2BCLK(x) ((x)*1250L)
44 * prototypes for static function
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);
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
56 #define DUMMY_READ() smc->hw.mc_dummy = (u_short) inp(ADDR(B0_RAP))
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 } \
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 } \
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}};
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.) */
80 * define my address
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
90 * useful interrupt bits
92 static const int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ;
93 static const int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0|
94 FM_STBURS | FM_STBURA0 ;
96 /* delete FM_SRBFL after tests */
97 static const int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL |
98 FM_SMYCLM ;
99 static const int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR |
100 FM_SERRCTR | FM_SLSTCTR |
101 FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ;
103 static const int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ;
104 static const int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ;
106 static const int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC |
107 FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ;
110 static u_long mac_get_tneg(struct s_smc *smc)
112 u_long tneg ;
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)) ;
119 void mac_update_counter(struct s_smc *smc)
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
133 * If the token counter is emulated it is updated in smt_event.
136 #else
137 smt_emulate_token_ct( smc, MAC0 );
138 #endif
142 * write long value into buffer memory over memory data register (MDR),
144 static void write_mdr(struct s_smc *smc, u_long val)
146 CHECK_NPP() ;
147 MDRW(val) ;
152 * clear buffer memory
154 static void init_ram(struct s_smc *smc)
156 u_short i ;
158 smc->hw.fp.fifo.rbc_ram_start = 0 ;
159 smc->hw.fp.fifo.rbc_ram_end =
160 smc->hw.fp.fifo.rbc_ram_start + RBC_MEM_SIZE ;
161 CHECK_NPP() ;
162 MARW(smc->hw.fp.fifo.rbc_ram_start) ;
163 for (i = smc->hw.fp.fifo.rbc_ram_start;
164 i < (u_short) (smc->hw.fp.fifo.rbc_ram_end-1); i++)
165 write_mdr(smc,0L) ;
166 /* Erase the last byte too */
167 write_mdr(smc,0L) ;
171 * set receive FIFO pointer
173 static void set_recvptr(struct s_smc *smc)
176 * initialize the pointer for receive queue 1
178 outpw(FM_A(FM_RPR1),smc->hw.fp.fifo.rx1_fifo_start) ; /* RPR1 */
179 outpw(FM_A(FM_SWPR1),smc->hw.fp.fifo.rx1_fifo_start) ; /* SWPR1 */
180 outpw(FM_A(FM_WPR1),smc->hw.fp.fifo.rx1_fifo_start) ; /* WPR1 */
181 outpw(FM_A(FM_EARV1),smc->hw.fp.fifo.tx_s_start-1) ; /* EARV1 */
184 * initialize the pointer for receive queue 2
186 if (smc->hw.fp.fifo.rx2_fifo_size) {
187 outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
188 outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
189 outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
190 outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
192 else {
193 outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
194 outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
195 outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
196 outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
201 * set transmit FIFO pointer
203 static void set_txptr(struct s_smc *smc)
205 outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ; /* reset transmit queues */
208 * initialize the pointer for asynchronous transmit queue
210 outpw(FM_A(FM_RPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* RPXA0 */
211 outpw(FM_A(FM_SWPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* SWPXA0 */
212 outpw(FM_A(FM_WPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* WPXA0 */
213 outpw(FM_A(FM_EAA0),smc->hw.fp.fifo.rx2_fifo_start-1) ; /* EAA0 */
216 * initialize the pointer for synchronous transmit queue
218 if (smc->hw.fp.fifo.tx_s_size) {
219 outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_s_start) ;
220 outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_s_start) ;
221 outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_s_start) ;
222 outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
224 else {
225 outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
226 outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
227 outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
228 outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
233 * init memory buffer management registers
235 static void init_rbc(struct s_smc *smc)
237 u_short rbc_ram_addr ;
240 * set unused pointers or permanent pointers
242 rbc_ram_addr = smc->hw.fp.fifo.rx2_fifo_start - 1 ;
244 outpw(FM_A(FM_RPXA1),rbc_ram_addr) ; /* a1-send pointer */
245 outpw(FM_A(FM_WPXA1),rbc_ram_addr) ;
246 outpw(FM_A(FM_SWPXA1),rbc_ram_addr) ;
247 outpw(FM_A(FM_EAA1),rbc_ram_addr) ;
249 set_recvptr(smc) ;
250 set_txptr(smc) ;
254 * init rx pointer
256 static void init_rx(struct s_smc *smc)
258 struct s_smt_rx_queue *queue ;
261 * init all tx data structures for receive queue 1
263 smc->hw.fp.rx[QUEUE_R1] = queue = &smc->hw.fp.rx_q[QUEUE_R1] ;
264 queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R1_CSR) ;
265 queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R1_DA) ;
268 * init all tx data structures for receive queue 2
270 smc->hw.fp.rx[QUEUE_R2] = queue = &smc->hw.fp.rx_q[QUEUE_R2] ;
271 queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R2_CSR) ;
272 queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R2_DA) ;
276 * set the TSYNC register of the FORMAC to regulate synchronous transmission
278 void set_formac_tsync(struct s_smc *smc, long sync_bw)
280 outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ;
284 * init all tx data structures
286 static void init_tx(struct s_smc *smc)
288 struct s_smt_tx_queue *queue ;
291 * init all tx data structures for the synchronous queue
293 smc->hw.fp.tx[QUEUE_S] = queue = &smc->hw.fp.tx_q[QUEUE_S] ;
294 queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XS_CSR) ;
295 queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XS_DA) ;
297 #ifdef ESS
298 set_formac_tsync(smc,smc->ess.sync_bw) ;
299 #endif
302 * init all tx data structures for the asynchronous queue 0
304 smc->hw.fp.tx[QUEUE_A0] = queue = &smc->hw.fp.tx_q[QUEUE_A0] ;
305 queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XA_CSR) ;
306 queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XA_DA) ;
309 llc_recover_tx(smc) ;
312 static void mac_counter_init(struct s_smc *smc)
314 int i ;
315 u_long *ec ;
318 * clear FORMAC+ frame-, lost- and error counter
320 outpw(FM_A(FM_FCNTR),0) ;
321 outpw(FM_A(FM_LCNTR),0) ;
322 outpw(FM_A(FM_ECNTR),0) ;
324 * clear internal error counter stucture
326 ec = (u_long *)&smc->hw.fp.err_stats ;
327 for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--)
328 *ec++ = 0L ;
329 smc->mib.m[MAC0].fddiMACRingOp_Ct = 0 ;
333 * set FORMAC address, and t_request
335 static void set_formac_addr(struct s_smc *smc)
337 long t_requ = smc->mib.m[MAC0].fddiMACT_Req ;
339 outpw(FM_A(FM_SAID),my_said) ; /* set short address */
340 outpw(FM_A(FM_LAIL),(unsigned)((smc->hw.fddi_home_addr.a[4]<<8) +
341 smc->hw.fddi_home_addr.a[5])) ;
342 outpw(FM_A(FM_LAIC),(unsigned)((smc->hw.fddi_home_addr.a[2]<<8) +
343 smc->hw.fddi_home_addr.a[3])) ;
344 outpw(FM_A(FM_LAIM),(unsigned)((smc->hw.fddi_home_addr.a[0]<<8) +
345 smc->hw.fddi_home_addr.a[1])) ;
347 outpw(FM_A(FM_SAGP),my_sagp) ; /* set short group address */
349 outpw(FM_A(FM_LAGL),(unsigned)((smc->hw.fp.group_addr.a[4]<<8) +
350 smc->hw.fp.group_addr.a[5])) ;
351 outpw(FM_A(FM_LAGC),(unsigned)((smc->hw.fp.group_addr.a[2]<<8) +
352 smc->hw.fp.group_addr.a[3])) ;
353 outpw(FM_A(FM_LAGM),(unsigned)((smc->hw.fp.group_addr.a[0]<<8) +
354 smc->hw.fp.group_addr.a[1])) ;
356 /* set r_request regs. (MSW & LSW of TRT ) */
357 outpw(FM_A(FM_TREQ1),(unsigned)(t_requ>>16)) ;
358 outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ;
361 static void set_int(char *p, int l)
363 p[0] = (char)(l >> 24) ;
364 p[1] = (char)(l >> 16) ;
365 p[2] = (char)(l >> 8) ;
366 p[3] = (char)(l >> 0) ;
370 * copy TX descriptor to buffer mem
371 * append FC field and MAC frame
372 * if more bit is set in descr
373 * append pointer to descriptor (endless loop)
374 * else
375 * append 'end of chain' pointer
377 static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
378 unsigned off, int len)
379 /* u_long td; transmit descriptor */
380 /* struct fddi_mac *mac; mac frame pointer */
381 /* unsigned off; start address within buffer memory */
382 /* int len ; length of the frame including the FC */
384 int i ;
385 __le32 *p ;
387 CHECK_NPP() ;
388 MARW(off) ; /* set memory address reg for writes */
390 p = (__le32 *) mac ;
391 for (i = (len + 3)/4 ; i ; i--) {
392 if (i == 1) {
393 /* last word, set the tag bit */
394 outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;
396 write_mdr(smc,le32_to_cpu(*p)) ;
397 p++ ;
400 outpw(FM_A(FM_CMDREG2),FM_ISTTB) ; /* set the tag bit */
401 write_mdr(smc,td) ; /* write over memory data reg to buffer */
405 BEGIN_MANUAL_ENTRY(module;tests;3)
406 How to test directed beacon frames
407 ----------------------------------------------------------------
409 o Insert a break point in the function build_claim_beacon()
410 before calling copy_tx_mac() for building the claim frame.
411 o Modify the RM3_DETECT case so that the RM6_DETECT state
412 will always entered from the RM3_DETECT state (function rmt_fsm(),
413 rmt.c)
414 o Compile the driver.
415 o Set the parameter TREQ in the protocol.ini or net.cfg to a
416 small value to make sure your station will win the claim
417 process.
418 o Start the driver.
419 o When you reach the break point, modify the SA and DA address
420 of the claim frame (e.g. SA = DA = 10005affffff).
421 o When you see RM3_DETECT and RM6_DETECT, observe the direct
422 beacon frames on the UPPSLANA.
424 END_MANUAL_ENTRY
426 static void directed_beacon(struct s_smc *smc)
428 SK_LOC_DECL(__le32,a[2]) ;
431 * set UNA in frame
432 * enable FORMAC to send endless queue of directed beacon
433 * important: the UNA starts at byte 1 (not at byte 0)
435 * (char *) a = (char) ((long)DBEACON_INFO<<24L) ;
436 a[1] = 0 ;
437 memcpy((char *)a+1,(char *) &smc->mib.m[MAC0].fddiMACUpstreamNbr,6) ;
439 CHECK_NPP() ;
440 /* set memory address reg for writes */
441 MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ;
442 write_mdr(smc,le32_to_cpu(a[0])) ;
443 outpw(FM_A(FM_CMDREG2),FM_ISTTB) ; /* set the tag bit */
444 write_mdr(smc,le32_to_cpu(a[1])) ;
446 outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ;
450 setup claim & beacon pointer
451 NOTE :
452 special frame packets end with a pointer to their own
453 descriptor, and the MORE bit is set in the descriptor
455 static void build_claim_beacon(struct s_smc *smc, u_long t_request)
457 u_int td ;
458 int len ;
459 struct fddi_mac_sf *mac ;
462 * build claim packet
464 len = 17 ;
465 td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
466 mac = &smc->hw.fp.mac_sfb ;
467 mac->mac_fc = FC_CLAIM ;
468 /* DA == SA in claim frame */
469 mac->mac_source = mac->mac_dest = MA ;
470 /* 2's complement */
471 set_int((char *)mac->mac_info,(int)t_request) ;
473 copy_tx_mac(smc,td,(struct fddi_mac *)mac,
474 smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ;
475 /* set CLAIM start pointer */
476 outpw(FM_A(FM_SACL),smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF) ;
479 * build beacon packet
481 len = 17 ;
482 td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
483 mac->mac_fc = FC_BEACON ;
484 mac->mac_source = MA ;
485 mac->mac_dest = null_addr ; /* DA == 0 in beacon frame */
486 set_int((char *) mac->mac_info,((int)BEACON_INFO<<24) + 0 ) ;
488 copy_tx_mac(smc,td,(struct fddi_mac *)mac,
489 smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ;
490 /* set beacon start pointer */
491 outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF) ;
494 * build directed beacon packet
495 * contains optional UNA
497 len = 23 ;
498 td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
499 mac->mac_fc = FC_BEACON ;
500 mac->mac_source = MA ;
501 mac->mac_dest = dbeacon_multi ; /* multicast */
502 set_int((char *) mac->mac_info,((int)DBEACON_INFO<<24) + 0 ) ;
503 set_int((char *) mac->mac_info+4,0) ;
504 set_int((char *) mac->mac_info+8,0) ;
506 copy_tx_mac(smc,td,(struct fddi_mac *)mac,
507 smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ;
509 /* end of claim/beacon queue */
510 outpw(FM_A(FM_EACB),smc->hw.fp.fifo.rx1_fifo_start-1) ;
512 outpw(FM_A(FM_WPXSF),0) ;
513 outpw(FM_A(FM_RPXSF),0) ;
516 static void formac_rcv_restart(struct s_smc *smc)
518 /* enable receive function */
519 SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
521 outpw(FM_A(FM_CMDREG1),FM_ICLLR) ; /* clear receive lock */
524 void formac_tx_restart(struct s_smc *smc)
526 outpw(FM_A(FM_CMDREG1),FM_ICLLS) ; /* clear s-frame lock */
527 outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */
530 static void enable_formac(struct s_smc *smc)
532 /* set formac IMSK : 0 enables irq */
533 outpw(FM_A(FM_IMSK1U),(unsigned short)~mac_imsk1u);
534 outpw(FM_A(FM_IMSK1L),(unsigned short)~mac_imsk1l);
535 outpw(FM_A(FM_IMSK2U),(unsigned short)~mac_imsk2u);
536 outpw(FM_A(FM_IMSK2L),(unsigned short)~mac_imsk2l);
537 outpw(FM_A(FM_IMSK3U),(unsigned short)~mac_imsk3u);
538 outpw(FM_A(FM_IMSK3L),(unsigned short)~mac_imsk3l);
542 static void disable_formac(struct s_smc *smc)
544 /* clear formac IMSK : 1 disables irq */
545 outpw(FM_A(FM_IMSK1U),MW) ;
546 outpw(FM_A(FM_IMSK1L),MW) ;
547 outpw(FM_A(FM_IMSK2U),MW) ;
548 outpw(FM_A(FM_IMSK2L),MW) ;
549 outpw(FM_A(FM_IMSK3U),MW) ;
550 outpw(FM_A(FM_IMSK3L),MW) ;
554 static void mac_ring_up(struct s_smc *smc, int up)
556 if (up) {
557 formac_rcv_restart(smc) ; /* enable receive function */
558 smc->hw.mac_ring_is_up = TRUE ;
559 llc_restart_tx(smc) ; /* TX queue */
561 else {
562 /* disable receive function */
563 SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
565 /* abort current transmit activity */
566 outpw(FM_A(FM_CMDREG2),FM_IACTR) ;
568 smc->hw.mac_ring_is_up = FALSE ;
572 /*--------------------------- ISR handling ----------------------------------*/
574 * mac1_irq is in drvfbi.c
578 * mac2_irq: status bits for the receive queue 1, and ring status
579 * ring status indication bits
581 void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l)
583 u_short change_s2l ;
584 u_short change_s2u ;
586 /* (jd) 22-Feb-1999
587 * Restart 2_DMax Timer after end of claiming or beaconing
589 if (code_s2u & (FM_SCLM|FM_SHICLM|FM_SBEC|FM_SOTRBEC)) {
590 queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
592 else if (code_s2l & (FM_STKISS)) {
593 queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
597 * XOR current st bits with the last to avoid useless RMT event queuing
599 change_s2l = smc->hw.fp.s2l ^ code_s2l ;
600 change_s2u = smc->hw.fp.s2u ^ code_s2u ;
602 if ((change_s2l & FM_SRNGOP) ||
603 (!smc->hw.mac_ring_is_up && ((code_s2l & FM_SRNGOP)))) {
604 if (code_s2l & FM_SRNGOP) {
605 mac_ring_up(smc,1) ;
606 queue_event(smc,EVENT_RMT,RM_RING_OP) ;
607 smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
609 else {
610 mac_ring_up(smc,0) ;
611 queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
613 goto mac2_end ;
615 if (code_s2l & FM_SMISFRM) { /* missed frame */
616 smc->mib.m[MAC0].fddiMACNotCopied_Ct++ ;
618 if (code_s2u & (FM_SRCVOVR | /* recv. FIFO overflow */
619 FM_SRBFL)) { /* recv. buffer full */
620 smc->hw.mac_ct.mac_r_restart_counter++ ;
621 /* formac_rcv_restart(smc) ; */
622 smt_stat_counter(smc,1) ;
623 /* goto mac2_end ; */
625 if (code_s2u & FM_SOTRBEC)
626 queue_event(smc,EVENT_RMT,RM_OTHER_BEACON) ;
627 if (code_s2u & FM_SMYBEC)
628 queue_event(smc,EVENT_RMT,RM_MY_BEACON) ;
629 if (change_s2u & code_s2u & FM_SLOCLM) {
630 DB_RMTN(2,"RMT : lower claim received\n",0,0) ;
632 if ((code_s2u & FM_SMYCLM) && !(code_s2l & FM_SDUPCLM)) {
634 * This is my claim and that claim is not detected as a
635 * duplicate one.
637 queue_event(smc,EVENT_RMT,RM_MY_CLAIM) ;
639 if (code_s2l & FM_SDUPCLM) {
641 * If a duplicate claim frame (same SA but T_Bid != T_Req)
642 * this flag will be set.
643 * In the RMT state machine we need a RM_VALID_CLAIM event
644 * to do the appropriate state change.
645 * RM(34c)
647 queue_event(smc,EVENT_RMT,RM_VALID_CLAIM) ;
649 if (change_s2u & code_s2u & FM_SHICLM) {
650 DB_RMTN(2,"RMT : higher claim received\n",0,0) ;
652 if ( (code_s2l & FM_STRTEXP) ||
653 (code_s2l & FM_STRTEXR) )
654 queue_event(smc,EVENT_RMT,RM_TRT_EXP) ;
655 if (code_s2l & FM_SMULTDA) {
657 * The MAC has found a 2. MAC with the same address.
658 * Signal dup_addr_test = failed to RMT state machine.
659 * RM(25)
661 smc->r.dup_addr_test = DA_FAILED ;
662 queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
664 if (code_s2u & FM_SBEC)
665 smc->hw.fp.err_stats.err_bec_stat++ ;
666 if (code_s2u & FM_SCLM)
667 smc->hw.fp.err_stats.err_clm_stat++ ;
668 if (code_s2l & FM_STVXEXP)
669 smc->mib.m[MAC0].fddiMACTvxExpired_Ct++ ;
670 if ((code_s2u & (FM_SBEC|FM_SCLM))) {
671 if (!(change_s2l & FM_SRNGOP) && (smc->hw.fp.s2l & FM_SRNGOP)) {
672 mac_ring_up(smc,0) ;
673 queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
675 mac_ring_up(smc,1) ;
676 queue_event(smc,EVENT_RMT,RM_RING_OP) ;
677 smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
680 if (code_s2l & FM_SPHINV)
681 smc->hw.fp.err_stats.err_phinv++ ;
682 if (code_s2l & FM_SSIFG)
683 smc->hw.fp.err_stats.err_sifg_det++ ;
684 if (code_s2l & FM_STKISS)
685 smc->hw.fp.err_stats.err_tkiss++ ;
686 if (code_s2l & FM_STKERR)
687 smc->hw.fp.err_stats.err_tkerr++ ;
688 if (code_s2l & FM_SFRMCTR)
689 smc->mib.m[MAC0].fddiMACFrame_Ct += 0x10000L ;
690 if (code_s2l & FM_SERRCTR)
691 smc->mib.m[MAC0].fddiMACError_Ct += 0x10000L ;
692 if (code_s2l & FM_SLSTCTR)
693 smc->mib.m[MAC0].fddiMACLost_Ct += 0x10000L ;
694 if (code_s2u & FM_SERRSF) {
695 SMT_PANIC(smc,SMT_E0114, SMT_E0114_MSG) ;
697 mac2_end:
698 /* notice old status */
699 smc->hw.fp.s2l = code_s2l ;
700 smc->hw.fp.s2u = code_s2u ;
701 outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ;
705 * mac3_irq: receive queue 2 bits and address detection bits
707 void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l)
709 UNUSED(code_s3l) ;
711 if (code_s3u & (FM_SRCVOVR2 | /* recv. FIFO overflow */
712 FM_SRBFL2)) { /* recv. buffer full */
713 smc->hw.mac_ct.mac_r_restart_counter++ ;
714 smt_stat_counter(smc,1);
718 if (code_s3u & FM_SRPERRQ2) { /* parity error receive queue 2 */
719 SMT_PANIC(smc,SMT_E0115, SMT_E0115_MSG) ;
721 if (code_s3u & FM_SRPERRQ1) { /* parity error receive queue 2 */
722 SMT_PANIC(smc,SMT_E0116, SMT_E0116_MSG) ;
728 * take formac offline
730 static void formac_offline(struct s_smc *smc)
732 outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */
734 /* disable receive function */
735 SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
737 /* FORMAC+ 'Initialize Mode' */
738 SETMASK(FM_A(FM_MDREG1),FM_MINIT,FM_MMODE) ;
740 disable_formac(smc) ;
741 smc->hw.mac_ring_is_up = FALSE ;
742 smc->hw.hw_state = STOPPED ;
746 * bring formac online
748 static void formac_online(struct s_smc *smc)
750 enable_formac(smc) ;
751 SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT |
752 smc->hw.fp.rx_mode, FM_MMODE | FM_SELRA | FM_ADDRX) ;
756 * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon)
758 int init_fplus(struct s_smc *smc)
760 smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
761 smc->hw.fp.rx_mode = FM_MDAMA ;
762 smc->hw.fp.group_addr = fddi_broadcast ;
763 smc->hw.fp.func_addr = 0 ;
764 smc->hw.fp.frselreg_init = 0 ;
766 init_driver_fplus(smc) ;
767 if (smc->s.sas == SMT_DAS)
768 smc->hw.fp.mdr3init |= FM_MENDAS ;
770 smc->hw.mac_ct.mac_nobuf_counter = 0 ;
771 smc->hw.mac_ct.mac_r_restart_counter = 0 ;
773 smc->hw.fp.fm_st1u = (HW_PTR) ADDR(B0_ST1U) ;
774 smc->hw.fp.fm_st1l = (HW_PTR) ADDR(B0_ST1L) ;
775 smc->hw.fp.fm_st2u = (HW_PTR) ADDR(B0_ST2U) ;
776 smc->hw.fp.fm_st2l = (HW_PTR) ADDR(B0_ST2L) ;
777 smc->hw.fp.fm_st3u = (HW_PTR) ADDR(B0_ST3U) ;
778 smc->hw.fp.fm_st3l = (HW_PTR) ADDR(B0_ST3L) ;
780 smc->hw.fp.s2l = smc->hw.fp.s2u = 0 ;
781 smc->hw.mac_ring_is_up = 0 ;
783 mac_counter_init(smc) ;
785 /* convert BCKL units to symbol time */
786 smc->hw.mac_pa.t_neg = (u_long)0 ;
787 smc->hw.mac_pa.t_pri = (u_long)0 ;
789 /* make sure all PCI settings are correct */
790 mac_do_pci_fix(smc) ;
792 return(init_mac(smc,1)) ;
793 /* enable_formac(smc) ; */
796 static int init_mac(struct s_smc *smc, int all)
798 u_short t_max,x ;
799 u_long time=0 ;
802 * clear memory
804 outpw(FM_A(FM_MDREG1),FM_MINIT) ; /* FORMAC+ init mode */
805 set_formac_addr(smc) ;
806 outpw(FM_A(FM_MDREG1),FM_MMEMACT) ; /* FORMAC+ memory activ mode */
807 /* Note: Mode register 2 is set here, incase parity is enabled. */
808 outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
810 if (all) {
811 init_ram(smc) ;
813 else {
815 * reset the HPI, the Master and the BMUs
817 outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
818 time = hwt_quick_read(smc) ;
822 * set all pointers, frames etc
824 smt_split_up_fifo(smc) ;
826 init_tx(smc) ;
827 init_rx(smc) ;
828 init_rbc(smc) ;
830 build_claim_beacon(smc,smc->mib.m[MAC0].fddiMACT_Req) ;
832 /* set RX threshold */
833 /* see Errata #SN2 Phantom receive overflow */
834 outpw(FM_A(FM_FRMTHR),14<<12) ; /* switch on */
836 /* set formac work mode */
837 outpw(FM_A(FM_MDREG1),MDR1INIT | FM_SELRA | smc->hw.fp.rx_mode) ;
838 outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
839 outpw(FM_A(FM_MDREG3),smc->hw.fp.mdr3init) ;
840 outpw(FM_A(FM_FRSELREG),smc->hw.fp.frselreg_init) ;
842 /* set timer */
844 * errata #22 fplus:
845 * T_MAX must not be FFFE
846 * or one of FFDF, FFB8, FF91 (-0x27 etc..)
848 t_max = (u_short)(smc->mib.m[MAC0].fddiMACT_Max/32) ;
849 x = t_max/0x27 ;
850 x *= 0x27 ;
851 if ((t_max == 0xfffe) || (t_max - x == 0x16))
852 t_max-- ;
853 outpw(FM_A(FM_TMAX),(u_short)t_max) ;
855 /* BugFix for report #10204 */
856 if (smc->mib.m[MAC0].fddiMACTvxValue < (u_long) (- US2BCLK(52))) {
857 outpw(FM_A(FM_TVX), (u_short) (- US2BCLK(52))/255 & MB) ;
858 } else {
859 outpw(FM_A(FM_TVX),
860 (u_short)((smc->mib.m[MAC0].fddiMACTvxValue/255) & MB)) ;
863 outpw(FM_A(FM_CMDREG1),FM_ICLLS) ; /* clear s-frame lock */
864 outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */
865 outpw(FM_A(FM_CMDREG1),FM_ICLLR); /* clear receive lock */
867 /* Auto unlock receice threshold for receive queue 1 and 2 */
868 outpw(FM_A(FM_UNLCKDLY),(0xff|(0xff<<8))) ;
870 rtm_init(smc) ; /* RT-Monitor */
872 if (!all) {
874 * after 10ms, reset the BMUs and repair the rings
876 hwt_wait_time(smc,time,MS2BCLK(10)) ;
877 outpd(ADDR(B0_R1_CSR),CSR_SET_RESET) ;
878 outpd(ADDR(B0_XA_CSR),CSR_SET_RESET) ;
879 outpd(ADDR(B0_XS_CSR),CSR_SET_RESET) ;
880 outp(ADDR(B0_CTRL), CTRL_HPI_CLR) ;
881 outpd(ADDR(B0_R1_CSR),CSR_CLR_RESET) ;
882 outpd(ADDR(B0_XA_CSR),CSR_CLR_RESET) ;
883 outpd(ADDR(B0_XS_CSR),CSR_CLR_RESET) ;
884 if (!smc->hw.hw_is_64bit) {
885 outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
886 outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
887 outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
889 smc->hw.hw_state = STOPPED ;
890 mac_drv_repair_descr(smc) ;
892 smc->hw.hw_state = STARTED ;
894 return(0) ;
899 * called by CFM
901 void config_mux(struct s_smc *smc, int mux)
903 plc_config_mux(smc,mux) ;
905 SETMASK(FM_A(FM_MDREG1),FM_SELRA,FM_SELRA) ;
909 * called by RMT
910 * enable CLAIM/BEACON interrupts
911 * (only called if these events are of interest, e.g. in DETECT state
912 * the interrupt must not be permanently enabled
913 * RMT calls this function periodically (timer driven polling)
915 void sm_mac_check_beacon_claim(struct s_smc *smc)
917 /* set formac IMSK : 0 enables irq */
918 outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ;
919 /* the driver must receive the directed beacons */
920 formac_rcv_restart(smc) ;
921 process_receive(smc) ;
924 /*-------------------------- interface functions ----------------------------*/
926 * control MAC layer (called by RMT)
928 void sm_ma_control(struct s_smc *smc, int mode)
930 switch(mode) {
931 case MA_OFFLINE :
932 /* Add to make the MAC offline in RM0_ISOLATED state */
933 formac_offline(smc) ;
934 break ;
935 case MA_RESET :
936 (void)init_mac(smc,0) ;
937 break ;
938 case MA_BEACON :
939 formac_online(smc) ;
940 break ;
941 case MA_DIRECTED :
942 directed_beacon(smc) ;
943 break ;
944 case MA_TREQ :
946 * no actions necessary, TREQ is already set
948 break ;
952 int sm_mac_get_tx_state(struct s_smc *smc)
954 return((inpw(FM_A(FM_STMCHN))>>4)&7) ;
958 * multicast functions
961 static struct s_fpmc* mac_get_mc_table(struct s_smc *smc,
962 struct fddi_addr *user,
963 struct fddi_addr *own,
964 int del, int can)
966 struct s_fpmc *tb ;
967 struct s_fpmc *slot ;
968 u_char *p ;
969 int i ;
972 * set own = can(user)
974 *own = *user ;
975 if (can) {
976 p = own->a ;
977 for (i = 0 ; i < 6 ; i++, p++)
978 *p = bitrev8(*p);
980 slot = NULL;
981 for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
982 if (!tb->n) { /* not used */
983 if (!del && !slot) /* if !del save first free */
984 slot = tb ;
985 continue ;
987 if (memcmp((char *)&tb->a,(char *)own,6))
988 continue ;
989 return(tb) ;
991 return(slot) ; /* return first free or NULL */
995 BEGIN_MANUAL_ENTRY(if,func;others;2)
997 void mac_clear_multicast(smc)
998 struct s_smc *smc ;
1000 Function DOWNCALL (SMT, fplustm.c)
1001 Clear all multicast entries
1003 END_MANUAL_ENTRY()
1005 void mac_clear_multicast(struct s_smc *smc)
1007 struct s_fpmc *tb ;
1008 int i ;
1010 smc->hw.fp.os_slots_used = 0 ; /* note the SMT addresses */
1011 /* will not be deleted */
1012 for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
1013 if (!tb->perm) {
1014 tb->n = 0 ;
1020 BEGIN_MANUAL_ENTRY(if,func;others;2)
1022 int mac_add_multicast(smc,addr,can)
1023 struct s_smc *smc ;
1024 struct fddi_addr *addr ;
1025 int can ;
1027 Function DOWNCALL (SMC, fplustm.c)
1028 Add an entry to the multicast table
1030 Para addr pointer to a multicast address
1031 can = 0: the multicast address has the physical format
1032 = 1: the multicast address has the canonical format
1033 | 0x80 permanent
1035 Returns 0: success
1036 1: address table full
1038 Note After a 'driver reset' or a 'station set address' all
1039 entries of the multicast table are cleared.
1040 In this case the driver has to fill the multicast table again.
1041 After the operating system dependent module filled
1042 the multicast table it must call mac_update_multicast
1043 to activate the new multicast addresses!
1045 END_MANUAL_ENTRY()
1047 int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
1049 SK_LOC_DECL(struct fddi_addr,own) ;
1050 struct s_fpmc *tb ;
1053 * check if there are free table entries
1055 if (can & 0x80) {
1056 if (smc->hw.fp.smt_slots_used >= SMT_MAX_MULTI) {
1057 return(1) ;
1060 else {
1061 if (smc->hw.fp.os_slots_used >= FPMAX_MULTICAST-SMT_MAX_MULTI) {
1062 return(1) ;
1067 * find empty slot
1069 if (!(tb = mac_get_mc_table(smc,addr,&own,0,can & ~0x80)))
1070 return(1) ;
1071 tb->n++ ;
1072 tb->a = own ;
1073 tb->perm = (can & 0x80) ? 1 : 0 ;
1075 if (can & 0x80)
1076 smc->hw.fp.smt_slots_used++ ;
1077 else
1078 smc->hw.fp.os_slots_used++ ;
1080 return(0) ;
1084 * mode
1087 #define RX_MODE_PROM 0x1
1088 #define RX_MODE_ALL_MULTI 0x2
1091 BEGIN_MANUAL_ENTRY(if,func;others;2)
1093 void mac_update_multicast(smc)
1094 struct s_smc *smc ;
1096 Function DOWNCALL (SMT, fplustm.c)
1097 Update FORMAC multicast registers
1099 END_MANUAL_ENTRY()
1101 void mac_update_multicast(struct s_smc *smc)
1103 struct s_fpmc *tb ;
1104 u_char *fu ;
1105 int i ;
1108 * invalidate the CAM
1110 outpw(FM_A(FM_AFCMD),FM_IINV_CAM) ;
1113 * set the functional address
1115 if (smc->hw.fp.func_addr) {
1116 fu = (u_char *) &smc->hw.fp.func_addr ;
1117 outpw(FM_A(FM_AFMASK2),0xffff) ;
1118 outpw(FM_A(FM_AFMASK1),(u_short) ~((fu[0] << 8) + fu[1])) ;
1119 outpw(FM_A(FM_AFMASK0),(u_short) ~((fu[2] << 8) + fu[3])) ;
1120 outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
1121 outpw(FM_A(FM_AFCOMP2), 0xc000) ;
1122 outpw(FM_A(FM_AFCOMP1), 0x0000) ;
1123 outpw(FM_A(FM_AFCOMP0), 0x0000) ;
1124 outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
1128 * set the mask and the personality register(s)
1130 outpw(FM_A(FM_AFMASK0),0xffff) ;
1131 outpw(FM_A(FM_AFMASK1),0xffff) ;
1132 outpw(FM_A(FM_AFMASK2),0xffff) ;
1133 outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
1135 for (i = 0, tb = smc->hw.fp.mc.table; i < FPMAX_MULTICAST; i++, tb++) {
1136 if (tb->n) {
1137 CHECK_CAM() ;
1140 * write the multicast address into the CAM
1142 outpw(FM_A(FM_AFCOMP2),
1143 (u_short)((tb->a.a[0]<<8)+tb->a.a[1])) ;
1144 outpw(FM_A(FM_AFCOMP1),
1145 (u_short)((tb->a.a[2]<<8)+tb->a.a[3])) ;
1146 outpw(FM_A(FM_AFCOMP0),
1147 (u_short)((tb->a.a[4]<<8)+tb->a.a[5])) ;
1148 outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
1154 BEGIN_MANUAL_ENTRY(if,func;others;3)
1156 void mac_set_rx_mode(smc,mode)
1157 struct s_smc *smc ;
1158 int mode ;
1160 Function DOWNCALL/INTERN (SMT, fplustm.c)
1161 This function enables / disables the selected receive.
1162 Don't call this function if the hardware module is
1163 used -- use mac_drv_rx_mode() instead of.
1165 Para mode = 1 RX_ENABLE_ALLMULTI enable all multicasts
1166 2 RX_DISABLE_ALLMULTI disable "enable all multicasts"
1167 3 RX_ENABLE_PROMISC enable promiscous
1168 4 RX_DISABLE_PROMISC disable promiscous
1169 5 RX_ENABLE_NSA enable reception of NSA frames
1170 6 RX_DISABLE_NSA disable reception of NSA frames
1172 Note The selected receive modes will be lost after 'driver reset'
1173 or 'set station address'
1175 END_MANUAL_ENTRY
1177 void mac_set_rx_mode(struct s_smc *smc, int mode)
1179 switch (mode) {
1180 case RX_ENABLE_ALLMULTI :
1181 smc->hw.fp.rx_prom |= RX_MODE_ALL_MULTI ;
1182 break ;
1183 case RX_DISABLE_ALLMULTI :
1184 smc->hw.fp.rx_prom &= ~RX_MODE_ALL_MULTI ;
1185 break ;
1186 case RX_ENABLE_PROMISC :
1187 smc->hw.fp.rx_prom |= RX_MODE_PROM ;
1188 break ;
1189 case RX_DISABLE_PROMISC :
1190 smc->hw.fp.rx_prom &= ~RX_MODE_PROM ;
1191 break ;
1192 case RX_ENABLE_NSA :
1193 smc->hw.fp.nsa_mode = FM_MDAMA ;
1194 smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
1195 smc->hw.fp.nsa_mode ;
1196 break ;
1197 case RX_DISABLE_NSA :
1198 smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
1199 smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
1200 smc->hw.fp.nsa_mode ;
1201 break ;
1203 if (smc->hw.fp.rx_prom & RX_MODE_PROM) {
1204 smc->hw.fp.rx_mode = FM_MLIMPROM ;
1206 else if (smc->hw.fp.rx_prom & RX_MODE_ALL_MULTI) {
1207 smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode | FM_EXGPA0 ;
1209 else
1210 smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode ;
1211 SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
1212 mac_update_multicast(smc) ;
1216 BEGIN_MANUAL_ENTRY(module;tests;3)
1217 How to test the Restricted Token Monitor
1218 ----------------------------------------------------------------
1220 o Insert a break point in the function rtm_irq()
1221 o Remove all stations with a restricted token monitor from the
1222 network.
1223 o Connect a UPPS ISA or EISA station to the network.
1224 o Give the FORMAC of UPPS station the command to send
1225 restricted tokens until the ring becomes instable.
1226 o Now connect your test test client.
1227 o The restricted token monitor should detect the restricted token,
1228 and your break point will be reached.
1229 o You can ovserve how the station will clean the ring.
1231 END_MANUAL_ENTRY
1233 void rtm_irq(struct s_smc *smc)
1235 outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ; /* clear IRQ */
1236 if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) {
1237 outpw(FM_A(FM_CMDREG1),FM_ICL) ; /* force claim */
1238 DB_RMT("RMT: fddiPATHT_Rmode expired\n",0,0) ;
1239 AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
1240 (u_long) FDDI_SMT_EVENT,
1241 (u_long) FDDI_RTT, smt_get_event_word(smc));
1243 outpw(ADDR(B2_RTM_CRTL),TIM_START) ; /* enable RTM monitoring */
1246 static void rtm_init(struct s_smc *smc)
1248 outpd(ADDR(B2_RTM_INI),0) ; /* timer = 0 */
1249 outpw(ADDR(B2_RTM_CRTL),TIM_START) ; /* enable IRQ */
1252 void rtm_set_timer(struct s_smc *smc)
1255 * MIB timer and hardware timer have the same resolution of 80nS
1257 DB_RMT("RMT: setting new fddiPATHT_Rmode, t = %d ns\n",
1258 (int) smc->mib.a[PATH0].fddiPATHT_Rmode,0) ;
1259 outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ;
1262 static void smt_split_up_fifo(struct s_smc *smc)
1266 BEGIN_MANUAL_ENTRY(module;mem;1)
1267 -------------------------------------------------------------
1268 RECEIVE BUFFER MEMORY DIVERSION
1269 -------------------------------------------------------------
1271 R1_RxD == SMT_R1_RXD_COUNT
1272 R2_RxD == SMT_R2_RXD_COUNT
1274 SMT_R1_RXD_COUNT must be unequal zero
1276 | R1_RxD R2_RxD |R1_RxD R2_RxD | R1_RxD R2_RxD
1277 | x 0 | x 1-3 | x < 3
1278 ----------------------------------------------------------------------
1279 | 63,75 kB | 54,75 | R1_RxD
1280 rx queue 1 | RX_FIFO_SPACE | RX_LARGE_FIFO| ------------- * 63,75 kB
1281 | | | R1_RxD+R2_RxD
1282 ----------------------------------------------------------------------
1283 | | 9 kB | R2_RxD
1284 rx queue 2 | 0 kB | RX_SMALL_FIFO| ------------- * 63,75 kB
1285 | (not used) | | R1_RxD+R2_RxD
1287 END_MANUAL_ENTRY
1290 if (SMT_R1_RXD_COUNT == 0) {
1291 SMT_PANIC(smc,SMT_E0117, SMT_E0117_MSG) ;
1294 switch(SMT_R2_RXD_COUNT) {
1295 case 0:
1296 smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE ;
1297 smc->hw.fp.fifo.rx2_fifo_size = 0 ;
1298 break ;
1299 case 1:
1300 case 2:
1301 case 3:
1302 smc->hw.fp.fifo.rx1_fifo_size = RX_LARGE_FIFO ;
1303 smc->hw.fp.fifo.rx2_fifo_size = RX_SMALL_FIFO ;
1304 break ;
1305 default: /* this is not the real defaule */
1306 smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE *
1307 SMT_R1_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
1308 smc->hw.fp.fifo.rx2_fifo_size = RX_FIFO_SPACE *
1309 SMT_R2_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
1310 break ;
1314 BEGIN_MANUAL_ENTRY(module;mem;1)
1315 -------------------------------------------------------------
1316 TRANSMIT BUFFER MEMORY DIVERSION
1317 -------------------------------------------------------------
1320 | no sync bw | sync bw available and | sync bw available and
1321 | available | SynchTxMode = SPLIT | SynchTxMode = ALL
1322 -----------------------------------------------------------------------
1323 sync tx | 0 kB | 32 kB | 55 kB
1324 queue | | TX_MEDIUM_FIFO | TX_LARGE_FIFO
1325 -----------------------------------------------------------------------
1326 async tx | 64 kB | 32 kB | 9 k
1327 queue | TX_FIFO_SPACE| TX_MEDIUM_FIFO | TX_SMALL_FIFO
1329 END_MANUAL_ENTRY
1333 * set the tx mode bits
1335 if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
1336 #ifdef ESS
1337 smc->hw.fp.fifo.fifo_config_mode |=
1338 smc->mib.fddiESSSynchTxMode | SYNC_TRAFFIC_ON ;
1339 #endif
1341 else {
1342 smc->hw.fp.fifo.fifo_config_mode &=
1343 ~(SEND_ASYNC_AS_SYNC|SYNC_TRAFFIC_ON) ;
1347 * split up the FIFO
1349 if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON) {
1350 if (smc->hw.fp.fifo.fifo_config_mode & SEND_ASYNC_AS_SYNC) {
1351 smc->hw.fp.fifo.tx_s_size = TX_LARGE_FIFO ;
1352 smc->hw.fp.fifo.tx_a0_size = TX_SMALL_FIFO ;
1354 else {
1355 smc->hw.fp.fifo.tx_s_size = TX_MEDIUM_FIFO ;
1356 smc->hw.fp.fifo.tx_a0_size = TX_MEDIUM_FIFO ;
1359 else {
1360 smc->hw.fp.fifo.tx_s_size = 0 ;
1361 smc->hw.fp.fifo.tx_a0_size = TX_FIFO_SPACE ;
1364 smc->hw.fp.fifo.rx1_fifo_start = smc->hw.fp.fifo.rbc_ram_start +
1365 RX_FIFO_OFF ;
1366 smc->hw.fp.fifo.tx_s_start = smc->hw.fp.fifo.rx1_fifo_start +
1367 smc->hw.fp.fifo.rx1_fifo_size ;
1368 smc->hw.fp.fifo.tx_a0_start = smc->hw.fp.fifo.tx_s_start +
1369 smc->hw.fp.fifo.tx_s_size ;
1370 smc->hw.fp.fifo.rx2_fifo_start = smc->hw.fp.fifo.tx_a0_start +
1371 smc->hw.fp.fifo.tx_a0_size ;
1373 DB_SMT("FIFO split: mode = %x\n",smc->hw.fp.fifo.fifo_config_mode,0) ;
1374 DB_SMT("rbc_ram_start = %x rbc_ram_end = %x\n",
1375 smc->hw.fp.fifo.rbc_ram_start, smc->hw.fp.fifo.rbc_ram_end) ;
1376 DB_SMT("rx1_fifo_start = %x tx_s_start = %x\n",
1377 smc->hw.fp.fifo.rx1_fifo_start, smc->hw.fp.fifo.tx_s_start) ;
1378 DB_SMT("tx_a0_start = %x rx2_fifo_start = %x\n",
1379 smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start) ;
1382 void formac_reinit_tx(struct s_smc *smc)
1385 * Split up the FIFO and reinitialize the MAC if synchronous
1386 * bandwidth becomes available but no synchronous queue is
1387 * configured.
1389 if (!smc->hw.fp.fifo.tx_s_size && smc->mib.a[PATH0].fddiPATHSbaPayload){
1390 (void)init_mac(smc,0) ;