📄 velocity_hw.c
字号:
CSR_WRITE_1(hw, 0, MAC_REG_CAMADDR); /*Select CAM mask */ BYTE_REG_BITS_SET(hw, CAMCR_PS_MAR,CAMCR_PS1|CAMCR_PS0, MAC_REG_CAMCR);}void mac_set_cam(struct velocity_hw *hw, int idx, PU8 addr, VELOCITY_CAM_TYPE cam_type) { int i; /*Select CAM mask*/ BYTE_REG_BITS_SET(hw, CAMCR_PS_CAM_DATA,CAMCR_PS1|CAMCR_PS0, MAC_REG_CAMCR); idx&=(64-1); if (cam_type==VELOCITY_VLAN_ID_CAM) CSR_WRITE_1(hw, CAMADDR_CAMEN | CAMADDR_VCAMSL | idx, MAC_REG_CAMADDR); else CSR_WRITE_1(hw, CAMADDR_CAMEN|idx, MAC_REG_CAMADDR); if (cam_type==VELOCITY_VLAN_ID_CAM) CSR_WRITE_2(hw, *((PU16) addr), MAC_REG_MAR); else { for (i=0;i<6;i++) { CSR_WRITE_1(hw, *addr++,MAC_REG_MAR+i); } } BYTE_REG_BITS_ON(hw, CAMCR_CAMWR, MAC_REG_CAMCR); udelay(10); CSR_WRITE_1(hw, 0, MAC_REG_CAMADDR); /*Select CAM mask*/ BYTE_REG_BITS_SET(hw, CAMCR_PS_MAR,CAMCR_PS1|CAMCR_PS0, MAC_REG_CAMCR);}void mac_get_cam(struct velocity_hw *hw, int idx, PU8 addr, VELOCITY_CAM_TYPE cam_type) { int i; /*Select CAM mask*/ BYTE_REG_BITS_SET(hw, CAMCR_PS_CAM_DATA,CAMCR_PS1|CAMCR_PS0, MAC_REG_CAMCR); idx&=(64-1); if (cam_type==VELOCITY_VLAN_ID_CAM) CSR_WRITE_1(hw, CAMADDR_CAMEN | CAMADDR_VCAMSL|idx, MAC_REG_CAMADDR); else CSR_WRITE_1(hw, CAMADDR_CAMEN |idx, MAC_REG_CAMADDR); BYTE_REG_BITS_ON(hw, CAMCR_CAMRD, MAC_REG_CAMCR); udelay(10); if (cam_type==VELOCITY_VLAN_ID_CAM) *((PU16) addr)=CSR_READ_2(hw, MAC_REG_MAR); else for (i=0;i<6;i++, addr++) *((PU8)addr)=CSR_READ_1(hw, MAC_REG_MAR+i); CSR_WRITE_1(hw, 0, MAC_REG_CAMADDR); /*Select CAM mask*/ BYTE_REG_BITS_SET(hw, CAMCR_PS_MAR,CAMCR_PS1|CAMCR_PS0, MAC_REG_CAMCR);}void mac_wol_reset(struct velocity_hw *hw) { /* Turn off SWPTAG right after leaving power mode */ BYTE_REG_BITS_OFF(hw, STICKHW_SWPTAG,MAC_REG_STICKHW); /* clear sticky bits */ BYTE_REG_BITS_OFF(hw, (STICKHW_DS1|STICKHW_DS0), MAC_REG_STICKHW); BYTE_REG_BITS_OFF(hw, CHIPGCR_FCGMII,MAC_REG_CHIPGCR); BYTE_REG_BITS_OFF(hw, CHIPGCR_FCMODE,MAC_REG_CHIPGCR); /* disable force PME-enable */ CSR_WRITE_1(hw, WOLCFG_PMEOVR, MAC_REG_WOLCFG_CLR); /* disable power-event config bit */ CSR_WRITE_2(hw, 0xFFFF, MAC_REG_WOLCR0_CLR); /* clear power status */ CSR_WRITE_2(hw, 0xFFFF, MAC_REG_WOLSR0_CLR);}void SafeDisableMiiAutoPoll (struct velocity_hw *hw) { WORD ww; /* turn off MAUTO */ CSR_WRITE_1(hw, 0, MAC_REG_MIICR); for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { udelay(1); if (BYTE_REG_BITS_IS_ON(hw, MIISR_MIDLE, MAC_REG_MIISR)) break; }}void EnableMiiAutoPoll(struct velocity_hw* hw) { int ii; CSR_WRITE_1(hw, 0, MAC_REG_MIICR); CSR_WRITE_1(hw, MIIADR_SWMPL, MAC_REG_MIIADR); for (ii=0; ii<W_MAX_TIMEOUT; ii++) { udelay(1); if (BYTE_REG_BITS_IS_ON(hw, MIISR_MIDLE, MAC_REG_MIISR)) break; } CSR_WRITE_1(hw, MIICR_MAUTO, MAC_REG_MIICR); for (ii=0; ii<W_MAX_TIMEOUT; ii++) { udelay(1); if (!BYTE_REG_BITS_IS_ON(hw, MIISR_MIDLE, MAC_REG_MIISR)) break; }}void velocity_init_cam_filter(struct velocity_hw *hw){ /* turn on MCFG_PQEN, turn off MCFG_RTGOPT */ WORD_REG_BITS_SET(hw, MCFG_PQEN, MCFG_RTGOPT, MAC_REG_MCFG0); WORD_REG_BITS_ON(hw, MCFG_VIDFR, MAC_REG_MCFG0); /* Disable all CAM */ memset(hw->abyVCAMMask, 0, sizeof(U8)*8); memset(hw->abyMCAMMask, 0, sizeof(U8)*8); mac_set_cam_mask(hw,hw->abyVCAMMask,VELOCITY_VLAN_ID_CAM); mac_set_cam_mask(hw,hw->abyMCAMMask,VELOCITY_MULTICAST_CAM); /* Enable first VCAM */ if (hw->flags & VELOCITY_FLAGS_TAGGING) { /* if Tagging option is enabled and VLAN ID is not zero, then turn on MCFG_RTGOPT also */ if (hw->sOpts.vid != 0) WORD_REG_BITS_ON(hw, MCFG_RTGOPT, MAC_REG_MCFG0); mac_set_cam(hw, 0, (PU8)&(hw->sOpts.vid), VELOCITY_VLAN_ID_CAM); hw->abyVCAMMask[0] |= 1; mac_set_cam_mask(hw, hw->abyVCAMMask, VELOCITY_VLAN_ID_CAM); } else { U16 wTemp = 0; mac_set_cam(hw, 0, (PU8)&wTemp, VELOCITY_VLAN_ID_CAM); wTemp = 1; mac_set_cam_mask(hw, (PU8)&(wTemp), VELOCITY_VLAN_ID_CAM); }}void velocity_update_hw_mibs(struct velocity_hw *hw) { U32 dwTmp; int i; BYTE_REG_BITS_ON(hw, MIBCR_MIBFLSH, MAC_REG_MIBCR); while (BYTE_REG_BITS_IS_ON(hw, MIBCR_MIBFLSH, MAC_REG_MIBCR)); BYTE_REG_BITS_ON(hw, MIBCR_MPTRINI, MAC_REG_MIBCR); for (i=0;i<HW_MIB_SIZE;i++) { dwTmp=CSR_READ_4(hw, MAC_REG_MIBREAD) & 0x00FFFFFFUL; hw->adwHWMIBCounters[i]+=dwTmp; }}void velocity_rx_reset(struct velocity_hw *hw){ int i; hw->iCurrRDIdx = 0; /* init state, all RD is chip's */ for(i=0; i<hw->sOpts.nRxDescs; i++) hw->aRDRing[i].rdesc0 |= cpu_to_le32(RDESC0_OWN); CSR_WRITE_2(hw, hw->sOpts.nRxDescs, MAC_REG_RBRDU); CSR_WRITE_4(hw, hw->rd_pool_dma, MAC_REG_RDBASE_LO); CSR_WRITE_2(hw, 0, MAC_REG_RDINDX); CSR_WRITE_2(hw, hw->sOpts.nRxDescs-1, MAC_REG_RDCSIZE);}void velocity_print_link_status(struct velocity_hw *hw) { if (hw->mii_status & VELOCITY_LINK_FAIL) { VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "failed to detect cable link.\n"); } else { if (hw->sOpts.spd_dpx == SPD_DPX_AUTO) { VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "Link auto-negotiation"); if (hw->mii_status & VELOCITY_SPEED_1000) VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO," speed 1000M bps"); else if (hw->mii_status & VELOCITY_SPEED_100) VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO," speed 100M bps"); else VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO," speed 10M bps"); if (hw->mii_status & VELOCITY_DUPLEX_FULL) VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " full duplex\n"); else VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " half duplex\n"); } else { VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "Link forced"); switch(hw->sOpts.spd_dpx) { case SPD_DPX_100_HALF: VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " speed 100M bps half duplex\n"); break; case SPD_DPX_100_FULL: VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " speed 100M bps full duplex\n"); break; case SPD_DPX_10_HALF: VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " speed 10M bps half duplex\n"); break; case SPD_DPX_10_FULL: VELOCITY_PRT(hw->msglevel, MSG_LEVEL_INFO, " speed 10M bps full duplex\n"); break; default: break; } } }}int velocity_set_media_mode(struct velocity_hw *hw, SPD_DPX_OPT spd_dpx){ U16 wANARMask; U16 wOrigANAR, wOrigG1000CR; U16 wANAR=0, wG1000CR=0; U32 status=VELOCITY_LINK_UNCHANGE; velocity_mii_read(hw, MII_REG_ANAR, &wOrigANAR); velocity_mii_read(hw, MII_REG_G1000CR, &wOrigG1000CR); wANARMask = wOrigANAR; wANARMask &= ~(ANLPAR_ASMDIR|ANLPAR_PAUSE|ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10); wOrigANAR &= (ANLPAR_ASMDIR|ANLPAR_PAUSE|ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10); wOrigG1000CR &= (G1000CR_1000FD|G1000CR_1000); /* Set mii link status */ wANAR = set_mii_flow_control(hw); if (PHYID_GET_PHY_ID(hw->dwPHYId) == PHYID_CICADA_CS8201) { MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, hw); } /* if connection type is AUTO */ if (spd_dpx == SPD_DPX_AUTO) { /*VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "Velocity is AUTO mode\n");*/ /* auto */ wANAR |= (ANAR_TXFD|ANAR_TX|ANAR_10FD|ANAR_10); wG1000CR |= (G1000CR_1000FD|G1000CR_1000); /* clear force MAC mode bit */ BYTE_REG_BITS_OFF(hw, CHIPGCR_FCMODE, MAC_REG_CHIPGCR); /* set duplex mode of MAC according to duplex mode of MII */ MII_REG_BITS_ON(BMCR_SPEED1G, MII_REG_BMCR, hw); if(wOrigANAR != wANAR || wOrigG1000CR != wG1000CR) { wANAR |= wANARMask; velocity_mii_write(hw, MII_REG_ANAR, wANAR); MII_REG_BITS_ON(G1000CR_1000FD|G1000CR_1000, MII_REG_G1000CR, hw); /* enable AUTO-NEGO mode */ MII_REG_BITS_ON((BMCR_AUTO | BMCR_REAUTO), MII_REG_BMCR, hw); /* Link changed */ status = VELOCITY_LINK_CHANGE; } } else { U8 byCHIPGCR; /* 1. if it's 3119, disable frame bursting in halfduplex mode and // enable it in fullduplex mode // 2. set correct MII/GMII and half/full duplex mode in CHIPGCR // 3. only enable CD heart beat counter in 10HD mode // set force MAC mode bit */ BYTE_REG_BITS_ON(hw, CHIPGCR_FCMODE, MAC_REG_CHIPGCR); byCHIPGCR = CSR_READ_1(hw, MAC_REG_CHIPGCR); byCHIPGCR &= ~CHIPGCR_FCGMII; if( spd_dpx == SPD_DPX_100_FULL || spd_dpx == SPD_DPX_10_FULL ){ byCHIPGCR |= CHIPGCR_FCFDX; CSR_WRITE_1(hw, byCHIPGCR, MAC_REG_CHIPGCR); /*VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "Set Velocity to forced full mode\n");*/ if (hw->byRevId < REV_ID_VT3216_A0) BYTE_REG_BITS_OFF(hw, TCR_TB2BDIS, MAC_REG_TCR); } else { byCHIPGCR &= ~CHIPGCR_FCFDX; /*VELOCITY_HW_PRT(hw, MSG_LEVEL_INFO, "Set Velocity to forced half mode\n");*/ CSR_WRITE_1(hw, byCHIPGCR, MAC_REG_CHIPGCR); if (hw->byRevId < REV_ID_VT3216_A0) BYTE_REG_BITS_ON(hw, TCR_TB2BDIS, MAC_REG_TCR); } /* No force 1000Mbps */ wG1000CR=0; switch(spd_dpx) { case SPD_DPX_100_HALF: wANAR |= ANLPAR_TX; break; case SPD_DPX_100_FULL: wANAR |= ANLPAR_TXFD; break; case SPD_DPX_10_HALF: wANAR |= ANLPAR_10; break; case SPD_DPX_10_FULL: wANAR |= ANLPAR_10FD; break; default: break; } if(wANAR != wOrigANAR || wG1000CR != wOrigG1000CR) { wANAR |= wANARMask; velocity_mii_write(hw, MII_REG_ANAR, wANAR); MII_REG_BITS_OFF(G1000CR_1000FD|G1000CR_1000, MII_REG_G1000CR, hw); /* enable AUTO-NEGO mode */ MII_REG_BITS_ON((BMCR_AUTO | BMCR_REAUTO), MII_REG_BMCR, hw); /* Link changed */ status = VELOCITY_LINK_CHANGE; } } return status;}void velocity_adaptive_init(struct velocity_hw *hw){ hw->IntMask = INT_MASK_DEF; /*------------------------------------------------------------ // [1.18] Adaptive Interrupt // Set Tx Interrupt Suppression Threshold: 31 (0x001F) */ CSR_WRITE_1(hw, CAMCR_PS0, MAC_REG_CAMCR); CSR_WRITE_2(hw, 0x001F, MAC_REG_ISR_CTL); /*pInfo->IntMask &= ~(ISR_PTXI | ISR_PTX0I | ISR_PTX1I | ISR_PTX2I | ISR_PTX3I);*/ /* Set Rx Interrupt Suppression Threshold: 31 (0x001F) */ CSR_WRITE_1(hw, CAMCR_PS1, MAC_REG_CAMCR); CSR_WRITE_2(hw, 0x001F, MAC_REG_ISR_CTL); /*pInfo->IntMask &= ~ISR_PRXI;*/ /* Select page to interrupt hold timer */ CSR_WRITE_1(hw, 0x00, MAC_REG_CAMCR); /* Modify IMR */ hw->IntMask &= ~(ISR_PTXI | ISR_PTX0I | ISR_PTX1I | ISR_PTX2I | ISR_PTX3I | ISR_PRXI); /* Enable Memory-Read-Line, both VT3119 and VT3216 // ==> DCFG1_XMRL = 0 */ BYTE_REG_BITS_OFF(hw, DCFG1_XMRL, MAC_REG_DCFG1);}void velocity_init_register_reset( struct velocity_hw *hw){ /* reset RX to prevent RX pointer not on the 4X location */ velocity_rx_reset(hw); mac_rx_queue_run(hw); mac_rx_queue_wake(hw); CSR_WRITE_4(hw, CR0_STOP, MAC_REG_CR0_CLR); CSR_WRITE_4(hw, (CR0_DPOLL|CR0_TXON|CR0_RXON|CR0_STRT), MAC_REG_CR0_SET); if (velocity_set_media_mode(hw,hw->sOpts.spd_dpx)!=VELOCITY_LINK_CHANGE) { hw->mii_status = check_connectiontype(hw); velocity_print_link_status(hw); } enable_flow_control_ability(hw); mac_clear_isr(hw);}void velocity_init_register_cold( struct velocity_hw *hw){ int i; U32 mii_status; mac_set_rx_thresh(hw, hw->sOpts.rx_thresh); mac_set_dma_length(hw, hw->sOpts.DMA_length); CSR_WRITE_1(hw, (WOLCFG_SAM | WOLCFG_SAB), MAC_REG_WOLCFG_SET); /* back off algorithm use original IEEE standard */ BYTE_REG_BITS_SET(hw, CFGB_OFSET, (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT), MAC_REG_CFGB); /* enable MII auto-polling */ EnableMiiAutoPoll(hw); velocity_adaptive_init(hw); CSR_WRITE_4(hw, hw->rd_pool_dma, MAC_REG_RDBASE_LO); CSR_WRITE_2(hw, hw->sOpts.nRxDescs-1, MAC_REG_RDCSIZE); mac_rx_queue_run(hw); mac_rx_queue_wake(hw); CSR_WRITE_2(hw, hw->sOpts.nTxDescs-1, MAC_REG_TDCSIZE); for (i=0;i<hw->nTxQueues;i++) { CSR_WRITE_4(hw, hw->td_pool_dma[i], (MAC_REG_TDBASE_LO+(i*4)) ); mac_tx_queue_run(hw,i); } velocity_init_cam_filter(hw); init_flow_control_register(hw); CSR_WRITE_4(hw, CR0_STOP, MAC_REG_CR0_CLR); CSR_WRITE_4(hw, (CR0_DPOLL|CR0_TXON|CR0_RXON|CR0_STRT), MAC_REG_CR0_SET); mii_status = velocity_get_opt_media_mode(hw); mac_clear_isr(hw); mii_init(hw, mii_status);#ifdef LINUX if (velocity_set_media_mode(hw,hw->sOpts.spd_dpx) != VELOCITY_LINK_CHANGE) { hw->mii_status = check_connectiontype(hw); velocity_print_link_status(hw); }#else velocity_set_media_mode(hw,hw->sOpts.spd_dpx);#endif enable_flow_control_ability(hw); mac_hw_mibs_init(hw); mac_write_int_mask(hw->IntMask, hw); mac_clear_isr(hw);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -