⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sis900.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -