2171 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/******************************************************************************3 *4 * (C)Copyright 1998,1999 SysKonnect,5 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.6 *7 * See the file "skfddi.c" for further information.8 *9 * The information in this file is provided "AS IS" without warranty.10 *11 ******************************************************************************/12 13#define HWMTM14 15#ifndef FDDI16#define FDDI17#endif18 19#include "h/types.h"20#include "h/fddi.h"21#include "h/smc.h"22#include "h/supern_2.h"23#include "h/skfbiinc.h"24 25/*26 -------------------------------------------------------------27 DOCUMENTATION28 -------------------------------------------------------------29 BEGIN_MANUAL_ENTRY(DOCUMENTATION)30 31 T B D32 33 END_MANUAL_ENTRY34*/35/*36 -------------------------------------------------------------37 LOCAL VARIABLES:38 -------------------------------------------------------------39*/40#ifdef COMMON_MB_POOL41static SMbuf *mb_start;42static SMbuf *mb_free;43static int mb_init = FALSE ;44static int call_count;45#endif46 47/*48 -------------------------------------------------------------49 EXTERNE VARIABLES:50 -------------------------------------------------------------51*/52 53#ifdef DEBUG54#ifndef DEBUG_BRD55extern struct smt_debug debug ;56#endif57#endif58 59#ifdef NDIS_OS260extern u_char offDepth ;61extern u_char force_irq_pending ;62#endif63 64/*65 -------------------------------------------------------------66 LOCAL FUNCTIONS:67 -------------------------------------------------------------68*/69 70static void queue_llc_rx(struct s_smc *smc, SMbuf *mb);71static void smt_to_llc(struct s_smc *smc, SMbuf *mb);72static void init_txd_ring(struct s_smc *smc);73static void init_rxd_ring(struct s_smc *smc);74static void queue_txd_mb(struct s_smc *smc, SMbuf *mb);75static u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start,76 int count);77static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue);78static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue);79static SMbuf* get_llc_rx(struct s_smc *smc);80static SMbuf* get_txd_mb(struct s_smc *smc);81static void mac_drv_clear_txd(struct s_smc *smc);82 83/*84 -------------------------------------------------------------85 EXTERNAL FUNCTIONS:86 -------------------------------------------------------------87*/88/* The external SMT functions are listed in cmtdef.h */89 90extern void* mac_drv_get_space(struct s_smc *smc, unsigned int size);91extern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size);92extern void mac_drv_fill_rxd(struct s_smc *smc);93extern void mac_drv_tx_complete(struct s_smc *smc,94 volatile struct s_smt_fp_txd *txd);95extern void mac_drv_rx_complete(struct s_smc *smc,96 volatile struct s_smt_fp_rxd *rxd,97 int frag_count, int len);98extern void mac_drv_requeue_rxd(struct s_smc *smc, 99 volatile struct s_smt_fp_rxd *rxd,100 int frag_count);101extern void mac_drv_clear_rxd(struct s_smc *smc,102 volatile struct s_smt_fp_rxd *rxd, int frag_count);103 104#ifdef USE_OS_CPY105extern void hwm_cpy_rxd2mb(void);106extern void hwm_cpy_txd2mb(void);107#endif108 109#ifdef ALL_RX_COMPLETE110extern void mac_drv_all_receives_complete(void);111#endif112 113extern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt);114extern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag);115 116#ifdef NDIS_OS2117extern void post_proc(void);118#else119extern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,120 int flag);121#endif122 123extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,124 int la_len);125 126/*127 -------------------------------------------------------------128 PUBLIC FUNCTIONS:129 -------------------------------------------------------------130*/131void process_receive(struct s_smc *smc);132void fddi_isr(struct s_smc *smc);133void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);134void init_driver_fplus(struct s_smc *smc);135void mac_drv_rx_mode(struct s_smc *smc, int mode);136void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);137void mac_drv_clear_tx_queue(struct s_smc *smc);138void mac_drv_clear_rx_queue(struct s_smc *smc);139void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,140 int frame_status);141void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,142 int frame_status);143 144int mac_drv_init(struct s_smc *smc);145int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,146 int frame_status);147 148u_int mac_drv_check_space(void);149 150SMbuf* smt_get_mbuf(struct s_smc *smc);151 152#ifdef DEBUG153 void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev);154#endif155 156/*157 -------------------------------------------------------------158 MACROS:159 -------------------------------------------------------------160*/161#ifndef UNUSED162#ifdef lint163#define UNUSED(x) (x) = (x)164#else165#define UNUSED(x)166#endif167#endif168 169#ifdef USE_CAN_ADDR170#define MA smc->hw.fddi_canon_addr.a171#define GROUP_ADDR_BIT 0x01172#else173#define MA smc->hw.fddi_home_addr.a174#define GROUP_ADDR_BIT 0x80175#endif176 177#define RXD_TXD_COUNT (HWM_ASYNC_TXD_COUNT+HWM_SYNC_TXD_COUNT+\178 SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT)179 180#ifdef MB_OUTSIDE_SMC181#define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd) +\182 MAX_MBUF*sizeof(SMbuf))183#define EXT_VIRT_MEM_2 ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))184#else185#define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))186#endif187 188 /*189 * define critical read for 16 Bit drivers190 */191#if defined(NDIS_OS2) || defined(ODI2)192#define CR_READ(var) ((var) & 0xffff0000 | ((var) & 0xffff))193#else194#define CR_READ(var) (__le32)(var)195#endif196 197#define IMASK_SLOW (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \198 IS_MINTR1 | IS_MINTR2 | IS_MINTR3 | IS_R1_P | \199 IS_R1_C | IS_XA_C | IS_XS_C)200 201/*202 -------------------------------------------------------------203 INIT- AND SMT FUNCTIONS:204 -------------------------------------------------------------205*/206 207 208/*209 * BEGIN_MANUAL_ENTRY(mac_drv_check_space)210 * u_int mac_drv_check_space()211 *212 * function DOWNCALL (drvsr.c)213 * This function calculates the needed non virtual214 * memory for MBufs, RxD and TxD descriptors etc.215 * needed by the driver.216 *217 * return u_int memory in bytes218 *219 * END_MANUAL_ENTRY220 */221u_int mac_drv_check_space(void)222{223#ifdef MB_OUTSIDE_SMC224#ifdef COMMON_MB_POOL225 call_count++ ;226 if (call_count == 1) {227 return EXT_VIRT_MEM;228 }229 else {230 return EXT_VIRT_MEM_2;231 }232#else233 return EXT_VIRT_MEM;234#endif235#else236 return 0;237#endif238}239 240/*241 * BEGIN_MANUAL_ENTRY(mac_drv_init)242 * void mac_drv_init(smc)243 *244 * function DOWNCALL (drvsr.c)245 * In this function the hardware module allocates it's246 * memory.247 * The operating system dependent module should call248 * mac_drv_init once, after the adatper is detected.249 * END_MANUAL_ENTRY250 */251int mac_drv_init(struct s_smc *smc)252{253 if (sizeof(struct s_smt_fp_rxd) % 16) {254 SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ;255 }256 if (sizeof(struct s_smt_fp_txd) % 16) {257 SMT_PANIC(smc,HWM_E0002,HWM_E0002_MSG) ;258 }259 260 /*261 * get the required memory for the RxDs and TxDs262 */263 if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *)264 mac_drv_get_desc_mem(smc,(u_int)265 (RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) {266 return 1; /* no space the hwm modul can't work */267 }268 269 /*270 * get the memory for the SMT MBufs271 */272#ifndef MB_OUTSIDE_SMC273 smc->os.hwm.mbuf_pool.mb_start=(SMbuf *)(&smc->os.hwm.mbuf_pool.mb[0]) ;274#else275#ifndef COMMON_MB_POOL276 if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc,277 MAX_MBUF*sizeof(SMbuf)))) {278 return 1; /* no space the hwm modul can't work */279 }280#else281 if (!mb_start) {282 if (!(mb_start = (SMbuf *) mac_drv_get_space(smc,283 MAX_MBUF*sizeof(SMbuf)))) {284 return 1; /* no space the hwm modul can't work */285 }286 }287#endif288#endif289 return 0;290}291 292/*293 * BEGIN_MANUAL_ENTRY(init_driver_fplus)294 * init_driver_fplus(smc)295 *296 * Sets hardware modul specific values for the mode register 2297 * (e.g. the byte alignment for the received frames, the position of the298 * least significant byte etc.)299 * END_MANUAL_ENTRY300 */301void init_driver_fplus(struct s_smc *smc)302{303 smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ;304 305#ifdef PCI306 smc->hw.fp.mdr2init |= FM_CHKPAR | FM_PARITY ;307#endif308 smc->hw.fp.mdr3init = FM_MENRQAUNLCK | FM_MENRS ;309 310#ifdef USE_CAN_ADDR311 /* enable address bit swapping */312 smc->hw.fp.frselreg_init = FM_ENXMTADSWAP | FM_ENRCVADSWAP ;313#endif314}315 316static u_long init_descr_ring(struct s_smc *smc,317 union s_fp_descr volatile *start,318 int count)319{320 int i ;321 union s_fp_descr volatile *d1 ;322 union s_fp_descr volatile *d2 ;323 u_long phys ;324 325 DB_GEN(3, "descr ring starts at = %p", start);326 for (i=count-1, d1=start; i ; i--) {327 d2 = d1 ;328 d1++ ; /* descr is owned by the host */329 d2->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;330 d2->r.rxd_next = &d1->r ;331 phys = mac_drv_virt2phys(smc,(void *)d1) ;332 d2->r.rxd_nrdadr = cpu_to_le32(phys) ;333 }334 DB_GEN(3, "descr ring ends at = %p", d1);335 d1->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;336 d1->r.rxd_next = &start->r ;337 phys = mac_drv_virt2phys(smc,(void *)start) ;338 d1->r.rxd_nrdadr = cpu_to_le32(phys) ;339 340 for (i=count, d1=start; i ; i--) {341 DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;342 d1++;343 }344 return phys;345}346 347static void init_txd_ring(struct s_smc *smc)348{349 struct s_smt_fp_txd volatile *ds ;350 struct s_smt_tx_queue *queue ;351 u_long phys ;352 353 /*354 * initialize the transmit descriptors355 */356 ds = (struct s_smt_fp_txd volatile *) ((char *)smc->os.hwm.descr_p +357 SMT_R1_RXD_COUNT*sizeof(struct s_smt_fp_rxd)) ;358 queue = smc->hw.fp.tx[QUEUE_A0] ;359 DB_GEN(3, "Init async TxD ring, %d TxDs", HWM_ASYNC_TXD_COUNT);360 (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,361 HWM_ASYNC_TXD_COUNT) ;362 phys = le32_to_cpu(ds->txd_ntdadr) ;363 ds++ ;364 queue->tx_curr_put = queue->tx_curr_get = ds ;365 ds-- ;366 queue->tx_free = HWM_ASYNC_TXD_COUNT ;367 queue->tx_used = 0 ;368 outpd(ADDR(B5_XA_DA),phys) ;369 370 ds = (struct s_smt_fp_txd volatile *) ((char *)ds +371 HWM_ASYNC_TXD_COUNT*sizeof(struct s_smt_fp_txd)) ;372 queue = smc->hw.fp.tx[QUEUE_S] ;373 DB_GEN(3, "Init sync TxD ring, %d TxDs", HWM_SYNC_TXD_COUNT);374 (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,375 HWM_SYNC_TXD_COUNT) ;376 phys = le32_to_cpu(ds->txd_ntdadr) ;377 ds++ ;378 queue->tx_curr_put = queue->tx_curr_get = ds ;379 queue->tx_free = HWM_SYNC_TXD_COUNT ;380 queue->tx_used = 0 ;381 outpd(ADDR(B5_XS_DA),phys) ;382}383 384static void init_rxd_ring(struct s_smc *smc)385{386 struct s_smt_fp_rxd volatile *ds ;387 struct s_smt_rx_queue *queue ;388 u_long phys ;389 390 /*391 * initialize the receive descriptors392 */393 ds = (struct s_smt_fp_rxd volatile *) smc->os.hwm.descr_p ;394 queue = smc->hw.fp.rx[QUEUE_R1] ;395 DB_GEN(3, "Init RxD ring, %d RxDs", SMT_R1_RXD_COUNT);396 (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,397 SMT_R1_RXD_COUNT) ;398 phys = le32_to_cpu(ds->rxd_nrdadr) ;399 ds++ ;400 queue->rx_curr_put = queue->rx_curr_get = ds ;401 queue->rx_free = SMT_R1_RXD_COUNT ;402 queue->rx_used = 0 ;403 outpd(ADDR(B4_R1_DA),phys) ;404}405 406/*407 * BEGIN_MANUAL_ENTRY(init_fddi_driver)408 * void init_fddi_driver(smc,mac_addr)409 *410 * initializes the driver and it's variables411 *412 * END_MANUAL_ENTRY413 */414void init_fddi_driver(struct s_smc *smc, u_char *mac_addr)415{416 SMbuf *mb ;417 int i ;418 419 init_board(smc,mac_addr) ;420 (void)init_fplus(smc) ;421 422 /*423 * initialize the SMbufs for the SMT424 */425#ifndef COMMON_MB_POOL426 mb = smc->os.hwm.mbuf_pool.mb_start ;427 smc->os.hwm.mbuf_pool.mb_free = (SMbuf *)NULL ;428 for (i = 0; i < MAX_MBUF; i++) {429 mb->sm_use_count = 1 ;430 smt_free_mbuf(smc,mb) ;431 mb++ ;432 }433#else434 mb = mb_start ;435 if (!mb_init) {436 mb_free = 0 ;437 for (i = 0; i < MAX_MBUF; i++) {438 mb->sm_use_count = 1 ;439 smt_free_mbuf(smc,mb) ;440 mb++ ;441 }442 mb_init = TRUE ;443 }444#endif445 446 /*447 * initialize the other variables448 */449 smc->os.hwm.llc_rx_pipe = smc->os.hwm.llc_rx_tail = (SMbuf *)NULL ;450 smc->os.hwm.txd_tx_pipe = smc->os.hwm.txd_tx_tail = NULL ;451 smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = smc->os.hwm.pass_DB = 0 ;452 smc->os.hwm.pass_llc_promisc = TRUE ;453 smc->os.hwm.queued_rx_frames = smc->os.hwm.queued_txd_mb = 0 ;454 smc->os.hwm.detec_count = 0 ;455 smc->os.hwm.rx_break = 0 ;456 smc->os.hwm.rx_len_error = 0 ;457 smc->os.hwm.isr_flag = FALSE ;458 459 /*460 * make sure that the start pointer is 16 byte aligned461 */462 i = 16 - ((long)smc->os.hwm.descr_p & 0xf) ;463 if (i != 16) {464 DB_GEN(3, "i = %d", i);465 smc->os.hwm.descr_p = (union s_fp_descr volatile *)466 ((char *)smc->os.hwm.descr_p+i) ;467 }468 DB_GEN(3, "pt to descr area = %p", smc->os.hwm.descr_p);469 470 init_txd_ring(smc) ;471 init_rxd_ring(smc) ;472 mac_drv_fill_rxd(smc) ;473 474 init_plc(smc) ;475}476 477 478SMbuf *smt_get_mbuf(struct s_smc *smc)479{480 register SMbuf *mb ;481 482#ifndef COMMON_MB_POOL483 mb = smc->os.hwm.mbuf_pool.mb_free ;484#else485 mb = mb_free ;486#endif487 if (mb) {488#ifndef COMMON_MB_POOL489 smc->os.hwm.mbuf_pool.mb_free = mb->sm_next ;490#else491 mb_free = mb->sm_next ;492#endif493 mb->sm_off = 8 ;494 mb->sm_use_count = 1 ;495 }496 DB_GEN(3, "get SMbuf: mb = %p", mb);497 return mb; /* May be NULL */498}499 500void smt_free_mbuf(struct s_smc *smc, SMbuf *mb)501{502 503 if (mb) {504 mb->sm_use_count-- ;505 DB_GEN(3, "free_mbuf: sm_use_count = %d", mb->sm_use_count);506 /*507 * If the use_count is != zero the MBuf is queued508 * more than once and must not queued into the509 * free MBuf queue510 */511 if (!mb->sm_use_count) {512 DB_GEN(3, "free SMbuf: mb = %p", mb);513#ifndef COMMON_MB_POOL514 mb->sm_next = smc->os.hwm.mbuf_pool.mb_free ;515 smc->os.hwm.mbuf_pool.mb_free = mb ;516#else517 mb->sm_next = mb_free ;518 mb_free = mb ;519#endif520 }521 }522 else523 SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ;524}525 526 527/*528 * BEGIN_MANUAL_ENTRY(mac_drv_repair_descr)529 * void mac_drv_repair_descr(smc)530 *531 * function called from SMT (HWM / hwmtm.c)532 * The BMU is idle when this function is called.533 * Mac_drv_repair_descr sets up the physical address534 * for all receive and transmit queues where the BMU535 * should continue.536 * It may be that the BMU was reseted during a fragmented537 * transfer. In this case there are some fragments which will538 * never completed by the BMU. The OWN bit of this fragments539 * must be switched to be owned by the host.540 *541 * Give a start command to the receive BMU.542 * Start the transmit BMUs if transmit frames pending.543 *544 * END_MANUAL_ENTRY545 */546void mac_drv_repair_descr(struct s_smc *smc)547{548 u_long phys ;549 550 if (smc->hw.hw_state != STOPPED) {551 SK_BREAK() ;552 SMT_PANIC(smc,HWM_E0013,HWM_E0013_MSG) ;553 return ;554 }555 556 /*557 * repair tx queues: don't start558 */559 phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_A0]) ;560 outpd(ADDR(B5_XA_DA),phys) ;561 if (smc->hw.fp.tx_q[QUEUE_A0].tx_used) {562 outpd(ADDR(B0_XA_CSR),CSR_START) ;563 }564 phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_S]) ;565 outpd(ADDR(B5_XS_DA),phys) ;566 if (smc->hw.fp.tx_q[QUEUE_S].tx_used) {567 outpd(ADDR(B0_XS_CSR),CSR_START) ;568 }569 570 /*571 * repair rx queues572 */573 phys = repair_rxd_ring(smc,smc->hw.fp.rx[QUEUE_R1]) ;574 outpd(ADDR(B4_R1_DA),phys) ;575 outpd(ADDR(B0_R1_CSR),CSR_START) ;576}577 578static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)579{580 int i ;581 int tx_used ;582 u_long phys ;583 u_long tbctrl ;584 struct s_smt_fp_txd volatile *t ;585 586 SK_UNUSED(smc) ;587 588 t = queue->tx_curr_get ;589 tx_used = queue->tx_used ;590 for (i = tx_used+queue->tx_free-1 ; i ; i-- ) {591 t = t->txd_next ;592 }593 phys = le32_to_cpu(t->txd_ntdadr) ;594 595 t = queue->tx_curr_get ;596 while (tx_used) {597 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;598 tbctrl = le32_to_cpu(t->txd_tbctrl) ;599 600 if (tbctrl & BMU_OWN) {601 if (tbctrl & BMU_STF) {602 break ; /* exit the loop */603 }604 else {605 /*606 * repair the descriptor607 */608 t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;609 }610 }611 phys = le32_to_cpu(t->txd_ntdadr) ;612 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;613 t = t->txd_next ;614 tx_used-- ;615 }616 return phys;617}618 619/*620 * Repairs the receive descriptor ring and returns the physical address621 * where the BMU should continue working.622 *623 * o The physical address where the BMU was stopped has to be624 * determined. This is the next RxD after rx_curr_get with an OWN625 * bit set.626 * o The BMU should start working at beginning of the next frame.627 * RxDs with an OWN bit set but with a reset STF bit should be628 * skipped and owned by the driver (OWN = 0). 629 */630static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)631{632 int i ;633 int rx_used ;634 u_long phys ;635 u_long rbctrl ;636 struct s_smt_fp_rxd volatile *r ;637 638 SK_UNUSED(smc) ;639 640 r = queue->rx_curr_get ;641 rx_used = queue->rx_used ;642 for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) {643 r = r->rxd_next ;644 }645 phys = le32_to_cpu(r->rxd_nrdadr) ;646 647 r = queue->rx_curr_get ;648 while (rx_used) {649 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;650 rbctrl = le32_to_cpu(r->rxd_rbctrl) ;651 652 if (rbctrl & BMU_OWN) {653 if (rbctrl & BMU_STF) {654 break ; /* exit the loop */655 }656 else {657 /*658 * repair the descriptor659 */660 r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;661 }662 }663 phys = le32_to_cpu(r->rxd_nrdadr) ;664 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;665 r = r->rxd_next ;666 rx_used-- ;667 }668 return phys;669}670 671 672/*673 -------------------------------------------------------------674 INTERRUPT SERVICE ROUTINE:675 -------------------------------------------------------------676*/677 678/*679 * BEGIN_MANUAL_ENTRY(fddi_isr)680 * void fddi_isr(smc)681 *682 * function DOWNCALL (drvsr.c)683 * interrupt service routine, handles the interrupt requests684 * generated by the FDDI adapter.685 *686 * NOTE: The operating system dependent module must guarantee that the687 * interrupts of the adapter are disabled when it calls fddi_isr.688 *689 * About the USE_BREAK_ISR mechanismn:690 *691 * The main requirement of this mechanismn is to force an timer IRQ when692 * leaving process_receive() with leave_isr set. process_receive() may693 * be called at any time from anywhere!694 * To be sure we don't miss such event we set 'force_irq' per default.695 * We have to force and Timer IRQ if 'smc->os.hwm.leave_isr' AND696 * 'force_irq' are set. 'force_irq' may be reset if a receive complete697 * IRQ is pending.698 *699 * END_MANUAL_ENTRY700 */701void fddi_isr(struct s_smc *smc)702{703 u_long is ; /* ISR source */704 u_short stu, stl ;705 SMbuf *mb ;706 707#ifdef USE_BREAK_ISR708 int force_irq ;709#endif710 711#ifdef ODI2712 if (smc->os.hwm.rx_break) {713 mac_drv_fill_rxd(smc) ;714 if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) {715 smc->os.hwm.rx_break = 0 ;716 process_receive(smc) ;717 }718 else {719 smc->os.hwm.detec_count = 0 ;720 smt_force_irq(smc) ;721 }722 }723#endif724 smc->os.hwm.isr_flag = TRUE ;725 726#ifdef USE_BREAK_ISR727 force_irq = TRUE ;728 if (smc->os.hwm.leave_isr) {729 smc->os.hwm.leave_isr = FALSE ;730 process_receive(smc) ;731 }732#endif733 734 while ((is = GET_ISR() & ISR_MASK)) {735 NDD_TRACE("CH0B",is,0,0) ;736 DB_GEN(7, "ISA = 0x%lx", is);737 738 if (is & IMASK_SLOW) {739 NDD_TRACE("CH1b",is,0,0) ;740 if (is & IS_PLINT1) { /* PLC1 */741 plc1_irq(smc) ;742 }743 if (is & IS_PLINT2) { /* PLC2 */744 plc2_irq(smc) ;745 }746 if (is & IS_MINTR1) { /* FORMAC+ STU1(U/L) */747 stu = inpw(FM_A(FM_ST1U)) ;748 stl = inpw(FM_A(FM_ST1L)) ;749 DB_GEN(6, "Slow transmit complete");750 mac1_irq(smc,stu,stl) ;751 }752 if (is & IS_MINTR2) { /* FORMAC+ STU2(U/L) */753 stu= inpw(FM_A(FM_ST2U)) ;754 stl= inpw(FM_A(FM_ST2L)) ;755 DB_GEN(6, "Slow receive complete");756 DB_GEN(7, "stl = %x : stu = %x", stl, stu);757 mac2_irq(smc,stu,stl) ;758 }759 if (is & IS_MINTR3) { /* FORMAC+ STU3(U/L) */760 stu= inpw(FM_A(FM_ST3U)) ;761 stl= inpw(FM_A(FM_ST3L)) ;762 DB_GEN(6, "FORMAC Mode Register 3");763 mac3_irq(smc,stu,stl) ;764 }765 if (is & IS_TIMINT) { /* Timer 82C54-2 */766 timer_irq(smc) ;767#ifdef NDIS_OS2768 force_irq_pending = 0 ;769#endif770 /*771 * out of RxD detection772 */773 if (++smc->os.hwm.detec_count > 4) {774 /*775 * check out of RxD condition776 */777 process_receive(smc) ;778 }779 }780 if (is & IS_TOKEN) { /* Restricted Token Monitor */781 rtm_irq(smc) ;782 }783 if (is & IS_R1_P) { /* Parity error rx queue 1 */784 /* clear IRQ */785 outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ;786 SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ;787 }788 if (is & IS_R1_C) { /* Encoding error rx queue 1 */789 /* clear IRQ */790 outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ;791 SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ;792 }793 if (is & IS_XA_C) { /* Encoding error async tx q */794 /* clear IRQ */795 outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ;796 SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ;797 }798 if (is & IS_XS_C) { /* Encoding error sync tx q */799 /* clear IRQ */800 outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ;801 SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ;802 }803 }804 805 /*806 * Fast Tx complete Async/Sync Queue (BMU service)807 */808 if (is & (IS_XS_F|IS_XA_F)) {809 DB_GEN(6, "Fast tx complete queue");810 /*811 * clear IRQ, Note: no IRQ is lost, because812 * we always service both queues813 */814 outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ;815 outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ;816 mac_drv_clear_txd(smc) ;817 llc_restart_tx(smc) ;818 }819 820 /*821 * Fast Rx Complete (BMU service)822 */823 if (is & IS_R1_F) {824 DB_GEN(6, "Fast receive complete");825 /* clear IRQ */826#ifndef USE_BREAK_ISR827 outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;828 process_receive(smc) ;829#else830 process_receive(smc) ;831 if (smc->os.hwm.leave_isr) {832 force_irq = FALSE ;833 } else {834 outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;835 process_receive(smc) ;836 }837#endif838 }839 840#ifndef NDIS_OS2841 while ((mb = get_llc_rx(smc))) {842 smt_to_llc(smc,mb) ;843 }844#else845 if (offDepth)846 post_proc() ;847 848 while (!offDepth && (mb = get_llc_rx(smc))) {849 smt_to_llc(smc,mb) ;850 }851 852 if (!offDepth && smc->os.hwm.rx_break) {853 process_receive(smc) ;854 }855#endif856 if (smc->q.ev_get != smc->q.ev_put) {857 NDD_TRACE("CH2a",0,0,0) ;858 ev_dispatcher(smc) ;859 }860#ifdef NDIS_OS2861 post_proc() ;862 if (offDepth) { /* leave fddi_isr because */863 break ; /* indications not allowed */864 }865#endif866#ifdef USE_BREAK_ISR867 if (smc->os.hwm.leave_isr) {868 break ; /* leave fddi_isr */869 }870#endif871 872 /* NOTE: when the isr is left, no rx is pending */873 } /* end of interrupt source polling loop */874 875#ifdef USE_BREAK_ISR876 if (smc->os.hwm.leave_isr && force_irq) {877 smt_force_irq(smc) ;878 }879#endif880 smc->os.hwm.isr_flag = FALSE ;881 NDD_TRACE("CH0E",0,0,0) ;882}883 884 885/*886 -------------------------------------------------------------887 RECEIVE FUNCTIONS:888 -------------------------------------------------------------889*/890 891#ifndef NDIS_OS2892/*893 * BEGIN_MANUAL_ENTRY(mac_drv_rx_mode)894 * void mac_drv_rx_mode(smc,mode)895 *896 * function DOWNCALL (fplus.c)897 * Corresponding to the parameter mode, the operating system898 * dependent module can activate several receive modes.899 *900 * para mode = 1: RX_ENABLE_ALLMULTI enable all multicasts901 * = 2: RX_DISABLE_ALLMULTI disable "enable all multicasts"902 * = 3: RX_ENABLE_PROMISC enable promiscuous903 * = 4: RX_DISABLE_PROMISC disable promiscuous904 * = 5: RX_ENABLE_NSA enable rec. of all NSA frames905 * (disabled after 'driver reset' & 'set station address')906 * = 6: RX_DISABLE_NSA disable rec. of all NSA frames907 *908 * = 21: RX_ENABLE_PASS_SMT ( see description )909 * = 22: RX_DISABLE_PASS_SMT ( " " )910 * = 23: RX_ENABLE_PASS_NSA ( " " )911 * = 24: RX_DISABLE_PASS_NSA ( " " )912 * = 25: RX_ENABLE_PASS_DB ( " " )913 * = 26: RX_DISABLE_PASS_DB ( " " )914 * = 27: RX_DISABLE_PASS_ALL ( " " )915 * = 28: RX_DISABLE_LLC_PROMISC ( " " )916 * = 29: RX_ENABLE_LLC_PROMISC ( " " )917 *918 *919 * RX_ENABLE_PASS_SMT / RX_DISABLE_PASS_SMT920 *921 * If the operating system dependent module activates the922 * mode RX_ENABLE_PASS_SMT, the hardware module923 * duplicates all SMT frames with the frame control924 * FC_SMT_INFO and passes them to the LLC receive channel925 * by calling mac_drv_rx_init.926 * The SMT Frames which are sent by the local SMT and the NSA927 * frames whose A- and C-Indicator is not set are also duplicated928 * and passed.929 * The receive mode RX_DISABLE_PASS_SMT disables the passing930 * of SMT frames.931 *932 * RX_ENABLE_PASS_NSA / RX_DISABLE_PASS_NSA933 *934 * If the operating system dependent module activates the935 * mode RX_ENABLE_PASS_NSA, the hardware module936 * duplicates all NSA frames with frame control FC_SMT_NSA937 * and a set A-Indicator and passed them to the LLC938 * receive channel by calling mac_drv_rx_init.939 * All NSA Frames which are sent by the local SMT940 * are also duplicated and passed.941 * The receive mode RX_DISABLE_PASS_NSA disables the passing942 * of NSA frames with the A- or C-Indicator set.943 *944 * NOTE: For fear that the hardware module receives NSA frames with945 * a reset A-Indicator, the operating system dependent module946 * has to call mac_drv_rx_mode with the mode RX_ENABLE_NSA947 * before activate the RX_ENABLE_PASS_NSA mode and after every948 * 'driver reset' and 'set station address'.949 *950 * RX_ENABLE_PASS_DB / RX_DISABLE_PASS_DB951 *952 * If the operating system dependent module activates the953 * mode RX_ENABLE_PASS_DB, direct BEACON frames954 * (FC_BEACON frame control) are passed to the LLC receive955 * channel by mac_drv_rx_init.956 * The receive mode RX_DISABLE_PASS_DB disables the passing957 * of direct BEACON frames.958 *959 * RX_DISABLE_PASS_ALL960 *961 * Disables all special receives modes. It is equal to962 * call mac_drv_set_rx_mode successively with the963 * parameters RX_DISABLE_NSA, RX_DISABLE_PASS_SMT,964 * RX_DISABLE_PASS_NSA and RX_DISABLE_PASS_DB.965 *966 * RX_ENABLE_LLC_PROMISC967 *968 * (default) all received LLC frames and all SMT/NSA/DBEACON969 * frames depending on the attitude of the flags970 * PASS_SMT/PASS_NSA/PASS_DBEACON will be delivered to the971 * LLC layer972 *973 * RX_DISABLE_LLC_PROMISC974 *975 * all received SMT/NSA/DBEACON frames depending on the976 * attitude of the flags PASS_SMT/PASS_NSA/PASS_DBEACON977 * will be delivered to the LLC layer.978 * all received LLC frames with a directed address, Multicast979 * or Broadcast address will be delivered to the LLC980 * layer too.981 *982 * END_MANUAL_ENTRY983 */984void mac_drv_rx_mode(struct s_smc *smc, int mode)985{986 switch(mode) {987 case RX_ENABLE_PASS_SMT:988 smc->os.hwm.pass_SMT = TRUE ;989 break ;990 case RX_DISABLE_PASS_SMT:991 smc->os.hwm.pass_SMT = FALSE ;992 break ;993 case RX_ENABLE_PASS_NSA:994 smc->os.hwm.pass_NSA = TRUE ;995 break ;996 case RX_DISABLE_PASS_NSA:997 smc->os.hwm.pass_NSA = FALSE ;998 break ;999 case RX_ENABLE_PASS_DB:1000 smc->os.hwm.pass_DB = TRUE ;1001 break ;1002 case RX_DISABLE_PASS_DB:1003 smc->os.hwm.pass_DB = FALSE ;1004 break ;1005 case RX_DISABLE_PASS_ALL:1006 smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = FALSE ;1007 smc->os.hwm.pass_DB = FALSE ;1008 smc->os.hwm.pass_llc_promisc = TRUE ;1009 mac_set_rx_mode(smc,RX_DISABLE_NSA) ;1010 break ;1011 case RX_DISABLE_LLC_PROMISC:1012 smc->os.hwm.pass_llc_promisc = FALSE ;1013 break ;1014 case RX_ENABLE_LLC_PROMISC:1015 smc->os.hwm.pass_llc_promisc = TRUE ;1016 break ;1017 case RX_ENABLE_ALLMULTI:1018 case RX_DISABLE_ALLMULTI:1019 case RX_ENABLE_PROMISC:1020 case RX_DISABLE_PROMISC:1021 case RX_ENABLE_NSA:1022 case RX_DISABLE_NSA:1023 default:1024 mac_set_rx_mode(smc,mode) ;1025 break ;1026 }1027}1028#endif /* ifndef NDIS_OS2 */1029 1030/*1031 * process receive queue1032 */1033void process_receive(struct s_smc *smc)1034{1035 int i ;1036 int n ;1037 int frag_count ; /* number of RxDs of the curr rx buf */1038 int used_frags ; /* number of RxDs of the curr frame */1039 struct s_smt_rx_queue *queue ; /* points to the queue ctl struct */1040 struct s_smt_fp_rxd volatile *r ; /* rxd pointer */1041 struct s_smt_fp_rxd volatile *rxd ; /* first rxd of rx frame */1042 u_long rbctrl ; /* receive buffer control word */1043 u_long rfsw ; /* receive frame status word */1044 u_short rx_used ;1045 u_char far *virt ;1046 char far *data ;1047 SMbuf *mb ;1048 u_char fc ; /* Frame control */1049 int len ; /* Frame length */1050 1051 smc->os.hwm.detec_count = 0 ;1052 queue = smc->hw.fp.rx[QUEUE_R1] ;1053 NDD_TRACE("RHxB",0,0,0) ;1054 for ( ; ; ) {1055 r = queue->rx_curr_get ;1056 rx_used = queue->rx_used ;1057 frag_count = 0 ;1058 1059#ifdef USE_BREAK_ISR1060 if (smc->os.hwm.leave_isr) {1061 goto rx_end ;1062 }1063#endif1064#ifdef NDIS_OS21065 if (offDepth) {1066 smc->os.hwm.rx_break = 1 ;1067 goto rx_end ;1068 }1069 smc->os.hwm.rx_break = 0 ;1070#endif1071#ifdef ODI21072 if (smc->os.hwm.rx_break) {1073 goto rx_end ;1074 }1075#endif1076 n = 0 ;1077 do {1078 DB_RX(5, "Check RxD %p for OWN and EOF", r);1079 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;1080 rbctrl = le32_to_cpu(CR_READ(r->rxd_rbctrl));1081 1082 if (rbctrl & BMU_OWN) {1083 NDD_TRACE("RHxE",r,rfsw,rbctrl) ;1084 DB_RX(4, "End of RxDs");1085 goto rx_end ;1086 }1087 /*1088 * out of RxD detection1089 */1090 if (!rx_used) {1091 SK_BREAK() ;1092 SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ;1093 /* Either we don't have an RxD or all1094 * RxDs are filled. Therefore it's allowed1095 * for to set the STOPPED flag */1096 smc->hw.hw_state = STOPPED ;1097 mac_drv_clear_rx_queue(smc) ;1098 smc->hw.hw_state = STARTED ;1099 mac_drv_fill_rxd(smc) ;1100 smc->os.hwm.detec_count = 0 ;1101 goto rx_end ;1102 }1103 rfsw = le32_to_cpu(r->rxd_rfsw) ;1104 if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {1105 /*1106 * The BMU_STF bit is deleted, 1 frame is1107 * placed into more than 1 rx buffer1108 *1109 * skip frame by setting the rx len to 01110 *1111 * if fragment count == 01112 * The missing STF bit belongs to the1113 * current frame, search for the1114 * EOF bit to complete the frame1115 * else1116 * the fragment belongs to the next frame,1117 * exit the loop and process the frame1118 */1119 SK_BREAK() ;1120 rfsw = 0 ;1121 if (frag_count) {1122 break ;1123 }1124 }1125 n += rbctrl & 0xffff ;1126 r = r->rxd_next ;1127 frag_count++ ;1128 rx_used-- ;1129 } while (!(rbctrl & BMU_EOF)) ;1130 used_frags = frag_count ;1131 DB_RX(5, "EOF set in RxD, used_frags = %d", used_frags);1132 1133 /* may be next 2 DRV_BUF_FLUSH() can be skipped, because */1134 /* BMU_ST_BUF will not be changed by the ASIC */1135 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;1136 while (rx_used && !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {1137 DB_RX(5, "Check STF bit in %p", r);1138 r = r->rxd_next ;1139 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;1140 frag_count++ ;1141 rx_used-- ;1142 }1143 DB_RX(5, "STF bit found");1144 1145 /*1146 * The received frame is finished for the process receive1147 */1148 rxd = queue->rx_curr_get ;1149 queue->rx_curr_get = r ;1150 queue->rx_free += frag_count ;1151 queue->rx_used = rx_used ;1152 1153 /*1154 * ASIC Errata no. 7 (STF - Bit Bug)1155 */1156 rxd->rxd_rbctrl &= cpu_to_le32(~BMU_STF) ;1157 1158 for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){1159 DB_RX(5, "dma_complete for RxD %p", r);1160 dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);1161 }1162 smc->hw.fp.err_stats.err_valid++ ;1163 smc->mib.m[MAC0].fddiMACCopied_Ct++ ;1164 1165 /* the length of the data including the FC */1166 len = (rfsw & RD_LENGTH) - 4 ;1167 1168 DB_RX(4, "frame length = %d", len);1169 /*1170 * check the frame_length and all error flags1171 */1172 if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){1173 if (rfsw & RD_S_MSRABT) {1174 DB_RX(2, "Frame aborted by the FORMAC");1175 smc->hw.fp.err_stats.err_abort++ ;1176 }1177 /*1178 * check frame status1179 */1180 if (rfsw & RD_S_SEAC2) {1181 DB_RX(2, "E-Indicator set");1182 smc->hw.fp.err_stats.err_e_indicator++ ;1183 }1184 if (rfsw & RD_S_SFRMERR) {1185 DB_RX(2, "CRC error");1186 smc->hw.fp.err_stats.err_crc++ ;1187 }1188 if (rfsw & RX_FS_IMPL) {1189 DB_RX(2, "Implementer frame");1190 smc->hw.fp.err_stats.err_imp_frame++ ;1191 }1192 goto abort_frame ;1193 }1194 if (len > FDDI_RAW_MTU-4) {1195 DB_RX(2, "Frame too long error");1196 smc->hw.fp.err_stats.err_too_long++ ;1197 goto abort_frame ;1198 }1199 /*1200 * SUPERNET 3 Bug: FORMAC delivers status words1201 * of aborted frames to the BMU1202 */1203 if (len <= 4) {1204 DB_RX(2, "Frame length = 0");1205 goto abort_frame ;1206 }1207 1208 if (len != (n-4)) {1209 DB_RX(4, "BMU: rx len differs: [%d:%d]", len, n);1210 smc->os.hwm.rx_len_error++ ;1211 goto abort_frame ;1212 }1213 1214 /*1215 * Check SA == MA1216 */1217 virt = (u_char far *) rxd->rxd_virt ;1218 DB_RX(2, "FC = %x", *virt);1219 if (virt[12] == MA[5] &&1220 virt[11] == MA[4] &&1221 virt[10] == MA[3] &&1222 virt[9] == MA[2] &&1223 virt[8] == MA[1] &&1224 (virt[7] & ~GROUP_ADDR_BIT) == MA[0]) {1225 goto abort_frame ;1226 }1227 1228 /*1229 * test if LLC frame1230 */1231 if (rfsw & RX_FS_LLC) {1232 /*1233 * if pass_llc_promisc is disable1234 * if DA != Multicast or Broadcast or DA!=MA1235 * abort the frame1236 */1237 if (!smc->os.hwm.pass_llc_promisc) {1238 if(!(virt[1] & GROUP_ADDR_BIT)) {1239 if (virt[6] != MA[5] ||1240 virt[5] != MA[4] ||1241 virt[4] != MA[3] ||1242 virt[3] != MA[2] ||1243 virt[2] != MA[1] ||1244 virt[1] != MA[0]) {1245 DB_RX(2, "DA != MA and not multi- or broadcast");1246 goto abort_frame ;1247 }1248 }1249 }1250 1251 /*1252 * LLC frame received1253 */1254 DB_RX(4, "LLC - receive");1255 mac_drv_rx_complete(smc,rxd,frag_count,len) ;1256 }1257 else {1258 if (!(mb = smt_get_mbuf(smc))) {1259 smc->hw.fp.err_stats.err_no_buf++ ;1260 DB_RX(4, "No SMbuf; receive terminated");1261 goto abort_frame ;1262 }1263 data = smtod(mb,char *) - 1 ;1264 1265 /*1266 * copy the frame into a SMT_MBuf1267 */1268#ifdef USE_OS_CPY1269 hwm_cpy_rxd2mb(rxd,data,len) ;1270#else1271 for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){1272 n = le32_to_cpu(r->rxd_rbctrl) & RD_LENGTH ;1273 DB_RX(6, "cp SMT frame to mb: len = %d", n);1274 memcpy(data,r->rxd_virt,n) ;1275 data += n ;1276 }1277 data = smtod(mb,char *) - 1 ;1278#endif1279 fc = *(char *)mb->sm_data = *data ;1280 mb->sm_len = len - 1 ; /* len - fc */1281 data++ ;1282 1283 /*1284 * SMT frame received1285 */1286 switch(fc) {1287 case FC_SMT_INFO :1288 smc->hw.fp.err_stats.err_smt_frame++ ;1289 DB_RX(5, "SMT frame received");1290 1291 if (smc->os.hwm.pass_SMT) {1292 DB_RX(5, "pass SMT frame");1293 mac_drv_rx_complete(smc, rxd,1294 frag_count,len) ;1295 }1296 else {1297 DB_RX(5, "requeue RxD");1298 mac_drv_requeue_rxd(smc,rxd,frag_count);1299 }1300 1301 smt_received_pack(smc,mb,(int)(rfsw>>25)) ;1302 break ;1303 case FC_SMT_NSA :1304 smc->hw.fp.err_stats.err_smt_frame++ ;1305 DB_RX(5, "SMT frame received");1306 1307 /* if pass_NSA set pass the NSA frame or */1308 /* pass_SMT set and the A-Indicator */1309 /* is not set, pass the NSA frame */1310 if (smc->os.hwm.pass_NSA ||1311 (smc->os.hwm.pass_SMT &&1312 !(rfsw & A_INDIC))) {1313 DB_RX(5, "pass SMT frame");1314 mac_drv_rx_complete(smc, rxd,1315 frag_count,len) ;1316 }1317 else {1318 DB_RX(5, "requeue RxD");1319 mac_drv_requeue_rxd(smc,rxd,frag_count);1320 }1321 1322 smt_received_pack(smc,mb,(int)(rfsw>>25)) ;1323 break ;1324 case FC_BEACON :1325 if (smc->os.hwm.pass_DB) {1326 DB_RX(5, "pass DB frame");1327 mac_drv_rx_complete(smc, rxd,1328 frag_count,len) ;1329 }1330 else {1331 DB_RX(5, "requeue RxD");1332 mac_drv_requeue_rxd(smc,rxd,frag_count);1333 }1334 smt_free_mbuf(smc,mb) ;1335 break ;1336 default :1337 /*1338 * unknown FC abort the frame1339 */1340 DB_RX(2, "unknown FC error");1341 smt_free_mbuf(smc,mb) ;1342 DB_RX(5, "requeue RxD");1343 mac_drv_requeue_rxd(smc,rxd,frag_count) ;1344 if ((fc & 0xf0) == FC_MAC)1345 smc->hw.fp.err_stats.err_mac_frame++ ;1346 else1347 smc->hw.fp.err_stats.err_imp_frame++ ;1348 1349 break ;1350 }1351 }1352 1353 DB_RX(3, "next RxD is %p", queue->rx_curr_get);1354 NDD_TRACE("RHx1",queue->rx_curr_get,0,0) ;1355 1356 continue ;1357 /*--------------------------------------------------------------------*/1358abort_frame:1359 DB_RX(5, "requeue RxD");1360 mac_drv_requeue_rxd(smc,rxd,frag_count) ;1361 1362 DB_RX(3, "next RxD is %p", queue->rx_curr_get);1363 NDD_TRACE("RHx2",queue->rx_curr_get,0,0) ;1364 }1365rx_end:1366#ifdef ALL_RX_COMPLETE1367 mac_drv_all_receives_complete(smc) ;1368#endif1369 return ; /* lint bug: needs return detect end of function */1370}1371 1372static void smt_to_llc(struct s_smc *smc, SMbuf *mb)1373{1374 u_char fc ;1375 1376 DB_RX(4, "send a queued frame to the llc layer");1377 smc->os.hwm.r.len = mb->sm_len ;1378 smc->os.hwm.r.mb_pos = smtod(mb,char *) ;1379 fc = *smc->os.hwm.r.mb_pos ;1380 (void)mac_drv_rx_init(smc,(int)mb->sm_len,(int)fc,1381 smc->os.hwm.r.mb_pos,(int)mb->sm_len) ;1382 smt_free_mbuf(smc,mb) ;1383}1384 1385/*1386 * BEGIN_MANUAL_ENTRY(hwm_rx_frag)1387 * void hwm_rx_frag(smc,virt,phys,len,frame_status)1388 *1389 * function MACRO (hardware module, hwmtm.h)1390 * This function calls dma_master for preparing the1391 * system hardware for the DMA transfer and initializes1392 * the current RxD with the length and the physical and1393 * virtual address of the fragment. Furthermore, it sets the1394 * STF and EOF bits depending on the frame status byte,1395 * switches the OWN flag of the RxD, so that it is owned by the1396 * adapter and issues an rx_start.1397 *1398 * para virt virtual pointer to the fragment1399 * len the length of the fragment1400 * frame_status status of the frame, see design description1401 *1402 * NOTE: It is possible to call this function with a fragment length1403 * of zero.1404 *1405 * END_MANUAL_ENTRY1406 */1407void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,1408 int frame_status)1409{1410 struct s_smt_fp_rxd volatile *r ;1411 __le32 rbctrl;1412 1413 NDD_TRACE("RHfB",virt,len,frame_status) ;1414 DB_RX(2, "hwm_rx_frag: len = %d, frame_status = %x", len, frame_status);1415 r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ;1416 r->rxd_virt = virt ;1417 r->rxd_rbadr = cpu_to_le32(phys) ;1418 rbctrl = cpu_to_le32( (((__u32)frame_status &1419 (FIRST_FRAG|LAST_FRAG))<<26) |1420 (((u_long) frame_status & FIRST_FRAG) << 21) |1421 BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ;1422 r->rxd_rbctrl = rbctrl ;1423 1424 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;1425 outpd(ADDR(B0_R1_CSR),CSR_START) ;1426 smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ;1427 smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ;1428 smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ;1429 NDD_TRACE("RHfE",r,le32_to_cpu(r->rxd_rbadr),0) ;1430}1431 1432/*1433 * BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue)1434 *1435 * void mac_drv_clear_rx_queue(smc)1436 * struct s_smc *smc ;1437 *1438 * function DOWNCALL (hardware module, hwmtm.c)1439 * mac_drv_clear_rx_queue is called by the OS-specific module1440 * after it has issued a card_stop.1441 * In this case, the frames in the receive queue are obsolete and1442 * should be removed. For removing mac_drv_clear_rx_queue1443 * calls dma_master for each RxD and mac_drv_clear_rxd for each1444 * receive buffer.1445 *1446 * NOTE: calling sequence card_stop:1447 * CLI_FBI(), card_stop(),1448 * mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),1449 *1450 * NOTE: The caller is responsible that the BMUs are idle1451 * when this function is called.1452 *1453 * END_MANUAL_ENTRY1454 */1455void mac_drv_clear_rx_queue(struct s_smc *smc)1456{1457 struct s_smt_fp_rxd volatile *r ;1458 struct s_smt_fp_rxd volatile *next_rxd ;1459 struct s_smt_rx_queue *queue ;1460 int frag_count ;1461 int i ;1462 1463 if (smc->hw.hw_state != STOPPED) {1464 SK_BREAK() ;1465 SMT_PANIC(smc,HWM_E0012,HWM_E0012_MSG) ;1466 return ;1467 }1468 1469 queue = smc->hw.fp.rx[QUEUE_R1] ;1470 DB_RX(5, "clear_rx_queue");1471 1472 /*1473 * dma_complete and mac_drv_clear_rxd for all RxDs / receive buffers1474 */1475 r = queue->rx_curr_get ;1476 while (queue->rx_used) {1477 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;1478 DB_RX(5, "switch OWN bit of RxD 0x%p", r);1479 r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;1480 frag_count = 1 ;1481 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;1482 r = r->rxd_next ;1483 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;1484 while (r != queue->rx_curr_put &&1485 !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {1486 DB_RX(5, "Check STF bit in %p", r);1487 r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;1488 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;1489 r = r->rxd_next ;1490 DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;1491 frag_count++ ;1492 }1493 DB_RX(5, "STF bit found");1494 next_rxd = r ;1495 1496 for (r=queue->rx_curr_get,i=frag_count; i ; r=r->rxd_next,i--){1497 DB_RX(5, "dma_complete for RxD %p", r);1498 dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);1499 }1500 1501 DB_RX(5, "mac_drv_clear_rxd: RxD %p frag_count %d",1502 queue->rx_curr_get, frag_count);1503 mac_drv_clear_rxd(smc,queue->rx_curr_get,frag_count) ;1504 1505 queue->rx_curr_get = next_rxd ;1506 queue->rx_used -= frag_count ;1507 queue->rx_free += frag_count ;1508 }1509}1510 1511 1512/*1513 -------------------------------------------------------------1514 SEND FUNCTIONS:1515 -------------------------------------------------------------1516*/1517 1518/*1519 * BEGIN_MANUAL_ENTRY(hwm_tx_init)1520 * int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status)1521 *1522 * function DOWN_CALL (hardware module, hwmtm.c)1523 * hwm_tx_init checks if the frame can be sent through the1524 * corresponding send queue.1525 *1526 * para fc the frame control. To determine through which1527 * send queue the frame should be transmitted.1528 * 0x50 - 0x57: asynchronous LLC frame1529 * 0xD0 - 0xD7: synchronous LLC frame1530 * 0x41, 0x4F: SMT frame to the network1531 * 0x42: SMT frame to the network and to the local SMT1532 * 0x43: SMT frame to the local SMT1533 * frag_count count of the fragments for this frame1534 * frame_len length of the frame1535 * frame_status status of the frame, the send queue bit is already1536 * specified1537 *1538 * return frame_status1539 *1540 * END_MANUAL_ENTRY1541 */1542int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,1543 int frame_status)1544{1545 NDD_TRACE("THiB",fc,frag_count,frame_len) ;1546 smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ;1547 smc->os.hwm.tx_descr = TX_DESCRIPTOR | (((u_long)(frame_len-1)&3)<<27) ;1548 smc->os.hwm.tx_len = frame_len ;1549 DB_TX(3, "hwm_tx_init: fc = %x, len = %d", fc, frame_len);1550 if ((fc & ~(FC_SYNC_BIT|FC_LLC_PRIOR)) == FC_ASYNC_LLC) {1551 frame_status |= LAN_TX ;1552 }1553 else {1554 switch (fc) {1555 case FC_SMT_INFO :1556 case FC_SMT_NSA :1557 frame_status |= LAN_TX ;1558 break ;1559 case FC_SMT_LOC :1560 frame_status |= LOC_TX ;1561 break ;1562 case FC_SMT_LAN_LOC :1563 frame_status |= LAN_TX | LOC_TX ;1564 break ;1565 default :1566 SMT_PANIC(smc,HWM_E0010,HWM_E0010_MSG) ;1567 }1568 }1569 if (!smc->hw.mac_ring_is_up) {1570 frame_status &= ~LAN_TX ;1571 frame_status |= RING_DOWN ;1572 DB_TX(2, "Ring is down: terminate LAN_TX");1573 }1574 if (frag_count > smc->os.hwm.tx_p->tx_free) {1575#ifndef NDIS_OS21576 mac_drv_clear_txd(smc) ;1577 if (frag_count > smc->os.hwm.tx_p->tx_free) {1578 DB_TX(2, "Out of TxDs, terminate LAN_TX");1579 frame_status &= ~LAN_TX ;1580 frame_status |= OUT_OF_TXD ;1581 }1582#else1583 DB_TX(2, "Out of TxDs, terminate LAN_TX");1584 frame_status &= ~LAN_TX ;1585 frame_status |= OUT_OF_TXD ;1586#endif1587 }1588 DB_TX(3, "frame_status = %x", frame_status);1589 NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ;1590 return frame_status;1591}1592 1593/*1594 * BEGIN_MANUAL_ENTRY(hwm_tx_frag)1595 * void hwm_tx_frag(smc,virt,phys,len,frame_status)1596 *1597 * function DOWNCALL (hardware module, hwmtm.c)1598 * If the frame should be sent to the LAN, this function calls1599 * dma_master, fills the current TxD with the virtual and the1600 * physical address, sets the STF and EOF bits dependent on1601 * the frame status, and requests the BMU to start the1602 * transmit.1603 * If the frame should be sent to the local SMT, an SMT_MBuf1604 * is allocated if the FIRST_FRAG bit is set in the frame_status.1605 * The fragment of the frame is copied into the SMT MBuf.1606 * The function smt_received_pack is called if the LAST_FRAG1607 * bit is set in the frame_status word.1608 *1609 * para virt virtual pointer to the fragment1610 * len the length of the fragment1611 * frame_status status of the frame, see design description1612 *1613 * return nothing returned, no parameter is modified1614 *1615 * NOTE: It is possible to invoke this macro with a fragment length1616 * of zero.1617 *1618 * END_MANUAL_ENTRY1619 */1620void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,1621 int frame_status)1622{1623 struct s_smt_fp_txd volatile *t ;1624 struct s_smt_tx_queue *queue ;1625 __le32 tbctrl ;1626 1627 queue = smc->os.hwm.tx_p ;1628 1629 NDD_TRACE("THfB",virt,len,frame_status) ;1630 /* Bug fix: AF / May 31 1999 (#missing)1631 * snmpinfo problem reported by IBM is caused by invalid1632 * t-pointer (txd) if LAN_TX is not set but LOC_TX only.1633 * Set: t = queue->tx_curr_put here !1634 */1635 t = queue->tx_curr_put ;1636 1637 DB_TX(2, "hwm_tx_frag: len = %d, frame_status = %x", len, frame_status);1638 if (frame_status & LAN_TX) {1639 /* '*t' is already defined */1640 DB_TX(3, "LAN_TX: TxD = %p, virt = %p", t, virt);1641 t->txd_virt = virt ;1642 t->txd_txdscr = cpu_to_le32(smc->os.hwm.tx_descr) ;1643 t->txd_tbadr = cpu_to_le32(phys) ;1644 tbctrl = cpu_to_le32((((__u32)frame_status &1645 (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |1646 BMU_OWN|BMU_CHECK |len) ;1647 t->txd_tbctrl = tbctrl ;1648 1649#ifndef AIX1650 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;1651 outpd(queue->tx_bmu_ctl,CSR_START) ;1652#else /* ifndef AIX */1653 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;1654 if (frame_status & QUEUE_A0) {1655 outpd(ADDR(B0_XA_CSR),CSR_START) ;1656 }1657 else {1658 outpd(ADDR(B0_XS_CSR),CSR_START) ;1659 }1660#endif1661 queue->tx_free-- ;1662 queue->tx_used++ ;1663 queue->tx_curr_put = t->txd_next ;1664 if (frame_status & LAST_FRAG) {1665 smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;1666 }1667 }1668 if (frame_status & LOC_TX) {1669 DB_TX(3, "LOC_TX:");1670 if (frame_status & FIRST_FRAG) {1671 if(!(smc->os.hwm.tx_mb = smt_get_mbuf(smc))) {1672 smc->hw.fp.err_stats.err_no_buf++ ;1673 DB_TX(4, "No SMbuf; transmit terminated");1674 }1675 else {1676 smc->os.hwm.tx_data =1677 smtod(smc->os.hwm.tx_mb,char *) - 1 ;1678#ifdef USE_OS_CPY1679#ifdef PASS_1ST_TXD_2_TX_COMP1680 hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,1681 smc->os.hwm.tx_len) ;1682#endif1683#endif1684 }1685 }1686 if (smc->os.hwm.tx_mb) {1687#ifndef USE_OS_CPY1688 DB_TX(3, "copy fragment into MBuf");1689 memcpy(smc->os.hwm.tx_data,virt,len) ;1690 smc->os.hwm.tx_data += len ;1691#endif1692 if (frame_status & LAST_FRAG) {1693#ifdef USE_OS_CPY1694#ifndef PASS_1ST_TXD_2_TX_COMP1695 /*1696 * hwm_cpy_txd2mb(txd,data,len) copies 'len' 1697 * bytes from the virtual pointer in 'rxd'1698 * to 'data'. The virtual pointer of the 1699 * os-specific tx-buffer should be written1700 * in the LAST txd.1701 */ 1702 hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,1703 smc->os.hwm.tx_len) ;1704#endif /* nPASS_1ST_TXD_2_TX_COMP */1705#endif /* USE_OS_CPY */1706 smc->os.hwm.tx_data =1707 smtod(smc->os.hwm.tx_mb,char *) - 1 ;1708 *(char *)smc->os.hwm.tx_mb->sm_data =1709 *smc->os.hwm.tx_data ;1710 smc->os.hwm.tx_data++ ;1711 smc->os.hwm.tx_mb->sm_len =1712 smc->os.hwm.tx_len - 1 ;1713 DB_TX(3, "pass LLC frame to SMT");1714 smt_received_pack(smc,smc->os.hwm.tx_mb,1715 RD_FS_LOCAL) ;1716 }1717 }1718 }1719 NDD_TRACE("THfE",t,queue->tx_free,0) ;1720}1721 1722 1723/*1724 * queues a receive for later send1725 */1726static void queue_llc_rx(struct s_smc *smc, SMbuf *mb)1727{1728 DB_GEN(4, "queue_llc_rx: mb = %p", mb);1729 smc->os.hwm.queued_rx_frames++ ;1730 mb->sm_next = (SMbuf *)NULL ;1731 if (smc->os.hwm.llc_rx_pipe == NULL) {1732 smc->os.hwm.llc_rx_pipe = mb ;1733 }1734 else {1735 smc->os.hwm.llc_rx_tail->sm_next = mb ;1736 }1737 smc->os.hwm.llc_rx_tail = mb ;1738 1739 /*1740 * force an timer IRQ to receive the data1741 */1742 if (!smc->os.hwm.isr_flag) {1743 smt_force_irq(smc) ;1744 }1745}1746 1747/*1748 * get a SMbuf from the llc_rx_queue1749 */1750static SMbuf *get_llc_rx(struct s_smc *smc)1751{1752 SMbuf *mb ;1753 1754 if ((mb = smc->os.hwm.llc_rx_pipe)) {1755 smc->os.hwm.queued_rx_frames-- ;1756 smc->os.hwm.llc_rx_pipe = mb->sm_next ;1757 }1758 DB_GEN(4, "get_llc_rx: mb = 0x%p", mb);1759 return mb;1760}1761 1762/*1763 * queues a transmit SMT MBuf during the time were the MBuf is1764 * queued the TxD ring1765 */1766static void queue_txd_mb(struct s_smc *smc, SMbuf *mb)1767{1768 DB_GEN(4, "_rx: queue_txd_mb = %p", mb);1769 smc->os.hwm.queued_txd_mb++ ;1770 mb->sm_next = (SMbuf *)NULL ;1771 if (smc->os.hwm.txd_tx_pipe == NULL) {1772 smc->os.hwm.txd_tx_pipe = mb ;1773 }1774 else {1775 smc->os.hwm.txd_tx_tail->sm_next = mb ;1776 }1777 smc->os.hwm.txd_tx_tail = mb ;1778}1779 1780/*1781 * get a SMbuf from the txd_tx_queue1782 */1783static SMbuf *get_txd_mb(struct s_smc *smc)1784{1785 SMbuf *mb ;1786 1787 if ((mb = smc->os.hwm.txd_tx_pipe)) {1788 smc->os.hwm.queued_txd_mb-- ;1789 smc->os.hwm.txd_tx_pipe = mb->sm_next ;1790 }1791 DB_GEN(4, "get_txd_mb: mb = 0x%p", mb);1792 return mb;1793}1794 1795/*1796 * SMT Send function1797 */1798void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)1799{1800 char far *data ;1801 int len ;1802 int n ;1803 int i ;1804 int frag_count ;1805 int frame_status ;1806 SK_LOC_DECL(char far,*virt[3]) ;1807 int frag_len[3] ;1808 struct s_smt_tx_queue *queue ;1809 struct s_smt_fp_txd volatile *t ;1810 u_long phys ;1811 __le32 tbctrl;1812 1813 NDD_TRACE("THSB",mb,fc,0) ;1814 DB_TX(4, "smt_send_mbuf: mb = 0x%p, fc = 0x%x", mb, fc);1815 1816 mb->sm_off-- ; /* set to fc */1817 mb->sm_len++ ; /* + fc */1818 data = smtod(mb,char *) ;1819 *data = fc ;1820 if (fc == FC_SMT_LOC)1821 *data = FC_SMT_INFO ;1822 1823 /*1824 * determine the frag count and the virt addresses of the frags1825 */1826 frag_count = 0 ;1827 len = mb->sm_len ;1828 while (len) {1829 n = SMT_PAGESIZE - ((long)data & (SMT_PAGESIZE-1)) ;1830 if (n >= len) {1831 n = len ;1832 }1833 DB_TX(5, "frag: virt/len = 0x%p/%d", data, n);1834 virt[frag_count] = data ;1835 frag_len[frag_count] = n ;1836 frag_count++ ;1837 len -= n ;1838 data += n ;1839 }1840 1841 /*1842 * determine the frame status1843 */1844 queue = smc->hw.fp.tx[QUEUE_A0] ;1845 if (fc == FC_BEACON || fc == FC_SMT_LOC) {1846 frame_status = LOC_TX ;1847 }1848 else {1849 frame_status = LAN_TX ;1850 if ((smc->os.hwm.pass_NSA &&(fc == FC_SMT_NSA)) ||1851 (smc->os.hwm.pass_SMT &&(fc == FC_SMT_INFO)))1852 frame_status |= LOC_TX ;1853 }1854 1855 if (!smc->hw.mac_ring_is_up || frag_count > queue->tx_free) {1856 frame_status &= ~LAN_TX;1857 if (frame_status) {1858 DB_TX(2, "Ring is down: terminate LAN_TX");1859 }1860 else {1861 DB_TX(2, "Ring is down: terminate transmission");1862 smt_free_mbuf(smc,mb) ;1863 return ;1864 }1865 }1866 DB_TX(5, "frame_status = 0x%x", frame_status);1867 1868 if ((frame_status & LAN_TX) && (frame_status & LOC_TX)) {1869 mb->sm_use_count = 2 ;1870 }1871 1872 if (frame_status & LAN_TX) {1873 t = queue->tx_curr_put ;1874 frame_status |= FIRST_FRAG ;1875 for (i = 0; i < frag_count; i++) {1876 DB_TX(5, "init TxD = 0x%p", t);1877 if (i == frag_count-1) {1878 frame_status |= LAST_FRAG ;1879 t->txd_txdscr = cpu_to_le32(TX_DESCRIPTOR |1880 (((__u32)(mb->sm_len-1)&3) << 27)) ;1881 }1882 t->txd_virt = virt[i] ;1883 phys = dma_master(smc, (void far *)virt[i],1884 frag_len[i], DMA_RD|SMT_BUF) ;1885 t->txd_tbadr = cpu_to_le32(phys) ;1886 tbctrl = cpu_to_le32((((__u32)frame_status &1887 (FIRST_FRAG|LAST_FRAG)) << 26) |1888 BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ;1889 t->txd_tbctrl = tbctrl ;1890#ifndef AIX1891 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;1892 outpd(queue->tx_bmu_ctl,CSR_START) ;1893#else1894 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;1895 outpd(ADDR(B0_XA_CSR),CSR_START) ;1896#endif1897 frame_status &= ~FIRST_FRAG ;1898 queue->tx_curr_put = t = t->txd_next ;1899 queue->tx_free-- ;1900 queue->tx_used++ ;1901 }1902 smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;1903 queue_txd_mb(smc,mb) ;1904 }1905 1906 if (frame_status & LOC_TX) {1907 DB_TX(5, "pass Mbuf to LLC queue");1908 queue_llc_rx(smc,mb) ;1909 }1910 1911 /*1912 * We need to unqueue the free SMT_MBUFs here, because it may1913 * be that the SMT want's to send more than 1 frame for one down call1914 */1915 mac_drv_clear_txd(smc) ;1916 NDD_TRACE("THSE",t,queue->tx_free,frag_count) ;1917}1918 1919/* BEGIN_MANUAL_ENTRY(mac_drv_clear_txd)1920 * void mac_drv_clear_txd(smc)1921 *1922 * function DOWNCALL (hardware module, hwmtm.c)1923 * mac_drv_clear_txd searches in both send queues for TxD's1924 * which were finished by the adapter. It calls dma_complete1925 * for each TxD. If the last fragment of an LLC frame is1926 * reached, it calls mac_drv_tx_complete to release the1927 * send buffer.1928 *1929 * return nothing1930 *1931 * END_MANUAL_ENTRY1932 */1933static void mac_drv_clear_txd(struct s_smc *smc)1934{1935 struct s_smt_tx_queue *queue ;1936 struct s_smt_fp_txd volatile *t1 ;1937 struct s_smt_fp_txd volatile *t2 = NULL ;1938 SMbuf *mb ;1939 u_long tbctrl ;1940 int i ;1941 int frag_count ;1942 int n ;1943 1944 NDD_TRACE("THcB",0,0,0) ;1945 for (i = QUEUE_S; i <= QUEUE_A0; i++) {1946 queue = smc->hw.fp.tx[i] ;1947 t1 = queue->tx_curr_get ;1948 DB_TX(5, "clear_txd: QUEUE = %d (0=sync/1=async)", i);1949 1950 for ( ; ; ) {1951 frag_count = 0 ;1952 1953 do {1954 DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ;1955 DB_TX(5, "check OWN/EOF bit of TxD 0x%p", t1);1956 tbctrl = le32_to_cpu(CR_READ(t1->txd_tbctrl));1957 1958 if (tbctrl & BMU_OWN || !queue->tx_used){1959 DB_TX(4, "End of TxDs queue %d", i);1960 goto free_next_queue ; /* next queue */1961 }1962 t1 = t1->txd_next ;1963 frag_count++ ;1964 } while (!(tbctrl & BMU_EOF)) ;1965 1966 t1 = queue->tx_curr_get ;1967 for (n = frag_count; n; n--) {1968 tbctrl = le32_to_cpu(t1->txd_tbctrl) ;1969 dma_complete(smc,1970 (union s_fp_descr volatile *) t1,1971 (int) (DMA_RD |1972 ((tbctrl & BMU_SMT_TX) >> 18))) ;1973 t2 = t1 ;1974 t1 = t1->txd_next ;1975 }1976 1977 if (tbctrl & BMU_SMT_TX) {1978 mb = get_txd_mb(smc) ;1979 smt_free_mbuf(smc,mb) ;1980 }1981 else {1982#ifndef PASS_1ST_TXD_2_TX_COMP1983 DB_TX(4, "mac_drv_tx_comp for TxD 0x%p", t2);1984 mac_drv_tx_complete(smc,t2) ;1985#else1986 DB_TX(4, "mac_drv_tx_comp for TxD 0x%x",1987 queue->tx_curr_get);1988 mac_drv_tx_complete(smc,queue->tx_curr_get) ;1989#endif1990 }1991 queue->tx_curr_get = t1 ;1992 queue->tx_free += frag_count ;1993 queue->tx_used -= frag_count ;1994 }1995free_next_queue: ;1996 }1997 NDD_TRACE("THcE",0,0,0) ;1998}1999 2000/*2001 * BEGINN_MANUAL_ENTRY(mac_drv_clear_tx_queue)2002 *2003 * void mac_drv_clear_tx_queue(smc)2004 * struct s_smc *smc ;2005 *2006 * function DOWNCALL (hardware module, hwmtm.c)2007 * mac_drv_clear_tx_queue is called from the SMT when2008 * the RMT state machine has entered the ISOLATE state.2009 * This function is also called by the os-specific module2010 * after it has called the function card_stop().2011 * In this case, the frames in the send queues are obsolete and2012 * should be removed.2013 *2014 * note calling sequence:2015 * CLI_FBI(), card_stop(),2016 * mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),2017 *2018 * NOTE: The caller is responsible that the BMUs are idle2019 * when this function is called.2020 *2021 * END_MANUAL_ENTRY2022 */2023void mac_drv_clear_tx_queue(struct s_smc *smc)2024{2025 struct s_smt_fp_txd volatile *t ;2026 struct s_smt_tx_queue *queue ;2027 int tx_used ;2028 int i ;2029 2030 if (smc->hw.hw_state != STOPPED) {2031 SK_BREAK() ;2032 SMT_PANIC(smc,HWM_E0011,HWM_E0011_MSG) ;2033 return ;2034 }2035 2036 for (i = QUEUE_S; i <= QUEUE_A0; i++) {2037 queue = smc->hw.fp.tx[i] ;2038 DB_TX(5, "clear_tx_queue: QUEUE = %d (0=sync/1=async)", i);2039 2040 /*2041 * switch the OWN bit of all pending frames to the host2042 */2043 t = queue->tx_curr_get ;2044 tx_used = queue->tx_used ;2045 while (tx_used) {2046 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;2047 DB_TX(5, "switch OWN bit of TxD 0x%p", t);2048 t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;2049 DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;2050 t = t->txd_next ;2051 tx_used-- ;2052 }2053 }2054 2055 /*2056 * release all TxD's for both send queues2057 */2058 mac_drv_clear_txd(smc) ;2059 2060 for (i = QUEUE_S; i <= QUEUE_A0; i++) {2061 queue = smc->hw.fp.tx[i] ;2062 t = queue->tx_curr_get ;2063 2064 /*2065 * write the phys pointer of the NEXT descriptor into the2066 * BMU's current address descriptor pointer and set2067 * tx_curr_get and tx_curr_put to this position2068 */2069 if (i == QUEUE_S) {2070 outpd(ADDR(B5_XS_DA),le32_to_cpu(t->txd_ntdadr)) ;2071 }2072 else {2073 outpd(ADDR(B5_XA_DA),le32_to_cpu(t->txd_ntdadr)) ;2074 }2075 2076 queue->tx_curr_put = queue->tx_curr_get->txd_next ;2077 queue->tx_curr_get = queue->tx_curr_put ;2078 }2079}2080 2081 2082/*2083 -------------------------------------------------------------2084 TEST FUNCTIONS:2085 -------------------------------------------------------------2086*/2087 2088#ifdef DEBUG2089/*2090 * BEGIN_MANUAL_ENTRY(mac_drv_debug_lev)2091 * void mac_drv_debug_lev(smc,flag,lev)2092 *2093 * function DOWNCALL (drvsr.c)2094 * To get a special debug info the user can assign a debug level2095 * to any debug flag.2096 *2097 * para flag debug flag, possible values are:2098 * = 0: reset all debug flags (the defined level is2099 * ignored)2100 * = 1: debug.d_smtf2101 * = 2: debug.d_smt2102 * = 3: debug.d_ecm2103 * = 4: debug.d_rmt2104 * = 5: debug.d_cfm2105 * = 6: debug.d_pcm2106 *2107 * = 10: debug.d_os.hwm_rx (hardware module receive path)2108 * = 11: debug.d_os.hwm_tx(hardware module transmit path)2109 * = 12: debug.d_os.hwm_gen(hardware module general flag)2110 *2111 * lev debug level2112 *2113 * END_MANUAL_ENTRY2114 */2115void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev)2116{2117 switch(flag) {2118 case (int)NULL:2119 DB_P.d_smtf = DB_P.d_smt = DB_P.d_ecm = DB_P.d_rmt = 0 ;2120 DB_P.d_cfm = 0 ;2121 DB_P.d_os.hwm_rx = DB_P.d_os.hwm_tx = DB_P.d_os.hwm_gen = 0 ;2122#ifdef SBA2123 DB_P.d_sba = 0 ;2124#endif2125#ifdef ESS2126 DB_P.d_ess = 0 ;2127#endif2128 break ;2129 case DEBUG_SMTF:2130 DB_P.d_smtf = lev ;2131 break ;2132 case DEBUG_SMT:2133 DB_P.d_smt = lev ;2134 break ;2135 case DEBUG_ECM:2136 DB_P.d_ecm = lev ;2137 break ;2138 case DEBUG_RMT:2139 DB_P.d_rmt = lev ;2140 break ;2141 case DEBUG_CFM:2142 DB_P.d_cfm = lev ;2143 break ;2144 case DEBUG_PCM:2145 DB_P.d_pcm = lev ;2146 break ;2147 case DEBUG_SBA:2148#ifdef SBA2149 DB_P.d_sba = lev ;2150#endif2151 break ;2152 case DEBUG_ESS:2153#ifdef ESS2154 DB_P.d_ess = lev ;2155#endif2156 break ;2157 case DB_HWM_RX:2158 DB_P.d_os.hwm_rx = lev ;2159 break ;2160 case DB_HWM_TX:2161 DB_P.d_os.hwm_tx = lev ;2162 break ;2163 case DB_HWM_GEN:2164 DB_P.d_os.hwm_gen = lev ;2165 break ;2166 default:2167 break ;2168 }2169}2170#endif2171