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

📄 sis900.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
{    int i = 0;    u32 status = TxRCMP | RxRCMP;    outl(0, ioaddr + ier);    outl(0, ioaddr + imr);    outl(0, ioaddr + rfcr);    outl(RxRESET | TxRESET | RESET, ioaddr + cr);            /* Check that the chip has finished the reset. */    while (status && (i++ < 1000)) {        status ^= (inl(isr + ioaddr) & status);    }    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);    /* 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){    txd.link   = (u32) 0;    txd.cmdsts = (u32) 0;    txd.bufptr = (u32) &txb[0];    /* load Transmit Descriptor Register */    outl((u32) &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) {     int i;    cur_rx = 0;     /* init RX descriptor */    for (i = 0; i < NUM_RX_DESC; i++) {        rxd[i].link   = (i+1 < NUM_RX_DESC) ? (u32) &rxd[i+1] : (u32) &rxd[0];        rxd[i].cmdsts = (u32) RX_BUF_SIZE;        rxd[i].bufptr = (u32) &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((u32) &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){    int i;    /* Configure Multicast Hash Table in Receive Filter        to reject all MCAST packets */    for (i = 0; i < 8; i++) {        /* why plus 0x04? That makes the correct value for hash table. */        outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);        outl((u32)(0x0), ioaddr + rfdr);    }    /* Accept Broadcast packets, destination addresses that match        our MAC address */    outl(RFEN | RFAAB, 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);    tx_flags = TxATP | (TX_DMA_BURST << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);    rx_flags = RX_DMA_BURST << 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);        rx_flags |= RxATX;    }    outl (tx_flags, ioaddr + txcfg);    outl (rx_flags, ioaddr + rxcfg);}/* Function: sis900_read_mode * * Description: retrieves and displays speed and duplex *    parameters from the NIC *     * Arguments: struct nic *nic:          NIC data structure * * Returns:   void. */static voidsis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex){    int i = 0;    u32 status;            /* STSOUT register is Latched on Transition, read operation updates it */    while (i++ < 2)        status = sis900_mdio_read(phy_addr, MII_STSOUT);    if (status & MII_STSOUT_SPD)        *speed = HW_SPEED_100_MBPS;    else        *speed = HW_SPEED_10_MBPS;    if (status & MII_STSOUT_DPLX)        *duplex = FDX_CAPABLE_FULL_SELECTED;    else        *duplex = FDX_CAPABLE_HALF_SELECTED;    if (status & MII_STSOUT_LINK_FAIL)        printf("sis900_read_mode: Media Link Off\n");    else        printf("sis900_read_mode: Media Link On %s %s-duplex \n",                *speed == HW_SPEED_100_MBPS ?                "100mbps" : "10mbps",               *duplex == FDX_CAPABLE_FULL_SELECTED ?               "full" : "half");}/* Function: amd79c901_read_mode * * Description: retrieves and displays speed and duplex *    parameters from the NIC *     * Arguments: struct nic *nic:          NIC data structure * * Returns:   void. */static voidamd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex){    int i;    u16 status;            for (i = 0; i < 2; i++)        status = sis900_mdio_read(phy_addr, MII_STATUS);    if (status & MII_STAT_CAN_AUTO) {        /* 10BASE-T PHY */        for (i = 0; i < 2; i++)            status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY);        if (status & MII_STSSUM_SPD)            *speed = HW_SPEED_100_MBPS;        else            *speed = HW_SPEED_10_MBPS;        if (status & MII_STSSUM_DPLX)            *duplex = FDX_CAPABLE_FULL_SELECTED;        else            *duplex = FDX_CAPABLE_HALF_SELECTED;        if (status & MII_STSSUM_LINK)            printf("amd79c901_read_mode: Media Link On %s %s-duplex \n",                    *speed == HW_SPEED_100_MBPS ?                    "100mbps" : "10mbps",                   *duplex == FDX_CAPABLE_FULL_SELECTED ?                   "full" : "half");        else            printf("amd79c901_read_mode: Media Link Off\n");    }    else {        /* HomePNA */        *speed = HW_SPEED_HOME;        *duplex = FDX_CAPABLE_HALF_SELECTED;        if (status & MII_STAT_LINK)            printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n");        else            printf("amd79c901_read_mode: Media Link Off\n");    }}/** *	ics1893_read_mode: - read media mode for ICS1893 PHY *	@net_dev: the net device to read mode for *	@phy_addr: mii phy address *	@speed: the transmit speed to be determined *	@duplex: the duplex mode to be determined * *	ICS1893 PHY use Quick Poll Detailed Status register *	to determine the speed and duplex mode for sis900 */static void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex){	int i = 0;	u32 status;	/* MII_QPDSTS is Latched, read twice in succession will reflect the current state */	for (i = 0; i < 2; i++)		status = sis900_mdio_read(phy_addr, MII_QPDSTS);	if (status & MII_STSICS_SPD)		*speed = HW_SPEED_100_MBPS;	else		*speed = HW_SPEED_10_MBPS;	if (status & MII_STSICS_DPLX)		*duplex = FDX_CAPABLE_FULL_SELECTED;	else		*duplex = FDX_CAPABLE_HALF_SELECTED;	if (status & MII_STSICS_LINKSTS)		printf("ics1893_read_mode: Media Link On %s %s-duplex \n",		       *speed == HW_SPEED_100_MBPS ?		       "100mbps" : "10mbps",		       *duplex == FDX_CAPABLE_FULL_SELECTED ?		       "full" : "half");	else		printf("ics1893_read_mode: Media Link Off\n");}/** *	rtl8201_read_mode: - read media mode for rtl8201 phy *	@nic: the net device to read mode for *	@phy_addr: mii phy address *	@speed: the transmit speed to be determined *	@duplex: the duplex mode to be determined * *	read MII_STATUS register from rtl8201 phy *	to determine the speed and duplex mode for sis900 */static void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex){	u32 status;	status = sis900_mdio_read(phy_addr, MII_STATUS);	if (status & MII_STAT_CAN_TX_FDX) {		*speed = HW_SPEED_100_MBPS;		*duplex = FDX_CAPABLE_FULL_SELECTED;	}	else if (status & MII_STAT_CAN_TX) {		*speed = HW_SPEED_100_MBPS;		*duplex = FDX_CAPABLE_HALF_SELECTED;	}	else if (status & MII_STAT_CAN_T_FDX) {		*speed = HW_SPEED_10_MBPS;		*duplex = FDX_CAPABLE_FULL_SELECTED;	}	else if (status & MII_STAT_CAN_T) {		*speed = HW_SPEED_10_MBPS;		*duplex = FDX_CAPABLE_HALF_SELECTED;	}	if (status & MII_STAT_LINK)		printf("rtl8201_read_mode: Media Link On %s %s-duplex \n",		       *speed == HW_SPEED_100_MBPS ?		       "100mbps" : "10mbps",		       *duplex == FDX_CAPABLE_FULL_SELECTED ?		       "full" : "half");	else		printf("rtl9201_read_config_mode: Media Link Off\n");}/* Function: sis900_transmit * * Description: transmits a packet and waits for completion or timeout. * * Arguments: char d[6]:          destination ethernet address. *            unsigned short t:   ethernet protocol type. *            unsigned short s:   size of the data-part of the packet. *            char *p:            the data for the packet. *     * Returns:   void. */static voidsis900_transmit(struct nic  *nic,                const char  *d,     /* Destination */                unsigned int t,     /* Type */                unsigned int s,     /* size */                const char  *p)     /* Packet */{    u32 status, to, nstype;    u32 tx_status;        /* Stop the transmitter */    outl(TxDIS, ioaddr + cr);    /* load Transmit Descriptor Register */    outl((u32) &txd, ioaddr + txdp);     if (sis900_debug > 1)        printf("sis900_transmit: TX descriptor register loaded with: %X\n",                inl(ioaddr + txdp));    memcpy(txb, d, ETH_ALEN);    memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);    nstype = htons(t);    memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);    memcpy(txb + ETH_HLEN, p, s);    s += ETH_HLEN;    s &= DSIZE;    if (sis900_debug > 1)        printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);    /* pad to minimum packet size */    while (s < ETH_ZLEN)          txb[s++] = '\0';    /* set the transmit buffer descriptor and enable Transmit State Machine */    txd.bufptr = (u32) &txb[0];    txd.cmdsts = (u32) OWN | s;    /* restart the transmitter */    outl(TxENA, ioaddr + cr);    if (sis900_debug > 1)        printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s);    to = currticks() + TX_TIMEOUT;    while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))        /* wait */ ;    if (currticks() >= to) {        printf("sis900_transmit: TX Timeout! Tx status %X.\n", tx_status);    }        if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {        /* packet unsuccessfully transmited */        printf("sis900_transmit: Transmit error, Tx status %X.\n", tx_status);    }    /* Disable interrupts by clearing the interrupt mask. */    outl(0, ioaddr + imr);}/* Function: sis900_poll * * Description: checks for a received packet and returns it if found. * * Arguments: struct nic *nic:          NIC data structure * * Returns:   1 if a packet was recieved. *            0 if no pacet was recieved. * * Side effects: *            Returns (copies) the packet to the array nic->packet. *            Returns the length of the packet in nic->packetlen. */static intsis900_poll(struct nic *nic){    u32 rx_status = rxd[cur_rx].cmdsts;    int retstat = 0;    if (sis900_debug > 2)        printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx, rx_status);    if (!(rx_status & OWN))        return retstat;    if (sis900_debug > 1)        printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",               cur_rx, rx_status);    nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;    if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {        /* corrupted packet received */        printf("sis900_poll: Corrupted packet received, buffer status = %X\n",               rx_status);        retstat = 0;    } else {        /* give packet to higher level routine */        memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);        retstat = 1;    }    /* return the descriptor and buffer to receive ring */    rxd[cur_rx].cmdsts = RX_BUF_SIZE;    rxd[cur_rx].bufptr = (u32) &rxb[cur_rx*RX_BUF_SIZE];            if (++cur_rx == NUM_RX_DESC)        cur_rx = 0;    /* re-enable the potentially idle receive state machine */    outl(RxENA , ioaddr + cr);    return retstat;}/* Function: sis900_disable * * Description: Turns off interrupts and stops Tx and Rx engines *     * Arguments: struct nic *nic:          NIC data structure * * Returns:   void. */static voidsis900_disable(struct nic *nic){    /* Disable interrupts by clearing the interrupt mask. */    outl(0, ioaddr + imr);    outl(0, ioaddr + ier);        /* Stop the chip's Tx and Rx Status Machine */    outl(RxDIS | TxDIS, ioaddr + cr);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -