📄 natsemi.c
字号:
for (i = 0; i < 16; i++) { outl(EE_ChipSelect | EE_ShiftClk, ee_addr); eeprom_delay(ee_addr); retval |= (inl(ee_addr) & EE_DataOut) ? 1 << i : 0; outl(EE_ChipSelect, ee_addr); eeprom_delay(ee_addr); } /* Terminate the EEPROM access. */ outl(EE_Write0, ee_addr); outl(0, ee_addr); return retval;}/* MII transceiver control section. The 83815 series has an internal transceiver, and we present the management registers as if they were MII connected. */static int mdio_read(int phy_id, int location){ if (phy_id == 1 && location < 32) return inl(ioaddr + 0x80 + (location<<2)) & 0xffff; else return 0xffff;}/* Function: natsemi_init * * Description: resets the ethernet controller chip and configures * registers and data structures required for sending and receiving packets. * * Arguments: struct nic *nic: NIC data structure * * returns: void. */static voidnatsemi_init(struct nic *nic){ natsemi_reset(nic); /* Disable PME: * The PME bit is initialized from the EEPROM contents. * PCI cards probably have PME disabled, but motherboard * implementations may have PME set to enable WakeOnLan. * With PME set the chip will scan incoming packets but * nothing will be written to memory. */ outl(SavedClkRun & ~0x100, ioaddr + ClkRun); natsemi_init_rxfilter(nic); natsemi_init_txd(nic); natsemi_init_rxd(nic); /* Initialize other registers. */ /* Configure the PCI bus bursts and FIFO thresholds. */ /* Configure for standard, in-spec Ethernet. */ if (inl(ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */ tx_config = 0xD0801002; rx_config = 0x10000020; } else { tx_config = 0x10801002; rx_config = 0x0020; } outl(tx_config, ioaddr + TxConfig); outl(rx_config, ioaddr + RxConfig); natsemi_check_duplex(nic); natsemi_set_rx_mode(nic); outl(RxOn, ioaddr + ChipCmd);}/* * Function: natsemi_reset * * Description: soft resets the controller chip * * Arguments: struct nic *nic: NIC data structure * * Returns: void. */static void natsemi_reset(struct nic *nic){ outl(ChipReset, ioaddr + ChipCmd); /* On page 78 of the spec, they recommend some settings for "optimum performance" to be done in sequence. These settings optimize some of the 100Mbit autodetection circuitry. Also, we only want to do this for rev C of the chip. */ if (inl(ioaddr + SiliconRev) == 0x302) { outw(0x0001, ioaddr + PGSEL); outw(0x189C, ioaddr + PMDCSR); outw(0x0000, ioaddr + TSTDAT); outw(0x5040, ioaddr + DSPCFG); outw(0x008C, ioaddr + SDCFG); } /* Disable interrupts using the mask. */ outl(0, ioaddr + IntrMask); outl(0, ioaddr + IntrEnable);}/* Function: natsemi_init_rxfilter * * Description: sets receive filter address to our MAC address * * Arguments: struct nic *nic: NIC data structure * * returns: void. */static voidnatsemi_init_rxfilter(struct nic *nic){ int i; for (i = 0; i < ETH_ALEN; i += 2) { outl(i, ioaddr + RxFilterAddr); outw(nic->node_addr[i] + (nic->node_addr[i+1] << 8), ioaddr + RxFilterData); }}/* * Function: natsemi_init_txd * * Description: initializes the Tx descriptor * * Arguments: struct nic *nic: NIC data structure * * returns: void. */static voidnatsemi_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 + TxRingPtr); if (natsemi_debug > 1) printf("natsemi_init_txd: TX descriptor register loaded with: %X\n", inl(ioaddr + TxRingPtr));}/* Function: natsemi_init_rxd * * Description: initializes the Rx descriptor ring * * Arguments: struct nic *nic: NIC data structure * * Returns: void. */ static void natsemi_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 (natsemi_debug > 1) printf("natsemi_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 + RxRingPtr); if (natsemi_debug > 1) printf("natsemi_init_rxd: RX descriptor register loaded with: %X\n", inl(ioaddr + RxRingPtr));}/* Function: natsemi_set_rx_mode * * 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 natsemi_set_rx_mode(struct nic *nic){ u32 rx_mode = AcceptBroadcast | AcceptMyPhys; outl(rx_mode, ioaddr + RxFilterAddr);}static void natsemi_check_duplex(struct nic *nic){ int duplex = inl(ioaddr + ChipConfig) & 0x20000000 ? 1 : 0; if (natsemi_debug) printf("%s: Setting %s-duplex based on negotiated link" " capability.\n", nic_name, duplex ? "full" : "half"); if (duplex) { rx_config |= 0x10000000; tx_config |= 0xC0000000; } else { rx_config &= ~0x10000000; tx_config &= ~0xC0000000; } outl(tx_config, ioaddr + TxConfig); outl(rx_config, ioaddr + RxConfig);}/* Function: natsemi_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 voidnatsemi_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(TxOff, ioaddr + ChipCmd); /* load Transmit Descriptor Register */ outl((u32) &txd, ioaddr + TxRingPtr); if (natsemi_debug > 1) printf("natsemi_transmit: TX descriptor register loaded with: %X\n", inl(ioaddr + TxRingPtr)); 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 (natsemi_debug > 1) printf("natsemi_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(TxOn, ioaddr + ChipCmd); if (natsemi_debug > 1) printf("natsemi_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("natsemi_transmit: TX Timeout! Tx status %X.\n", tx_status); } if (!(tx_status & 0x08000000)) { printf("natsemi_transmit: Transmit error, Tx status %X.\n", tx_status); }}/* Function: natsemi_poll * * Description: checks for a received packet and returns it if found. * * Arguments: struct nic *nic: NIC data structure * * Returns: 1 if packet was received. * 0 if no packet was received. * * Side effects: * Returns (copies) the packet to the array nic->packet. * Returns the length of the packet in nic->packetlen. */static intnatsemi_poll(struct nic *nic){ u32 rx_status = rxd[cur_rx].cmdsts; int retstat = 0; if (natsemi_debug > 2) printf("natsemi_poll: cur_rx:%d, status:%X\n", cur_rx, rx_status); if (!(rx_status & OWN)) return retstat; if (natsemi_debug > 1) printf("natsemi_poll: got a packet: cur_rx:%d, status:%X\n", cur_rx, rx_status); nic->packetlen = (rx_status & DSIZE) - CRC_SIZE; if ((rx_status & (DescMore|DescPktOK|RxTooLong)) != DescPktOK) { /* corrupted packet received */ printf("natsemi_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(RxOn, ioaddr + ChipCmd); return retstat;}/* Function: natsemi_disable * * Description: Turns off interrupts and stops Tx and Rx engines * * Arguments: struct nic *nic: NIC data structure * * Returns: void. */static voidnatsemi_disable(struct nic *nic){ /* Disable interrupts using the mask. */ outl(0, ioaddr + IntrMask); outl(0, ioaddr + IntrEnable); /* Stop the chip's Tx and Rx processes. */ outl(RxOff | TxOff, ioaddr + ChipCmd); /* Restore PME enable bit */ outl(SavedClkRun, ioaddr + ClkRun);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -