38 |
#include "nic.h" |
#include "nic.h" |
39 |
#include "pci.h" |
#include "pci.h" |
40 |
#include "cards.h" |
#include "cards.h" |
41 |
|
#include "timer.h" |
42 |
|
|
|
#define TIME_OUT 60000 |
|
43 |
#define XCVR_MAGIC (0x5A00) |
#define XCVR_MAGIC (0x5A00) |
44 |
/** any single transmission fails after 16 collisions or other errors |
/** any single transmission fails after 16 collisions or other errors |
45 |
** this is the number of times to retry the transmission -- this should |
** this is the number of times to retry the transmission -- this should |
243 |
unsigned char isBrev; |
unsigned char isBrev; |
244 |
unsigned char CurrentWindow; |
unsigned char CurrentWindow; |
245 |
unsigned int IOAddr; |
unsigned int IOAddr; |
246 |
unsigned char HWAddr[6]; |
unsigned char HWAddr[ETH_ALEN]; |
247 |
TXD TransmitDPD; |
TXD TransmitDPD; |
248 |
RXD ReceiveUPD; |
RXD ReceiveUPD; |
249 |
} |
} |
479 |
|
|
480 |
struct eth_hdr |
struct eth_hdr |
481 |
{ |
{ |
482 |
unsigned char dst_addr[6]; |
unsigned char dst_addr[ETH_ALEN]; |
483 |
unsigned char src_addr[6]; |
unsigned char src_addr[ETH_ALEN]; |
484 |
unsigned short type; |
unsigned short type; |
485 |
} hdr; |
} hdr; |
486 |
|
|
487 |
unsigned char status; |
unsigned char status; |
488 |
unsigned timeout, i, retries; |
unsigned i, retries; |
489 |
|
|
490 |
for (retries=0; retries < XMIT_RETRIES ; retries++) |
for (retries=0; retries < XMIT_RETRIES ; retries++) |
491 |
{ |
{ |
504 |
hdr.type = htons(t); |
hdr.type = htons(t); |
505 |
|
|
506 |
/** Copy the destination address **/ |
/** Copy the destination address **/ |
507 |
memcpy(hdr.dst_addr, d, 6); |
memcpy(hdr.dst_addr, d, ETH_ALEN); |
508 |
|
|
509 |
/** Copy our MAC address **/ |
/** Copy our MAC address **/ |
510 |
memcpy(hdr.src_addr, INF_3C90X.HWAddr, 6); |
memcpy(hdr.src_addr, INF_3C90X.HWAddr, ETH_ALEN); |
511 |
|
|
512 |
/** Setup the DPD (download descriptor) **/ |
/** Setup the DPD (download descriptor) **/ |
513 |
INF_3C90X.TransmitDPD.DnNextPtr = 0; |
INF_3C90X.TransmitDPD.DnNextPtr = 0; |
528 |
; |
; |
529 |
|
|
530 |
/** Wait for NIC Transmit to Complete **/ |
/** Wait for NIC Transmit to Complete **/ |
531 |
timeout=TIME_OUT; |
load_timer2(10*TICKS_PER_MS); /* Give it 10 ms */ |
532 |
while (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004) && |
while (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004) && |
533 |
--timeout) |
timer2_running()) |
534 |
for(i=0;i<TIME_OUT;i++); |
; |
535 |
|
|
536 |
if (timeout==0) |
if (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004)) |
537 |
{ |
{ |
538 |
printf("3C90X: Tx Timeout\n"); |
printf("3C90X: Tx Timeout\n"); |
539 |
continue; |
continue; |
548 |
if ((status & 0xbf) == 0x80) |
if ((status & 0xbf) == 0x80) |
549 |
return; |
return; |
550 |
|
|
551 |
printf("3C90X: Status (%x)\n", status); |
printf("3C90X: Status (%hhX)\n", status); |
552 |
/** check error codes **/ |
/** check error codes **/ |
553 |
if (status & 0x02) |
if (status & 0x02) |
554 |
{ |
{ |
555 |
printf("3C90X: Tx Reclaim Error (%x)\n", status); |
printf("3C90X: Tx Reclaim Error (%hhX)\n", status); |
556 |
a3c90x_reset(NULL); |
a3c90x_reset(NULL); |
557 |
} |
} |
558 |
else if (status & 0x04) |
else if (status & 0x04) |
559 |
{ |
{ |
560 |
printf("3C90X: Tx Status Overflow (%x)\n", status); |
printf("3C90X: Tx Status Overflow (%hhX)\n", status); |
561 |
for (i=0; i<32; i++) |
for (i=0; i<32; i++) |
562 |
outb(0x00, INF_3C90X.IOAddr + regTxStatus_b); |
outb(0x00, INF_3C90X.IOAddr + regTxStatus_b); |
563 |
/** must re-enable after max collisions before re-issuing tx **/ |
/** must re-enable after max collisions before re-issuing tx **/ |
565 |
} |
} |
566 |
else if (status & 0x08) |
else if (status & 0x08) |
567 |
{ |
{ |
568 |
printf("3C90X: Tx Max Collisions (%x)\n", status); |
printf("3C90X: Tx Max Collisions (%hhX)\n", status); |
569 |
/** must re-enable after max collisions before re-issuing tx **/ |
/** must re-enable after max collisions before re-issuing tx **/ |
570 |
a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxEnable, 0); |
a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxEnable, 0); |
571 |
} |
} |
572 |
else if (status & 0x10) |
else if (status & 0x10) |
573 |
{ |
{ |
574 |
printf("3C90X: Tx Underrun (%x)\n", status); |
printf("3C90X: Tx Underrun (%hhX)\n", status); |
575 |
a3c90x_reset(NULL); |
a3c90x_reset(NULL); |
576 |
} |
} |
577 |
else if (status & 0x20) |
else if (status & 0x20) |
578 |
{ |
{ |
579 |
printf("3C90X: Tx Jabber (%x)\n", status); |
printf("3C90X: Tx Jabber (%hhX)\n", status); |
580 |
a3c90x_reset(NULL); |
a3c90x_reset(NULL); |
581 |
} |
} |
582 |
else if ((status & 0x80) != 0x80) |
else if ((status & 0x80) != 0x80) |
583 |
{ |
{ |
584 |
printf("3C90X: Internal Error - Incomplete Transmission (%x)\n", |
printf("3C90X: Internal Error - Incomplete Transmission (%hhX)\n", |
585 |
status); |
status); |
586 |
a3c90x_reset(NULL); |
a3c90x_reset(NULL); |
587 |
} |
} |
634 |
{ |
{ |
635 |
errcode = INF_3C90X.ReceiveUPD.UpPktStatus; |
errcode = INF_3C90X.ReceiveUPD.UpPktStatus; |
636 |
if (errcode & (1<<16)) |
if (errcode & (1<<16)) |
637 |
printf("3C90X: Rx Overrun (%x)\n",errcode>>16); |
printf("3C90X: Rx Overrun (%hX)\n",errcode>>16); |
638 |
else if (errcode & (1<<17)) |
else if (errcode & (1<<17)) |
639 |
printf("3C90X: Runt Frame (%x)\n",errcode>>16); |
printf("3C90X: Runt Frame (%hX)\n",errcode>>16); |
640 |
else if (errcode & (1<<18)) |
else if (errcode & (1<<18)) |
641 |
printf("3C90X: Alignment Error (%x)\n",errcode>>16); |
printf("3C90X: Alignment Error (%hX)\n",errcode>>16); |
642 |
else if (errcode & (1<<19)) |
else if (errcode & (1<<19)) |
643 |
printf("3C90X: CRC Error (%x)\n",errcode>>16); |
printf("3C90X: CRC Error (%hX)\n",errcode>>16); |
644 |
else if (errcode & (1<<20)) |
else if (errcode & (1<<20)) |
645 |
printf("3C90X: Oversized Frame (%x)\n",errcode>>16); |
printf("3C90X: Oversized Frame (%hX)\n",errcode>>16); |
646 |
else |
else |
647 |
printf("3C90X: Packet error (%x)\n",errcode>>16); |
printf("3C90X: Packet error (%hX)\n",errcode>>16); |
648 |
return 0; |
return 0; |
649 |
} |
} |
650 |
|
|
659 |
/*** a3c90x_disable: exported routine to disable the card. What's this for? |
/*** a3c90x_disable: exported routine to disable the card. What's this for? |
660 |
*** the eepro100.c driver didn't have one, so I just left this one empty too. |
*** the eepro100.c driver didn't have one, so I just left this one empty too. |
661 |
*** Ideas anyone? |
*** Ideas anyone? |
662 |
|
*** Must turn off receiver at least so stray packets will not corrupt memory |
663 |
|
*** [Ken] |
664 |
***/ |
***/ |
665 |
static void |
static void |
666 |
a3c90x_disable(struct nic *nic) |
a3c90x_disable(struct nic *nic) |
667 |
{ |
{ |
668 |
|
/* Disable the receiver and transmitter. */ |
669 |
|
outw(cmdRxDisable, INF_3C90X.IOAddr + regCommandIntStatus_w); |
670 |
|
outw(cmdTxDisable, INF_3C90X.IOAddr + regCommandIntStatus_w); |
671 |
} |
} |
672 |
|
|
673 |
|
|
688 |
if (probeaddrs == 0 || probeaddrs[0] == 0) |
if (probeaddrs == 0 || probeaddrs[0] == 0) |
689 |
return 0; |
return 0; |
690 |
|
|
691 |
|
adjust_pci_device(pci); |
692 |
|
|
693 |
INF_3C90X.IOAddr = probeaddrs[0] & ~3; |
INF_3C90X.IOAddr = probeaddrs[0] & ~3; |
694 |
INF_3C90X.CurrentWindow = 255; |
INF_3C90X.CurrentWindow = 255; |
695 |
switch (a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, 0x03)) |
switch (a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, 0x03)) |
766 |
INF_3C90X.HWAddr[3] = eeprom[1]&0xFF; |
INF_3C90X.HWAddr[3] = eeprom[1]&0xFF; |
767 |
INF_3C90X.HWAddr[4] = eeprom[2]>>8; |
INF_3C90X.HWAddr[4] = eeprom[2]>>8; |
768 |
INF_3C90X.HWAddr[5] = eeprom[2]&0xFF; |
INF_3C90X.HWAddr[5] = eeprom[2]&0xFF; |
769 |
printf("MAC Address = %b:%b:%b:%b:%b:%b\n", |
printf("MAC Address = %!\n", INF_3C90X.HWAddr); |
|
INF_3C90X.HWAddr[0],INF_3C90X.HWAddr[1],INF_3C90X.HWAddr[2], |
|
|
INF_3C90X.HWAddr[3],INF_3C90X.HWAddr[4],INF_3C90X.HWAddr[5]); |
|
770 |
|
|
771 |
/** Program the MAC address into the station address registers **/ |
/** Program the MAC address into the station address registers **/ |
772 |
a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winAddressing2); |
a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winAddressing2); |
778 |
outw(0, INF_3C90X.IOAddr + regStationMask_2_3w+4); |
outw(0, INF_3C90X.IOAddr + regStationMask_2_3w+4); |
779 |
|
|
780 |
/** Fill in our entry in the etherboot arp table **/ |
/** Fill in our entry in the etherboot arp table **/ |
781 |
for(i=0;i<6;i++) nic->node_addr[i] = (eeprom[i/2] >> (8*((i&1)^1))) & 0xff; |
for(i=0;i<ETH_ALEN;i++) |
782 |
|
nic->node_addr[i] = (eeprom[i/2] >> (8*((i&1)^1))) & 0xff; |
783 |
|
|
784 |
/** Read the media options register, print a message and set default |
/** Read the media options register, print a message and set default |
785 |
** xcvr. |
** xcvr. |