📄 net_3c59x.cxx
字号:
alignment contraint on tx_ring[] and rx_ring[]. */struct boom_rx_desc { uint32_t next; uint32_t status; uint32_t addr; uint32_t length;};/* Values for the Rx status entry. */#define RX_COMPLETE 0x00008000struct boom_tx_desc { uint32_t next; uint32_t status; uint32_t addr; uint32_t length;};/* The action to take with a media selection timer tick. Note that we deviate from the 3Com order by checking 10base2 before AUI. */static struct media_table { char *name; uint32_t media_bits:16; /* Bits to set in Wn4_Media register. */ uint32_t mask:8; /* The transceiver-present bit in Wn3_Config.*/ uint32_t next:8; /* The media type to try next. */ uint64_t wait; /* Time (ms) before we check media status. */} media_tbl[] = { { "10baseT", Media_10TP,0x08, 3 /* 10baseT->10base2 */, 1400 }, { "10Mbs AUI", Media_SQE, 0x20, 8 /* AUI->default */, 1000 }, { "undefined", 0, 0x80, 0 /* Undefined */, 500000 }, { "10base2", 0, 0x10, 1 /* 10base2->AUI. */, 200 }, { "100baseTX", Media_Lnk, 0x02, 5 /* 100baseTX->100baseFX */, 1400 }, { "100baseFX", Media_Lnk, 0x04, 6 /* 100baseFX->MII */, 1400 }, { "MII", 0, 0x40, 0 /* MII->10baseT */, 1400 }, { "undefined", 0, 0x01, 0 /* Undefined/100baseT4 */, 500000 }, { "Default", 0, 0xFF, 0 /* Use default */, 500000 },};struct vortex_private { /* The Rx and Tx rings are here to keep them quad-word-aligned. */ struct boom_rx_desc rx_ring[RX_RING_SIZE];#if 0 struct boom_tx_desc tx_ring[TX_RING_SIZE];#endif /* The addresses of transmit- and receive-in-place buffers. We can * fit two packets per page */ uint8_t *rx_pkt_buf[RX_RING_SIZE]; struct sk_buff* rx_skbuff[RX_RING_SIZE];#if 0 struct sk_buff* tx_skbuff[TX_RING_SIZE];#endif#if 0 unsigned int cur_rx, cur_tx; /* The next free ring entry */ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */#endif const char *product_name;#if 0 struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */#endif int capabilities; /* Adapter capabilities word. */ int options; /* User-settable misc. driver options. */ int lastRxPackets; /* For media autoselection. */ uint32_t availMedia : 8; /* From Wn3Options */ uint32_t mediaOverride : 3; /* From Wn3Options */ uint32_t defaultMedia : 3; /* Read from the EEPROM. */ uint32_t fullDuplex : 1; uint32_t autoSelect : 1; uint32_t busMaster : 1; /* Vortex can only do a fragment bus-m. */ uint32_t fullBusMasterTX : 1; uint32_t fullBusMasterRX : 1; /* Boomerang */ uint32_t txFull : 1; uint16_t txStartThresh;};#define private devInfo[0] #define rxFilter devInfo[1]#define curInts devInfo[2]const int vortex_debug = 4;static void Invoke(NetInterface *, Invocation& inv); /* FORWARD */static void RxPacket(NetInterface *); /* FORWARD */static void ReadPacket(NetInterface *ni, Invocation& inv); /* FORWARD */#ifdef NET_MULTIREADstatic void MultiReadPacket(NetInterface *ni, Invocation& inv); /* FORWARD */#endifstatic void WritePacket(NetInterface *ni, Invocation& inv); /* FORWARD */#if 0static void Disable(NetInterface *); /* FORWARD */#endifstatic void Enable(NetInterface *); /* FORWARD */static void UpdateStatistics(NetInterface *); /* FORWARD */static void HandleInterrupt(NetInterface *); /* FORWARD */static void HandleInterrupt(IntAction *); /* FORWARD */inline voidOutCmd(NetInterface *ni, uint16_t cmd, bool andWait = false){ out16(cmd, ni->ioAddr + El3Cmd); if (andWait) while (in16(ni->ioAddr + El3Status) & CmdInProgress) ;}inline voidSetWindow(NetInterface* ni, int whichWindow){ OutCmd(ni, SelectWindow | whichWindow);}static voidvortex_probe1(NetInterface *ni){ vortex_private *vp = (vortex_private *) ni->private; uint32_t eeprom[0x40]; uint32_t checksum = 0; MsgLog::dprintf(false, "NI: 3Com %s io=0x%x ", ni->name, ni->ioAddr); SetWindow(ni, 0); for(int i = 0; i < RX_RING_SIZE; i++) { if ((i % 2) == 0) { vp->rx_pkt_buf[i] = new (0) uint8_t[EROS_PAGE_SIZE]; vp->rx_pkt_buf[i+1] = vp->rx_pkt_buf[i] + (EROS_PAGE_SIZE/2); vp->rx_ring[i].next = (uint32_t) &vp->rx_ring[(i+1)%RX_RING_SIZE]; vp->rx_ring[i].status = 0; /* Clear complete bit. */ vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000; vp->rx_ring[i].addr = (uint32_t) vp->rx_pkt_buf[i]; } } /* Fetch out the enet address: */ for (int i = 0; i < 0x18; i++) { uint16_t *phys_addr = (uint16_t *)ni->info.niAddr; out16(EEPROM_Read + i, ni->ioAddr + Wn0EepromCmd); /* must wait at least 162us, this is conservative */#if 0 Machine::SpinWaitUs(162); uint16_t hw = in16(ni->ioAddr + Wn0EepromCmd); if ((hw & 0x8000u) != 0) MsgLog::dprintf(true, "3c59x.c: Couldn't read EEPROM (0x%04x)\n", hw);#endif for (int timer = 162*4 + 400; timer >= 0; timer--) { /* SLOW_DOWN_IO; */ if ((in16(ni->ioAddr + Wn0EepromCmd) & 0x8000) == 0) break; } eeprom[i] = inw(ni->ioAddr + Wn0EepromData); checksum ^= eeprom[i]; /* First three locations are the ethernet address : */ if (i < 3) phys_addr[i] = htons(in16(ni->ioAddr + Wn0EepromData)); } ni->info.niAddrLen = 6; checksum = (checksum ^ (checksum >> 8)) & 0xff; if (checksum != 0x00) MsgLog::dprintf(true, "*** INVALID CHECKSUM 0x%x\n", checksum); for (int i = 0; i < 6; i++) MsgLog::printf("%c%02x", i ? ':' : ' ', (uint8_t) ni->info.niAddr[i]); MsgLog::dprintf(false, ", IRQ %d\n", ni->irq); { char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; union wn3_config config; SetWindow(ni, 3); vp->availMedia = in16(ni->ioAddr + Wn3Options); config.i = in32(ni->ioAddr + Wn3Config); if (vortex_debug > 1) MsgLog::dprintf(false, " Internal config register is 0x%4x, transceivers 0x%x.\n", config.i, in16(ni->ioAddr + Wn3Options)); MsgLog::dprintf(false, " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", 8 << config.u.ram_size, config.u.ram_width ? "word" : "byte", ram_split[config.u.ram_split], config.u.autoselect ? "autoselect/" : "", media_tbl[config.u.xcvr].name); ni->xcvr = config.u.xcvr; vp->defaultMedia = config.u.xcvr; vp->autoSelect = config.u.autoselect;#if 0 config.u.ram_split = 0; out32(ni->ioAddr + Wn3Config, config.i); MsgLog::dprintf(true, " Overrode to 5:3 (rx:tx) split\n");#endif } if (vp->mediaOverride != 7) { MsgLog::dprintf(false, " Media override to transceiver type %d (%s).\n", vp->mediaOverride, media_tbl[vp->mediaOverride].name); ni->xcvr = vp->mediaOverride; } vp->capabilities = eeprom[16]; vp->fullBusMasterTX = (vp->capabilities & 0x20) ? 1 : 0; /* Rx is broken at 10mbps, so we always disable it. */ /* vp->full_bus_master_rx = 0;*/ vp->fullBusMasterRX = (vp->capabilities & 0x20) ? 1 : 0; vp->txStartThresh = 64; SetWindow(ni, 7);#if 0 /* We do a request_region() to register /proc/ioports info. */ /* Not in the EROS logic. */ request_region(ioaddr, VORTEX_TOTAL_SIZE, vp->product_name);#endif}static NetInterface *vortex_found_device(uint32_t ioAddr, uint8_t irq, uint16_t boardNdx, uint32_t options){ NetInterface *ni = NetInterface::Alloc(); if (ni == 0) { MsgLog::dprintf(true, "Failed to allocate NetInterface struct\n"); return 0; } ni->irq = irq; ni->ioAddr = ioAddr; ni->ioLen = product_info[boardNdx].ioSize; ni->addr = 0; ni->len = 0; ni->xcvr = 6; /* until proven otherwise */ ni->name = product_info[boardNdx].name; ni->devClass = DEV_NET_ENET; ni->Invoke = Invoke; ni->info.niStatus = 0; ni->watchDog.client_ptr = ni; ni->updateStats = UpdateStatistics; if (options == 0) options = product_info[boardNdx].defaultOptions; /* Private storage must be aligned to quadword boundary. */ vortex_private *vp = (vortex_private *) PhysMem::Alloc(sizeof(vortex_private), McMemHi, 8); if (vp) bzero(vp, sizeof (vortex_private)); else MsgLog::dprintf(true, "Vortex: private memory allocation failed!\n"); ni->private = (uint32_t) vp; vp->options = options;#if 0 vp->mediaOverride = ((options & 7) == 2) ? 0 : (options & 7); vp->busMaster = (options & 16) ? 1 : 0; vp->fullDuplex = (options & 8) ? 1 : 0; if (options == 0) vp->mediaOverride = 7;#else vp->mediaOverride = 6; /* require 100baseTX for now */ vp->busMaster = 1; vp->fullDuplex = 1;#endif vortex_probe1(ni); return ni;}static boolPCI_Probe(AutoConf * /* ac */){ bool result = false; #if 0 MsgLog::dprintf(true, "Probing for vortex boards...\n");#endif uint32_t nCards = 0; if (PciBios::Present()) { for (int ndx = 0; ndx < 0xff; ndx++) { uint8_t bus; uint8_t devFn; uint16_t vendor; uint16_t device; uint16_t pciCmd; uint8_t pciLatency; uint8_t irq; uint32_t ioAddr; uint32_t result =PciBios::FindClass(PCI_CLASS_NETWORK_ETHERNET << 8, ndx, bus, devFn);#if 0 MsgLog::dprintf(true, "Result of FindClass(%x, %x, ..., ...)" " = 0x%08x\n", PCI_CLASS_NETWORK_ETHERNET << 8, ndx, result);#endif if (result != PciBios::OK) break; PciBios::ReadConfig16(bus, devFn, PCI_VENDOR_ID, vendor); PciBios::ReadConfig16(bus, devFn, PCI_DEVICE_ID, device); PciBios::ReadConfig8(bus, devFn, PCI_INTERRUPT_LINE, irq); PciBios::ReadConfig32(bus, devFn, PCI_BASE_ADDRESS_0, ioAddr); ioAddr &= ~0x3; /* kill off I/O space marker */ if (vendor != PCI_VENDOR_ID_3COM) continue;#if 0 MsgLog::dprintf(false, "Found PCI card. ven=0x%04x, dev=0x%04x" " irq=%d io=0x%03x\n", vendor, device, irq, ioAddr);#endif uint32_t whichBoard = 0; for (; product_info[whichBoard].prodId; whichBoard++) { if (device == product_info[whichBoard].prodId) break; } if (product_info[whichBoard].prodId == 0) { MsgLog::dprintf(true, "Unknown 3com PCI ethernet adapter type" " 0x%04x detected: not configured\n", device); continue; }#if 0 /* Do not check the I/O region until attach time. */ if (IoRegion::IsAvailable(ioAddr, product_info[whichBoard].ioSize) == false) continue;#endif NetInterface *ni = vortex_found_device(ioAddr, irq, whichBoard, nCards); if (ni) { PciBios::ReadConfig16(bus, devFn, PCI_COMMAND, pciCmd); if (!pciCmd & PCI_COMMAND_MASTER) { MsgLog::dprintf(false, "PCI Master bit not set. Setting....\n"); pciCmd |= pciCmd; PciBios::WriteConfig16(bus, devFn, PCI_COMMAND, pciCmd); } PciBios::ReadConfig8(bus, devFn, PCI_COMMAND, pciLatency); if (pciLatency != 248) { MsgLog::dprintf(false, "%s: Overriding PCI latency" " timer (CFLT) setting of %d, new value is 248.\n", ni->name, pciLatency); PciBios::WriteConfig8(bus, devFn, PCI_LATENCY_TIMER, 248); } nCards++; result = true; } } } return result;}static boolProbe(struct AutoConf * ac){ return PCI_Probe(ac); /* No EtherLink III family cards are present until proven otherwise. */}static voidni_Attach(NetInterface* ni){ MsgLog::dprintf(false, "Attaching %s io=0x%x, irq=%d " " [%02x:%02x:%02x:%02x:%02x:%02x]\n", ni->name, ni->ioAddr, ni->irq, ni->info.niAddr[0], ni->info.niAddr[1], ni->info.niAddr[2], ni->info.niAddr[3], ni->info.niAddr[4], ni->info.niAddr[5]); if (ni->info.niStatus & NI_ATTACHED) { MsgLog::dprintf(true, "NI 0x%08x already attached\n", ni); return; } /* Reserve I/O port addresses used by adapter. */ if ( IoRegion::Allocate(ni->ioAddr, ni->ioLen, ni->name) == false ) { MsgLog::dprintf(true, "Unable to allocate I/O region io=0x%x: " "port range is taken\n", ni->ioAddr); return; } /* Reserve the IRQ: */ IntAction *ia = new IntAction(ni->irq, ni->name, HandleInterrupt, (uint32_t) ni); if ( IRQ::WireExclusive(ia) == false ) { IoRegion::Release(ni->ioAddr, ni->ioLen); MsgLog::dprintf(true, "Unable to enable %s at io=0x%x: " "irq %d is taken\n", ni->name, ni->ioAddr, ni->irq); return; } /* Interrupt is reserved, but not enabled at this point. */ ni->info.niStatus |= NI_ATTACHED; Enable(ni);}static boolAttach(struct AutoConf * /* ac */){ for (uint32_t i = 0; i < KTUNE_NNETDEV; i++) { NetInterface *ni; if ( (ni = NetInterface::Get(i)) == 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -