/*
02 JUL 2007 Udayan Kumar 1.2 ported the driver from etherboot to gPXE API
- Added a circular buffer for transmit and receive.
- transmit routine will not wait for transmission to finish
- poll routine deals with it.
+ Added a circular buffer for transmit and receive.
+ transmit routine will not wait for transmission to finish.
+ poll routine deals with it.
- 13 Dec 2003 timlegge 1.1 Enabled Multicast Support
- 29 May 2001 mdc 1.0
- Initial Release. Tested with Netgear FA311 and FA312 boards
+ 13 Dec 2003 timlegge 1.1 Enabled Multicast Support
+ 29 May 2001 mdc 1.0
+ Initial Release. Tested with Netgear FA311 and FA312 boards
*/
struct nvo_block nvo;
};
-
/* NATSEMI: Offsets to the device registers.
* Unlike software-only systems, device drivers interact with complex hardware.
* It's not useful to define symbolic names for every register bit in the
PhyStatus = 0xC0,
MIntrCtrl = 0xC4,
MIntrStatus = 0xC8,
-
- /* These are from the spec, around page 78... on a separate table. */
+ /* These are from the spec, around page 78... on a separate table.
+ */
PGSEL = 0xCC,
PMDCSR = 0xE4,
TSTDAT = 0xFC,
};
-
-
-
-/* Bit in ChipCmd. */
+/* Bit in ChipCmd.
+ */
enum ChipCmdBits {
ChipReset = 0x100,
RxReset = 0x20,
TxOn = 0x01
};
-
-/* Bits in the RxMode register. */
+/* Bits in the RxMode register.
+ */
enum rx_mode_bits {
AcceptErr = 0x20,
AcceptRunt = 0x10,
RxFilterEnable = 0x80000000
};
-/* Bits in network_desc.status */
+/* Bits in network_desc.status
+ */
enum desc_status_bits {
DescOwn = 0x80000000,
DescMore = 0x40000000,
RxTooLong = 0x00400000
};
-/*Bits in Interrupt Mask register */
-
+/*Bits in Interrupt Mask register
+ */
enum Intr_mask_register_bits {
RxOk = 0x001,
RxErr = 0x004,
TxErr = 0x100
};
-
-/* EEPROM access , values are devices specific*/
+/* EEPROM access , values are devices specific
+ */
#define EE_CS 0x08 /* EEPROM chip select */
#define EE_SK 0x04 /* EEPROM shift clock */
#define EE_DI 0x01 /* Data in */
#define EE_DO 0x02 /* Data out */
-/* Offsets within EEPROM (these are word offsets) */
+/* Offsets within EEPROM (these are word offsets)
+ */
#define EE_MAC 7
#define EE_REG EECtrl
static uint32_t SavedClkRun;
-
static const uint8_t nat_ee_bits[] = {
[SPI_BIT_SCLK] = EE_SK,
[SPI_BIT_MOSI] = EE_DI,
*/
void nat_init_eeprom ( struct natsemi_nic *nat ) {
- /* Initialise three-wire bus */
+ /* Initialise three-wire bus
+ */
nat->spibit.basher.op = &nat_basher_ops;
nat->spibit.bus.mode = SPI_MODE_THREEWIRE;
nat->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
init_spi_bit_basher ( &nat->spibit );
- /*natsemi DP 83815 only supports at93c46 */
+ /*natsemi DP 83815 only supports at93c46
+ */
init_at93c46 ( &nat->eeprom, 16 );
nat->eeprom.bus = &nat->spibit.bus;
static void nat_reset ( struct natsemi_nic *nat ) {
int i;
- /* Reset chip */
+ /* Reset chip
+ */
outl ( ChipReset, nat->ioaddr + ChipCmd );
mdelay ( 10 );
nat->tx_dirty=0;
outl(TxOff|RxOff, nat->ioaddr + ChipCmd);
- /* Restore PME enable bit */
+ /* Restore PME enable bit
+ */
outl(SavedClkRun, nat->ioaddr + ClkRun);
}
SavedClkRun = inl(nat->ioaddr + ClkRun);
outl(SavedClkRun & ~0x100, nat->ioaddr + ClkRun);
- /* Setting up Mac address in the NIC */
+ /* Setting up Mac address in the NIC
+ */
for ( i = 0 ; i < ETH_ALEN ; i+=2 ) {
outl(i,nat->ioaddr+RxFilterAddr);
- outw ( netdev->ll_addr[i] + (netdev->ll_addr[i+1]<<8), nat->ioaddr +RxFilterData);
+ outw ( netdev->ll_addr[i] + (netdev->ll_addr[i+1]<<8),
+ nat->ioaddr +RxFilterData);
}
- /*Set up the Tx Ring */
+ /*Set up the Tx Ring
+ */
nat->tx_cur=0;
nat->tx_dirty=0;
for (i=0;i<TX_RING_SIZE;i++) {
nat->tx[i].bufptr = 0;
}
- /* Set up RX ring */
+ /* Set up RX ring
+ */
nat->rx_cur=0;
for (i=0;i<NUM_RX_DESC;i++) {
nat->rx[i].bufptr = virt_to_bus(nat->iobuf[i]->data);
}
- /* load Receive Descriptor Register */
+ /* load Receive Descriptor Register
+ */
outl(virt_to_bus(&nat->rx[0]), nat->ioaddr + RxRingPtr);
- DBG("Natsemi Rx descriptor loaded with: %X\n",(unsigned int)inl(nat->ioaddr+RxRingPtr));
+ DBG("Natsemi Rx descriptor loaded with: %X\n",
+ (unsigned int)inl(nat->ioaddr+RxRingPtr));
- /* setup Tx ring */
+ /* setup Tx ring
+ */
outl(virt_to_bus(&nat->tx[0]),nat->ioaddr+TxRingPtr);
- DBG("Natsemi Tx descriptor loaded with: %X\n",(unsigned int)inl(nat->ioaddr+TxRingPtr));
+ DBG("Natsemi Tx descriptor loaded with: %X\n",
+ (unsigned int)inl(nat->ioaddr+TxRingPtr));
- /* Enables RX */
- outl(RxFilterEnable|AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys, nat->ioaddr+RxFilterAddr);
+ /* Enables RX
+ */
+ outl(RxFilterEnable|AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys,
+ nat->ioaddr+RxFilterAddr);
/* Initialize other registers.
* Configure the PCI bus bursts and FIFO thresholds.
outl(tx_config, nat->ioaddr + TxConfig);
outl(rx_config, nat->ioaddr + RxConfig);
- /*start the receiver */
+ /*start the receiver
+ */
outl(RxOn, nat->ioaddr + ChipCmd);
- /*enable interrupts*/
+ /*enable interrupts
+ */
outl((RxOk|RxErr|TxOk|TxErr),nat->ioaddr + IntrMask);
//outl(1,nat->ioaddr +IntrEnable);
int i;
- /* Reset the hardware to disable everything in one go */
+ /* Reset the hardware to disable everything in one go
+ */
nat_reset ( nat );
- /* Free RX ring */
+ /* Free RX ring
+ */
for (i=0;i<NUM_RX_DESC;i++) {
free_iob( nat->iobuf[i] );
}
- /* disable interrupts */
+ /* disable interrupts
+ */
//outl(0,nat->ioaddr + IntrMask) ;
}
static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
struct natsemi_nic *nat = netdev->priv;
- /* check for space in TX ring */
+ /* check for space in TX ring
+ */
if (nat->tx[nat->tx_cur].cmdsts !=0) {
DBG( "TX overflow\n" );
return -ENOBUFS;
}
- /* to be used in netdev_tx_complete*/
+ /* to be used in netdev_tx_complete
+ */
nat->tx_iobuf[nat->tx_cur]=iobuf;
- /* Pad and align packet */
- iob_pad ( iobuf, ETH_ZLEN );
+ /* Pad and align packet has been ignored because its not required here
+ * iob_pad ( iobuf, ETH_ZLEN ); can be used to achieve it
+ */
- /* Add to TX ring */
+ /* Add to TX ring
+ */
DBG ( "TX id %d at %lx+%x\n", nat->tx_cur,
virt_to_bus ( &iobuf->data ), iob_len ( iobuf ) );
nat->tx[nat->tx_cur].bufptr = virt_to_bus(iobuf->data);
nat->tx[nat->tx_cur].cmdsts= iob_len(iobuf)|OWN;
- /* increment the circular buffer pointer to the next buffer location */
+ /* increment the circular buffer pointer to the next buffer location
+ */
nat->tx_cur=(nat->tx_cur+1) % TX_RING_SIZE;
- /*start the transmitter */
+ /*start the transmitter
+ */
outl(TxOn, nat->ioaddr + ChipCmd);
return 0;
int i;
//outl(1,nat->ioaddr +IntrEnable);
- /* read the interrupt register */
+ /* read the interrupt register
+ */
intr_status=inl(nat->ioaddr+IntrStatus);
if(!intr_status)
goto end;
- /* check the status of packets given to card for transmission */
+ /* check the status of packets given to card for transmission
+ */
DBG("Intr status %X\n",intr_status);
i=nat->tx_dirty;
DBG("value of tx_dirty = %d tx_cur=%d status=%X\n",
nat->tx_dirty,nat->tx_cur,status);
- /* check if current packet has been transmitted or not */
+ /* check if current packet has been transmitted or not
+ */
if(status & OWN)
break;
- /* Check if any errors in transmission */
+ /* Check if any errors in transmission
+ */
if (! (status & DescPktOK)) {
DBG("Error in sending Packet status:%X\n",
(unsigned int)status);
DBG("Success in transmitting Packet\n");
netdev_tx_complete(netdev,nat->tx_iobuf[nat->tx_dirty]);
}
- /* setting cmdsts zero, indicating that it can be reused */
+ /* setting cmdsts zero, indicating that it can be reused
+ */
nat->tx[nat->tx_dirty].cmdsts=0;
nat->tx_dirty=(nat->tx_dirty +1) % TX_RING_SIZE;
i=(i+1) % TX_RING_SIZE;
}
- /* Handle received packets */
+ /* Handle received packets
+ */
rx_status=(unsigned int)nat->rx[nat->rx_cur].cmdsts;
while (rx_quota && (rx_status & OWN)) {
rx_len= (rx_status & DSIZE) - CRC_SIZE;
- /*check for the corrupt packet */
+ /*check for the corrupt packet
+ */
if((rx_status & (DescMore|DescPktOK|RxTooLong)) != DescPktOK) {
DBG("natsemi_poll: Corrupted packet received, "
"buffer status = %X ^ %X \n",rx_status,
} else {
rx_iob = alloc_iob(rx_len);
if(!rx_iob)
- /* leave packet for next call to poll*/
+ /* leave packet for next call to poll
+ */
goto end;
memcpy(iob_put(rx_iob,rx_len),
nat->iobuf[nat->rx_cur]->data,rx_len);
DBG("received packet\n");
- /* add to the receive queue. */
+ /* add to the receive queue.
+ */
netdev_rx(netdev,rx_iob);
rx_quota--;
}
end:
- /* re-enable the potentially idle receive state machine */
+ /* re-enable the potentially idle receive state machine
+ */
outl(RxOn, nat->ioaddr + ChipCmd);
// outl(1,nat->ioaddr +IntrEnable);
}
uint8_t last=0;
uint8_t last1=0;
- /* Allocate net device */
+ /* Allocate net device
+ */
netdev = alloc_etherdev ( sizeof ( *nat ) );
if ( ! netdev )
return -ENOMEM;
memset ( nat, 0, sizeof ( *nat ) );
nat->ioaddr = pci->ioaddr;
- /* Fix up PCI device */
+ /* Fix up PCI device
+ */
adjust_pci_device ( pci );
- /* Reset the NIC, set up EEPROM access and read MAC address */
+ /* Reset the NIC, set up EEPROM access and read MAC address
+ */
nat_reset ( nat );
nat_init_eeprom ( nat );
nvs_read ( &nat->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN );
last=(ll_addr_encoded[i+1]>>7);
netdev->ll_addr[i+1]=(ll_addr_encoded[i+1]<<1)+last1;
}
- /* TODO remove the block below */
- DBG("Contents of the EEPROM\n");
- uint8_t eetest[108];
- nvs_read(&nat->eeprom.nvs,0,eetest,108);
- DBG_HD(&eetest,108);
-
- /* Point to NIC specific routines */
- /*
- netdev->open = nat_open;
- netdev->close = nat_close;
- netdev->transmit = nat_transmit;
- netdev->poll = nat_poll;
- */
- /* Register network device */
+
+ /* Register network device
+ */
if ( ( rc = register_netdev ( netdev ) ) != 0 )
goto err_register_netdev;
- /* Register non-volatile storage */
+ /* Register non-volatile storage
+ */
if ( nat->nvo.nvs ) {
if ( ( rc = nvo_register ( &nat->nvo ) ) != 0 )
goto err_register_nvo;
err_register_nvo:
unregister_netdev ( netdev );
err_register_netdev:
- /* Disable NIC */
+ /* Disable NIC
+ */
nat_reset ( nat );
- /* Free net device */
+ /* Free net device
+ */
netdev_put ( netdev );
return rc;
}