📄 fplustm.c
字号:
set_int((char *) mac->mac_info+4,0) ; set_int((char *) mac->mac_info+8,0) ; copy_tx_mac(smc,td,(struct fddi_mac *)mac, smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ; /* end of claim/beacon queue */ outpw(FM_A(FM_EACB),smc->hw.fp.fifo.rx1_fifo_start-1) ; outpw(FM_A(FM_WPXSF),0) ; outpw(FM_A(FM_RPXSF),0) ;}static void formac_rcv_restart(struct s_smc *smc){ /* enable receive function */ SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ; outpw(FM_A(FM_CMDREG1),FM_ICLLR) ; /* clear receive lock */}void formac_tx_restart(struct s_smc *smc){ outpw(FM_A(FM_CMDREG1),FM_ICLLS) ; /* clear s-frame lock */ outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */}static void enable_formac(struct s_smc *smc){ /* set formac IMSK : 0 enables irq */ outpw(FM_A(FM_IMSK1U),~mac_imsk1u) ; outpw(FM_A(FM_IMSK1L),~mac_imsk1l) ; outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ; outpw(FM_A(FM_IMSK2L),~mac_imsk2l) ; outpw(FM_A(FM_IMSK3U),~mac_imsk3u) ; outpw(FM_A(FM_IMSK3L),~mac_imsk3l) ;}#if 0 /* Removed because the driver should use the ASICs TX complete IRQ. */ /* The FORMACs tx complete IRQ should be used any longer *//* BEGIN_MANUAL_ENTRY(if,func;others;4) void enable_tx_irq(smc, queue) struct s_smc *smc ; u_short queue ;Function DOWNCALL (SMT, fplustm.c) enable_tx_irq() enables the FORMACs transmit complete interrupt of the queue.Para queue = QUEUE_S: synchronous queue = QUEUE_A0: asynchronous queueNote After any ring operational change the transmit complete interrupts are disabled. The operating system dependent module must enable the transmit complete interrupt of a queue, - when it queues the first frame, because of no transmit resources are beeing available and - when it escapes from the function llc_restart_tx while some frames are still queued. END_MANUAL_ENTRY */void enable_tx_irq(struct s_smc *smc, u_short queue)/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */{ u_short imask ; imask = ~(inpw(FM_A(FM_IMSK1U))) ; if (queue == 0) { outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMS)) ; } if (queue == 1) { outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMA0)) ; }}/* BEGIN_MANUAL_ENTRY(if,func;others;4) void disable_tx_irq(smc, queue) struct s_smc *smc ; u_short queue ;Function DOWNCALL (SMT, fplustm.c) disable_tx_irq disables the FORMACs transmit complete interrupt of the queuePara queue = QUEUE_S: synchronous queue = QUEUE_A0: asynchronous queueNote The operating system dependent module should disable the transmit complete interrupts if it escapes from the function llc_restart_tx and no frames are queued. END_MANUAL_ENTRY */void disable_tx_irq(struct s_smc *smc, u_short queue)/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */{ u_short imask ; imask = ~(inpw(FM_A(FM_IMSK1U))) ; if (queue == 0) { outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMS)) ; } if (queue == 1) { outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMA0)) ; }}#endifstatic void disable_formac(struct s_smc *smc){ /* clear formac IMSK : 1 disables irq */ outpw(FM_A(FM_IMSK1U),MW) ; outpw(FM_A(FM_IMSK1L),MW) ; outpw(FM_A(FM_IMSK2U),MW) ; outpw(FM_A(FM_IMSK2L),MW) ; outpw(FM_A(FM_IMSK3U),MW) ; outpw(FM_A(FM_IMSK3L),MW) ;}static void mac_ring_up(struct s_smc *smc, int up){ if (up) { formac_rcv_restart(smc) ; /* enable receive function */ smc->hw.mac_ring_is_up = TRUE ; llc_restart_tx(smc) ; /* TX queue */ } else { /* disable receive function */ SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ; /* abort current transmit activity */ outpw(FM_A(FM_CMDREG2),FM_IACTR) ; smc->hw.mac_ring_is_up = FALSE ; }}/*--------------------------- ISR handling ----------------------------------*//* * mac1_irq is in drvfbi.c *//* * mac2_irq: status bits for the receive queue 1, and ring status * ring status indication bits */void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l){ u_short change_s2l ; u_short change_s2u ; /* (jd) 22-Feb-1999 * Restart 2_DMax Timer after end of claiming or beaconing */ if (code_s2u & (FM_SCLM|FM_SHICLM|FM_SBEC|FM_SOTRBEC)) { queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ; } else if (code_s2l & (FM_STKISS)) { queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ; } /* * XOR current st bits with the last to avoid useless RMT event queuing */ change_s2l = smc->hw.fp.s2l ^ code_s2l ; change_s2u = smc->hw.fp.s2u ^ code_s2u ; if ((change_s2l & FM_SRNGOP) || (!smc->hw.mac_ring_is_up && ((code_s2l & FM_SRNGOP)))) { if (code_s2l & FM_SRNGOP) { mac_ring_up(smc,1) ; queue_event(smc,EVENT_RMT,RM_RING_OP) ; smc->mib.m[MAC0].fddiMACRingOp_Ct++ ; } else { mac_ring_up(smc,0) ; queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ; } goto mac2_end ; } if (code_s2l & FM_SMISFRM) { /* missed frame */ smc->mib.m[MAC0].fddiMACNotCopied_Ct++ ; } if (code_s2u & (FM_SRCVOVR | /* recv. FIFO overflow */ FM_SRBFL)) { /* recv. buffer full */ smc->hw.mac_ct.mac_r_restart_counter++ ;/* formac_rcv_restart(smc) ; */ smt_stat_counter(smc,1) ;/* goto mac2_end ; */ } if (code_s2u & FM_SOTRBEC) queue_event(smc,EVENT_RMT,RM_OTHER_BEACON) ; if (code_s2u & FM_SMYBEC) queue_event(smc,EVENT_RMT,RM_MY_BEACON) ; if (change_s2u & code_s2u & FM_SLOCLM) { DB_RMTN(2,"RMT : lower claim received\n",0,0) ; } if ((code_s2u & FM_SMYCLM) && !(code_s2l & FM_SDUPCLM)) { /* * This is my claim and that claim is not detected as a * duplicate one. */ queue_event(smc,EVENT_RMT,RM_MY_CLAIM) ; } if (code_s2l & FM_SDUPCLM) { /* * If a duplicate claim frame (same SA but T_Bid != T_Req) * this flag will be set. * In the RMT state machine we need a RM_VALID_CLAIM event * to do the appropriate state change. * RM(34c) */ queue_event(smc,EVENT_RMT,RM_VALID_CLAIM) ; } if (change_s2u & code_s2u & FM_SHICLM) { DB_RMTN(2,"RMT : higher claim received\n",0,0) ; } if ( (code_s2l & FM_STRTEXP) || (code_s2l & FM_STRTEXR) ) queue_event(smc,EVENT_RMT,RM_TRT_EXP) ; if (code_s2l & FM_SMULTDA) { /* * The MAC has found a 2. MAC with the same address. * Signal dup_addr_test = failed to RMT state machine. * RM(25) */ smc->r.dup_addr_test = DA_FAILED ; queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ; } if (code_s2u & FM_SBEC) smc->hw.fp.err_stats.err_bec_stat++ ; if (code_s2u & FM_SCLM) smc->hw.fp.err_stats.err_clm_stat++ ; if (code_s2l & FM_STVXEXP) smc->mib.m[MAC0].fddiMACTvxExpired_Ct++ ; if ((code_s2u & (FM_SBEC|FM_SCLM))) { if (!(change_s2l & FM_SRNGOP) && (smc->hw.fp.s2l & FM_SRNGOP)) { mac_ring_up(smc,0) ; queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ; mac_ring_up(smc,1) ; queue_event(smc,EVENT_RMT,RM_RING_OP) ; smc->mib.m[MAC0].fddiMACRingOp_Ct++ ; } } if (code_s2l & FM_SPHINV) smc->hw.fp.err_stats.err_phinv++ ; if (code_s2l & FM_SSIFG) smc->hw.fp.err_stats.err_sifg_det++ ; if (code_s2l & FM_STKISS) smc->hw.fp.err_stats.err_tkiss++ ; if (code_s2l & FM_STKERR) smc->hw.fp.err_stats.err_tkerr++ ; if (code_s2l & FM_SFRMCTR) smc->mib.m[MAC0].fddiMACFrame_Ct += 0x10000L ; if (code_s2l & FM_SERRCTR) smc->mib.m[MAC0].fddiMACError_Ct += 0x10000L ; if (code_s2l & FM_SLSTCTR) smc->mib.m[MAC0].fddiMACLost_Ct += 0x10000L ; if (code_s2u & FM_SERRSF) { SMT_PANIC(smc,SMT_E0114, SMT_E0114_MSG) ; }mac2_end: /* notice old status */ smc->hw.fp.s2l = code_s2l ; smc->hw.fp.s2u = code_s2u ; outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ;}/* * mac3_irq: receive queue 2 bits and address detection bits */void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l){ UNUSED(code_s3l) ; if (code_s3u & (FM_SRCVOVR2 | /* recv. FIFO overflow */ FM_SRBFL2)) { /* recv. buffer full */ smc->hw.mac_ct.mac_r_restart_counter++ ; smt_stat_counter(smc,1); } if (code_s3u & FM_SRPERRQ2) { /* parity error receive queue 2 */ SMT_PANIC(smc,SMT_E0115, SMT_E0115_MSG) ; } if (code_s3u & FM_SRPERRQ1) { /* parity error receive queue 2 */ SMT_PANIC(smc,SMT_E0116, SMT_E0116_MSG) ; }}/* * take formac offline */static void formac_offline(struct s_smc *smc){ outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */ /* disable receive function */ SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ; /* FORMAC+ 'Initialize Mode' */ SETMASK(FM_A(FM_MDREG1),FM_MINIT,FM_MMODE) ; disable_formac(smc) ; smc->hw.mac_ring_is_up = FALSE ; smc->hw.hw_state = STOPPED ;}/* * bring formac online */static void formac_online(struct s_smc *smc){ enable_formac(smc) ; SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT | smc->hw.fp.rx_mode, FM_MMODE | FM_SELRA | FM_ADDRX) ;}/* * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon) */int init_fplus(struct s_smc *smc){ smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ; smc->hw.fp.rx_mode = FM_MDAMA ; smc->hw.fp.group_addr = fddi_broadcast ; smc->hw.fp.func_addr = 0 ; smc->hw.fp.frselreg_init = 0 ; init_driver_fplus(smc) ; if (smc->s.sas == SMT_DAS) smc->hw.fp.mdr3init |= FM_MENDAS ; smc->hw.mac_ct.mac_nobuf_counter = 0 ; smc->hw.mac_ct.mac_r_restart_counter = 0 ; smc->hw.fp.fm_st1u = (HW_PTR) ADDR(B0_ST1U) ; smc->hw.fp.fm_st1l = (HW_PTR) ADDR(B0_ST1L) ; smc->hw.fp.fm_st2u = (HW_PTR) ADDR(B0_ST2U) ; smc->hw.fp.fm_st2l = (HW_PTR) ADDR(B0_ST2L) ; smc->hw.fp.fm_st3u = (HW_PTR) ADDR(B0_ST3U) ; smc->hw.fp.fm_st3l = (HW_PTR) ADDR(B0_ST3L) ; smc->hw.fp.s2l = smc->hw.fp.s2u = 0 ; smc->hw.mac_ring_is_up = 0 ; mac_counter_init(smc) ; /* convert BCKL units to symbol time */ smc->hw.mac_pa.t_neg = (u_long)0 ; smc->hw.mac_pa.t_pri = (u_long)0 ; /* make sure all PCI settings are correct */ mac_do_pci_fix(smc) ; return(init_mac(smc,1)) ; /* enable_formac(smc) ; */}static int init_mac(struct s_smc *smc, int all){ u_short t_max,x ; u_long time=0 ; /* * clear memory */ outpw(FM_A(FM_MDREG1),FM_MINIT) ; /* FORMAC+ init mode */ set_formac_addr(smc) ; outpw(FM_A(FM_MDREG1),FM_MMEMACT) ; /* FORMAC+ memory activ mode */ /* Note: Mode register 2 is set here, incase parity is enabled. */ outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ; if (all) { init_ram(smc) ; } else { /* * reset the HPI, the Master and the BMUs */ outp(ADDR(B0_CTRL), CTRL_HPI_SET) ; time = hwt_quick_read(smc) ; } /* * set all pointers, frames etc */ smt_split_up_fifo(smc) ; init_tx(smc) ; init_rx(smc) ; init_rbc(smc) ; build_claim_beacon(smc,smc->mib.m[MAC0].fddiMACT_Req) ; /* set RX threshold */ /* see Errata #SN2 Phantom receive overflow */ outpw(FM_A(FM_FRMTHR),14<<12) ; /* switch on */ /* set formac work mode */ outpw(FM_A(FM_MDREG1),MDR1INIT | FM_SELRA | smc->hw.fp.rx_mode) ; outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ; outpw(FM_A(FM_MDREG3),smc->hw.fp.mdr3init) ; outpw(FM_A(FM_FRSELREG),smc->hw.fp.frselreg_init) ; /* set timer */ /* * errata #22 fplus: * T_MAX must not be FFFE * or one of FFDF, FFB8, FF91 (-0x27 etc..) */ t_max = (u_short)(smc->mib.m[MAC0].fddiMACT_Max/32) ; x = t_max/0x27 ; x *= 0x27 ; if ((t_max == 0xfffe) || (t_max - x == 0x16)) t_max-- ; outpw(FM_A(FM_TMAX),(u_short)t_max) ; /* BugFix for report #10204 */ if (smc->mib.m[MAC0].fddiMACTvxValue < (u_long) (- US2BCLK(52))) { outpw(FM_A(FM_TVX), (u_short) (- US2BCLK(52))/255 & MB) ; } else { outpw(FM_A(FM_TVX), (u_short)((smc->mib.m[MAC0].fddiMACTvxValue/255) & MB)) ; } outpw(FM_A(FM_CMDREG1),FM_ICLLS) ; /* clear s-frame lock */ outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */ outpw(FM_A(FM_CMDREG1),FM_ICLLR); /* clear receive lock */ /* Auto unlock receice threshold for receive queue 1 and 2 */ outpw(FM_A(FM_UNLCKDLY),(0xff|(0xff<<8))) ; rtm_init(smc) ; /* RT-Monitor */ if (!all) { /* * after 10ms, reset the BMUs and repair the rings */ hwt_wait_time(smc,time,MS2BCLK(10)) ; outpd(ADDR(B0_R1_CSR),CSR_SET_RESET) ; outpd(ADDR(B0_XA_CSR),CSR_SET_RESET) ; outpd(ADDR(B0_XS_CSR),CSR_SET_RESET) ; outp(ADDR(B0_CTRL), CTRL_HPI_CLR) ; outpd(ADDR(B0_R1_CSR),CSR_CLR_RESET) ; outpd(ADDR(B0_XA_CSR),CSR_CLR_RESET) ; outpd(ADDR(B0_XS_CSR),CSR_CLR_RESET) ; if (!smc->hw.hw_is_64bit) { outpd(ADDR(B4_R1_F), RX_WATERMARK) ; outpd(ADDR(B5_XA_F), TX_WATERMARK) ; outpd(ADDR(B5_XS_F), TX_WATERMARK) ; } smc->hw.hw_state = STOPPED ; mac_drv_repair_descr(smc) ; } smc->hw.hw_state = STARTED ; return(0) ;}/* * called by CFM */void config_mux(struct s_smc *smc, int mux){ plc_config_mux(smc,mux) ; SETMASK(FM_A(FM_MDREG1),FM_SELRA,FM_SELRA) ;}/* * called by RMT * enable CLAIM/BEACON interrupts * (only called if these events are of interest, e.g. in DETECT state * the interrupt must not be permanently enabled * RMT calls this function periodically (timer driven polling) */void sm_mac_check_beacon_claim(struct s_smc *smc){ /* set formac IMSK : 0 enables irq */ outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ; /* the driver must receive the directed beacons */ formac_rcv_restart(smc) ; process_receive(smc) ;}/*-------------------------- interface functions ----------------------------*//* * control MAC layer (called by RMT) */void sm_ma_control(struct s_smc *smc, int mode){ switch(mode) { case MA_OFFLINE : /* Add to make the MAC offline in RM0_ISOLATED state */ formac_offline(smc) ; break ; case MA_RESET : (void)init_mac(smc,0) ; break ; case MA_BEACON : formac_online(smc) ; break ; case MA_DIRECTED : directed_beacon(smc) ; break ; case MA_TREQ :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -