📄 sis900.c
字号:
nic->transmit = sis900_transmit; return 1;}/* * EEPROM Routines: These functions read and write to EEPROM for * retrieving the MAC address and other configuration information about * the card. *//* Delay between EEPROM clock transitions. */#define eeprom_delay() inl(ee_addr)/* Function: sis900_read_eeprom * * Description: reads and returns a given location from EEPROM * * Arguments: int location: requested EEPROM location * * Returns: u16: contents of requested EEPROM location * *//* Read Serial EEPROM through EEPROM Access Register, Note that location is in word (16 bits) unit */static u16 sis900_read_eeprom(int location){ int i; u16 retval = 0; long ee_addr = ioaddr + mear; u32 read_cmd = location | EEread; outl(0, ee_addr); eeprom_delay(); outl(EECLK, ee_addr); eeprom_delay(); /* Shift the read command (9) bits out. */ for (i = 8; i >= 0; i--) { u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS; outl(dataval, ee_addr); eeprom_delay(); outl(dataval | EECLK, ee_addr); eeprom_delay(); } outb(EECS, ee_addr); eeprom_delay(); /* read the 16-bits data in */ for (i = 16; i > 0; i--) { outl(EECS, ee_addr); eeprom_delay(); outl(EECS | EECLK, ee_addr); eeprom_delay(); retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0); eeprom_delay(); } /* Terminate the EEPROM access. */ outl(0, ee_addr); eeprom_delay(); outl(EECLK, ee_addr); return (retval);}#define sis900_mdio_delay() inl(mdio_addr)/* Read and write the MII management registers using software-generated serial MDIO protocol. Note that the command bits and data bits are send out seperately */static void sis900_mdio_idle(long mdio_addr){ outl(MDIO | MDDIR, mdio_addr); sis900_mdio_delay(); outl(MDIO | MDDIR | MDC, mdio_addr);}/* Syncronize the MII management interface by shifting 32 one bits out. */static void sis900_mdio_reset(long mdio_addr){ int i; for (i = 31; i >= 0; i--) { outl(MDDIR | MDIO, mdio_addr); sis900_mdio_delay(); outl(MDDIR | MDIO | MDC, mdio_addr); sis900_mdio_delay(); } return;}static u16 sis900_mdio_read(int phy_id, int location){ long mdio_addr = ioaddr + mear; int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift); u16 retval = 0; int i; sis900_mdio_reset(mdio_addr); sis900_mdio_idle(mdio_addr); for (i = 15; i >= 0; i--) { int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR; outl(dataval, mdio_addr); sis900_mdio_delay(); outl(dataval | MDC, mdio_addr); sis900_mdio_delay(); } /* Read the 16 data bits. */ for (i = 16; i > 0; i--) { outl(0, mdio_addr); sis900_mdio_delay(); retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0); outl(MDC, mdio_addr); sis900_mdio_delay(); } outl(0x00, mdio_addr); return retval;}static void sis900_mdio_write(int phy_id, int location, int value){ long mdio_addr = ioaddr + mear; int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift); int i; sis900_mdio_reset(mdio_addr); sis900_mdio_idle(mdio_addr); /* Shift the command bits out. */ for (i = 15; i >= 0; i--) { int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR; outb(dataval, mdio_addr); sis900_mdio_delay(); outb(dataval | MDC, mdio_addr); sis900_mdio_delay(); } sis900_mdio_delay(); /* Shift the value bits out. */ for (i = 15; i >= 0; i--) { int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR; outl(dataval, mdio_addr); sis900_mdio_delay(); outl(dataval | MDC, mdio_addr); sis900_mdio_delay(); } sis900_mdio_delay(); /* Clear out extra bits. */ for (i = 2; i > 0; i--) { outb(0, mdio_addr); sis900_mdio_delay(); outb(MDC, mdio_addr); sis900_mdio_delay(); } outl(0x00, mdio_addr); return;}/* Function: sis900_init * * Description: resets the ethernet controller chip and various * data structures required for sending and receiving packets. * * Arguments: struct nic *nic: NIC data structure * * returns: void. */static voidsis900_init(struct nic *nic){ /* Soft reset the chip. */ sis900_reset(nic); sis900_init_rxfilter(nic); sis900_init_txd(nic); sis900_init_rxd(nic); sis900_set_rx_mode(nic); sis900_check_mode(nic); outl(RxENA| inl(ioaddr + cr), ioaddr + cr);}/* * Function: sis900_reset * * Description: disables interrupts and soft resets the controller chip * * Arguments: struct nic *nic: NIC data structure * * Returns: void. */static void sis900_reset(struct nic *nic __unused){ int i = 0; u32 status = TxRCMP | RxRCMP; outl(0, ioaddr + ier); outl(0, ioaddr + imr); outl(0, ioaddr + rfcr); outl(RxRESET | TxRESET | RESET | inl(ioaddr + cr), ioaddr + cr); /* Check that the chip has finished the reset. */ while (status && (i++ < 1000)) { status ^= (inl(isr + ioaddr) & status); } if( (pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV) ) outl(PESEL | RND_CNT, ioaddr + cfg); else outl(PESEL, ioaddr + cfg);}/* Function: sis_init_rxfilter * * Description: sets receive filter address to our MAC address * * Arguments: struct nic *nic: NIC data structure * * returns: void. */static voidsis900_init_rxfilter(struct nic *nic){ u32 rfcrSave; int i; rfcrSave = inl(rfcr + ioaddr); /* disable packet filtering before setting filter */ outl(rfcrSave & ~RFEN, rfcr + ioaddr); /* load MAC addr to filter data register */ for (i = 0 ; i < 3 ; i++) { u32 w; w = (u32) *((u16 *)(nic->node_addr)+i); outl((i << RFADDR_shift), ioaddr + rfcr); outl(w, ioaddr + rfdr); if (sis900_debug > 0) printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n", i, inl(ioaddr + rfdr)); } /* enable packet filitering */ outl(rfcrSave | RFEN, rfcr + ioaddr);}/* * Function: sis_init_txd * * Description: initializes the Tx descriptor * * Arguments: struct nic *nic: NIC data structure * * returns: void. */static voidsis900_init_txd(struct nic *nic __unused){ txd.link = (u32) 0; txd.cmdsts = (u32) 0; txd.bufptr = virt_to_bus(&txb[0]); /* load Transmit Descriptor Register */ outl(virt_to_bus(&txd), ioaddr + txdp); if (sis900_debug > 0) printf("sis900_init_txd: TX descriptor register loaded with: %X\n", inl(ioaddr + txdp));}/* Function: sis_init_rxd * * Description: initializes the Rx descriptor ring * * Arguments: struct nic *nic: NIC data structure * * Returns: void. */static void sis900_init_rxd(struct nic *nic __unused) { int i; cur_rx = 0; /* init RX descriptor */ for (i = 0; i < NUM_RX_DESC; i++) { rxd[i].link = virt_to_bus((i+1 < NUM_RX_DESC) ? &rxd[i+1] : &rxd[0]); rxd[i].cmdsts = (u32) RX_BUF_SIZE; rxd[i].bufptr = virt_to_bus(&rxb[i*RX_BUF_SIZE]); if (sis900_debug > 0) printf("sis900_init_rxd: rxd[%d]=%X link=%X cmdsts=%X bufptr=%X\n", i, &rxd[i], rxd[i].link, rxd[i].cmdsts, rxd[i].bufptr); } /* load Receive Descriptor Register */ outl(virt_to_bus(&rxd[0]), ioaddr + rxdp); if (sis900_debug > 0) printf("sis900_init_rxd: RX descriptor register loaded with: %X\n", inl(ioaddr + rxdp));}/* Function: sis_init_rxd * * Description: * sets the receive mode to accept all broadcast packets and packets * with our MAC address, and reject all multicast packets. * * Arguments: struct nic *nic: NIC data structure * * Returns: void. */static void sis900_set_rx_mode(struct nic *nic __unused){ int i, table_entries; u32 rx_mode; u16 mc_filter[16] = {0}; /* 256/128 bits multicast hash table */ if((pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV)) table_entries = 16; else table_entries = 8; /* accept all multicast packet */ rx_mode = RFAAB | RFAAM; for (i = 0; i < table_entries; i++) mc_filter[i] = 0xffff; /* update Multicast Hash Table in Receive Filter */ for (i = 0; i < table_entries; i++) { /* why plus 0x04? That makes the correct value for hash table. */ outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr); outl(mc_filter[i], ioaddr + rfdr); } /* Accept Broadcast and multicast packets, destination addresses that match our MAC address */ outl(RFEN | rx_mode, ioaddr + rfcr); return;}/* Function: sis900_check_mode * * Description: checks the state of transmit and receive * parameters on the NIC, and updates NIC registers to match * * Arguments: struct nic *nic: NIC data structure * * Returns: void. */static voidsis900_check_mode(struct nic *nic){ int speed, duplex; u32 tx_flags = 0, rx_flags = 0; mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex); if( inl(ioaddr + cfg) & EDB_MASTER_EN ) { tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift); rx_flags = DMA_BURST_64 << RxMXDMA_shift; } else { tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift); rx_flags = DMA_BURST_512 << RxMXDMA_shift; } if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) { rx_flags |= (RxDRNT_10 << RxDRNT_shift); tx_flags |= (TxDRNT_10 << TxDRNT_shift); } else { rx_flags |= (RxDRNT_100 << RxDRNT_shift); tx_flags |= (TxDRNT_100 << TxDRNT_shift); } if (duplex == FDX_CAPABLE_FULL_SELECTED) { tx_flags |= (TxCSI | TxHBI);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -