natsemi.c is workin
This commit is contained in:
parent
a86b12728a
commit
4f2fab2e14
@ -107,10 +107,12 @@ struct natsemi_nic {
|
|||||||
struct natsemi_rx rx[NUM_RX_DESC];
|
struct natsemi_rx rx[NUM_RX_DESC];
|
||||||
/* need to add iobuf as we cannot free iobuf->data in close without this
|
/* need to add iobuf as we cannot free iobuf->data in close without this
|
||||||
* alternatively substracting sizeof(head) and sizeof(list_head) can also
|
* alternatively substracting sizeof(head) and sizeof(list_head) can also
|
||||||
* give the same.*/
|
* give the same.
|
||||||
|
*/
|
||||||
struct io_buffer *iobuf[NUM_RX_DESC];
|
struct io_buffer *iobuf[NUM_RX_DESC];
|
||||||
/* netdev_tx_complete needs pointer to the iobuf of the data so as to free
|
/* netdev_tx_complete needs pointer to the iobuf of the data so as to free
|
||||||
it from the memory.*/
|
* it from the memory.
|
||||||
|
*/
|
||||||
struct io_buffer *tx_iobuf[TX_RING_SIZE];
|
struct io_buffer *tx_iobuf[TX_RING_SIZE];
|
||||||
struct spi_bit_basher spibit;
|
struct spi_bit_basher spibit;
|
||||||
struct spi_device eeprom;
|
struct spi_device eeprom;
|
||||||
@ -119,9 +121,9 @@ struct natsemi_nic {
|
|||||||
|
|
||||||
|
|
||||||
/* NATSEMI: Offsets to the device registers.
|
/* NATSEMI: Offsets to the device registers.
|
||||||
Unlike software-only systems, device drivers interact with complex hardware.
|
* Unlike software-only systems, device drivers interact with complex hardware.
|
||||||
It's not useful to define symbolic names for every register bit in the
|
* It's not useful to define symbolic names for every register bit in the
|
||||||
device.
|
* device.
|
||||||
*/
|
*/
|
||||||
enum register_offsets {
|
enum register_offsets {
|
||||||
ChipCmd = 0x00,
|
ChipCmd = 0x00,
|
||||||
@ -258,25 +260,24 @@ static struct bit_basher_operations nat_basher_ops = {
|
|||||||
.read = nat_spi_read_bit,
|
.read = nat_spi_read_bit,
|
||||||
.write = nat_spi_write_bit,
|
.write = nat_spi_write_bit,
|
||||||
};
|
};
|
||||||
/** Portion of EEPROM available for non-volatile stored options
|
|
||||||
*
|
/* It looks that this portion of EEPROM can be used for
|
||||||
* We use offset 0x40 (i.e. address 0x20), length 0x40. This block is
|
* non-volatile stored options. Data sheet does not talk about this region.
|
||||||
* marked as VPD in the rtl8139 datasheets, so we use it only if we
|
* Currently it is not working. But with some efforts it can.
|
||||||
* detect that the card is not supporting VPD.
|
|
||||||
*/
|
*/
|
||||||
static struct nvo_fragment nat_nvo_fragments[] = {
|
static struct nvo_fragment nat_nvo_fragments[] = {
|
||||||
{ 0x0c, 0x40 },
|
{ 0x0c, 0x68 },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Set up for EEPROM access
|
* Set up for EEPROM access
|
||||||
*
|
*
|
||||||
* @v NAT NATSEMI NIC
|
* @v NAT NATSEMI NIC
|
||||||
*/
|
*/
|
||||||
void nat_init_eeprom ( struct natsemi_nic *nat ) {
|
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.basher.op = &nat_basher_ops;
|
||||||
nat->spibit.bus.mode = SPI_MODE_THREEWIRE;
|
nat->spibit.bus.mode = SPI_MODE_THREEWIRE;
|
||||||
nat->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
|
nat->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
|
||||||
@ -290,7 +291,7 @@ static struct nvo_fragment nat_nvo_fragments[] = {
|
|||||||
nat->nvo.fragments = nat_nvo_fragments;
|
nat->nvo.fragments = nat_nvo_fragments;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Reset NIC
|
* Reset NIC
|
||||||
*
|
*
|
||||||
* @v NATSEMI NIC
|
* @v NATSEMI NIC
|
||||||
@ -305,8 +306,7 @@ static void nat_reset ( struct natsemi_nic *nat ) {
|
|||||||
mdelay ( 10 );
|
mdelay ( 10 );
|
||||||
nat->tx_dirty=0;
|
nat->tx_dirty=0;
|
||||||
nat->tx_cur=0;
|
nat->tx_cur=0;
|
||||||
for(i=0;i<TX_RING_SIZE;i++)
|
for(i=0;i<TX_RING_SIZE;i++) {
|
||||||
{
|
|
||||||
nat->tx[i].link=0;
|
nat->tx[i].link=0;
|
||||||
nat->tx[i].cmdsts=0;
|
nat->tx[i].cmdsts=0;
|
||||||
nat->tx[i].bufptr=0;
|
nat->tx[i].bufptr=0;
|
||||||
@ -321,7 +321,7 @@ static void nat_reset ( struct natsemi_nic *nat ) {
|
|||||||
outl(SavedClkRun, nat->ioaddr + ClkRun);
|
outl(SavedClkRun, nat->ioaddr + ClkRun);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Open NIC
|
* Open NIC
|
||||||
*
|
*
|
||||||
* @v netdev Net device
|
* @v netdev Net device
|
||||||
@ -337,46 +337,29 @@ static int nat_open ( struct net_device *netdev ) {
|
|||||||
* PCI cards probably have PME disabled, but motherboard
|
* PCI cards probably have PME disabled, but motherboard
|
||||||
* implementations may have PME set to enable WakeOnLan.
|
* implementations may have PME set to enable WakeOnLan.
|
||||||
* With PME set the chip will scan incoming packets but
|
* With PME set the chip will scan incoming packets but
|
||||||
* nothing will be written to memory. */
|
* nothing will be written to memory.
|
||||||
|
*/
|
||||||
SavedClkRun = inl(nat->ioaddr + ClkRun);
|
SavedClkRun = inl(nat->ioaddr + ClkRun);
|
||||||
outl(SavedClkRun & ~0x100, nat->ioaddr + ClkRun);
|
outl(SavedClkRun & ~0x100, nat->ioaddr + ClkRun);
|
||||||
|
|
||||||
|
/* Setting up Mac address in the NIC */
|
||||||
|
for ( i = 0 ; i < ETH_ALEN ; i+=2 ) {
|
||||||
|
|
||||||
uint8_t last=0;
|
|
||||||
uint8_t last1=0;
|
|
||||||
for ( i = 0 ; i < ETH_ALEN ; i+=2 )
|
|
||||||
{
|
|
||||||
outl(i,nat->ioaddr+RxFilterAddr);
|
outl(i,nat->ioaddr+RxFilterAddr);
|
||||||
last1=netdev->ll_addr[i]>>7;
|
|
||||||
netdev->ll_addr[i]=netdev->ll_addr[i]<<1|last;
|
|
||||||
last=(netdev->ll_addr[i+1]>>7);
|
|
||||||
netdev->ll_addr[i+1]=(netdev->ll_addr[i+1]<<1)+last1;
|
|
||||||
|
|
||||||
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_cur=0;
|
||||||
nat->tx_dirty=0;
|
nat->tx_dirty=0;
|
||||||
for (i=0;i<TX_RING_SIZE;i++)
|
for (i=0;i<TX_RING_SIZE;i++) {
|
||||||
{
|
|
||||||
nat->tx[i].link = virt_to_bus((i+1 < TX_RING_SIZE) ? &nat->tx[i+1] : &nat->tx[0]);
|
nat->tx[i].link = virt_to_bus((i+1 < TX_RING_SIZE) ? &nat->tx[i+1] : &nat->tx[0]);
|
||||||
nat->tx[i].cmdsts = 0;
|
nat->tx[i].cmdsts = 0;
|
||||||
nat->tx[i].bufptr = 0;
|
nat->tx[i].bufptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Set up RX ring */
|
/* Set up RX ring */
|
||||||
nat->rx_cur=0;
|
nat->rx_cur=0;
|
||||||
for (i=0;i<NUM_RX_DESC;i++)
|
for (i=0;i<NUM_RX_DESC;i++) {
|
||||||
{
|
|
||||||
|
|
||||||
nat->iobuf[i] = alloc_iob ( RX_BUF_SIZE );
|
nat->iobuf[i] = alloc_iob ( RX_BUF_SIZE );
|
||||||
if (!nat->iobuf[i])
|
if (!nat->iobuf[i])
|
||||||
@ -386,7 +369,6 @@ static int nat_open ( struct net_device *netdev ) {
|
|||||||
nat->rx[i].bufptr = virt_to_bus(nat->iobuf[i]->data);
|
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);
|
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));
|
||||||
@ -398,9 +380,10 @@ static int nat_open ( struct net_device *netdev ) {
|
|||||||
/* Enables RX */
|
/* Enables RX */
|
||||||
outl(RxFilterEnable|AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys, nat->ioaddr+RxFilterAddr);
|
outl(RxFilterEnable|AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys, nat->ioaddr+RxFilterAddr);
|
||||||
|
|
||||||
/* Initialize other registers. */
|
/* Initialize other registers.
|
||||||
/* Configure the PCI bus bursts and FIFO thresholds. */
|
* Configure the PCI bus bursts and FIFO thresholds.
|
||||||
/* Configure for standard, in-spec Ethernet. */
|
* Configure for standard, in-spec Ethernet.
|
||||||
|
*/
|
||||||
if (inl(nat->ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */
|
if (inl(nat->ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */
|
||||||
tx_config = 0xD0801002;
|
tx_config = 0xD0801002;
|
||||||
rx_config = 0x10000020;
|
rx_config = 0x10000020;
|
||||||
@ -411,17 +394,12 @@ static int nat_open ( struct net_device *netdev ) {
|
|||||||
outl(tx_config, nat->ioaddr + TxConfig);
|
outl(tx_config, nat->ioaddr + TxConfig);
|
||||||
outl(rx_config, nat->ioaddr + RxConfig);
|
outl(rx_config, nat->ioaddr + RxConfig);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*start the receiver */
|
/*start the receiver */
|
||||||
outl(RxOn, nat->ioaddr + ChipCmd);
|
outl(RxOn, nat->ioaddr + ChipCmd);
|
||||||
|
|
||||||
/*enable interrupts*/
|
/*enable interrupts*/
|
||||||
outl((RxOk|RxErr|TxOk|TxErr),nat->ioaddr + IntrMask);
|
outl((RxOk|RxErr|TxOk|TxErr),nat->ioaddr + IntrMask);
|
||||||
outl(1,nat->ioaddr +IntrEnable);
|
//outl(1,nat->ioaddr +IntrEnable);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -440,13 +418,12 @@ static void nat_close ( struct net_device *netdev ) {
|
|||||||
nat_reset ( nat );
|
nat_reset ( nat );
|
||||||
|
|
||||||
/* Free RX ring */
|
/* Free RX ring */
|
||||||
for (i=0;i<NUM_RX_DESC;i++)
|
for (i=0;i<NUM_RX_DESC;i++) {
|
||||||
{
|
|
||||||
|
|
||||||
free_iob( nat->iobuf[i] );
|
free_iob( nat->iobuf[i] );
|
||||||
}
|
}
|
||||||
/* disable interrupts */
|
/* disable interrupts */
|
||||||
outl(0,nat->ioaddr + IntrMask) ;
|
//outl(0,nat->ioaddr + IntrMask) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -460,10 +437,8 @@ static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
|
|||||||
struct natsemi_nic *nat = netdev->priv;
|
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) {
|
||||||
if (nat->tx[nat->tx_cur].cmdsts !=0)
|
DBG( "TX overflow\n" );
|
||||||
{
|
|
||||||
printf ( "TX overflow\n" );
|
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,9 +453,8 @@ static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
|
|||||||
virt_to_bus ( &iobuf->data ), iob_len ( iobuf ) );
|
virt_to_bus ( &iobuf->data ), iob_len ( iobuf ) );
|
||||||
|
|
||||||
nat->tx[nat->tx_cur].bufptr = virt_to_bus(iobuf->data);
|
nat->tx[nat->tx_cur].bufptr = virt_to_bus(iobuf->data);
|
||||||
nat->tx[nat->tx_cur].cmdsts= (uint32_t) iob_len(iobuf)|OWN;
|
nat->tx[nat->tx_cur].cmdsts= iob_len(iobuf)|OWN;
|
||||||
|
/* increment the circular buffer pointer to the next buffer location */
|
||||||
|
|
||||||
nat->tx_cur=(nat->tx_cur+1) % TX_RING_SIZE;
|
nat->tx_cur=(nat->tx_cur+1) % TX_RING_SIZE;
|
||||||
|
|
||||||
/*start the transmitter */
|
/*start the transmitter */
|
||||||
@ -513,10 +487,8 @@ static void nat_poll ( struct net_device *netdev, unsigned int rx_quota ) {
|
|||||||
/* 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);
|
DBG("Intr status %X\n",intr_status);
|
||||||
|
|
||||||
|
|
||||||
i=nat->tx_dirty;
|
i=nat->tx_dirty;
|
||||||
while(i!=nat->tx_cur)
|
while(i!=nat->tx_cur) {
|
||||||
{
|
|
||||||
status=nat->tx[nat->tx_dirty].cmdsts;
|
status=nat->tx[nat->tx_dirty].cmdsts;
|
||||||
DBG("value of tx_dirty = %d tx_cur=%d status=%X\n",
|
DBG("value of tx_dirty = %d tx_cur=%d status=%X\n",
|
||||||
nat->tx_dirty,nat->tx_cur,status);
|
nat->tx_dirty,nat->tx_cur,status);
|
||||||
@ -525,47 +497,37 @@ static void nat_poll ( struct net_device *netdev, unsigned int rx_quota ) {
|
|||||||
if(status & OWN)
|
if(status & OWN)
|
||||||
break;
|
break;
|
||||||
/* Check if any errors in transmission */
|
/* Check if any errors in transmission */
|
||||||
if (! (status & DescPktOK))
|
if (! (status & DescPktOK)) {
|
||||||
{
|
DBG("Error in sending Packet status:%X\n",
|
||||||
printf("Error in sending Packet status:%X\n",
|
|
||||||
(unsigned int)status);
|
(unsigned int)status);
|
||||||
}
|
netdev_tx_complete_err(netdev,nat->tx_iobuf[nat->tx_dirty],-EINVAL);
|
||||||
else
|
} else {
|
||||||
{
|
DBG("Success in transmitting Packet\n");
|
||||||
DBG("Success in transmitting Packet with data\n");
|
|
||||||
// DBG_HD(&nat->tx[nat->tx_dirty].bufptr,130);
|
|
||||||
}
|
|
||||||
netdev_tx_complete(netdev,nat->tx_iobuf[nat->tx_dirty]);
|
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[nat->tx_dirty].cmdsts=0;
|
||||||
nat->tx_dirty=(nat->tx_dirty +1) % TX_RING_SIZE;
|
nat->tx_dirty=(nat->tx_dirty +1) % TX_RING_SIZE;
|
||||||
i=(i+1) % TX_RING_SIZE;
|
i=(i+1) % TX_RING_SIZE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rx_status=(unsigned int)nat->rx[nat->rx_cur].cmdsts;
|
|
||||||
/* Handle received packets */
|
/* Handle received packets */
|
||||||
while (rx_quota && (rx_status & OWN))
|
rx_status=(unsigned int)nat->rx[nat->rx_cur].cmdsts;
|
||||||
{
|
while (rx_quota && (rx_status & OWN)) {
|
||||||
rx_len= (rx_status & DSIZE) - CRC_SIZE;
|
rx_len= (rx_status & DSIZE) - CRC_SIZE;
|
||||||
|
|
||||||
/*check for the corrupt packet */
|
/*check for the corrupt packet */
|
||||||
if((rx_status & (DescMore|DescPktOK|RxTooLong)) != DescPktOK)
|
if((rx_status & (DescMore|DescPktOK|RxTooLong)) != DescPktOK) {
|
||||||
{
|
DBG("natsemi_poll: Corrupted packet received, "
|
||||||
printf("natsemi_poll: Corrupted packet received, "
|
|
||||||
"buffer status = %X ^ %X \n",rx_status,
|
"buffer status = %X ^ %X \n",rx_status,
|
||||||
(unsigned int) nat->rx[nat->rx_cur].cmdsts);
|
(unsigned int) nat->rx[nat->rx_cur].cmdsts);
|
||||||
}
|
netdev_rx_err(netdev,NULL,-EINVAL);
|
||||||
else
|
} else {
|
||||||
{
|
|
||||||
rx_iob = alloc_iob(rx_len);
|
rx_iob = alloc_iob(rx_len);
|
||||||
if(!rx_iob)
|
if(!rx_iob)
|
||||||
/* leave packet for next call to poll*/
|
/* leave packet for next call to poll*/
|
||||||
goto end;
|
goto end;
|
||||||
memcpy(iob_put(rx_iob,rx_len),
|
memcpy(iob_put(rx_iob,rx_len),
|
||||||
bus_to_virt(nat->rx[nat->rx_cur].bufptr),rx_len);
|
nat->iobuf[nat->rx_cur]->data,rx_len);
|
||||||
|
|
||||||
DBG("received packet\n");
|
DBG("received packet\n");
|
||||||
/* add to the receive queue. */
|
/* add to the receive queue. */
|
||||||
netdev_rx(netdev,rx_iob);
|
netdev_rx(netdev,rx_iob);
|
||||||
@ -573,7 +535,7 @@ static void nat_poll ( struct net_device *netdev, unsigned int rx_quota ) {
|
|||||||
}
|
}
|
||||||
nat->rx[nat->rx_cur].cmdsts = RX_BUF_SIZE;
|
nat->rx[nat->rx_cur].cmdsts = RX_BUF_SIZE;
|
||||||
nat->rx_cur=(nat->rx_cur+1) % NUM_RX_DESC;
|
nat->rx_cur=(nat->rx_cur+1) % NUM_RX_DESC;
|
||||||
rx_status=(unsigned int)nat->rx[nat->rx_cur].cmdsts;
|
rx_status=nat->rx[nat->rx_cur].cmdsts;
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
@ -583,12 +545,15 @@ end:
|
|||||||
// outl(1,nat->ioaddr +IntrEnable);
|
// outl(1,nat->ioaddr +IntrEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** RTL8139 net device operations */
|
||||||
|
static struct net_device_operations nat_operations = {
|
||||||
|
.open = nat_open,
|
||||||
|
.close = nat_close,
|
||||||
|
.transmit = nat_transmit,
|
||||||
|
.poll = nat_poll,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Probe PCI device
|
* Probe PCI device
|
||||||
*
|
*
|
||||||
* @v pci PCI device
|
* @v pci PCI device
|
||||||
@ -599,89 +564,71 @@ static int nat_probe ( struct pci_device *pci,
|
|||||||
const struct pci_device_id *id __unused ) {
|
const struct pci_device_id *id __unused ) {
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
struct natsemi_nic *nat = NULL;
|
struct natsemi_nic *nat = NULL;
|
||||||
int registered_netdev = 0;
|
|
||||||
int rc;
|
int rc;
|
||||||
uint32_t advertising;
|
int i;
|
||||||
|
uint8_t ll_addr_encoded[MAX_LL_ADDR_LEN];
|
||||||
/* Fix up PCI device */
|
uint8_t last=0;
|
||||||
adjust_pci_device ( pci );
|
uint8_t last1=0;
|
||||||
|
|
||||||
/* Allocate net device */
|
/* Allocate net device */
|
||||||
netdev = alloc_etherdev ( sizeof ( *nat ) );
|
netdev = alloc_etherdev ( sizeof ( *nat ) );
|
||||||
if ( ! netdev ) {
|
if ( ! netdev )
|
||||||
rc = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto err;
|
netdev_init(netdev,&nat_operations);
|
||||||
}
|
|
||||||
nat = netdev->priv;
|
nat = netdev->priv;
|
||||||
pci_set_drvdata ( pci, netdev );
|
pci_set_drvdata ( pci, netdev );
|
||||||
netdev->dev = &pci->dev;
|
netdev->dev = &pci->dev;
|
||||||
memset ( nat, 0, sizeof ( *nat ) );
|
memset ( nat, 0, sizeof ( *nat ) );
|
||||||
nat->ioaddr = pci->ioaddr;
|
nat->ioaddr = pci->ioaddr;
|
||||||
|
|
||||||
/* getting the IRQ vector */
|
/* Fix up PCI device */
|
||||||
unsigned long vector_phys = IRQ_INT ( pci->irq ) * 4;
|
adjust_pci_device ( pci );
|
||||||
DBG_HDA ( vector_phys, phys_to_virt ( vector_phys ), 4 );
|
|
||||||
DBG_HD ( phys_to_virt ( 0xfaea5 ), 64 );
|
|
||||||
DBG (" PIC state %X\n", irq_enabled(pci->irq));
|
|
||||||
DBG (" IRQ Number %X\n",pci->irq);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* 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_reset ( nat );
|
||||||
nat_init_eeprom ( nat );
|
nat_init_eeprom ( nat );
|
||||||
nvs_read ( &nat->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
|
nvs_read ( &nat->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN );
|
||||||
uint8_t eetest[128];
|
|
||||||
nvs_read ( &nat->eeprom.nvs, 0, eetest,128 );
|
|
||||||
|
|
||||||
|
/* decoding the MAC address read from NVS
|
||||||
/* mdio routine of etherboot-5.4.0 natsemi driver has been removed and
|
* and save it in netdev->ll_addr
|
||||||
* statement to read from MII transceiver control section is used directly
|
|
||||||
*/
|
*/
|
||||||
|
for ( i = 0 ; i < ETH_ALEN ; i+=2 ) {
|
||||||
advertising = inl(nat->ioaddr + 0x80 + (4<<2)) & 0xffff;
|
last1=ll_addr_encoded[i]>>7;
|
||||||
{
|
netdev->ll_addr[i]=ll_addr_encoded[i]<<1|last;
|
||||||
uint32_t chip_config = inl(nat->ioaddr + ChipConfig);
|
last=(ll_addr_encoded[i+1]>>7);
|
||||||
DBG("%s: Transceiver default autoneg. %s 10 %s %s duplex.\n",
|
netdev->ll_addr[i+1]=(ll_addr_encoded[i+1]<<1)+last1;
|
||||||
pci->driver_name,
|
|
||||||
chip_config & 0x2000 ? "enabled, advertise" : "disabled, force",
|
|
||||||
chip_config & 0x4000 ? "0" : "",
|
|
||||||
chip_config & 0x8000 ? "full" : "half");
|
|
||||||
}
|
}
|
||||||
DBG("%s: Transceiver status %hX advertising %hX\n",pci->driver_name, (int)inl(nat->ioaddr + 0x84),(unsigned int) advertising);
|
/* 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 */
|
/* Point to NIC specific routines */
|
||||||
|
/*
|
||||||
netdev->open = nat_open;
|
netdev->open = nat_open;
|
||||||
netdev->close = nat_close;
|
netdev->close = nat_close;
|
||||||
netdev->transmit = nat_transmit;
|
netdev->transmit = nat_transmit;
|
||||||
netdev->poll = nat_poll;
|
netdev->poll = nat_poll;
|
||||||
|
*/
|
||||||
/* Register network device */
|
/* Register network device */
|
||||||
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
||||||
goto err;
|
goto err_register_netdev;
|
||||||
registered_netdev = 1;
|
|
||||||
|
|
||||||
/* Register non-volatile storagei
|
|
||||||
* uncomment lines below in final version*/
|
|
||||||
|
|
||||||
|
/* Register non-volatile storage */
|
||||||
if ( nat->nvo.nvs ) {
|
if ( nat->nvo.nvs ) {
|
||||||
if ( ( rc = nvo_register ( &nat->nvo ) ) != 0 )
|
if ( ( rc = nvo_register ( &nat->nvo ) ) != 0 )
|
||||||
goto err;
|
goto err_register_nvo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err_register_nvo:
|
||||||
/* Disable NIC */
|
|
||||||
if ( nat )
|
|
||||||
nat_reset ( nat );
|
|
||||||
if ( registered_netdev )
|
|
||||||
unregister_netdev ( netdev );
|
unregister_netdev ( netdev );
|
||||||
|
err_register_netdev:
|
||||||
|
/* Disable NIC */
|
||||||
|
nat_reset ( nat );
|
||||||
/* Free net device */
|
/* Free net device */
|
||||||
netdev_put ( netdev );
|
netdev_put ( netdev );
|
||||||
return rc;
|
return rc;
|
||||||
|
Reference in New Issue
Block a user