📄 3c90x.c
字号:
/*** a3c90x_disable: exported routine to disable the card. What's this for? *** the eepro100.c driver didn't have one, so I just left this one empty too. *** Ideas anyone? *** Must turn off receiver at least so stray packets will not corrupt memory *** [Ken] ***/static voida3c90x_disable(struct dev *dev __unused){ /* reset and disable merge */ a3c90x_reset(); /* Disable the receiver and transmitter. */ outw(cmdRxDisable, INF_3C90X.IOAddr + regCommandIntStatus_w); outw(cmdTxDisable, INF_3C90X.IOAddr + regCommandIntStatus_w);}/*** a3c90x_probe: exported routine to probe for the 3c905 card and perform *** initialization. If this routine is called, the pci functions did find the *** card. We just have to init it here. ***/static int a3c90x_probe(struct dev *dev, struct pci_device *pci){ struct nic *nic = (struct nic *)dev; int i, c; unsigned short eeprom[0x21]; unsigned int cfg; unsigned int mopt; unsigned int mstat; unsigned short linktype;#define HWADDR_OFFSET 10 if (pci->ioaddr == 0) return 0; adjust_pci_device(pci); INF_3C90X.IOAddr = pci->ioaddr & ~3; INF_3C90X.CurrentWindow = 255; switch (a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, 0x03)) { case 0x9000: /** 10 Base TPO **/ case 0x9001: /** 10/100 T4 **/ case 0x9050: /** 10/100 TPO **/ case 0x9051: /** 10 Base Combo **/ INF_3C90X.isBrev = 0; break; case 0x9004: /** 10 Base TPO **/ case 0x9005: /** 10 Base Combo **/ case 0x9006: /** 10 Base TPO and Base2 **/ case 0x900A: /** 10 Base FL **/ case 0x9055: /** 10/100 TPO **/ case 0x9056: /** 10/100 T4 **/ case 0x905A: /** 10 Base FX **/ default: INF_3C90X.isBrev = 1; break; } /** Load the EEPROM contents **/ if (INF_3C90X.isBrev) { for(i=0;i<=0x20;i++) { eeprom[i] = a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, i); }#ifdef CFG_3C90X_BOOTROM_FIX /** Set xcvrSelect in InternalConfig in eeprom. **/ /* only necessary for 3c905b revision cards with boot PROM bug!!! */ a3c90x_internal_WriteEeprom(INF_3C90X.IOAddr, 0x13, 0x0160);#endif#ifdef CFG_3C90X_XCVR if (CFG_3C90X_XCVR == 255) { /** Clear the LanWorks register **/ a3c90x_internal_WriteEeprom(INF_3C90X.IOAddr, 0x16, 0); } else { /** Set the selected permanent-xcvrSelect in the ** LanWorks register **/ a3c90x_internal_WriteEeprom(INF_3C90X.IOAddr, 0x16, XCVR_MAGIC + ((CFG_3C90X_XCVR) & 0x000F)); }#endif } else { for(i=0;i<=0x17;i++) { eeprom[i] = a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, i); } } /** Print identification message **/ printf("\n\n3C90X Driver 2.00 " "Copyright 1999 LightSys Technology Services, Inc.\n" "Portions Copyright 1999 Steve Smith\n"); printf("Provided with ABSOLUTELY NO WARRANTY.\n");#ifdef CFG_3C90X_BOOTROM_FIX if (INF_3C90X.isBrev) { printf("NOTE: 3c905b bootrom fix enabled; has side " "effects. See 3c90x.txt for info.\n"); }#endif printf("-------------------------------------------------------" "------------------------\n"); /** Retrieve the Hardware address and print it on the screen. **/ INF_3C90X.HWAddr[0] = eeprom[HWADDR_OFFSET + 0]>>8; INF_3C90X.HWAddr[1] = eeprom[HWADDR_OFFSET + 0]&0xFF; INF_3C90X.HWAddr[2] = eeprom[HWADDR_OFFSET + 1]>>8; INF_3C90X.HWAddr[3] = eeprom[HWADDR_OFFSET + 1]&0xFF; INF_3C90X.HWAddr[4] = eeprom[HWADDR_OFFSET + 2]>>8; INF_3C90X.HWAddr[5] = eeprom[HWADDR_OFFSET + 2]&0xFF; printf("MAC Address = %!\n", INF_3C90X.HWAddr); /* Test if the link is good, if not continue */ a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winDiagnostics4); mstat = inw(INF_3C90X.IOAddr + regMediaStatus_4_w); if((mstat & (1<<11)) == 0) { printf("Valid link not established\n"); return 0; } /** Program the MAC address into the station address registers **/ a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winAddressing2); outw(htons(eeprom[HWADDR_OFFSET + 0]), INF_3C90X.IOAddr + regStationAddress_2_3w); outw(htons(eeprom[HWADDR_OFFSET + 1]), INF_3C90X.IOAddr + regStationAddress_2_3w+2); outw(htons(eeprom[HWADDR_OFFSET + 2]), INF_3C90X.IOAddr + regStationAddress_2_3w+4); outw(0, INF_3C90X.IOAddr + regStationMask_2_3w+0); outw(0, INF_3C90X.IOAddr + regStationMask_2_3w+2); outw(0, INF_3C90X.IOAddr + regStationMask_2_3w+4); /** Fill in our entry in the etherboot arp table **/ for(i=0;i<ETH_ALEN;i++) nic->node_addr[i] = (eeprom[HWADDR_OFFSET + i/2] >> (8*((i&1)^1))) & 0xff; /** Read the media options register, print a message and set default ** xcvr. ** ** Uses Media Option command on B revision, Reset Option on non-B ** revision cards -- same register address **/ a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winTxRxOptions3); mopt = inw(INF_3C90X.IOAddr + regResetMediaOptions_3_w); /** mask out VCO bit that is defined as 10baseFL bit on B-rev cards **/ if (! INF_3C90X.isBrev) { mopt &= 0x7F; } printf("Connectors present: "); c = 0; linktype = 0x0008; if (mopt & 0x01) { printf("%s100Base-T4",(c++)?", ":""); linktype = 0x0006; } if (mopt & 0x04) { printf("%s100Base-FX",(c++)?", ":""); linktype = 0x0005; } if (mopt & 0x10) { printf("%s10Base-2",(c++)?", ":""); linktype = 0x0003; } if (mopt & 0x20) { printf("%sAUI",(c++)?", ":""); linktype = 0x0001; } if (mopt & 0x40) { printf("%sMII",(c++)?", ":""); linktype = 0x0006; } if ((mopt & 0xA) == 0xA) { printf("%s10Base-T / 100Base-TX",(c++)?", ":""); linktype = 0x0008; } else if ((mopt & 0xA) == 0x2) { printf("%s100Base-TX",(c++)?", ":""); linktype = 0x0008; } else if ((mopt & 0xA) == 0x8) { printf("%s10Base-T",(c++)?", ":""); linktype = 0x0008; } printf(".\n"); /** Determine transceiver type to use, depending on value stored in ** eeprom 0x16 **/ if (INF_3C90X.isBrev) { if ((eeprom[0x16] & 0xFF00) == XCVR_MAGIC) { /** User-defined **/ linktype = eeprom[0x16] & 0x000F; } } else {#ifdef CFG_3C90X_XCVR if (CFG_3C90X_XCVR != 255) linktype = CFG_3C90X_XCVR;#endif /* CFG_3C90X_XCVR */ /** I don't know what MII MAC only mode is!!! **/ if (linktype == 0x0009) { if (INF_3C90X.isBrev) printf("WARNING: MII External MAC Mode only supported on B-revision " "cards!!!!\nFalling Back to MII Mode\n"); linktype = 0x0006; } } /** enable DC converter for 10-Base-T **/ if (linktype == 0x0003) { a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdEnableDcConverter, 0); } /** Set the link to the type we just determined. **/ a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winTxRxOptions3); cfg = inl(INF_3C90X.IOAddr + regInternalConfig_3_l); cfg &= ~(0xF<<20); cfg |= (linktype<<20); outl(cfg, INF_3C90X.IOAddr + regInternalConfig_3_l); /** Now that we set the xcvr type, reset the Tx and Rx, re-enable. **/ a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxReset, 0x00); while (inw(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_CMDINPROGRESS) ; if (!INF_3C90X.isBrev) outb(0x01, INF_3C90X.IOAddr + regTxFreeThresh_b); a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxEnable, 0); /** ** reset of the receiver on B-revision cards re-negotiates the link ** takes several seconds (a computer eternity) **/ if (INF_3C90X.isBrev) a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdRxReset, 0x04); else a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdRxReset, 0x00); while (inw(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_CMDINPROGRESS) ; /** Set the RX filter = receive only individual pkts & multicast & bcast. **/ a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdSetRxFilter, 0x01 + 0x02 + 0x04); a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdRxEnable, 0); /** ** set Indication and Interrupt flags , acknowledge any IRQ's **/ a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdSetInterruptEnable, 0); a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdSetIndicationEnable, 0x0014); a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdAcknowledgeInterrupt, 0x661); /** Set our exported functions **/ dev->disable = a3c90x_disable; nic->poll = a3c90x_poll; nic->transmit = a3c90x_transmit; return 1;}static struct pci_id a3c90x_nics[] = {/* Original 90x revisions: */PCI_ROM(0x10b7, 0x9000, "3c905-tpo", "3Com900-TPO"), /* 10 Base TPO */PCI_ROM(0x10b7, 0x9001, "3c905-t4", "3Com900-Combo"), /* 10/100 T4 */PCI_ROM(0x10b7, 0x9050, "3c905-tpo100", "3Com905-TX"), /* 100 Base TX / 10/100 TPO */PCI_ROM(0x10b7, 0x9051, "3c905-combo", "3Com905-T4"), /* 100 Base T4 / 10 Base Combo *//* Newer 90xB revisions: */PCI_ROM(0x10b7, 0x9004, "3c905b-tpo", "3Com900B-TPO"), /* 10 Base TPO */PCI_ROM(0x10b7, 0x9005, "3c905b-combo", "3Com900B-Combo"), /* 10 Base Combo */PCI_ROM(0x10b7, 0x9006, "3c905b-tpb2", "3Com900B-2/T"), /* 10 Base TP and Base2 */PCI_ROM(0x10b7, 0x900a, "3c905b-fl", "3Com900B-FL"), /* 10 Base FL */PCI_ROM(0x10b7, 0x9055, "3c905b-tpo100", "3Com905B-TX"), /* 10/100 TPO */PCI_ROM(0x10b7, 0x9056, "3c905b-t4", "3Com905B-T4"), /* 10/100 T4 */PCI_ROM(0x10b7, 0x9058, "3c905b-9058", "3Com905B-9058"), /* Cyclone 10/100/BNC */PCI_ROM(0x10b7, 0x905a, "3c905b-fx", "3Com905B-FL"), /* 100 Base FX / 10 Base FX *//* Newer 90xC revision: */PCI_ROM(0x10b7, 0x9200, "3c905c-tpo", "3Com905C-TXM"), /* 10/100 TPO (3C905C-TXM) */PCI_ROM(0x10b7, 0x9210, "3c920b-emb-wnm","3Com20B-EMB WNM"),PCI_ROM(0x10b7, 0x9800, "3c980", "3Com980-Cyclone"), /* Cyclone */PCI_ROM(0x10b7, 0x9805, "3c9805", "3Com9805"), /* Dual Port Server Cyclone */PCI_ROM(0x10b7, 0x7646, "3csoho100-tx", "3CSOHO100-TX"), /* Hurricane */PCI_ROM(0x10b7, 0x4500, "3c450", "3Com450 HomePNA Tornado"),PCI_ROM(0x10b7, 0x1201, "3c982a", "3Com982A"),PCI_ROM(0x10b7, 0x1202, "3c982b", "3Com982B"),};static struct pci_driver a3c90x_driver __pci_driver = { .type = NIC_DRIVER, .name = "3C90X", .probe = a3c90x_probe, .ids = a3c90x_nics, .id_count = sizeof(a3c90x_nics)/sizeof(a3c90x_nics[0]), .class = 0,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -