📄 natsemi.c
字号:
#ifdef NATSEMI_DEBUG printf("write_eeprom: %08x, %04hx, %04hx\n", dev->iobase + ee_addr, write_cmd, value);#endif /* Shift the write enable command bits out. */ for (i = 9; i >= 0; i--) { short cmdval = (wren_cmd & (1 << i)) ? EE_Write1 : EE_Write0; OUTL(dev, cmdval, ee_addr); eeprom_delay(ee_addr); OUTL(dev, cmdval | EE_ShiftClk, ee_addr); eeprom_delay(ee_addr); } OUTL(dev, 0, ee_addr); /*bring chip select low*/ OUTL(dev, EE_ShiftClk, ee_addr); eeprom_delay(ee_addr); /* Shift the write command bits out. */ for (i = 9; i >= 0; i--) { short cmdval = (write_cmd & (1 << i)) ? EE_Write1 : EE_Write0; OUTL(dev, cmdval, ee_addr); eeprom_delay(ee_addr); OUTL(dev, cmdval | EE_ShiftClk, ee_addr); eeprom_delay(ee_addr); } for (i = 0; i < 16; i++) { short cmdval = (value & (1 << i)) ? EE_Write1 : EE_Write0; OUTL(dev, cmdval, ee_addr); eeprom_delay(ee_addr); OUTL(dev, cmdval | EE_ShiftClk, ee_addr); eeprom_delay(ee_addr); } OUTL(dev, 0, ee_addr); /*bring chip select low*/ OUTL(dev, EE_ShiftClk, ee_addr); for (i = 0; i < 200000; i++) { OUTL(dev, EE_Write0, ee_addr); /*poll for done*/ if (INL(dev, ee_addr) & EE_DataOut) { break; /*finished*/ } } eeprom_delay(ee_addr); /* Terminate the EEPROM access. */ OUTL(dev, EE_Write0, ee_addr); OUTL(dev, 0, ee_addr); return;}#endifstatic intread_eeprom(struct eth_device *dev, long addr, int location){ int i; int retval = 0; int ee_addr = (typeof(ee_addr))addr; int read_cmd = location | EE_ReadCmd; OUTL(dev, EE_Write0, ee_addr); /* Shift the read command bits out. */ for (i = 10; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0; OUTL(dev, dataval, ee_addr); eeprom_delay(ee_addr); OUTL(dev, dataval | EE_ShiftClk, ee_addr); eeprom_delay(ee_addr); } OUTL(dev, EE_ChipSelect, ee_addr); eeprom_delay(ee_addr); for (i = 0; i < 16; i++) { OUTL(dev, EE_ChipSelect | EE_ShiftClk, ee_addr); eeprom_delay(ee_addr); retval |= (INL(dev, ee_addr) & EE_DataOut) ? 1 << i : 0; OUTL(dev, EE_ChipSelect, ee_addr); eeprom_delay(ee_addr); } /* Terminate the EEPROM access. */ OUTL(dev, EE_Write0, ee_addr); OUTL(dev, 0, ee_addr);#ifdef NATSEMI_DEBUG if (natsemi_debug) printf("read_eeprom: %08x, %08x, retval %08x\n", dev->iobase + ee_addr, read_cmd, retval);#endif 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 intmdio_read(struct eth_device *dev, int phy_id, int location){ if (phy_id == 1 && location < 32) return INL(dev, BasicControl+(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 eth_device *dev: NIC data structure * * returns: int. */static intnatsemi_init(struct eth_device *dev, bd_t * bis){ natsemi_reset(dev); /* 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(dev, SavedClkRun & ~0x100, ClkRun); natsemi_init_rxfilter(dev); natsemi_init_txd(dev); natsemi_init_rxd(dev); /* Configure the PCI bus bursts and FIFO thresholds. */ tx_config = TxAutoPad | TxCollRetry | TxMxdma_256 | (0x1002); rx_config = RxMxdma_256 | 0x20;#ifdef NATSEMI_DEBUG printf("%s: Setting TxConfig Register %#08X\n", dev->name, tx_config); printf("%s: Setting RxConfig Register %#08X\n", dev->name, rx_config);#endif OUTL(dev, tx_config, TxConfig); OUTL(dev, rx_config, RxConfig); natsemi_check_duplex(dev); natsemi_set_rx_mode(dev); OUTL(dev, (RxOn | TxOn), ChipCmd); return 1;}/* * Function: natsemi_reset * * Description: soft resets the controller chip * * Arguments: struct eth_device *dev: NIC data structure * * Returns: void. */static voidnatsemi_reset(struct eth_device *dev){ OUTL(dev, ChipReset, 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(dev, SiliconRev) == 0x302) { OUTW(dev, 0x0001, PGSEL); OUTW(dev, 0x189C, PMDCSR); OUTW(dev, 0x0000, TSTDAT); OUTW(dev, 0x5040, DSPCFG); OUTW(dev, 0x008C, SDCFG); } /* Disable interrupts using the mask. */ OUTL(dev, 0, IntrMask); OUTL(dev, 0, IntrEnable);}/* Function: natsemi_init_rxfilter * * Description: sets receive filter address to our MAC address * * Arguments: struct eth_device *dev: NIC data structure * * returns: void. */static voidnatsemi_init_rxfilter(struct eth_device *dev){ int i; for (i = 0; i < ETH_ALEN; i += 2) { OUTL(dev, i, RxFilterAddr); OUTW(dev, dev->enetaddr[i] + (dev->enetaddr[i + 1] << 8), RxFilterData); }}/* * Function: natsemi_init_txd * * Description: initializes the Tx descriptor * * Arguments: struct eth_device *dev: NIC data structure * * returns: void. */static voidnatsemi_init_txd(struct eth_device *dev){ txd.link = (u32) 0; txd.cmdsts = (u32) 0; txd.bufptr = (u32) & txb[0]; /* load Transmit Descriptor Register */ OUTL(dev, (u32) & txd, TxRingPtr);#ifdef NATSEMI_DEBUG printf("natsemi_init_txd: TX descriptor reg loaded with: %#08X\n", INL(dev, TxRingPtr));#endif}/* Function: natsemi_init_rxd * * Description: initializes the Rx descriptor ring * * Arguments: struct eth_device *dev: NIC data structure * * Returns: void. */static voidnatsemi_init_rxd(struct eth_device *dev){ int i; cur_rx = 0; /* init RX descriptor */ for (i = 0; i < NUM_RX_DESC; i++) { rxd[i].link = cpu_to_le32((i + 1 < NUM_RX_DESC) ? (u32) & rxd[i + 1] : (u32) & rxd[0]); rxd[i].cmdsts = cpu_to_le32((u32) RX_BUF_SIZE); rxd[i].bufptr = cpu_to_le32((u32) & rxb[i * RX_BUF_SIZE]);#ifdef NATSEMI_DEBUG printf ("natsemi_init_rxd: rxd[%d]=%p link=%X cmdsts=%lX bufptr=%X\n", i, &rxd[i], le32_to_cpu(rxd[i].link), rxd[i].cmdsts, rxd[i].bufptr);#endif } /* load Receive Descriptor Register */ OUTL(dev, (u32) & rxd[0], RxRingPtr);#ifdef NATSEMI_DEBUG printf("natsemi_init_rxd: RX descriptor register loaded with: %X\n", INL(dev, RxRingPtr));#endif}/* 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 eth_device *dev: NIC data structure * * Returns: void. */static voidnatsemi_set_rx_mode(struct eth_device *dev){ u32 rx_mode = AcceptBroadcast | AcceptMyPhys; OUTL(dev, rx_mode, RxFilterAddr);}static voidnatsemi_check_duplex(struct eth_device *dev){ int duplex = INL(dev, ChipConfig) & FullDuplex ? 1 : 0;#ifdef NATSEMI_DEBUG printf("%s: Setting %s-duplex based on negotiated link" " capability.\n", dev->name, duplex ? "full" : "half");#endif if (duplex) { rx_config |= RxAcceptTx; tx_config |= (TxCarrierIgn | TxHeartIgn); } else { rx_config &= ~RxAcceptTx; tx_config &= ~(TxCarrierIgn | TxHeartIgn); } OUTL(dev, tx_config, TxConfig); OUTL(dev, rx_config, RxConfig);}/* Function: natsemi_send * * Description: transmits a packet and waits for completion or timeout. * * Returns: void. */static intnatsemi_send(struct eth_device *dev, volatile void *packet, int length){ u32 i, status = 0; u32 tx_status = 0; /* Stop the transmitter */ OUTL(dev, TxOff, ChipCmd);#ifdef NATSEMI_DEBUG if (natsemi_debug) printf("natsemi_send: sending %d bytes\n", (int) length);#endif /* set the transmit buffer descriptor and enable Transmit State Machine */ txd.link = cpu_to_le32(0); txd.bufptr = cpu_to_le32(phys_to_bus((u32) packet)); txd.cmdsts = cpu_to_le32(DescOwn | length); /* load Transmit Descriptor Register */ OUTL(dev, phys_to_bus((u32) & txd), TxRingPtr);#ifdef NATSEMI_DEBUG if (natsemi_debug) printf("natsemi_send: TX descriptor register loaded with: %#08X\n", INL(dev, TxRingPtr));#endif /* restart the transmitter */ OUTL(dev, TxOn, ChipCmd); for (i = 0; ((vu_long)tx_status = le32_to_cpu(txd.cmdsts)) & DescOwn; i++) { if (i >= TOUT_LOOP) { printf ("%s: tx error buffer not ready: txd.cmdsts == %#X\n", dev->name, tx_status); goto Done; } } if (!(tx_status & DescPktOK)) { printf("natsemi_send: Transmit error, Tx status %X.\n", tx_status); goto Done; } status = 1; Done: return status;}/* Function: natsemi_poll * * Description: checks for a received packet and returns it if found. * * Arguments: struct eth_device *dev: NIC data structure * * Returns: 1 if packet was received. * 0 if no packet was received. * * Side effects: * Returns (copies) the packet to the array dev->packet. * Returns the length of the packet. */static intnatsemi_poll(struct eth_device *dev){ int retstat = 0; int length = 0; u32 rx_status = le32_to_cpu(rxd[cur_rx].cmdsts); if (!(rx_status & (u32) DescOwn)) return retstat;#ifdef NATSEMI_DEBUG if (natsemi_debug) printf("natsemi_poll: got a packet: cur_rx:%d, status:%X\n", cur_rx, rx_status);#endif length = (rx_status & DSIZE) - CRC_SIZE; if ((rx_status & (DescMore | DescPktOK | DescRxLong)) != DescPktOK) { printf ("natsemi_poll: Corrupted packet received, buffer status = %X\n", rx_status); retstat = 0; } else { /* give packet to higher level routine */ NetReceive((rxb + cur_rx * RX_BUF_SIZE), length); retstat = 1; } /* return the descriptor and buffer to receive ring */ rxd[cur_rx].cmdsts = cpu_to_le32(RX_BUF_SIZE); rxd[cur_rx].bufptr = cpu_to_le32((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(dev, RxOn, ChipCmd); return retstat;}/* Function: natsemi_disable * * Description: Turns off interrupts and stops Tx and Rx engines * * Arguments: struct eth_device *dev: NIC data structure * * Returns: void. */static voidnatsemi_disable(struct eth_device *dev){ /* Disable interrupts using the mask. */ OUTL(dev, 0, IntrMask); OUTL(dev, 0, IntrEnable); /* Stop the chip's Tx and Rx processes. */ OUTL(dev, RxOff | TxOff, ChipCmd); /* Restore PME enable bit */ OUTL(dev, SavedClkRun, ClkRun);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -