📄 hwmtm.c
字号:
if (smc->hw.fp.tx_q[QUEUE_A0].tx_used) { outpd(ADDR(B0_XA_CSR),CSR_START) ; } phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_S]) ; outpd(ADDR(B5_XS_DA),phys) ; if (smc->hw.fp.tx_q[QUEUE_S].tx_used) { outpd(ADDR(B0_XS_CSR),CSR_START) ; } /* * repair rx queues */ phys = repair_rxd_ring(smc,smc->hw.fp.rx[QUEUE_R1]) ; outpd(ADDR(B4_R1_DA),phys) ; outpd(ADDR(B0_R1_CSR),CSR_START) ;}static u_long repair_txd_ring(smc,queue)struct s_smc *smc ;struct s_smt_tx_queue *queue ;{ int i ; int tx_used ; u_long phys ; u_long tbctrl ; struct s_smt_fp_txd volatile *t ; SK_UNUSED(smc) ; t = queue->tx_curr_get ; tx_used = queue->tx_used ; for (i = tx_used+queue->tx_free-1 ; i ; i-- ) { t = t->txd_next ; } phys = AIX_REVERSE(t->txd_ntdadr) ; t = queue->tx_curr_get ; while (tx_used) { DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ; tbctrl = AIX_REVERSE(t->txd_tbctrl) ; if (tbctrl & BMU_OWN) { if (tbctrl & BMU_STF) { break ; /* exit the loop */ } else { /* * repair the descriptor */ t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ; } } phys = AIX_REVERSE(t->txd_ntdadr) ; DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; t = t->txd_next ; tx_used-- ; } return(phys) ;}/* * Repairs the receive descriptor ring and returns the physical address * where the BMU should continue working. * * o The physical address where the BMU was stopped has to be * determined. This is the next RxD after rx_curr_get with an OWN * bit set. * o The BMU should start working at beginning of the next frame. * RxDs with an OWN bit set but with a reset STF bit should be * skipped and owned by the driver (OWN = 0). */static u_long repair_rxd_ring(smc,queue)struct s_smc *smc ;struct s_smt_rx_queue *queue ;{ int i ; int rx_used ; u_long phys ; u_long rbctrl ; struct s_smt_fp_rxd volatile *r ; SK_UNUSED(smc) ; r = queue->rx_curr_get ; rx_used = queue->rx_used ; for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) { r = r->rxd_next ; } phys = AIX_REVERSE(r->rxd_nrdadr) ; r = queue->rx_curr_get ; while (rx_used) { DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; rbctrl = AIX_REVERSE(r->rxd_rbctrl) ; if (rbctrl & BMU_OWN) { if (rbctrl & BMU_STF) { break ; /* exit the loop */ } else { /* * repair the descriptor */ r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ; } } phys = AIX_REVERSE(r->rxd_nrdadr) ; DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ; r = r->rxd_next ; rx_used-- ; } return(phys) ;}/* ------------------------------------------------------------- INTERRUPT SERVICE ROUTINE: -------------------------------------------------------------*//* * BEGIN_MANUAL_ENTRY(fddi_isr) * void fddi_isr(smc) * * function DOWNCALL (drvsr.c) * interrupt service routine, handles the interrupt requests * generated by the FDDI adapter. * * NOTE: The operating system dependent module must garantee that the * interrupts of the adapter are disabled when it calls fddi_isr. * * About the USE_BREAK_ISR mechanismn: * * The main requirement of this mechanismn is to force an timer IRQ when * leaving process_receive() with leave_isr set. process_receive() may * be called at any time from anywhere! * To be sure we don't miss such event we set 'force_irq' per default. * We have to force and Timer IRQ if 'smc->os.hwm.leave_isr' AND * 'force_irq' are set. 'force_irq' may be reset if a receive complete * IRQ is pending. * * END_MANUAL_ENTRY */void fddi_isr(smc)struct s_smc *smc ;{ u_long is ; /* ISR source */ u_short stu, stl ; SMbuf *mb ;#ifdef USE_BREAK_ISR int force_irq ;#endif#ifdef ODI2 if (smc->os.hwm.rx_break) { mac_drv_fill_rxd(smc) ; if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) { smc->os.hwm.rx_break = 0 ; process_receive(smc) ; } else { smc->os.hwm.detec_count = 0 ; smt_force_irq(smc) ; } }#endif smc->os.hwm.isr_flag = TRUE ;#ifdef USE_BREAK_ISR force_irq = TRUE ; if (smc->os.hwm.leave_isr) { smc->os.hwm.leave_isr = FALSE ; process_receive(smc) ; }#endif while ((is = GET_ISR() & ISR_MASK)) { NDD_TRACE("CH0B",is,0,0) ; DB_GEN("ISA = 0x%x",is,0,7) ; if (is & IMASK_SLOW) { NDD_TRACE("CH1b",is,0,0) ; if (is & IS_PLINT1) { /* PLC1 */ plc1_irq(smc) ; } if (is & IS_PLINT2) { /* PLC2 */ plc2_irq(smc) ; } if (is & IS_MINTR1) { /* FORMAC+ STU1(U/L) */ stu = inpw(FM_A(FM_ST1U)) ; stl = inpw(FM_A(FM_ST1L)) ; DB_GEN("Slow transmit complete",0,0,6) ; mac1_irq(smc,stu,stl) ; } if (is & IS_MINTR2) { /* FORMAC+ STU2(U/L) */ stu= inpw(FM_A(FM_ST2U)) ; stl= inpw(FM_A(FM_ST2L)) ; DB_GEN("Slow receive complete",0,0,6) ; DB_GEN("stl = %x : stu = %x",stl,stu,7) ; mac2_irq(smc,stu,stl) ; } if (is & IS_MINTR3) { /* FORMAC+ STU3(U/L) */ stu= inpw(FM_A(FM_ST3U)) ; stl= inpw(FM_A(FM_ST3L)) ; DB_GEN("FORMAC Mode Register 3",0,0,6) ; mac3_irq(smc,stu,stl) ; } if (is & IS_TIMINT) { /* Timer 82C54-2 */ timer_irq(smc) ;#ifdef NDIS_OS2 force_irq_pending = 0 ;#endif /* * out of RxD detection */ if (++smc->os.hwm.detec_count > 4) { /* * check out of RxD condition */ process_receive(smc) ; } } if (is & IS_TOKEN) { /* Restricted Token Monitor */ rtm_irq(smc) ; } if (is & IS_R1_P) { /* Parity error rx queue 1 */ /* clear IRQ */ outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ; SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ; } if (is & IS_R1_C) { /* Encoding error rx queue 1 */ /* clear IRQ */ outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ; SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ; } if (is & IS_XA_C) { /* Encoding error async tx q */ /* clear IRQ */ outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ; SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ; } if (is & IS_XS_C) { /* Encoding error sync tx q */ /* clear IRQ */ outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ; SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ; } } /* * Fast Tx complete Async/Sync Queue (BMU service) */ if (is & (IS_XS_F|IS_XA_F)) { DB_GEN("Fast tx complete queue",0,0,6) ; /* * clear IRQ, Note: no IRQ is lost, because * we always service both queues */ outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ; outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ; mac_drv_clear_txd(smc) ; llc_restart_tx(smc) ; } /* * Fast Rx Complete (BMU service) */ if (is & IS_R1_F) { DB_GEN("Fast receive complete",0,0,6) ; /* clear IRQ */#ifndef USE_BREAK_ISR outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ; process_receive(smc) ;#else process_receive(smc) ; if (smc->os.hwm.leave_isr) { force_irq = FALSE ; } else { outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ; process_receive(smc) ; }#endif }#ifndef NDIS_OS2 while ((mb = get_llc_rx(smc))) { smt_to_llc(smc,mb) ; }#else if (offDepth) post_proc() ; while (!offDepth && (mb = get_llc_rx(smc))) { smt_to_llc(smc,mb) ; } if (!offDepth && smc->os.hwm.rx_break) { process_receive(smc) ; }#endif if (smc->q.ev_get != smc->q.ev_put) { NDD_TRACE("CH2a",0,0,0) ; ev_dispatcher(smc) ; }#ifdef NDIS_OS2 post_proc() ; if (offDepth) { /* leave fddi_isr because */ break ; /* indications not allowed */ }#endif#ifdef USE_BREAK_ISR if (smc->os.hwm.leave_isr) { break ; /* leave fddi_isr */ }#endif /* NOTE: when the isr is left, no rx is pending */ } /* end of interrupt source polling loop */#ifdef USE_BREAK_ISR if (smc->os.hwm.leave_isr && force_irq) { smt_force_irq(smc) ; }#endif smc->os.hwm.isr_flag = FALSE ; NDD_TRACE("CH0E",0,0,0) ;}/* ------------------------------------------------------------- RECEIVE FUNCTIONS: -------------------------------------------------------------*/#ifndef NDIS_OS2/* * BEGIN_MANUAL_ENTRY(mac_drv_rx_mode) * void mac_drv_rx_mode(smc,mode) * * function DOWNCALL (fplus.c) * Corresponding to the parameter mode, the operating system * dependent module can activate several receive modes. * * para mode = 1: RX_ENABLE_ALLMULTI enable all multicasts * = 2: RX_DISABLE_ALLMULTI disable "enable all multicasts" * = 3: RX_ENABLE_PROMISC enable promiscuous * = 4: RX_DISABLE_PROMISC disable promiscuous * = 5: RX_ENABLE_NSA enable rec. of all NSA frames * (disabled after 'driver reset' & 'set station address') * = 6: RX_DISABLE_NSA disable rec. of all NSA frames * * = 21: RX_ENABLE_PASS_SMT ( see description ) * = 22: RX_DISABLE_PASS_SMT ( " " ) * = 23: RX_ENABLE_PASS_NSA ( " " ) * = 24: RX_DISABLE_PASS_NSA ( " " ) * = 25: RX_ENABLE_PASS_DB ( " " ) * = 26: RX_DISABLE_PASS_DB ( " " ) * = 27: RX_DISABLE_PASS_ALL ( " " ) * = 28: RX_DISABLE_LLC_PROMISC ( " " ) * = 29: RX_ENABLE_LLC_PROMISC ( " " ) * * * RX_ENABLE_PASS_SMT / RX_DISABLE_PASS_SMT * * If the operating system dependent module activates the * mode RX_ENABLE_PASS_SMT, the hardware module * duplicates all SMT frames with the frame control * FC_SMT_INFO and passes them to the LLC receive channel * by calling mac_drv_rx_init. * The SMT Frames which are sent by the local SMT and the NSA * frames whose A- and C-Indicator is not set are also duplicated * and passed. * The receive mode RX_DISABLE_PASS_SMT disables the passing * of SMT frames. * * RX_ENABLE_PASS_NSA / RX_DISABLE_PASS_NSA * * If the operating system dependent module activates the * mode RX_ENABLE_PASS_NSA, the hardware module * duplicates all NSA frames with frame control FC_SMT_NSA * and a set A-Indicator and passed them to the LLC * receive channel by calling mac_drv_rx_init. * All NSA Frames which are sent by the local SMT * are also duplicated and passed. * The receive mode RX_DISABLE_PASS_NSA disables the passing * of NSA frames with the A- or C-Indicator set. * * NOTE: For fear that the hardware module receives NSA frames with * a reset A-Indicator, the operating system dependent module * has to call mac_drv_rx_mode with the mode RX_ENABLE_NSA * before activate the RX_ENABLE_PASS_NSA mode and after every * 'driver reset' and 'set station address'. * * RX_ENABLE_PASS_DB / RX_DISABLE_PASS_DB * * If the operating system dependent module activates the * mode RX_ENABLE_PASS_DB, direct BEACON frames * (FC_BEACON frame control) are passed to the LLC receive * channel by mac_drv_rx_init. * The receive mode RX_DISABLE_PASS_DB disables the passing * of direct BEACON frames. * * RX_DISABLE_PASS_ALL * * Disables all special receives modes. It is equal to * call mac_drv_set_rx_mode successively with the * parameters RX_DISABLE_NSA, RX_DISABLE_PASS_SMT, * RX_DISABLE_PASS_NSA and RX_DISABLE_PASS_DB. * * RX_ENABLE_LLC_PROMISC * * (default) all received LLC frames and all SMT/NSA/DBEACON * frames depending on the attitude of the flags * PASS_SMT/PASS_NSA/PASS_DBEACON will be delivered to the * LLC layer * * RX_DISABLE_LLC_PROMISC * * all received SMT/NSA/DBEACON frames depending on the * attitude of the flags PASS_SMT/PASS_NSA/PASS_DBEACON * will be delivered to the LLC layer. * all received LLC frames with a directed address, Multicast * or Broadcast address will be delivered to the LLC * layer too. * * END_MANUAL_ENTRY */void mac_drv_rx_mode(smc,mode)struct s_smc *smc ;int mode ;{ switch(mode) { case RX_ENABLE_PASS_SMT: smc->os.hwm.pass_SMT = TRUE ; break ; case RX_DISABLE_PASS_SMT: smc->os.hwm.pass_SMT = FALSE ; break ; case RX_ENABLE_PASS_NSA: smc->os.hwm.pass_NSA = TRUE ; break ; case RX_DISABLE_PASS_NSA: smc->os.hwm.pass_NSA = FALSE ; break ; case RX_ENABLE_PASS_DB: smc->os.hwm.pass_DB = TRUE ; break ; case RX_DISABLE_PASS_DB: smc->os.hwm.pass_DB = FALSE ; break ; case RX_DISABLE_PASS_ALL: smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = FALSE ; smc->os.hwm.pass_DB = FALSE ; smc->os.hwm.pass_llc_promisc = TRUE ; mac_set_rx_mode(smc,RX_DISABLE_NSA) ; break ; case RX_DISABLE_LLC_PROMISC: smc->os.hwm.pass_llc_promisc = FALSE ; break ; case RX_ENABLE_LLC_PROMISC: smc->os.hwm.pass_llc_promisc = TRUE ; break ; case RX_ENABLE_ALLMULTI: case RX_DISABLE_ALLMULTI: case RX_ENABLE_PROMISC: case RX_DISABLE_PROMISC: case RX_ENABLE_NSA: case RX_DISABLE_NSA: default: mac_set_rx_mode(smc,mode) ; break ; }}#endif /* ifndef NDIS_OS2 *//* * process receive queue */void process_receive(smc)struct s_smc *smc ;{ int i ; int n ; int frag_count ; /* number of RxDs of the curr rx buf */ int used_frags ; /* number of RxDs of the curr frame */ struct s_smt_rx_queue *queue ; /* points to the queue ctl struct */ struct s_smt_fp_rxd volatile *r ; /* rxd pointer */ struct s_smt_fp_rxd volatile *rxd ; /* first rxd of rx frame */ u_long rbctrl ; /* receive buffer control word */ u_long rfsw ; /* receive frame status word */ u_short rx_used ; u_char far *virt ; char far *data ; SMbuf *mb ; u_char fc ; /* Frame control */ int len ; /* Frame length */ smc->os.hwm.detec_count = 0 ; queue = smc->hw.fp.rx[QUEUE_R1] ; NDD_TRACE("RHxB",0,0,0) ; for ( ; ; ) { r = queue->rx_curr_get ; rx_used = queue->rx_used ; frag_count = 0 ;#ifdef USE_BREAK_ISR if (smc->os.hwm.leave_isr) { goto rx_end ; }#endif#ifdef NDIS_OS2 if (offDepth) { smc->os.hwm.rx_break = 1 ; goto rx_end ; } smc->os.hwm.rx_break = 0 ;#endif#ifdef ODI2 if (smc->os.hwm.rx_break) { goto rx_end ; }#endif n = 0 ; do { DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ; DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; rbctrl = CR_READ(r->rxd_rbctrl) ; rbctrl = AIX_REVERSE(rbctrl) ; if (rbctrl & BMU_OWN) { NDD_TRACE("RHxE",r,rfsw,rbctrl) ; DB_RX("End of RxDs",0,0,4) ; goto rx_end ; } /* * out of RxD detection */ if (!rx_used) { SK_BREAK() ; SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ; /* Either we don't have an RxD or all * RxDs are filled. Therefore it's allowed * for to set the STOPPED flag */ smc->hw.hw_state = STOPPED ; mac_drv_clear_rx_queue(smc) ; smc->hw.hw_state = STARTED ; mac_drv_fill_rxd(smc) ; smc->os.hwm.detec_count = 0 ; goto rx_end ; } rfsw = AIX_REVERSE(r->rxd_rfsw) ; if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) { /* * The BMU_STF bit is deleted, 1 frame is * placed into more than 1 rx buffer * * skip frame by setting the rx len to 0 * * if fragment count == 0 * The missing STF bit belongs to the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -