1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#ifndef lint
18static char const ID_sccs[] = "@(#)hwmtm.c 1.40 99/05/31 (C) SK" ;
19#endif
20
21#define HWMTM
22
23#ifndef FDDI
24#define FDDI
25#endif
26
27#include "h/types.h"
28#include "h/fddi.h"
29#include "h/smc.h"
30#include "h/supern_2.h"
31#include "h/skfbiinc.h"
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48#ifdef COMMON_MB_POOL
49static SMbuf *mb_start = 0 ;
50static SMbuf *mb_free = 0 ;
51static int mb_init = FALSE ;
52static int call_count = 0 ;
53#endif
54
55
56
57
58
59
60
61#ifdef DEBUG
62#ifndef DEBUG_BRD
63extern struct smt_debug debug ;
64#endif
65#endif
66
67#ifdef NDIS_OS2
68extern u_char offDepth ;
69extern u_char force_irq_pending ;
70#endif
71
72
73
74
75
76
77
78static void queue_llc_rx(struct s_smc *smc, SMbuf *mb);
79static void smt_to_llc(struct s_smc *smc, SMbuf *mb);
80static void init_txd_ring(struct s_smc *smc);
81static void init_rxd_ring(struct s_smc *smc);
82static void queue_txd_mb(struct s_smc *smc, SMbuf *mb);
83static u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start,
84 int count);
85static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue);
86static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue);
87static SMbuf* get_llc_rx(struct s_smc *smc);
88static SMbuf* get_txd_mb(struct s_smc *smc);
89static void mac_drv_clear_txd(struct s_smc *smc);
90
91
92
93
94
95
96
97
98extern void* mac_drv_get_space(struct s_smc *smc, unsigned int size);
99extern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size);
100extern void init_board(struct s_smc *smc, u_char *mac_addr);
101extern void mac_drv_fill_rxd(struct s_smc *smc);
102extern void plc1_irq(struct s_smc *smc);
103extern void mac_drv_tx_complete(struct s_smc *smc,
104 volatile struct s_smt_fp_txd *txd);
105extern void plc2_irq(struct s_smc *smc);
106extern void mac1_irq(struct s_smc *smc, u_short stu, u_short stl);
107extern void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l);
108extern void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l);
109extern void timer_irq(struct s_smc *smc);
110extern void mac_drv_rx_complete(struct s_smc *smc,
111 volatile struct s_smt_fp_rxd *rxd,
112 int frag_count, int len);
113extern void mac_drv_requeue_rxd(struct s_smc *smc,
114 volatile struct s_smt_fp_rxd *rxd,
115 int frag_count);
116extern void init_plc(struct s_smc *smc);
117extern void mac_drv_clear_rxd(struct s_smc *smc,
118 volatile struct s_smt_fp_rxd *rxd, int frag_count);
119
120#ifdef USE_OS_CPY
121extern void hwm_cpy_rxd2mb(void);
122extern void hwm_cpy_txd2mb(void);
123#endif
124
125#ifdef ALL_RX_COMPLETE
126extern void mac_drv_all_receives_complete(void);
127#endif
128
129extern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt);
130extern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag);
131
132#ifdef NDIS_OS2
133extern void post_proc(void);
134#else
135extern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,
136 int flag);
137#endif
138
139extern int init_fplus(struct s_smc *smc);
140extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
141 int la_len);
142
143
144
145
146
147
148void process_receive(struct s_smc *smc);
149void fddi_isr(struct s_smc *smc);
150void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);
151void init_driver_fplus(struct s_smc *smc);
152void mac_drv_rx_mode(struct s_smc *smc, int mode);
153void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);
154void mac_drv_clear_tx_queue(struct s_smc *smc);
155void mac_drv_clear_rx_queue(struct s_smc *smc);
156void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
157 int frame_status);
158void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
159 int frame_status);
160
161int mac_drv_init(struct s_smc *smc);
162int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
163 int frame_status);
164
165u_int mac_drv_check_space(void);
166
167SMbuf* smt_get_mbuf(struct s_smc *smc);
168
169#ifdef DEBUG
170 void mac_drv_debug_lev(void);
171#endif
172
173
174
175
176
177
178#ifndef UNUSED
179#ifdef lint
180#define UNUSED(x) (x) = (x)
181#else
182#define UNUSED(x)
183#endif
184#endif
185
186#ifdef USE_CAN_ADDR
187#define MA smc->hw.fddi_canon_addr.a
188#define GROUP_ADDR_BIT 0x01
189#else
190#define MA smc->hw.fddi_home_addr.a
191#define GROUP_ADDR_BIT 0x80
192#endif
193
194#define RXD_TXD_COUNT (HWM_ASYNC_TXD_COUNT+HWM_SYNC_TXD_COUNT+\
195 SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT)
196
197#ifdef MB_OUTSIDE_SMC
198#define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd) +\
199 MAX_MBUF*sizeof(SMbuf))
200#define EXT_VIRT_MEM_2 ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
201#else
202#define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
203#endif
204
205
206
207
208#if defined(NDIS_OS2) || defined(ODI2)
209#define CR_READ(var) ((var) & 0xffff0000 | ((var) & 0xffff))
210#else
211#define CR_READ(var) (u_long)(var)
212#endif
213
214#define IMASK_SLOW (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
215 IS_MINTR1 | IS_MINTR2 | IS_MINTR3 | IS_R1_P | \
216 IS_R1_C | IS_XA_C | IS_XS_C)
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238u_int mac_drv_check_space(void)
239{
240#ifdef MB_OUTSIDE_SMC
241#ifdef COMMON_MB_POOL
242 call_count++ ;
243 if (call_count == 1) {
244 return(EXT_VIRT_MEM) ;
245 }
246 else {
247 return(EXT_VIRT_MEM_2) ;
248 }
249#else
250 return (EXT_VIRT_MEM) ;
251#endif
252#else
253 return (0) ;
254#endif
255}
256
257
258
259
260
261
262
263
264
265
266
267
268int mac_drv_init(struct s_smc *smc)
269{
270 if (sizeof(struct s_smt_fp_rxd) % 16) {
271 SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ;
272 }
273 if (sizeof(struct s_smt_fp_txd) % 16) {
274 SMT_PANIC(smc,HWM_E0002,HWM_E0002_MSG) ;
275 }
276
277
278
279
280 if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *)
281 mac_drv_get_desc_mem(smc,(u_int)
282 (RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) {
283 return(1) ;
284 }
285
286
287
288
289#ifndef MB_OUTSIDE_SMC
290 smc->os.hwm.mbuf_pool.mb_start=(SMbuf *)(&smc->os.hwm.mbuf_pool.mb[0]) ;
291#else
292#ifndef COMMON_MB_POOL
293 if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc,
294 MAX_MBUF*sizeof(SMbuf)))) {
295 return(1) ;
296 }
297#else
298 if (!mb_start) {
299 if (!(mb_start = (SMbuf *) mac_drv_get_space(smc,
300 MAX_MBUF*sizeof(SMbuf)))) {
301 return(1) ;
302 }
303 }
304#endif
305#endif
306 return (0) ;
307}
308
309
310
311
312
313
314
315
316
317
318void init_driver_fplus(struct s_smc *smc)
319{
320 smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ;
321
322#ifdef PCI
323 smc->hw.fp.mdr2init |= FM_CHKPAR | FM_PARITY ;
324#endif
325 smc->hw.fp.mdr3init = FM_MENRQAUNLCK | FM_MENRS ;
326
327#ifdef USE_CAN_ADDR
328
329 smc->hw.fp.frselreg_init = FM_ENXMTADSWAP | FM_ENRCVADSWAP ;
330#endif
331}
332
333static u_long init_descr_ring(struct s_smc *smc,
334 union s_fp_descr volatile *start,
335 int count)
336{
337 int i ;
338 union s_fp_descr volatile *d1 ;
339 union s_fp_descr volatile *d2 ;
340 u_long phys ;
341
342 DB_GEN("descr ring starts at = %x ",(void *)start,0,3) ;
343 for (i=count-1, d1=start; i ; i--) {
344 d2 = d1 ;
345 d1++ ;
346 d2->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ;
347 d2->r.rxd_next = &d1->r ;
348 phys = mac_drv_virt2phys(smc,(void *)d1) ;
349 d2->r.rxd_nrdadr = AIX_REVERSE(phys) ;
350 }
351 DB_GEN("descr ring ends at = %x ",(void *)d1,0,3) ;
352 d1->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ;
353 d1->r.rxd_next = &start->r ;
354 phys = mac_drv_virt2phys(smc,(void *)start) ;
355 d1->r.rxd_nrdadr = AIX_REVERSE(phys) ;
356
357 for (i=count, d1=start; i ; i--) {
358 DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;
359 d1++;
360 }
361 return(phys) ;
362}
363
364static void init_txd_ring(struct s_smc *smc)
365{
366 struct s_smt_fp_txd volatile *ds ;
367 struct s_smt_tx_queue *queue ;
368 u_long phys ;
369
370
371
372
373 ds = (struct s_smt_fp_txd volatile *) ((char *)smc->os.hwm.descr_p +
374 SMT_R1_RXD_COUNT*sizeof(struct s_smt_fp_rxd)) ;
375 queue = smc->hw.fp.tx[QUEUE_A0] ;
376 DB_GEN("Init async TxD ring, %d TxDs ",HWM_ASYNC_TXD_COUNT,0,3) ;
377 (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
378 HWM_ASYNC_TXD_COUNT) ;
379 phys = AIX_REVERSE(ds->txd_ntdadr) ;
380 ds++ ;
381 queue->tx_curr_put = queue->tx_curr_get = ds ;
382 ds-- ;
383 queue->tx_free = HWM_ASYNC_TXD_COUNT ;
384 queue->tx_used = 0 ;
385 outpd(ADDR(B5_XA_DA),phys) ;
386
387 ds = (struct s_smt_fp_txd volatile *) ((char *)ds +
388 HWM_ASYNC_TXD_COUNT*sizeof(struct s_smt_fp_txd)) ;
389 queue = smc->hw.fp.tx[QUEUE_S] ;
390 DB_GEN("Init sync TxD ring, %d TxDs ",HWM_SYNC_TXD_COUNT,0,3) ;
391 (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
392 HWM_SYNC_TXD_COUNT) ;
393 phys = AIX_REVERSE(ds->txd_ntdadr) ;
394 ds++ ;
395 queue->tx_curr_put = queue->tx_curr_get = ds ;
396 queue->tx_free = HWM_SYNC_TXD_COUNT ;
397 queue->tx_used = 0 ;
398 outpd(ADDR(B5_XS_DA),phys) ;
399}
400
401static void init_rxd_ring(struct s_smc *smc)
402{
403 struct s_smt_fp_rxd volatile *ds ;
404 struct s_smt_rx_queue *queue ;
405 u_long phys ;
406
407
408
409
410 ds = (struct s_smt_fp_rxd volatile *) smc->os.hwm.descr_p ;
411 queue = smc->hw.fp.rx[QUEUE_R1] ;
412 DB_GEN("Init RxD ring, %d RxDs ",SMT_R1_RXD_COUNT,0,3) ;
413 (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
414 SMT_R1_RXD_COUNT) ;
415 phys = AIX_REVERSE(ds->rxd_nrdadr) ;
416 ds++ ;
417 queue->rx_curr_put = queue->rx_curr_get = ds ;
418 queue->rx_free = SMT_R1_RXD_COUNT ;
419 queue->rx_used = 0 ;
420 outpd(ADDR(B4_R1_DA),phys) ;
421}
422
423
424
425
426
427
428
429
430
431void init_fddi_driver(struct s_smc *smc, u_char *mac_addr)
432{
433 SMbuf *mb ;
434 int i ;
435
436 init_board(smc,mac_addr) ;
437 (void)init_fplus(smc) ;
438
439
440
441
442#ifndef COMMON_MB_POOL
443 mb = smc->os.hwm.mbuf_pool.mb_start ;
444 smc->os.hwm.mbuf_pool.mb_free = (SMbuf *)NULL ;
445 for (i = 0; i < MAX_MBUF; i++) {
446 mb->sm_use_count = 1 ;
447 smt_free_mbuf(smc,mb) ;
448 mb++ ;
449 }
450#else
451 mb = mb_start ;
452 if (!mb_init) {
453 mb_free = 0 ;
454 for (i = 0; i < MAX_MBUF; i++) {
455 mb->sm_use_count = 1 ;
456 smt_free_mbuf(smc,mb) ;
457 mb++ ;
458 }
459 mb_init = TRUE ;
460 }
461#endif
462
463
464
465
466 smc->os.hwm.llc_rx_pipe = smc->os.hwm.llc_rx_tail = (SMbuf *)NULL ;
467 smc->os.hwm.txd_tx_pipe = smc->os.hwm.txd_tx_tail = NULL ;
468 smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = smc->os.hwm.pass_DB = 0 ;
469 smc->os.hwm.pass_llc_promisc = TRUE ;
470 smc->os.hwm.queued_rx_frames = smc->os.hwm.queued_txd_mb = 0 ;
471 smc->os.hwm.detec_count = 0 ;
472 smc->os.hwm.rx_break = 0 ;
473 smc->os.hwm.rx_len_error = 0 ;
474 smc->os.hwm.isr_flag = FALSE ;
475
476
477
478
479 i = 16 - ((long)smc->os.hwm.descr_p & 0xf) ;
480 if (i != 16) {
481 DB_GEN("i = %d",i,0,3) ;
482 smc->os.hwm.descr_p = (union s_fp_descr volatile *)
483 ((char *)smc->os.hwm.descr_p+i) ;
484 }
485 DB_GEN("pt to descr area = %x",(void *)smc->os.hwm.descr_p,0,3) ;
486
487 init_txd_ring(smc) ;
488 init_rxd_ring(smc) ;
489 mac_drv_fill_rxd(smc) ;
490
491 init_plc(smc) ;
492}
493
494
495SMbuf *smt_get_mbuf(struct s_smc *smc)
496{
497 register SMbuf *mb ;
498
499#ifndef COMMON_MB_POOL
500 mb = smc->os.hwm.mbuf_pool.mb_free ;
501#else
502 mb = mb_free ;
503#endif
504 if (mb) {
505#ifndef COMMON_MB_POOL
506 smc->os.hwm.mbuf_pool.mb_free = mb->sm_next ;
507#else
508 mb_free = mb->sm_next ;
509#endif
510 mb->sm_off = 8 ;
511 mb->sm_use_count = 1 ;
512 }
513 DB_GEN("get SMbuf: mb = %x",(void *)mb,0,3) ;
514 return (mb) ;
515}
516
517void smt_free_mbuf(struct s_smc *smc, SMbuf *mb)
518{
519
520 if (mb) {
521 mb->sm_use_count-- ;
522 DB_GEN("free_mbuf: sm_use_count = %d",mb->sm_use_count,0,3) ;
523
524
525
526
527
528 if (!mb->sm_use_count) {
529 DB_GEN("free SMbuf: mb = %x",(void *)mb,0,3) ;
530#ifndef COMMON_MB_POOL
531 mb->sm_next = smc->os.hwm.mbuf_pool.mb_free ;
532 smc->os.hwm.mbuf_pool.mb_free = mb ;
533#else
534 mb->sm_next = mb_free ;
535 mb_free = mb ;
536#endif
537 }
538 }
539 else
540 SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ;
541}
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563void mac_drv_repair_descr(struct s_smc *smc)
564{
565 u_long phys ;
566
567 if (smc->hw.hw_state != STOPPED) {
568 SK_BREAK() ;
569 SMT_PANIC(smc,HWM_E0013,HWM_E0013_MSG) ;
570 return ;
571 }
572
573
574
575
576 phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_A0]) ;
577 outpd(ADDR(B5_XA_DA),phys) ;
578 if (smc->hw.fp.tx_q[QUEUE_A0].tx_used) {
579 outpd(ADDR(B0_XA_CSR),CSR_START) ;
580 }
581 phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_S]) ;
582 outpd(ADDR(B5_XS_DA),phys) ;
583 if (smc->hw.fp.tx_q[QUEUE_S].tx_used) {
584 outpd(ADDR(B0_XS_CSR),CSR_START) ;
585 }
586
587
588
589
590 phys = repair_rxd_ring(smc,smc->hw.fp.rx[QUEUE_R1]) ;
591 outpd(ADDR(B4_R1_DA),phys) ;
592 outpd(ADDR(B0_R1_CSR),CSR_START) ;
593}
594
595static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
596{
597 int i ;
598 int tx_used ;
599 u_long phys ;
600 u_long tbctrl ;
601 struct s_smt_fp_txd volatile *t ;
602
603 SK_UNUSED(smc) ;
604
605 t = queue->tx_curr_get ;
606 tx_used = queue->tx_used ;
607 for (i = tx_used+queue->tx_free-1 ; i ; i-- ) {
608 t = t->txd_next ;
609 }
610 phys = AIX_REVERSE(t->txd_ntdadr) ;
611
612 t = queue->tx_curr_get ;
613 while (tx_used) {
614 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
615 tbctrl = AIX_REVERSE(t->txd_tbctrl) ;
616
617 if (tbctrl & BMU_OWN) {
618 if (tbctrl & BMU_STF) {
619 break ;
620 }
621 else {
622
623
624
625 t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;
626 }
627 }
628 phys = AIX_REVERSE(t->txd_ntdadr) ;
629 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
630 t = t->txd_next ;
631 tx_used-- ;
632 }
633 return(phys) ;
634}
635
636
637
638
639
640
641
642
643
644
645
646
647static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
648{
649 int i ;
650 int rx_used ;
651 u_long phys ;
652 u_long rbctrl ;
653 struct s_smt_fp_rxd volatile *r ;
654
655 SK_UNUSED(smc) ;
656
657 r = queue->rx_curr_get ;
658 rx_used = queue->rx_used ;
659 for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) {
660 r = r->rxd_next ;
661 }
662 phys = AIX_REVERSE(r->rxd_nrdadr) ;
663
664 r = queue->rx_curr_get ;
665 while (rx_used) {
666 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
667 rbctrl = AIX_REVERSE(r->rxd_rbctrl) ;
668
669 if (rbctrl & BMU_OWN) {
670 if (rbctrl & BMU_STF) {
671 break ;
672 }
673 else {
674
675
676
677 r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
678 }
679 }
680 phys = AIX_REVERSE(r->rxd_nrdadr) ;
681 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
682 r = r->rxd_next ;
683 rx_used-- ;
684 }
685 return(phys) ;
686}
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718void fddi_isr(struct s_smc *smc)
719{
720 u_long is ;
721 u_short stu, stl ;
722 SMbuf *mb ;
723
724#ifdef USE_BREAK_ISR
725 int force_irq ;
726#endif
727
728#ifdef ODI2
729 if (smc->os.hwm.rx_break) {
730 mac_drv_fill_rxd(smc) ;
731 if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) {
732 smc->os.hwm.rx_break = 0 ;
733 process_receive(smc) ;
734 }
735 else {
736 smc->os.hwm.detec_count = 0 ;
737 smt_force_irq(smc) ;
738 }
739 }
740#endif
741 smc->os.hwm.isr_flag = TRUE ;
742
743#ifdef USE_BREAK_ISR
744 force_irq = TRUE ;
745 if (smc->os.hwm.leave_isr) {
746 smc->os.hwm.leave_isr = FALSE ;
747 process_receive(smc) ;
748 }
749#endif
750
751 while ((is = GET_ISR() & ISR_MASK)) {
752 NDD_TRACE("CH0B",is,0,0) ;
753 DB_GEN("ISA = 0x%x",is,0,7) ;
754
755 if (is & IMASK_SLOW) {
756 NDD_TRACE("CH1b",is,0,0) ;
757 if (is & IS_PLINT1) {
758 plc1_irq(smc) ;
759 }
760 if (is & IS_PLINT2) {
761 plc2_irq(smc) ;
762 }
763 if (is & IS_MINTR1) {
764 stu = inpw(FM_A(FM_ST1U)) ;
765 stl = inpw(FM_A(FM_ST1L)) ;
766 DB_GEN("Slow transmit complete",0,0,6) ;
767 mac1_irq(smc,stu,stl) ;
768 }
769 if (is & IS_MINTR2) {
770 stu= inpw(FM_A(FM_ST2U)) ;
771 stl= inpw(FM_A(FM_ST2L)) ;
772 DB_GEN("Slow receive complete",0,0,6) ;
773 DB_GEN("stl = %x : stu = %x",stl,stu,7) ;
774 mac2_irq(smc,stu,stl) ;
775 }
776 if (is & IS_MINTR3) {
777 stu= inpw(FM_A(FM_ST3U)) ;
778 stl= inpw(FM_A(FM_ST3L)) ;
779 DB_GEN("FORMAC Mode Register 3",0,0,6) ;
780 mac3_irq(smc,stu,stl) ;
781 }
782 if (is & IS_TIMINT) {
783 timer_irq(smc) ;
784#ifdef NDIS_OS2
785 force_irq_pending = 0 ;
786#endif
787
788
789
790 if (++smc->os.hwm.detec_count > 4) {
791
792
793
794 process_receive(smc) ;
795 }
796 }
797 if (is & IS_TOKEN) {
798 rtm_irq(smc) ;
799 }
800 if (is & IS_R1_P) {
801
802 outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ;
803 SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ;
804 }
805 if (is & IS_R1_C) {
806
807 outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ;
808 SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ;
809 }
810 if (is & IS_XA_C) {
811
812 outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ;
813 SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ;
814 }
815 if (is & IS_XS_C) {
816
817 outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ;
818 SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ;
819 }
820 }
821
822
823
824
825 if (is & (IS_XS_F|IS_XA_F)) {
826 DB_GEN("Fast tx complete queue",0,0,6) ;
827
828
829
830
831 outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ;
832 outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ;
833 mac_drv_clear_txd(smc) ;
834 llc_restart_tx(smc) ;
835 }
836
837
838
839
840 if (is & IS_R1_F) {
841 DB_GEN("Fast receive complete",0,0,6) ;
842
843#ifndef USE_BREAK_ISR
844 outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
845 process_receive(smc) ;
846#else
847 process_receive(smc) ;
848 if (smc->os.hwm.leave_isr) {
849 force_irq = FALSE ;
850 } else {
851 outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
852 process_receive(smc) ;
853 }
854#endif
855 }
856
857#ifndef NDIS_OS2
858 while ((mb = get_llc_rx(smc))) {
859 smt_to_llc(smc,mb) ;
860 }
861#else
862 if (offDepth)
863 post_proc() ;
864
865 while (!offDepth && (mb = get_llc_rx(smc))) {
866 smt_to_llc(smc,mb) ;
867 }
868
869 if (!offDepth && smc->os.hwm.rx_break) {
870 process_receive(smc) ;
871 }
872#endif
873 if (smc->q.ev_get != smc->q.ev_put) {
874 NDD_TRACE("CH2a",0,0,0) ;
875 ev_dispatcher(smc) ;
876 }
877#ifdef NDIS_OS2
878 post_proc() ;
879 if (offDepth) {
880 break ;
881 }
882#endif
883#ifdef USE_BREAK_ISR
884 if (smc->os.hwm.leave_isr) {
885 break ;
886 }
887#endif
888
889
890 }
891
892#ifdef USE_BREAK_ISR
893 if (smc->os.hwm.leave_isr && force_irq) {
894 smt_force_irq(smc) ;
895 }
896#endif
897 smc->os.hwm.isr_flag = FALSE ;
898 NDD_TRACE("CH0E",0,0,0) ;
899}
900
901
902
903
904
905
906
907
908#ifndef NDIS_OS2
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001void mac_drv_rx_mode(struct s_smc *smc, int mode)
1002{
1003 switch(mode) {
1004 case RX_ENABLE_PASS_SMT:
1005 smc->os.hwm.pass_SMT = TRUE ;
1006 break ;
1007 case RX_DISABLE_PASS_SMT:
1008 smc->os.hwm.pass_SMT = FALSE ;
1009 break ;
1010 case RX_ENABLE_PASS_NSA:
1011 smc->os.hwm.pass_NSA = TRUE ;
1012 break ;
1013 case RX_DISABLE_PASS_NSA:
1014 smc->os.hwm.pass_NSA = FALSE ;
1015 break ;
1016 case RX_ENABLE_PASS_DB:
1017 smc->os.hwm.pass_DB = TRUE ;
1018 break ;
1019 case RX_DISABLE_PASS_DB:
1020 smc->os.hwm.pass_DB = FALSE ;
1021 break ;
1022 case RX_DISABLE_PASS_ALL:
1023 smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = FALSE ;
1024 smc->os.hwm.pass_DB = FALSE ;
1025 smc->os.hwm.pass_llc_promisc = TRUE ;
1026 mac_set_rx_mode(smc,RX_DISABLE_NSA) ;
1027 break ;
1028 case RX_DISABLE_LLC_PROMISC:
1029 smc->os.hwm.pass_llc_promisc = FALSE ;
1030 break ;
1031 case RX_ENABLE_LLC_PROMISC:
1032 smc->os.hwm.pass_llc_promisc = TRUE ;
1033 break ;
1034 case RX_ENABLE_ALLMULTI:
1035 case RX_DISABLE_ALLMULTI:
1036 case RX_ENABLE_PROMISC:
1037 case RX_DISABLE_PROMISC:
1038 case RX_ENABLE_NSA:
1039 case RX_DISABLE_NSA:
1040 default:
1041 mac_set_rx_mode(smc,mode) ;
1042 break ;
1043 }
1044}
1045#endif
1046
1047
1048
1049
1050void process_receive(struct s_smc *smc)
1051{
1052 int i ;
1053 int n ;
1054 int frag_count ;
1055 int used_frags ;
1056 struct s_smt_rx_queue *queue ;
1057 struct s_smt_fp_rxd volatile *r ;
1058 struct s_smt_fp_rxd volatile *rxd ;
1059 u_long rbctrl ;
1060 u_long rfsw ;
1061 u_short rx_used ;
1062 u_char far *virt ;
1063 char far *data ;
1064 SMbuf *mb ;
1065 u_char fc ;
1066 int len ;
1067
1068 smc->os.hwm.detec_count = 0 ;
1069 queue = smc->hw.fp.rx[QUEUE_R1] ;
1070 NDD_TRACE("RHxB",0,0,0) ;
1071 for ( ; ; ) {
1072 r = queue->rx_curr_get ;
1073 rx_used = queue->rx_used ;
1074 frag_count = 0 ;
1075
1076#ifdef USE_BREAK_ISR
1077 if (smc->os.hwm.leave_isr) {
1078 goto rx_end ;
1079 }
1080#endif
1081#ifdef NDIS_OS2
1082 if (offDepth) {
1083 smc->os.hwm.rx_break = 1 ;
1084 goto rx_end ;
1085 }
1086 smc->os.hwm.rx_break = 0 ;
1087#endif
1088#ifdef ODI2
1089 if (smc->os.hwm.rx_break) {
1090 goto rx_end ;
1091 }
1092#endif
1093 n = 0 ;
1094 do {
1095 DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ;
1096 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1097 rbctrl = CR_READ(r->rxd_rbctrl) ;
1098 rbctrl = AIX_REVERSE(rbctrl) ;
1099
1100 if (rbctrl & BMU_OWN) {
1101 NDD_TRACE("RHxE",r,rfsw,rbctrl) ;
1102 DB_RX("End of RxDs",0,0,4) ;
1103 goto rx_end ;
1104 }
1105
1106
1107
1108 if (!rx_used) {
1109 SK_BREAK() ;
1110 SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ;
1111
1112
1113
1114 smc->hw.hw_state = STOPPED ;
1115 mac_drv_clear_rx_queue(smc) ;
1116 smc->hw.hw_state = STARTED ;
1117 mac_drv_fill_rxd(smc) ;
1118 smc->os.hwm.detec_count = 0 ;
1119 goto rx_end ;
1120 }
1121 rfsw = AIX_REVERSE(r->rxd_rfsw) ;
1122 if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137 SK_BREAK() ;
1138 rfsw = 0 ;
1139 if (frag_count) {
1140 break ;
1141 }
1142 }
1143 n += rbctrl & 0xffff ;
1144 r = r->rxd_next ;
1145 frag_count++ ;
1146 rx_used-- ;
1147 } while (!(rbctrl & BMU_EOF)) ;
1148 used_frags = frag_count ;
1149 DB_RX("EOF set in RxD, used_frags = %d ",used_frags,0,5) ;
1150
1151
1152
1153 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1154 while (rx_used && !(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {
1155 DB_RX("Check STF bit in %x",(void *)r,0,5) ;
1156 r = r->rxd_next ;
1157 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1158 frag_count++ ;
1159 rx_used-- ;
1160 }
1161 DB_RX("STF bit found",0,0,5) ;
1162
1163
1164
1165
1166 rxd = queue->rx_curr_get ;
1167 queue->rx_curr_get = r ;
1168 queue->rx_free += frag_count ;
1169 queue->rx_used = rx_used ;
1170
1171
1172
1173
1174 rxd->rxd_rbctrl &= AIX_REVERSE(~BMU_STF) ;
1175
1176 for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){
1177 DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
1178 dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
1179 }
1180 smc->hw.fp.err_stats.err_valid++ ;
1181 smc->mib.m[MAC0].fddiMACCopied_Ct++ ;
1182
1183
1184 len = (rfsw & RD_LENGTH) - 4 ;
1185
1186 DB_RX("frame length = %d",len,0,4) ;
1187
1188
1189
1190 if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){
1191 if (rfsw & RD_S_MSRABT) {
1192 DB_RX("Frame aborted by the FORMAC",0,0,2) ;
1193 smc->hw.fp.err_stats.err_abort++ ;
1194 }
1195
1196
1197
1198 if (rfsw & RD_S_SEAC2) {
1199 DB_RX("E-Indicator set",0,0,2) ;
1200 smc->hw.fp.err_stats.err_e_indicator++ ;
1201 }
1202 if (rfsw & RD_S_SFRMERR) {
1203 DB_RX("CRC error",0,0,2) ;
1204 smc->hw.fp.err_stats.err_crc++ ;
1205 }
1206 if (rfsw & RX_FS_IMPL) {
1207 DB_RX("Implementer frame",0,0,2) ;
1208 smc->hw.fp.err_stats.err_imp_frame++ ;
1209 }
1210 goto abort_frame ;
1211 }
1212 if (len > FDDI_RAW_MTU-4) {
1213 DB_RX("Frame too long error",0,0,2) ;
1214 smc->hw.fp.err_stats.err_too_long++ ;
1215 goto abort_frame ;
1216 }
1217
1218
1219
1220
1221 if (len <= 4) {
1222 DB_RX("Frame length = 0",0,0,2) ;
1223 goto abort_frame ;
1224 }
1225
1226 if (len != (n-4)) {
1227 DB_RX("BMU: rx len differs: [%d:%d]",len,n,4);
1228 smc->os.hwm.rx_len_error++ ;
1229 goto abort_frame ;
1230 }
1231
1232
1233
1234
1235 virt = (u_char far *) rxd->rxd_virt ;
1236 DB_RX("FC = %x",*virt,0,2) ;
1237 if (virt[12] == MA[5] &&
1238 virt[11] == MA[4] &&
1239 virt[10] == MA[3] &&
1240 virt[9] == MA[2] &&
1241 virt[8] == MA[1] &&
1242 (virt[7] & ~GROUP_ADDR_BIT) == MA[0]) {
1243 goto abort_frame ;
1244 }
1245
1246
1247
1248
1249 if (rfsw & RX_FS_LLC) {
1250
1251
1252
1253
1254
1255 if (!smc->os.hwm.pass_llc_promisc) {
1256 if(!(virt[1] & GROUP_ADDR_BIT)) {
1257 if (virt[6] != MA[5] ||
1258 virt[5] != MA[4] ||
1259 virt[4] != MA[3] ||
1260 virt[3] != MA[2] ||
1261 virt[2] != MA[1] ||
1262 virt[1] != MA[0]) {
1263 DB_RX("DA != MA and not multi- or broadcast",0,0,2) ;
1264 goto abort_frame ;
1265 }
1266 }
1267 }
1268
1269
1270
1271
1272 DB_RX("LLC - receive",0,0,4) ;
1273 mac_drv_rx_complete(smc,rxd,frag_count,len) ;
1274 }
1275 else {
1276 if (!(mb = smt_get_mbuf(smc))) {
1277 smc->hw.fp.err_stats.err_no_buf++ ;
1278 DB_RX("No SMbuf; receive terminated",0,0,4) ;
1279 goto abort_frame ;
1280 }
1281 data = smtod(mb,char *) - 1 ;
1282
1283
1284
1285
1286#ifdef USE_OS_CPY
1287 hwm_cpy_rxd2mb(rxd,data,len) ;
1288#else
1289 for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){
1290 n = AIX_REVERSE(r->rxd_rbctrl) & RD_LENGTH ;
1291 DB_RX("cp SMT frame to mb: len = %d",n,0,6) ;
1292 memcpy(data,r->rxd_virt,n) ;
1293 data += n ;
1294 }
1295 data = smtod(mb,char *) - 1 ;
1296#endif
1297 fc = *(char *)mb->sm_data = *data ;
1298 mb->sm_len = len - 1 ;
1299 data++ ;
1300
1301
1302
1303
1304 switch(fc) {
1305 case FC_SMT_INFO :
1306 smc->hw.fp.err_stats.err_smt_frame++ ;
1307 DB_RX("SMT frame received ",0,0,5) ;
1308
1309 if (smc->os.hwm.pass_SMT) {
1310 DB_RX("pass SMT frame ",0,0,5) ;
1311 mac_drv_rx_complete(smc, rxd,
1312 frag_count,len) ;
1313 }
1314 else {
1315 DB_RX("requeue RxD",0,0,5) ;
1316 mac_drv_requeue_rxd(smc,rxd,frag_count);
1317 }
1318
1319 smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
1320 break ;
1321 case FC_SMT_NSA :
1322 smc->hw.fp.err_stats.err_smt_frame++ ;
1323 DB_RX("SMT frame received ",0,0,5) ;
1324
1325
1326
1327
1328 if (smc->os.hwm.pass_NSA ||
1329 (smc->os.hwm.pass_SMT &&
1330 !(rfsw & A_INDIC))) {
1331 DB_RX("pass SMT frame ",0,0,5) ;
1332 mac_drv_rx_complete(smc, rxd,
1333 frag_count,len) ;
1334 }
1335 else {
1336 DB_RX("requeue RxD",0,0,5) ;
1337 mac_drv_requeue_rxd(smc,rxd,frag_count);
1338 }
1339
1340 smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
1341 break ;
1342 case FC_BEACON :
1343 if (smc->os.hwm.pass_DB) {
1344 DB_RX("pass DB frame ",0,0,5) ;
1345 mac_drv_rx_complete(smc, rxd,
1346 frag_count,len) ;
1347 }
1348 else {
1349 DB_RX("requeue RxD",0,0,5) ;
1350 mac_drv_requeue_rxd(smc,rxd,frag_count);
1351 }
1352 smt_free_mbuf(smc,mb) ;
1353 break ;
1354 default :
1355
1356
1357
1358 DB_RX("unknown FC error",0,0,2) ;
1359 smt_free_mbuf(smc,mb) ;
1360 DB_RX("requeue RxD",0,0,5) ;
1361 mac_drv_requeue_rxd(smc,rxd,frag_count) ;
1362 if ((fc & 0xf0) == FC_MAC)
1363 smc->hw.fp.err_stats.err_mac_frame++ ;
1364 else
1365 smc->hw.fp.err_stats.err_imp_frame++ ;
1366
1367 break ;
1368 }
1369 }
1370
1371 DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
1372 NDD_TRACE("RHx1",queue->rx_curr_get,0,0) ;
1373
1374 continue ;
1375
1376abort_frame:
1377 DB_RX("requeue RxD",0,0,5) ;
1378 mac_drv_requeue_rxd(smc,rxd,frag_count) ;
1379
1380 DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
1381 NDD_TRACE("RHx2",queue->rx_curr_get,0,0) ;
1382 }
1383rx_end:
1384#ifdef ALL_RX_COMPLETE
1385 mac_drv_all_receives_complete(smc) ;
1386#endif
1387 return ;
1388}
1389
1390static void smt_to_llc(struct s_smc *smc, SMbuf *mb)
1391{
1392 u_char fc ;
1393
1394 DB_RX("send a queued frame to the llc layer",0,0,4) ;
1395 smc->os.hwm.r.len = mb->sm_len ;
1396 smc->os.hwm.r.mb_pos = smtod(mb,char *) ;
1397 fc = *smc->os.hwm.r.mb_pos ;
1398 (void)mac_drv_rx_init(smc,(int)mb->sm_len,(int)fc,
1399 smc->os.hwm.r.mb_pos,(int)mb->sm_len) ;
1400 smt_free_mbuf(smc,mb) ;
1401}
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
1426 int frame_status)
1427{
1428 struct s_smt_fp_rxd volatile *r ;
1429 u_int rbctrl ;
1430
1431 NDD_TRACE("RHfB",virt,len,frame_status) ;
1432 DB_RX("hwm_rx_frag: len = %d, frame_status = %x\n",len,frame_status,2) ;
1433 r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ;
1434 r->rxd_virt = virt ;
1435 r->rxd_rbadr = AIX_REVERSE(phys) ;
1436 rbctrl = AIX_REVERSE( (((u_long)frame_status &
1437 (FIRST_FRAG|LAST_FRAG))<<26) |
1438 (((u_long) frame_status & FIRST_FRAG) << 21) |
1439 BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ;
1440 r->rxd_rbctrl = rbctrl ;
1441
1442 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
1443 outpd(ADDR(B0_R1_CSR),CSR_START) ;
1444 smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ;
1445 smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ;
1446 smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ;
1447 NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ;
1448}
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473void mac_drv_clear_rx_queue(struct s_smc *smc)
1474{
1475 struct s_smt_fp_rxd volatile *r ;
1476 struct s_smt_fp_rxd volatile *next_rxd ;
1477 struct s_smt_rx_queue *queue ;
1478 int frag_count ;
1479 int i ;
1480
1481 if (smc->hw.hw_state != STOPPED) {
1482 SK_BREAK() ;
1483 SMT_PANIC(smc,HWM_E0012,HWM_E0012_MSG) ;
1484 return ;
1485 }
1486
1487 queue = smc->hw.fp.rx[QUEUE_R1] ;
1488 DB_RX("clear_rx_queue",0,0,5) ;
1489
1490
1491
1492
1493 r = queue->rx_curr_get ;
1494 while (queue->rx_used) {
1495 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1496 DB_RX("switch OWN bit of RxD 0x%x ",r,0,5) ;
1497 r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
1498 frag_count = 1 ;
1499 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
1500 r = r->rxd_next ;
1501 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1502 while (r != queue->rx_curr_put &&
1503 !(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {
1504 DB_RX("Check STF bit in %x",(void *)r,0,5) ;
1505 r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
1506 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
1507 r = r->rxd_next ;
1508 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
1509 frag_count++ ;
1510 }
1511 DB_RX("STF bit found",0,0,5) ;
1512 next_rxd = r ;
1513
1514 for (r=queue->rx_curr_get,i=frag_count; i ; r=r->rxd_next,i--){
1515 DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
1516 dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
1517 }
1518
1519 DB_RX("mac_drv_clear_rxd: RxD %x frag_count %d ",
1520 (void *)queue->rx_curr_get,frag_count,5) ;
1521 mac_drv_clear_rxd(smc,queue->rx_curr_get,frag_count) ;
1522
1523 queue->rx_curr_get = next_rxd ;
1524 queue->rx_used -= frag_count ;
1525 queue->rx_free += frag_count ;
1526 }
1527}
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
1561 int frame_status)
1562{
1563 NDD_TRACE("THiB",fc,frag_count,frame_len) ;
1564 smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ;
1565 smc->os.hwm.tx_descr = TX_DESCRIPTOR | (((u_long)(frame_len-1)&3)<<27) ;
1566 smc->os.hwm.tx_len = frame_len ;
1567 DB_TX("hwm_tx_init: fc = %x, len = %d",fc,frame_len,3) ;
1568 if ((fc & ~(FC_SYNC_BIT|FC_LLC_PRIOR)) == FC_ASYNC_LLC) {
1569 frame_status |= LAN_TX ;
1570 }
1571 else {
1572 switch (fc) {
1573 case FC_SMT_INFO :
1574 case FC_SMT_NSA :
1575 frame_status |= LAN_TX ;
1576 break ;
1577 case FC_SMT_LOC :
1578 frame_status |= LOC_TX ;
1579 break ;
1580 case FC_SMT_LAN_LOC :
1581 frame_status |= LAN_TX | LOC_TX ;
1582 break ;
1583 default :
1584 SMT_PANIC(smc,HWM_E0010,HWM_E0010_MSG) ;
1585 }
1586 }
1587 if (!smc->hw.mac_ring_is_up) {
1588 frame_status &= ~LAN_TX ;
1589 frame_status |= RING_DOWN ;
1590 DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
1591 }
1592 if (frag_count > smc->os.hwm.tx_p->tx_free) {
1593#ifndef NDIS_OS2
1594 mac_drv_clear_txd(smc) ;
1595 if (frag_count > smc->os.hwm.tx_p->tx_free) {
1596 DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;
1597 frame_status &= ~LAN_TX ;
1598 frame_status |= OUT_OF_TXD ;
1599 }
1600#else
1601 DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;
1602 frame_status &= ~LAN_TX ;
1603 frame_status |= OUT_OF_TXD ;
1604#endif
1605 }
1606 DB_TX("frame_status = %x",frame_status,0,3) ;
1607 NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ;
1608 return(frame_status) ;
1609}
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
1639 int frame_status)
1640{
1641 struct s_smt_fp_txd volatile *t ;
1642 struct s_smt_tx_queue *queue ;
1643 u_int tbctrl ;
1644
1645 queue = smc->os.hwm.tx_p ;
1646
1647 NDD_TRACE("THfB",virt,len,frame_status) ;
1648
1649
1650
1651
1652
1653 t = queue->tx_curr_put ;
1654
1655 DB_TX("hwm_tx_frag: len = %d, frame_status = %x ",len,frame_status,2) ;
1656 if (frame_status & LAN_TX) {
1657
1658 DB_TX("LAN_TX: TxD = %x, virt = %x ",t,virt,3) ;
1659 t->txd_virt = virt ;
1660 t->txd_txdscr = AIX_REVERSE(smc->os.hwm.tx_descr) ;
1661 t->txd_tbadr = AIX_REVERSE(phys) ;
1662 tbctrl = AIX_REVERSE((((u_long)frame_status &
1663 (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |
1664 BMU_OWN|BMU_CHECK |len) ;
1665 t->txd_tbctrl = tbctrl ;
1666
1667#ifndef AIX
1668 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
1669 outpd(queue->tx_bmu_ctl,CSR_START) ;
1670#else
1671 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
1672 if (frame_status & QUEUE_A0) {
1673 outpd(ADDR(B0_XA_CSR),CSR_START) ;
1674 }
1675 else {
1676 outpd(ADDR(B0_XS_CSR),CSR_START) ;
1677 }
1678#endif
1679 queue->tx_free-- ;
1680 queue->tx_used++ ;
1681 queue->tx_curr_put = t->txd_next ;
1682 if (frame_status & LAST_FRAG) {
1683 smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
1684 }
1685 }
1686 if (frame_status & LOC_TX) {
1687 DB_TX("LOC_TX: ",0,0,3) ;
1688 if (frame_status & FIRST_FRAG) {
1689 if(!(smc->os.hwm.tx_mb = smt_get_mbuf(smc))) {
1690 smc->hw.fp.err_stats.err_no_buf++ ;
1691 DB_TX("No SMbuf; transmit terminated",0,0,4) ;
1692 }
1693 else {
1694 smc->os.hwm.tx_data =
1695 smtod(smc->os.hwm.tx_mb,char *) - 1 ;
1696#ifdef USE_OS_CPY
1697#ifdef PASS_1ST_TXD_2_TX_COMP
1698 hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
1699 smc->os.hwm.tx_len) ;
1700#endif
1701#endif
1702 }
1703 }
1704 if (smc->os.hwm.tx_mb) {
1705#ifndef USE_OS_CPY
1706 DB_TX("copy fragment into MBuf ",0,0,3) ;
1707 memcpy(smc->os.hwm.tx_data,virt,len) ;
1708 smc->os.hwm.tx_data += len ;
1709#endif
1710 if (frame_status & LAST_FRAG) {
1711#ifdef USE_OS_CPY
1712#ifndef PASS_1ST_TXD_2_TX_COMP
1713
1714
1715
1716
1717
1718
1719
1720 hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
1721 smc->os.hwm.tx_len) ;
1722#endif
1723#endif
1724 smc->os.hwm.tx_data =
1725 smtod(smc->os.hwm.tx_mb,char *) - 1 ;
1726 *(char *)smc->os.hwm.tx_mb->sm_data =
1727 *smc->os.hwm.tx_data ;
1728 smc->os.hwm.tx_data++ ;
1729 smc->os.hwm.tx_mb->sm_len =
1730 smc->os.hwm.tx_len - 1 ;
1731 DB_TX("pass LLC frame to SMT ",0,0,3) ;
1732 smt_received_pack(smc,smc->os.hwm.tx_mb,
1733 RD_FS_LOCAL) ;
1734 }
1735 }
1736 }
1737 NDD_TRACE("THfE",t,queue->tx_free,0) ;
1738}
1739
1740
1741
1742
1743
1744static void queue_llc_rx(struct s_smc *smc, SMbuf *mb)
1745{
1746 DB_GEN("queue_llc_rx: mb = %x",(void *)mb,0,4) ;
1747 smc->os.hwm.queued_rx_frames++ ;
1748 mb->sm_next = (SMbuf *)NULL ;
1749 if (smc->os.hwm.llc_rx_pipe == NULL) {
1750 smc->os.hwm.llc_rx_pipe = mb ;
1751 }
1752 else {
1753 smc->os.hwm.llc_rx_tail->sm_next = mb ;
1754 }
1755 smc->os.hwm.llc_rx_tail = mb ;
1756
1757
1758
1759
1760 if (!smc->os.hwm.isr_flag) {
1761 smt_force_irq(smc) ;
1762 }
1763}
1764
1765
1766
1767
1768static SMbuf *get_llc_rx(struct s_smc *smc)
1769{
1770 SMbuf *mb ;
1771
1772 if ((mb = smc->os.hwm.llc_rx_pipe)) {
1773 smc->os.hwm.queued_rx_frames-- ;
1774 smc->os.hwm.llc_rx_pipe = mb->sm_next ;
1775 }
1776 DB_GEN("get_llc_rx: mb = 0x%x",(void *)mb,0,4) ;
1777 return(mb) ;
1778}
1779
1780
1781
1782
1783
1784static void queue_txd_mb(struct s_smc *smc, SMbuf *mb)
1785{
1786 DB_GEN("_rx: queue_txd_mb = %x",(void *)mb,0,4) ;
1787 smc->os.hwm.queued_txd_mb++ ;
1788 mb->sm_next = (SMbuf *)NULL ;
1789 if (smc->os.hwm.txd_tx_pipe == NULL) {
1790 smc->os.hwm.txd_tx_pipe = mb ;
1791 }
1792 else {
1793 smc->os.hwm.txd_tx_tail->sm_next = mb ;
1794 }
1795 smc->os.hwm.txd_tx_tail = mb ;
1796}
1797
1798
1799
1800
1801static SMbuf *get_txd_mb(struct s_smc *smc)
1802{
1803 SMbuf *mb ;
1804
1805 if ((mb = smc->os.hwm.txd_tx_pipe)) {
1806 smc->os.hwm.queued_txd_mb-- ;
1807 smc->os.hwm.txd_tx_pipe = mb->sm_next ;
1808 }
1809 DB_GEN("get_txd_mb: mb = 0x%x",(void *)mb,0,4) ;
1810 return(mb) ;
1811}
1812
1813
1814
1815
1816void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
1817{
1818 char far *data ;
1819 int len ;
1820 int n ;
1821 int i ;
1822 int frag_count ;
1823 int frame_status ;
1824 SK_LOC_DECL(char far,*virt[3]) ;
1825 int frag_len[3] ;
1826 struct s_smt_tx_queue *queue ;
1827 struct s_smt_fp_txd volatile *t ;
1828 u_long phys ;
1829 u_int tbctrl ;
1830
1831 NDD_TRACE("THSB",mb,fc,0) ;
1832 DB_TX("smt_send_mbuf: mb = 0x%x, fc = 0x%x",mb,fc,4) ;
1833
1834 mb->sm_off-- ;
1835 mb->sm_len++ ;
1836 data = smtod(mb,char *) ;
1837 *data = fc ;
1838 if (fc == FC_SMT_LOC)
1839 *data = FC_SMT_INFO ;
1840
1841
1842
1843
1844 frag_count = 0 ;
1845 len = mb->sm_len ;
1846 while (len) {
1847 n = SMT_PAGESIZE - ((long)data & (SMT_PAGESIZE-1)) ;
1848 if (n >= len) {
1849 n = len ;
1850 }
1851 DB_TX("frag: virt/len = 0x%x/%d ",(void *)data,n,5) ;
1852 virt[frag_count] = data ;
1853 frag_len[frag_count] = n ;
1854 frag_count++ ;
1855 len -= n ;
1856 data += n ;
1857 }
1858
1859
1860
1861
1862 queue = smc->hw.fp.tx[QUEUE_A0] ;
1863 if (fc == FC_BEACON || fc == FC_SMT_LOC) {
1864 frame_status = LOC_TX ;
1865 }
1866 else {
1867 frame_status = LAN_TX ;
1868 if ((smc->os.hwm.pass_NSA &&(fc == FC_SMT_NSA)) ||
1869 (smc->os.hwm.pass_SMT &&(fc == FC_SMT_INFO)))
1870 frame_status |= LOC_TX ;
1871 }
1872
1873 if (!smc->hw.mac_ring_is_up || frag_count > queue->tx_free) {
1874 frame_status &= ~LAN_TX;
1875 if (frame_status) {
1876 DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
1877 }
1878 else {
1879 DB_TX("Ring is down: terminate transmission",0,0,2) ;
1880 smt_free_mbuf(smc,mb) ;
1881 return ;
1882 }
1883 }
1884 DB_TX("frame_status = 0x%x ",frame_status,0,5) ;
1885
1886 if ((frame_status & LAN_TX) && (frame_status & LOC_TX)) {
1887 mb->sm_use_count = 2 ;
1888 }
1889
1890 if (frame_status & LAN_TX) {
1891 t = queue->tx_curr_put ;
1892 frame_status |= FIRST_FRAG ;
1893 for (i = 0; i < frag_count; i++) {
1894 DB_TX("init TxD = 0x%x",(void *)t,0,5) ;
1895 if (i == frag_count-1) {
1896 frame_status |= LAST_FRAG ;
1897 t->txd_txdscr = AIX_REVERSE(TX_DESCRIPTOR |
1898 (((u_long)(mb->sm_len-1)&3) << 27)) ;
1899 }
1900 t->txd_virt = virt[i] ;
1901 phys = dma_master(smc, (void far *)virt[i],
1902 frag_len[i], DMA_RD|SMT_BUF) ;
1903 t->txd_tbadr = AIX_REVERSE(phys) ;
1904 tbctrl = AIX_REVERSE((((u_long) frame_status &
1905 (FIRST_FRAG|LAST_FRAG)) << 26) |
1906 BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ;
1907 t->txd_tbctrl = tbctrl ;
1908#ifndef AIX
1909 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
1910 outpd(queue->tx_bmu_ctl,CSR_START) ;
1911#else
1912 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
1913 outpd(ADDR(B0_XA_CSR),CSR_START) ;
1914#endif
1915 frame_status &= ~FIRST_FRAG ;
1916 queue->tx_curr_put = t = t->txd_next ;
1917 queue->tx_free-- ;
1918 queue->tx_used++ ;
1919 }
1920 smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
1921 queue_txd_mb(smc,mb) ;
1922 }
1923
1924 if (frame_status & LOC_TX) {
1925 DB_TX("pass Mbuf to LLC queue",0,0,5) ;
1926 queue_llc_rx(smc,mb) ;
1927 }
1928
1929
1930
1931
1932
1933 mac_drv_clear_txd(smc) ;
1934 NDD_TRACE("THSE",t,queue->tx_free,frag_count) ;
1935}
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951static void mac_drv_clear_txd(struct s_smc *smc)
1952{
1953 struct s_smt_tx_queue *queue ;
1954 struct s_smt_fp_txd volatile *t1 ;
1955 struct s_smt_fp_txd volatile *t2 = NULL ;
1956 SMbuf *mb ;
1957 u_long tbctrl ;
1958 int i ;
1959 int frag_count ;
1960 int n ;
1961
1962 NDD_TRACE("THcB",0,0,0) ;
1963 for (i = QUEUE_S; i <= QUEUE_A0; i++) {
1964 queue = smc->hw.fp.tx[i] ;
1965 t1 = queue->tx_curr_get ;
1966 DB_TX("clear_txd: QUEUE = %d (0=sync/1=async)",i,0,5) ;
1967
1968 for ( ; ; ) {
1969 frag_count = 0 ;
1970
1971 do {
1972 DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ;
1973 DB_TX("check OWN/EOF bit of TxD 0x%x",t1,0,5) ;
1974 tbctrl = CR_READ(t1->txd_tbctrl) ;
1975 tbctrl = AIX_REVERSE(tbctrl) ;
1976
1977 if (tbctrl & BMU_OWN || !queue->tx_used){
1978 DB_TX("End of TxDs queue %d",i,0,4) ;
1979 goto free_next_queue ;
1980 }
1981 t1 = t1->txd_next ;
1982 frag_count++ ;
1983 } while (!(tbctrl & BMU_EOF)) ;
1984
1985 t1 = queue->tx_curr_get ;
1986 for (n = frag_count; n; n--) {
1987 tbctrl = AIX_REVERSE(t1->txd_tbctrl) ;
1988 dma_complete(smc,
1989 (union s_fp_descr volatile *) t1,
1990 (int) (DMA_RD |
1991 ((tbctrl & BMU_SMT_TX) >> 18))) ;
1992 t2 = t1 ;
1993 t1 = t1->txd_next ;
1994 }
1995
1996 if (tbctrl & BMU_SMT_TX) {
1997 mb = get_txd_mb(smc) ;
1998 smt_free_mbuf(smc,mb) ;
1999 }
2000 else {
2001#ifndef PASS_1ST_TXD_2_TX_COMP
2002 DB_TX("mac_drv_tx_comp for TxD 0x%x",t2,0,4) ;
2003 mac_drv_tx_complete(smc,t2) ;
2004#else
2005 DB_TX("mac_drv_tx_comp for TxD 0x%x",
2006 queue->tx_curr_get,0,4) ;
2007 mac_drv_tx_complete(smc,queue->tx_curr_get) ;
2008#endif
2009 }
2010 queue->tx_curr_get = t1 ;
2011 queue->tx_free += frag_count ;
2012 queue->tx_used -= frag_count ;
2013 }
2014free_next_queue: ;
2015 }
2016 NDD_TRACE("THcE",0,0,0) ;
2017}
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042void mac_drv_clear_tx_queue(struct s_smc *smc)
2043{
2044 struct s_smt_fp_txd volatile *t ;
2045 struct s_smt_tx_queue *queue ;
2046 int tx_used ;
2047 int i ;
2048
2049 if (smc->hw.hw_state != STOPPED) {
2050 SK_BREAK() ;
2051 SMT_PANIC(smc,HWM_E0011,HWM_E0011_MSG) ;
2052 return ;
2053 }
2054
2055 for (i = QUEUE_S; i <= QUEUE_A0; i++) {
2056 queue = smc->hw.fp.tx[i] ;
2057 DB_TX("clear_tx_queue: QUEUE = %d (0=sync/1=async)",i,0,5) ;
2058
2059
2060
2061
2062 t = queue->tx_curr_get ;
2063 tx_used = queue->tx_used ;
2064 while (tx_used) {
2065 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
2066 DB_TX("switch OWN bit of TxD 0x%x ",t,0,5) ;
2067 t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;
2068 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
2069 t = t->txd_next ;
2070 tx_used-- ;
2071 }
2072 }
2073
2074
2075
2076
2077 mac_drv_clear_txd(smc) ;
2078
2079 for (i = QUEUE_S; i <= QUEUE_A0; i++) {
2080 queue = smc->hw.fp.tx[i] ;
2081 t = queue->tx_curr_get ;
2082
2083
2084
2085
2086
2087
2088 if (i == QUEUE_S) {
2089 outpd(ADDR(B5_XS_DA),AIX_REVERSE(t->txd_ntdadr)) ;
2090 }
2091 else {
2092 outpd(ADDR(B5_XA_DA),AIX_REVERSE(t->txd_ntdadr)) ;
2093 }
2094
2095 queue->tx_curr_put = queue->tx_curr_get->txd_next ;
2096 queue->tx_curr_get = queue->tx_curr_put ;
2097 }
2098}
2099
2100
2101
2102
2103
2104
2105
2106
2107#ifdef DEBUG
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev)
2135{
2136 switch(flag) {
2137 case (int)NULL:
2138 DB_P.d_smtf = DB_P.d_smt = DB_P.d_ecm = DB_P.d_rmt = 0 ;
2139 DB_P.d_cfm = 0 ;
2140 DB_P.d_os.hwm_rx = DB_P.d_os.hwm_tx = DB_P.d_os.hwm_gen = 0 ;
2141#ifdef SBA
2142 DB_P.d_sba = 0 ;
2143#endif
2144#ifdef ESS
2145 DB_P.d_ess = 0 ;
2146#endif
2147 break ;
2148 case DEBUG_SMTF:
2149 DB_P.d_smtf = lev ;
2150 break ;
2151 case DEBUG_SMT:
2152 DB_P.d_smt = lev ;
2153 break ;
2154 case DEBUG_ECM:
2155 DB_P.d_ecm = lev ;
2156 break ;
2157 case DEBUG_RMT:
2158 DB_P.d_rmt = lev ;
2159 break ;
2160 case DEBUG_CFM:
2161 DB_P.d_cfm = lev ;
2162 break ;
2163 case DEBUG_PCM:
2164 DB_P.d_pcm = lev ;
2165 break ;
2166 case DEBUG_SBA:
2167#ifdef SBA
2168 DB_P.d_sba = lev ;
2169#endif
2170 break ;
2171 case DEBUG_ESS:
2172#ifdef ESS
2173 DB_P.d_ess = lev ;
2174#endif
2175 break ;
2176 case DB_HWM_RX:
2177 DB_P.d_os.hwm_rx = lev ;
2178 break ;
2179 case DB_HWM_TX:
2180 DB_P.d_os.hwm_tx = lev ;
2181 break ;
2182 case DB_HWM_GEN:
2183 DB_P.d_os.hwm_gen = lev ;
2184 break ;
2185 default:
2186 break ;
2187 }
2188}
2189#endif
2190