| plan 9 kernel history: overview | file list | diff list |
pc/etherelnk3.c (diff list | history)
| 1996/0607/sys/src/9/pc/etherelnk3.c:564,570 – 1996/0608/sys/src/9/pc/etherelnk3.c:564,569 (short | long) | ||
| 1996/0607 | */ if(rxstatus & rxError){ if(ctlr->rxstatus9){ | |
| 1996/0607/sys/src/9/pc/etherelnk3.c:588,594 – 1996/0608/sys/src/9/pc/etherelnk3.c:587,592 | ||
| 1996/0607 | } else{ rxerror = inb(port+RxError); | |
| 1996/0608/sys/src/9/pc/etherelnk3.c:409,414 – 1996/0612/sys/src/9/pc/etherelnk3.c:409,415 (short | long) | ||
| 1996/0607 | x = interruptMask|interruptLatch; if(ctlr->busmaster) x &= ~(rxEarly|rxComplete); | |
| 1996/0612 | x &= ~rxEarly; | |
| 1996/0607 | COMMAND(port, SetIndicationEnable, x); COMMAND(port, SetInterruptEnable, x); | |
| 1996/0612/sys/src/9/pc/etherelnk3.c:2,7 – 1996/0613/sys/src/9/pc/etherelnk3.c:2,8 (short | long) | ||
| 1996/0607 | * Etherlink III and Fast EtherLink adapters. * To do: * check robustness in the face of errors; | |
| 1996/0613 | * RxEarly and busmaster; | |
| 1996/0607 | * autoSelect; * PCI latency timer and master enable; * errata list. | |
| 1996/0612/sys/src/9/pc/etherelnk3.c:409,415 – 1996/0613/sys/src/9/pc/etherelnk3.c:410,415 | ||
| 1996/0607 | x = interruptMask|interruptLatch; if(ctlr->busmaster) x &= ~(rxEarly|rxComplete); | |
| 1996/0612 |
| |
| 1996/0607 | COMMAND(port, SetIndicationEnable, x); COMMAND(port, SetInterruptEnable, x); | |
| 1996/0612/sys/src/9/pc/etherelnk3.c:745,750 – 1996/0613/sys/src/9/pc/etherelnk3.c:745,758 | ||
| 1996/0607 | } /* | |
| 1996/0613 | * Currently, this shouldn't happen. */ if(status & rxEarly){ COMMAND(port, AcknowledgeInterrupt, rxEarly); status &= ~rxEarly; } /* | |
| 1996/0607 | * Panic if there are any interrupts not dealt with. */ if(status & interruptMask) | |
| 1996/0612/sys/src/9/pc/etherelnk3.c:1039,1045 – 1996/0613/sys/src/9/pc/etherelnk3.c:1047,1053 | ||
| 1996/0607 | static int tcm5XXpcmcia(Ether* ether) { | |
| 1996/0613 | if(cistrcmp(ether->type, "3C589") == 0 || cistrcmp(ether->type, "3C562") == 0) | |
| 1996/0607 | return ether->port; return 0; | |
| 1996/0612/sys/src/9/pc/etherelnk3.c:1048,1054 – 1996/0613/sys/src/9/pc/etherelnk3.c:1056,1062 | ||
| 1996/0607 | int etherelnk3reset(Ether* ether) { | |
| 1996/0613 | int busmaster, i, port, rxearly, rxstatus9, x, xcvr; | |
| 1996/0607 | Adapter *ap, **app; uchar ea[Eaddrlen]; Ctlr *ctlr; | |
| 1996/0612/sys/src/9/pc/etherelnk3.c:1062,1067 – 1996/0613/sys/src/9/pc/etherelnk3.c:1070,1076 | ||
| 1996/0607 | * If an adapter is found save the IRQ and transceiver type. */ port = 0; | |
| 1996/0613 | rxearly = 2044; | |
| 1996/0607 | rxstatus9 = 0; xcvr = 0; for(app = &adapter, ap = *app; ap; app = &ap->next, ap = ap->next){ | |
| 1996/0612/sys/src/9/pc/etherelnk3.c:1079,1084 – 1996/0613/sys/src/9/pc/etherelnk3.c:1088,1094 | ||
| 1996/0607 | } else if(port == 0 && (port = tcm59Xpci(ether))){ COMMAND(port, SelectRegisterWindow, Wfifo); | |
| 1996/0613 | rxearly = 8188; | |
| 1996/0607 | xcvr = inl(port+InternalConfig) & xcvrMask; } else if(port == 0 && (port = tcm5XXeisa(ether))){ | |
| 1996/0612/sys/src/9/pc/etherelnk3.c:1085,1090 – 1996/0613/sys/src/9/pc/etherelnk3.c:1095,1101 | ||
| 1996/0607 | x = ins(port+ProductID); if((x & 0xFF00) == 0x5900){ COMMAND(port, SelectRegisterWindow, Wfifo); | |
| 1996/0613 | rxearly = 8188; | |
| 1996/0607 | xcvr = inl(port+InternalConfig) & xcvrMask; } else{ | |
| 1996/0612/sys/src/9/pc/etherelnk3.c:1207,1213 – 1996/0613/sys/src/9/pc/etherelnk3.c:1218,1224 | ||
| 1996/0607 | */ ctlr->txthreshold = ETHERMINTU; COMMAND(port, SetTxStartThresh, ETHERMINTU); | |
| 1996/0613 | COMMAND(port, SetRxEarlyThresh, rxearly); | |
| 1996/0607 | iunlock(&ctlr->wlock); | |
| 1996/0613/sys/src/9/pc/etherelnk3.c:328,333 – 1996/0925/sys/src/9/pc/etherelnk3.c:328,334 (short | long) | ||
| 1996/0607 | int xcvr; /* transceiver type */ int rxstatus9; /* old-style RxStatus register */ | |
| 1996/0925 | int ts; /* threshold shift */ | |
| 1996/0607 | } Ctlr; static Block* | |
| 1996/0613/sys/src/9/pc/etherelnk3.c:501,507 – 1996/0925/sys/src/9/pc/etherelnk3.c:502,508 | ||
| 1996/0607 | } else if(ctlr->txbusy == 0){ ctlr->txbusy = 1; | |
| 1996/0925 | COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts); | |
| 1996/0607 | return; } } | |
| 1996/0613/sys/src/9/pc/etherelnk3.c:724,730 – 1996/0925/sys/src/9/pc/etherelnk3.c:725,731 | ||
| 1996/0607 | COMMAND(port, TxReset, 0); while(STATUS(port) & commandInProgress) ; | |
| 1996/0925 | COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts); | |
| 1996/0607 | } COMMAND(port, TxEnable, 0); ether->oerrs++; | |
| 1996/0613/sys/src/9/pc/etherelnk3.c:1200,1205 – 1996/0925/sys/src/9/pc/etherelnk3.c:1201,1208 | ||
| 1996/0607 | ctlr->busmaster = busmaster; ctlr->xcvr = xcvr; ctlr->rxstatus9 = rxstatus9; | |
| 1996/0925 | if(rxearly >= 2048) ctlr->ts = 2; | |
| 1996/0607 | COMMAND(port, StatisticsEnable, 0); | |
| 1996/0613/sys/src/9/pc/etherelnk3.c:1217,1224 – 1996/0925/sys/src/9/pc/etherelnk3.c:1220,1227 | ||
| 1996/0607 | * interrupts happen. */ ctlr->txthreshold = ETHERMINTU; | |
| 1996/0613 |
| |
| 1996/0925 | COMMAND(port, SetTxStartThresh, ETHERMINTU>>ctlr->ts); COMMAND(port, SetRxEarlyThresh, rxearly>>ctlr->ts); | |
| 1996/0607 | iunlock(&ctlr->wlock); | |
| 1996/0925/sys/src/9/pc/etherelnk3.c:722,728 – 1996/0928/sys/src/9/pc/etherelnk3.c:722,728 (short | long) | ||
| 1996/0607 | } if(txstatus & (txJabber|txUnderrun)){ | |
| 1996/0928 | COMMAND(port, TxReset, dmaReset); | |
| 1996/0607 | while(STATUS(port) & commandInProgress) ; | |
| 1996/0925 | COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts); | |
| 1996/0925/sys/src/9/pc/etherelnk3.c:1219,1226 – 1996/0928/sys/src/9/pc/etherelnk3.c:1219,1226 | ||
| 1996/0607 | * if any txUnderrun errors occur and ensure no RxEarly * interrupts happen. */ | |
| 1996/0925 |
| |
| 1996/0928 | ctlr->txthreshold = ETHERMINTU*2; COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts); | |
| 1996/0925 | COMMAND(port, SetRxEarlyThresh, rxearly>>ctlr->ts); | |
| 1996/0607 | iunlock(&ctlr->wlock); | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:136,141 – 1996/0929/sys/src/9/pc/etherelnk3.c:136,142 (short | long) | ||
| 1996/0607 | EepromCommand = 0x000A, EepromData = 0x000C, /* AddressConfig Bits */ | |
| 1996/0929 | autoSelect9 = 0x0080, | |
| 1996/0607 | xcvrMask9 = 0xC000, /* ConfigControl bits */ Ena = 0x0001, | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:673,679 – 1996/0929/sys/src/9/pc/etherelnk3.c:674,683 | ||
| 1996/0607 | ether->ctlrno, status, x); if(x & txOverrun){ | |
| 1996/0929 | if(ctlr->busmaster == 0) COMMAND(port, TxReset, 0); else COMMAND(port, TxReset, dmaReset); | |
| 1996/0607 | COMMAND(port, TxEnable, 0); wakeup(ðer->tr); } | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:702,708 – 1996/0929/sys/src/9/pc/etherelnk3.c:706,713 | ||
| 1996/0607 | * Pop the TxStatus stack, accumulating errors. * Adjust the TX start threshold if there was an underrun. * If there was a Jabber or Underrun error, reset | |
| 1996/0929 | * the transmitter, taking care not to reset the dma logic * as a busmaster receive may be in progress. | |
| 1996/0607 | * For all conditions enable the transmitter. */ txstatus = 0; | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:722,728 – 1996/0929/sys/src/9/pc/etherelnk3.c:727,736 | ||
| 1996/0607 | } if(txstatus & (txJabber|txUnderrun)){ | |
| 1996/0928 |
| |
| 1996/0929 | if(ctlr->busmaster == 0) COMMAND(port, TxReset, 0); else COMMAND(port, TxReset, dmaReset); | |
| 1996/0607 | while(STATUS(port) & commandInProgress) ; | |
| 1996/0925 | COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts); | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:846,853 – 1996/0929/sys/src/9/pc/etherelnk3.c:854,861 | ||
| 1996/0607 | * One time only: * write ID sequence to get the attention of all adapters; * untag all adapters. | |
| 1996/0929 | * If a global reset is done here on all adapters it will confuse * any ISA cards configured for EISA mode. | |
| 1996/0607 | */ if(untag == 0){ outb(IDport, 0xD0); | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:874,880 – 1996/0929/sys/src/9/pc/etherelnk3.c:882,888 | ||
| 1996/0607 | * is the 'read EEPROM' command, 0x07 is the offset of * the Manufacturer ID field in the EEPROM). * The data comes back 1 bit at a time. | |
| 1996/0929 | * A delay seems necessary between reading the bits. | |
| 1996/0607 | * * If the ID doesn't match, there are no more adapters. */ | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:978,984 – 1996/0929/sys/src/9/pc/etherelnk3.c:986,992 | ||
| 1996/0607 | /* * Continue through the EISA slots looking for a match on both * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product. | |
| 1996/0929 | * If an adapter is found, select window 0, enable it and clear | |
| 1996/0607 | * out any lingering status and interrupts. */ while(slot < MaxEISA){ | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:1054,1059 – 1996/0929/sys/src/9/pc/etherelnk3.c:1062,1148 | ||
| 1996/0607 | return 0; } | |
| 1996/0929 | static int autoselect(int port, int rxstatus9) { int media, x; /* * Pathetic attempt at automatic media selection. * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX * cards operational. */ media = auiAvailable|coaxAvailable|base10TAvailable; if(rxstatus9 == 0){ COMMAND(port, SelectRegisterWindow, Wfifo); media = ins(port+ResetOptions); } COMMAND(port, SelectRegisterWindow, Wdiagnostic); x = ins(port+MediaStatus) & ~(dcConverterEnabled|linkBeatEnable|jabberGuardEnable); outs(port+MediaStatus, x); if(media & baseTXAvailable){ /* * Must have InternalConfig register. */ COMMAND(port, SelectRegisterWindow, Wfifo); x = inl(port+InternalConfig) & ~xcvrMask; x |= xcvr100BaseTX; outl(port+InternalConfig, x); COMMAND(port, TxReset, 0); while(STATUS(port) & commandInProgress) ; COMMAND(port, RxReset, 0); while(STATUS(port) & commandInProgress) ; COMMAND(port, SelectRegisterWindow, Wdiagnostic); x = ins(port+MediaStatus); outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x); delay(1); if(ins(port+MediaStatus) & linkBeatDetect) return xcvr100BaseTX; outs(port+MediaStatus, x); } if(media & base10TAvailable){ if(rxstatus9 == 0){ COMMAND(port, SelectRegisterWindow, Wfifo); x = inl(port+InternalConfig) & ~xcvrMask; x |= xcvr10BaseT; outl(port+InternalConfig, x); } else{ COMMAND(port, SelectRegisterWindow, Wsetup); x = ins(port+AddressConfig) & ~xcvrMask9; x |= (xcvr10BaseT>>20)<<14; outs(port+AddressConfig, x); } COMMAND(port, TxReset, 0); while(STATUS(port) & commandInProgress) ; COMMAND(port, RxReset, 0); while(STATUS(port) & commandInProgress) ; COMMAND(port, SelectRegisterWindow, Wdiagnostic); x = ins(port+MediaStatus); outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x); delay(1); if(ins(port+MediaStatus) & linkBeatDetect) return xcvr10BaseT; outs(port+MediaStatus, x); } /* * Botch. */ return autoSelect; } | |
| 1996/0607 | int etherelnk3reset(Ether* ether) { | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:1090,1096 – 1996/0929/sys/src/9/pc/etherelnk3.c:1179,1185 | ||
| 1996/0607 | else if(port == 0 && (port = tcm59Xpci(ether))){ COMMAND(port, SelectRegisterWindow, Wfifo); | |
| 1996/0613 | rxearly = 8188; | |
| 1996/0607 |
| |
| 1996/0929 | xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask); | |
| 1996/0607 | } else if(port == 0 && (port = tcm5XXeisa(ether))){ x = ins(port+ProductID); | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:1097,1111 – 1996/0929/sys/src/9/pc/etherelnk3.c:1186,1206 | ||
| 1996/0607 | if((x & 0xFF00) == 0x5900){ COMMAND(port, SelectRegisterWindow, Wfifo); | |
| 1996/0613 | rxearly = 8188; | |
| 1996/0607 |
| |
| 1996/0929 | xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask); | |
| 1996/0607 | } else{ | |
| 1996/0929 | x = ins(port+AddressConfig); xcvr = ((x & xcvrMask9)>>14)<<20; if(x & autoSelect9) xcvr |= autoSelect; | |
| 1996/0607 | rxstatus9 = 1; } } else if(port == 0 && (port = tcm509isa(ether))){ | |
| 1996/0929 | x = ins(port+AddressConfig); xcvr = ((x & xcvrMask9)>>14)<<20; if(x & autoSelect9) xcvr |= autoSelect; | |
| 1996/0607 | rxstatus9 = 1; } | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:1127,1134 – 1996/0929/sys/src/9/pc/etherelnk3.c:1222,1229 | ||
| 1996/0607 | while(EEPROMBUSY(port)) ; x = EEPROMDATA(port); | |
| 1996/0929 | ether->ea[2*i] = x>>8; ether->ea[2*i+1] = x; | |
| 1996/0607 | } } | |
| 1996/0928/sys/src/9/pc/etherelnk3.c:1141,1146 – 1996/0929/sys/src/9/pc/etherelnk3.c:1236,1243 | ||
| 1996/0607 | * busmastering can be used. Due to bugs in the first revision * of the 3C59[05], don't use busmastering at 10Mbps. */ | |
| 1996/0929 | if(xcvr & autoSelect) xcvr = autoselect(port, rxstatus9); | |
| 1996/0607 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable); outs(port+MediaStatus, x); | |
| 1996/0929/sys/src/9/pc/etherelnk3.c:1056,1062 – 1996/1025/sys/src/9/pc/etherelnk3.c:1056,1062 (short | long) | ||
| 1996/0607 | static int tcm5XXpcmcia(Ether* ether) { | |
| 1996/0613 |
| |
| 1996/1025 | if(!cistrcmp(ether->type, "3C589") || !cistrcmp(ether->type, "3C562")) | |
| 1996/0607 | return ether->port; return 0; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:1,11 – 1997/0327/sys/src/9/pc/etherelnk3.c:1,12 (short | long) | ||
| 1996/0607 | /* * Etherlink III and Fast EtherLink adapters. * To do: | |
| 1997/0327 | * check robustness in the face of errors (e.g. busmaster & rxUnderrun); | |
| 1996/0613 | * RxEarly and busmaster; | |
| 1996/0607 | * autoSelect; * PCI latency timer and master enable; | |
| 1997/0327 | * errata list; * 3C90x. | |
| 1996/0607 | * * Product ID: * 9150 ISA 3C509[B] | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:47,54 – 1997/0327/sys/src/9/pc/etherelnk3.c:48,55 | ||
| 1996/0607 | }; enum { /* all windows */ | |
| 1997/0327 | CommandR = 0x000E, IntStatusR = 0x000E, | |
| 1996/0607 | }; enum { /* Commands */ | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:122,129 – 1997/0327/sys/src/9/pc/etherelnk3.c:123,130 | ||
| 1996/0607 | interruptMask = 0x01FE, }; | |
| 1997/0327 | #define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a)) #define STATUS(port) ins((port)+IntStatusR) | |
| 1996/0607 | enum { /* Window 0 - setup */ Wsetup = 0x0000, | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:200,205 – 1997/0327/sys/src/9/pc/etherelnk3.c:201,210 | ||
| 1996/0607 | ResetOptions = 0x0008, /* 3C59[0257] */ RxFree = 0x000A, /* InternalConfig bits */ | |
| 1997/0327 | ramPartition5to3 = 0x00000000, ramPartition3to1 = 0x00010000, ramPartition1to1 = 0x00020000, ramPartitionMask = 0x00030000, | |
| 1996/0607 | xcvr10BaseT = 0x00000000, xcvrAui = 0x00100000, /* 10BASE5 */ xcvr10Base2 = 0x00300000, | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:256,262 – 1997/0327/sys/src/9/pc/etherelnk3.c:261,267 | ||
| 1996/0607 | Wstate = 0x0005, /* registers */ TxStartThresh = 0x0000, | |
| 1997/0327 | TxAvailableThresh = 0x0002, | |
| 1996/0607 | RxEarlyThresh = 0x0006, RxFilter = 0x0008, InterruptEnable = 0x000A, | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:303,313 – 1997/0327/sys/src/9/pc/etherelnk3.c:308,316 | ||
| 1996/0607 | int attached; int busmaster; | |
| 1997/0327 | Block* rbp; /* receive buffer */ | |
| 1996/0607 |
| |
| 1997/0327 | Block* txbp; /* */ | |
| 1996/0607 | int txthreshold; int txbusy; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:329,339 – 1997/0327/sys/src/9/pc/etherelnk3.c:332,343 | ||
| 1996/0607 | int xcvr; /* transceiver type */ int rxstatus9; /* old-style RxStatus register */ | |
| 1997/0327 | int rxearly; /* RxEarlyThreshold */ | |
| 1996/0925 | int ts; /* threshold shift */ | |
| 1996/0607 | } Ctlr; static Block* | |
| 1997/0327 | allocrbp(Block* (*f)(int)) | |
| 1996/0607 | { Block *bp; ulong addr; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:342,351 – 1997/0327/sys/src/9/pc/etherelnk3.c:346,356 | ||
| 1996/0607 | * The receive buffers must be on a 32-byte * boundary for EISA busmastering. */ | |
| 1997/0327 | if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){ addr = (ulong)bp->base; addr = ROUNDUP(addr, 32); bp->rp = (uchar*)addr; } | |
| 1996/0607 | return bp; } | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:364,370 – 1997/0327/sys/src/9/pc/etherelnk3.c:369,375 | ||
| 1996/0607 | wp = KADDR(inl(port+MasterAddress)); status = ins(port+MasterStatus); if(status & (masterInProgress|targetAbort|masterAbort)) | |
| 1997/0327 | print("#l%d: BM status 0x%uX\n", ether->ctlrno, status); | |
| 1996/0607 | outs(port+MasterStatus, masterMask); outl(port+MasterAddress, address); outs(port+MasterLen, sizeof(Etherpkt)); | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:409,415 – 1997/0327/sys/src/9/pc/etherelnk3.c:414,420 | ||
| 1996/0607 | */ promiscuous(ether, ether->prom); | |
| 1997/0327 | x = interruptMask; | |
| 1996/0607 | if(ctlr->busmaster) x &= ~(rxEarly|rxComplete); COMMAND(port, SetIndicationEnable, x); | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:422,430 – 1997/0327/sys/src/9/pc/etherelnk3.c:427,434 | ||
| 1996/0607 | * Prime the busmaster channel for receiving directly into a * receive packet buffer if necessary. */ | |
| 1997/0327 | startdma(ether, PADDR(ctlr->rbp->rp)); | |
| 1996/0607 | ctlr->attached = 1; iunlock(&ctlr->wlock); | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:472,478 – 1997/0327/sys/src/9/pc/etherelnk3.c:476,482 | ||
| 1996/0607 | } static void | |
| 1997/0327 | txstart(Ether* ether) | |
| 1996/0607 | { int port, len; Ctlr *ctlr; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:490,549 – 1997/0327/sys/src/9/pc/etherelnk3.c:494,545 | ||
| 1996/0607 | * level and expects to be called with ctlr->wlock already locked * and the correct register window (Wop) in place. */ | |
| 1997/0327 | for(;;){ if(ctlr->txbp){ bp = ctlr->txbp; ctlr->txbp = 0; } else{ bp = qget(ether->oq); if(bp == nil) break; } | |
| 1996/0607 | len = ROUNDUP(BLEN(bp), 4); if(len+4 <= ins(port+TxFree)){ outl(port+Fifo, BLEN(bp)); outsl(port+Fifo, bp->rp, len/4); | |
| 1996/0925 |
| |
| 1996/0607 |
| |
| 1997/0327 | else{ ctlr->txbp = bp; if(ctlr->txbusy == 0){ ctlr->txbusy = 1; COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts); } break; | |
| 1996/0607 | } } } | |
| 1997/0327 | static void transmit(Ether* ether) | |
| 1996/0607 | { Ctlr *ctlr; | |
| 1997/0327 | txstart(ether); | |
| 1996/0607 | COMMAND(port, SelectRegisterWindow, w); iunlock(&ctlr->wlock); | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:599,633 – 1997/0327/sys/src/9/pc/etherelnk3.c:595,641 | ||
| 1996/0607 | if(rxerror & crcError) ether->crcs++; } | |
| 1997/0327 | } | |
| 1996/0607 | ||
| 1997/0327 | /* * If there was an error or a new receive buffer can't be * allocated, discard the packet and go on to the next. */ if((rxstatus & rxError) || (bp = allocrbp(iallocb)) == 0){ | |
| 1996/0607 | COMMAND(port, RxDiscard, 0); while(STATUS(port) & commandInProgress) ; if(ctlr->busmaster) | |
| 1997/0327 | startdma(ether, PADDR(ctlr->rbp->rp)); continue; | |
| 1996/0607 | } | |
| 1997/0327 | /* * A valid receive packet awaits: * if using PIO, read it into the buffer; * discard the packet from the FIFO; * if using busmastering, start a new transfer for * the next packet and as a side-effect get the * end-pointer of the one just received; * pass the packet on to whoever wants it. */ if(ctlr->busmaster == 0){ len = (rxstatus & rxBytes9); ctlr->rbp->wp = ctlr->rbp->rp + len; insl(port+Fifo, ctlr->rbp->rp, HOWMANY(len, 4)); } | |
| 1996/0607 |
| |
| 1997/0327 | COMMAND(port, RxDiscard, 0); while(STATUS(port) & commandInProgress) ; | |
| 1996/0607 |
| |
| 1997/0327 | if(ctlr->busmaster) ctlr->rbp->wp = startdma(ether, PADDR(bp->rp)); | |
| 1996/0607 |
| |
| 1997/0327 | etheriq(ether, ctlr->rbp, 1); ctlr->rbp = bp; | |
| 1996/0607 | } } | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:635,641 – 1997/0327/sys/src/9/pc/etherelnk3.c:643,649 | ||
| 1996/0607 | interrupt(Ureg*, void* arg) { Ether *ether; | |
| 1997/0327 | int port, status, s, w, x; | |
| 1996/0607 | Ctlr *ctlr; ether = arg; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:648,666 – 1997/0327/sys/src/9/pc/etherelnk3.c:656,662 | ||
| 1996/0607 | ctlr->interrupts++; ctlr->timer += inb(port+Timer) & 0xFF; | |
| 1997/0327 | for(status = STATUS(port); status & interruptMask; status = STATUS(port)){ | |
| 1996/0607 | if(status & hostError){ /* * Adapter failure, try to find out why, reset if | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:670,676 – 1997/0327/sys/src/9/pc/etherelnk3.c:666,672 | ||
| 1996/0607 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); x = ins(port+FifoDiagnostic); COMMAND(port, SelectRegisterWindow, Wop); | |
| 1997/0327 | print("#l%d: status 0x%uX, diag 0x%uX\n", | |
| 1996/0607 | ether->ctlrno, status, x); if(x & txOverrun){ | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:679,695 – 1997/0327/sys/src/9/pc/etherelnk3.c:675,697 | ||
| 1996/0929 | else COMMAND(port, TxReset, dmaReset); | |
| 1996/0607 | COMMAND(port, TxEnable, 0); | |
| 1997/0327 | * Reset the receiver and restore the filter and RxEarly * threshold before re-enabling. | |
| 1996/0607 | * Need to restart any busmastering? */ | |
| 1997/0327 | COMMAND(port, SelectRegisterWindow, Wstate); s = (port+RxFilter) & 0x000F; COMMAND(port, SelectRegisterWindow, Wop); | |
| 1996/0607 | COMMAND(port, RxReset, 0); while(STATUS(port) & commandInProgress) ; | |
| 1997/0327 | COMMAND(port, SetRxFilter, s); COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts); | |
| 1996/0607 | COMMAND(port, RxEnable, 0); } | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:710,723 – 1997/0327/sys/src/9/pc/etherelnk3.c:712,725 | ||
| 1996/0929 | * as a busmaster receive may be in progress. | |
| 1996/0607 | * For all conditions enable the transmitter. */ | |
| 1997/0327 | s = 0; | |
| 1996/0607 | do{ if(x = inb(port+TxStatus)) outb(port+TxStatus, 0); | |
| 1997/0327 | s |= x; | |
| 1996/0607 | }while(STATUS(port) & txComplete); | |
| 1997/0327 | if(s & txUnderrun){ | |
| 1996/0607 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); while(ins(port+MediaStatus) & txInProg) ; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:726,732 – 1997/0327/sys/src/9/pc/etherelnk3.c:728,734 | ||
| 1996/0607 | ctlr->txthreshold += ETHERMINTU; } | |
| 1997/0327 | if(s & (txJabber|txUnderrun)){ | |
| 1996/0929 | if(ctlr->busmaster == 0) COMMAND(port, TxReset, 0); else | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:744,750 – 1997/0327/sys/src/9/pc/etherelnk3.c:746,752 | ||
| 1996/0607 | if(status & txAvailable){ COMMAND(port, AcknowledgeInterrupt, txAvailable); ctlr->txbusy = 0; | |
| 1997/0327 | txstart(ether); | |
| 1996/0607 | status &= ~txAvailable; } | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:765,772 – 1997/0327/sys/src/9/pc/etherelnk3.c:767,775 | ||
| 1996/0607 | * Panic if there are any interrupts not dealt with. */ if(status & interruptMask) | |
| 1997/0327 | panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status); | |
| 1996/0607 | } | |
| 1997/0327 | COMMAND(port, AcknowledgeInterrupt, interruptLatch); | |
| 1996/0607 | COMMAND(port, SelectRegisterWindow, w); unlock(&ctlr->wlock); | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:806,819 – 1997/0327/sys/src/9/pc/etherelnk3.c:809,837 | ||
| 1996/0607 | return readstr(offset, a, n, buf); } | |
| 1997/0327 | typedef struct Adapter { int port; int irq; int tbdf; } Adapter; static Block* adapter; | |
| 1996/0607 | ||
| 1997/0327 | static void tcmadapter(int port, int irq, int tbdf) { Block *bp; Adapter *ap; bp = allocb(sizeof(Adapter)); ap = (Adapter*)bp->rp; ap->port = port; ap->irq = irq; ap->tbdf = tbdf; bp->next = adapter; adapter = bp; } | |
| 1996/0607 | /* * Write two 0 bytes to identify the IDport and then reset the * ID sequence. Then send the ID sequence to the card to get | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:914,920 – 1997/0327/sys/src/9/pc/etherelnk3.c:932,937 | ||
| 1996/0607 | tcm509isa(Ether* ether) { int irq, port; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:958,968 – 1997/0327/sys/src/9/pc/etherelnk3.c:975,981 | ||
| 1996/0607 | return port; } | |
| 1997/0327 | tcmadapter(port, irq, BUSUNKNOWN); | |
| 1996/0607 | } return 0; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:974,980 – 1997/0327/sys/src/9/pc/etherelnk3.c:987,992 | ||
| 1996/0607 | static int slot = 1; ushort x; int irq, port; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:1010,1020 – 1997/0327/sys/src/9/pc/etherelnk3.c:1022,1028 | ||
| 1996/0607 | return port; } | |
| 1997/0327 | tcmadapter(port, irq, BUSUNKNOWN); | |
| 1996/0607 | } return 0; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:1023,1053 – 1997/0327/sys/src/9/pc/etherelnk3.c:1031,1049 | ||
| 1996/0607 | static int tcm59Xpci(Ether* ether) { | |
| 1997/0327 | static Pcidev *p; | |
| 1996/0607 | int irq, port; | |
| 1997/0327 | while(p = pcimatch(p, 0x10B7, 0)){ port = p->bar[0] & ~0x01; irq = p->intl; | |
| 1996/0607 | if(ether->port == 0 || ether->port == port){ ether->irq = irq; | |
| 1997/0327 | ether->tbdf = p->tbdf; | |
| 1996/0607 | return port; } | |
| 1997/0327 | tcmadapter(port, irq, p->tbdf); | |
| 1996/0607 | } return 0; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:1147,1153 – 1997/0327/sys/src/9/pc/etherelnk3.c:1143,1150 | ||
| 1996/0607 | etherelnk3reset(Ether* ether) { | |
| 1996/0613 | int busmaster, i, port, rxearly, rxstatus9, x, xcvr; | |
| 1996/0607 |
| |
| 1997/0327 | Block *bp, **bpp; Adapter *ap; | |
| 1996/0607 | uchar ea[Eaddrlen]; Ctlr *ctlr; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:1163,1176 – 1997/0327/sys/src/9/pc/etherelnk3.c:1160,1177 | ||
| 1996/0613 | rxearly = 2044; | |
| 1996/0607 | rxstatus9 = 0; xcvr = 0; | |
| 1997/0327 | bpp = &adapter; for(bp = *bpp; bp; bp = bp->next){ ap = (Adapter*)bp->rp; | |
| 1996/0607 | if(ether->port == 0 || ether->port == ap->port){ port = ap->port; ether->irq = ap->irq; | |
| 1997/0327 | ether->tbdf = ap->tbdf; *bpp = bp->next; freeb(bp); | |
| 1996/0607 | break; } | |
| 1997/0327 | bpp = &bp->next; | |
| 1996/0607 | } if(port == 0 && (port = tcm5XXpcmcia(ether))){ xcvr = ((ins(port+AddressConfig) & xcvrMask9)>>14)<<20; | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:1177,1182 – 1997/0327/sys/src/9/pc/etherelnk3.c:1178,1186 | ||
| 1996/0607 | rxstatus9 = 1; } else if(port == 0 && (port = tcm59Xpci(ether))){ | |
| 1997/0327 | COMMAND(port, GlobalReset, 0); while(STATUS(port) & commandInProgress) ; | |
| 1996/0607 | COMMAND(port, SelectRegisterWindow, Wfifo); | |
| 1996/0613 | rxearly = 8188; | |
| 1996/0929 | xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask); | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:1241,1248 – 1997/0327/sys/src/9/pc/etherelnk3.c:1245,1255 | ||
| 1996/0607 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable); outs(port+MediaStatus, x); | |
| 1997/0327 | if(x & dataRate100){ | |
| 1996/0607 | busmaster = 1; | |
| 1997/0327 | x = inl(port+InternalConfig) & ~ramPartitionMask; outl(port+InternalConfig, x|ramPartition1to1); } | |
| 1996/0607 | else busmaster = 0; switch(xcvr){ | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:1298,1303 – 1997/0327/sys/src/9/pc/etherelnk3.c:1305,1311 | ||
| 1996/0607 | ctlr->busmaster = busmaster; ctlr->xcvr = xcvr; ctlr->rxstatus9 = rxstatus9; | |
| 1997/0327 | ctlr->rxearly = rxearly; | |
| 1996/0925 | if(rxearly >= 2048) ctlr->ts = 2; | |
| 1996/0607 | ||
| 1996/1025/sys/src/9/pc/etherelnk3.c:1304,1315 – 1997/0327/sys/src/9/pc/etherelnk3.c:1312,1320 | ||
| 1996/0607 | COMMAND(port, StatisticsEnable, 0); /* | |
| 1997/0327 | * Allocate the receive buffer. | |
| 1996/0607 | */ | |
| 1997/0327 | ctlr->rbp = allocrbp(allocb); | |
| 1996/0607 | /* * Set a base TxStartThresh which will be incremented | |
| 1996/1025/sys/src/9/pc/etherelnk3.c:1316,1322 – 1997/0327/sys/src/9/pc/etherelnk3.c:1321,1327 | ||
| 1996/0607 | * if any txUnderrun errors occur and ensure no RxEarly * interrupts happen. */ | |
| 1996/0928 |
| |
| 1997/0327 | ctlr->txthreshold = ETHERMAXTU/2; | |
| 1996/0928 | COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts); | |
| 1996/0925 | COMMAND(port, SetRxEarlyThresh, rxearly>>ctlr->ts); | |
| 1996/0607 | ||
| 1996/1025/sys/src/9/pc/etherelnk3.c:1327,1333 – 1997/0327/sys/src/9/pc/etherelnk3.c:1332,1338 | ||
| 1996/0607 | */ ether->port = port; ether->attach = attach; | |
| 1997/0327 | ether->transmit = transmit; | |
| 1996/0607 | ether->interrupt = interrupt; ether->ifstat = ifstat; | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:6,12 – 1997/0328/sys/src/9/pc/etherelnk3.c:6,13 (short | long) | ||
| 1996/0607 | * autoSelect; * PCI latency timer and master enable; | |
| 1997/0327 | * errata list; | |
| 1997/0328 | * 3C90x full busmastering; * rewrite all initialisation. | |
| 1996/0607 | * * Product ID: * 9150 ISA 3C509[B] | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:27,32 – 1997/0328/sys/src/9/pc/etherelnk3.c:28,38 | ||
| 1996/0607 | * 5951 PCI 3C595-T4 Fast Etherlink Shared 10BASE-T/100BASE-T4 * 5952 PCI 3C595-MII Fast Etherlink 10BASE-T/MII * | |
| 1997/0328 | * 9000 PCI 3C900-TPO Etherlink III XL PCI 10BASE-T * 9001 PCI 3C900-COMBO Etherlink III XL PCI 10BASE-T/10BASE-2/AUI * 9050 PCI 3C905-TX Fast Etherlink XL Shared 10BASE-T/100BASE-TX * 9051 PCI 3C905-T4 Fast Etherlink Shared 10BASE-T/100BASE-T4 * | |
| 1996/0607 | * 9058 PCMCIA 3C589[B]-[TP|COMBO] * * 627C MCA 3C529 | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:54,65 – 1997/0328/sys/src/9/pc/etherelnk3.c:60,72 | ||
| 1996/0607 | enum { /* Commands */ GlobalReset = 0x0000, | |
| 1997/0328 | SelectRegisterWindow = 0x0001, | |
| 1996/0607 | EnableDcConverter = 0x0002, RxDisable = 0x0003, RxEnable = 0x0004, RxReset = 0x0005, | |
| 1997/0328 | Stall = 0x0006, /* 3C90x */ TxDone = 0x0007, | |
| 1996/0607 | RxDiscard = 0x0008, TxEnable = 0x0009, TxDisable = 0x000A, | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:91,100 – 1997/0328/sys/src/9/pc/etherelnk3.c:98,115 | ||
| 1996/0607 | hostReset = 0x0020, /* bus interface logic */ dmaReset = 0x0040, /* bus master logic */ vcoReset = 0x0080, /* on-board 10Mbps VCO */ | |
| 1997/0328 | updnReset = 0x0100, /* upload/download (Rx/TX) logic */ | |
| 1996/0607 |
| |
| 1997/0328 | resetMask = 0x01FF, | |
| 1996/0607 | }; | |
| 1997/0328 | enum { /* Stall command bits */ UpStall = 0x0000, UpUnStall = 0x0001, DnStall = 0x0002, DnUnStall = 0x0003, }; | |
| 1996/0607 | enum { /* SetRxFilter command bits */ receiveIndividual = 0x0001, /* match station address */ receiveMulticast = 0x0002, | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:117,126 – 1997/0328/sys/src/9/pc/etherelnk3.c:132,143 | ||
| 1996/0607 | intRequested = 0x0040, updateStats = 0x0080, transferInt = 0x0100, /* Bus Master Transfer Complete */ | |
| 1997/0328 | dnComplete = 0x0200, upComplete = 0x0400, | |
| 1996/0607 | busMasterInProgress = 0x0800, commandInProgress = 0x1000, | |
| 1997/0328 | interruptMask = 0x07FE, | |
| 1996/0607 | }; | |
| 1997/0327 | #define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a)) | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:201,209 – 1997/0328/sys/src/9/pc/etherelnk3.c:218,229 | ||
| 1996/0607 | ResetOptions = 0x0008, /* 3C59[0257] */ RxFree = 0x000A, /* InternalConfig bits */ | |
| 1997/0328 | disableBadSsdDetect = 0x00000100, ramLocation = 0x00000200, /* 0 external, 1 internal */ | |
| 1997/0327 | ramPartition5to3 = 0x00000000, ramPartition3to1 = 0x00010000, ramPartition1to1 = 0x00020000, | |
| 1997/0328 | ramPartition3to5 = 0x00030000, | |
| 1997/0327 | ramPartitionMask = 0x00030000, | |
| 1996/0607 | xcvr10BaseT = 0x00000000, xcvrAui = 0x00100000, /* 10BASE5 */ | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:225,231 – 1997/0328/sys/src/9/pc/etherelnk3.c:245,251 | ||
| 1996/0607 | base10TAvailable = 0x0008, coaxAvailable = 0x0010, auiAvailable = 0x0020, | |
| 1997/0328 | miiConnector = 0x0040, | |
| 1996/0607 | }; enum { /* Window 4 - diagnostic */ | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:237,242 – 1997/0328/sys/src/9/pc/etherelnk3.c:257,263 | ||
| 1996/0607 | PhysicalMgmt = 0x0008, MediaStatus = 0x000A, BadSSD = 0x000C, | |
| 1997/0328 | UpperBytesOk = 0x000D, | |
| 1996/0607 | /* FifoDiagnostic bits */ txOverrun = 0x0400, rxUnderrun = 0x2000, | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:254,260 – 1997/0328/sys/src/9/pc/etherelnk3.c:275,281 | ||
| 1996/0607 | linkBeatDetect = 0x0800, txInProg = 0x1000, dcConverterEnabled = 0x4000, | |
| 1997/0328 | auiDisable = 0x8000, /* 10BaseT transceiver selected */ | |
| 1996/0607 | }; enum { /* Window 5 - internal state */ | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:301,308 – 1997/0328/sys/src/9/pc/etherelnk3.c:322,380 | ||
| 1996/0607 | masterInProgress = 0x8000, masterMask = 0xD00F, | |
| 1997/0328 | }; | |
| 1996/0607 | ||
| 1997/0328 | enum { /* 3C90x extended register set */ PktStatus = 0x0020, /* 32-bits */ DnListPtr = 0x0024, /* 32-bits, 8-byte aligned */ FragAddr = 0x0028, /* 32-bits */ FragLen = 0x002C, /* 16-bits */ ListOffset = 0x002E, /* 8-bits */ TxFreeThresh = 0x002F, /* 8-bits */ UpPktStatus = 0x0030, /* 32-bits */ FreeTimer = 0x0034, /* 16-bits */ UpListPtr = 0x0038, /* 32-bits, 8-byte aligned */ /* PktStatus bits */ fragLast = 0x00000001, dnCmplReq = 0x00000002, dnStalled = 0x00000004, upCompleteX = 0x00000008, dnCompleteX = 0x00000010, upRxEarlyEnable = 0x00000020, armCountdown = 0x00000040, dnInProg = 0x00000080, counterSpeed = 0x00000010, /* 0 3.2uS, 1 320nS */ countdownMode = 0x00000020, /* UpPktStatus bits */ upPktLenMask = 0x00001FFF, upStalled = 0x00002000, upError = 0x00004000, upPktComplete = 0x00008000, upOverrrun = 0x00010000, /* RxError<<16 */ upRuntFrame = 0x00020000, upAlignmentError = 0x00040000, upCRCError = 0x00080000, upOversizedFrame = 0x00100000, upDribbleBits = 0x00800000, upOverflow = 0x01000000, }; /* * Up/Dn Packet Descriptor. * The hardware info (np, control, addr, len) must be 8-byte aligned. */ typedef struct Pd Pd; typedef struct Pd { Pd* next; Block* bp; ulong np; /* next pointer */ ulong control; /* FSH or UpPktStatus */ ulong addr; ulong len; }; | |
| 1996/0607 | typedef struct { Lock wlock; /* window access */ | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:316,334 – 1997/0328/sys/src/9/pc/etherelnk3.c:388,394 | ||
| 1996/0607 | long interrupts; /* statistics */ long timer; | |
| 1997/0328 | long stats[BytesRcvdOk+2]; | |
| 1996/0607 | int xcvr; /* transceiver type */ int rxstatus9; /* old-style RxStatus register */ | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:385,391 – 1997/0328/sys/src/9/pc/etherelnk3.c:445,451 | ||
| 1996/0607 | int filter, port; port = ((Ether*)arg)->port; | |
| 1997/0328 | ||
| 1996/0607 | filter = receiveBroadcast|receiveIndividual; if(on) filter |= receiveAllFrames; | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:437,443 – 1997/0328/sys/src/9/pc/etherelnk3.c:497,503 | ||
| 1996/0607 | static void statistics(Ether* ether) { | |
| 1997/0328 | int port, i, u, w; | |
| 1996/0607 | Ctlr *ctlr; port = ether->port; | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:451,475 – 1997/0328/sys/src/9/pc/etherelnk3.c:511,528 | ||
| 1996/0607 | COMMAND(port, SelectRegisterWindow, Wstatistics); STATUS(port); | |
| 1997/0328 | for(i = 0; i < UpperFramesOk; i++) ctlr->stats[i] += inb(port+i) & 0xFF; | |
| 1996/0607 | u = inb(port+UpperFramesOk) & 0xFF; | |
| 1997/0328 | ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4; ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8; ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF; ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF; | |
| 1996/0607 | if(ctlr->xcvr == xcvr100BaseTX || ctlr->xcvr == xcvr100BaseFX){ COMMAND(port, SelectRegisterWindow, Wdiagnostic); STATUS(port); | |
| 1997/0328 | ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD); | |
| 1996/0607 | } COMMAND(port, SelectRegisterWindow, w); | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:656,662 – 1997/0328/sys/src/9/pc/etherelnk3.c:709,715 | ||
| 1996/0607 | ctlr->interrupts++; ctlr->timer += inb(port+Timer) & 0xFF; | |
| 1997/0327 |
| |
| 1997/0328 | while((status = STATUS(port)) & (interruptMask|interruptLatch)){ | |
| 1996/0607 | if(status & hostError){ /* * Adapter failure, try to find out why, reset if | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:732,738 – 1997/0328/sys/src/9/pc/etherelnk3.c:785,791 | ||
| 1996/0929 | if(ctlr->busmaster == 0) COMMAND(port, TxReset, 0); else | |
| 1997/0328 | COMMAND(port, TxReset, (updnReset|dmaReset)); | |
| 1996/0607 | while(STATUS(port) & commandInProgress) ; | |
| 1996/0925 | COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts); | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:768,775 – 1997/0328/sys/src/9/pc/etherelnk3.c:821,829 | ||
| 1996/0607 | */ if(status & interruptMask) | |
| 1997/0327 | panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status); | |
| 1997/0328 | COMMAND(port, AcknowledgeInterrupt, interruptLatch); | |
| 1996/0607 | } | |
| 1997/0327 |
| |
| 1996/0607 | COMMAND(port, SelectRegisterWindow, w); unlock(&ctlr->wlock); | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:793,810 – 1997/0328/sys/src/9/pc/etherelnk3.c:847,864 | ||
| 1996/0607 | len = sprint(buf, "interrupts: %ld\n", ctlr->interrupts); len += sprint(buf+len, "timer: %ld\n", ctlr->timer); | |
| 1997/0328 | len += sprint(buf+len, "carrierlost: %ld\n", ctlr->stats[CarrierLost]); len += sprint(buf+len, "sqeerrors: %ld\n", ctlr->stats[SqeErrors]); len += sprint(buf+len, "multiplecolls: %ld\n", ctlr->stats[MultipleColls]); len += sprint(buf+len, "singlecollframes: %ld\n", ctlr->stats[SingleCollFrames]); len += sprint(buf+len, "latecollisions: %ld\n", ctlr->stats[LateCollisions]); len += sprint(buf+len, "rxoverruns: %ld\n", ctlr->stats[RxOverruns]); len += sprint(buf+len, "framesxmittedok: %ld\n", ctlr->stats[FramesXmittedOk]); len += sprint(buf+len, "framesrcvdok: %ld\n", ctlr->stats[FramesRcvdOk]); len += sprint(buf+len, "framesdeferred: %ld\n", ctlr->stats[FramesDeferred]); len += sprint(buf+len, "bytesrcvdok: %ld\n", ctlr->stats[BytesRcvdOk]); len += sprint(buf+len, "bytesxmittedok: %ld\n", ctlr->stats[BytesRcvdOk+1]); sprint(buf+len, "badssd: %ld\n", ctlr->stats[BytesRcvdOk+2]); | |
| 1996/0607 | return readstr(offset, a, n, buf); } | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:1037,1042 – 1997/0328/sys/src/9/pc/etherelnk3.c:1091,1099 | ||
| 1997/0327 | while(p = pcimatch(p, 0x10B7, 0)){ port = p->bar[0] & ~0x01; irq = p->intl; | |
| 1997/0328 | COMMAND(port, GlobalReset, 0); while(STATUS(port) & commandInProgress) ; | |
| 1996/0607 | if(ether->port == 0 || ether->port == port){ ether->irq = irq; | |
| 1997/0327 | ether->tbdf = p->tbdf; | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:1074,1079 – 1997/0328/sys/src/9/pc/etherelnk3.c:1131,1139 | ||
| 1996/0929 | media = ins(port+ResetOptions); } | |
| 1997/0328 | if(media & miiConnector) return xcvrMii; | |
| 1996/0929 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); x = ins(port+MediaStatus) & ~(dcConverterEnabled|linkBeatEnable|jabberGuardEnable); outs(port+MediaStatus, x); | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:1139,1148 – 1997/0328/sys/src/9/pc/etherelnk3.c:1199,1220 | ||
| 1996/0929 | return autoSelect; } | |
| 1997/0328 | static int eepromdata(int port, int offset) { COMMAND(port, SelectRegisterWindow, Wsetup); while(EEPROMBUSY(port)) ; EEPROMCMD(port, EepromReadRegister, offset); while(EEPROMBUSY(port)) ; return EEPROMDATA(port); } | |
| 1996/0607 | int etherelnk3reset(Ether* ether) { | |
| 1996/0613 |
| |
| 1997/0328 | int busmaster, did, i, port, rxearly, rxstatus9, x, xcvr; | |
| 1997/0327 | Block *bp, **bpp; Adapter *ap; | |
| 1996/0607 | uchar ea[Eaddrlen]; | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:1157,1165 – 1997/0328/sys/src/9/pc/etherelnk3.c:1229,1234 | ||
| 1996/0607 | * If an adapter is found save the IRQ and transceiver type. */ port = 0; | |
| 1996/0613 |
| |
| 1996/0607 |
| |
| 1997/0327 | bpp = &adapter; for(bp = *bpp; bp; bp = bp->next){ ap = (Adapter*)bp->rp; | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:1173,1216 – 1997/0328/sys/src/9/pc/etherelnk3.c:1242,1301 | ||
| 1996/0607 | } | |
| 1997/0327 | bpp = &bp->next; | |
| 1996/0607 | } | |
| 1997/0327 |
| |
| 1997/0328 | if(port == 0) port = tcm5XXpcmcia(ether); if(port == 0) port = tcm59Xpci(ether); if(port == 0) port = tcm5XXeisa(ether); if(port == 0) port = tcm509isa(ether); if(port == 0) return -1; /* * Read the DeviceID from the EEPROM, it's at offset 0x03, * and do something depending on capabilities. */ switch(did = eepromdata(port, 0x03)){ case 0x9000: case 0x9001: case 0x9050: case 0x9051: if(BUSTYPE(ether->tbdf) != BusPCI) goto buggery; busmaster = 2; goto vortex; case 0x5900: case 0x5920: case 0x5950: case 0x5951: case 0x5952: case 0x5970: case 0x5971: case 0x5972: busmaster = 1; vortex: | |
| 1996/0607 | COMMAND(port, SelectRegisterWindow, Wfifo); | |
| 1996/0613 |
| |
| 1996/0929 | xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask); | |
| 1996/0607 |
| |
| 1996/0613 |
| |
| 1996/0929 |
| |
| 1996/0607 |
| |
| 1996/0929 |
| |
| 1996/0607 |
| |
| 1997/0328 | rxearly = 8188; rxstatus9 = 0; break; buggery: default: busmaster = 0; COMMAND(port, SelectRegisterWindow, Wsetup); | |
| 1996/0929 | x = ins(port+AddressConfig); xcvr = ((x & xcvrMask9)>>14)<<20; if(x & autoSelect9) xcvr |= autoSelect; | |
| 1997/0328 | rxearly = 2044; | |
| 1996/0607 | rxstatus9 = 1; | |
| 1997/0328 | break; | |
| 1996/0607 | } | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:1218,1231 – 1997/0328/sys/src/9/pc/etherelnk3.c:1303,1310 | ||
| 1996/0607 | */ memset(ea, 0, Eaddrlen); if(memcmp(ea, ether->ea, Eaddrlen) == 0){ | |
| 1997/0328 | x = eepromdata(port, i); | |
| 1996/0929 | ether->ea[2*i] = x>>8; ether->ea[2*i+1] = x; | |
| 1996/0607 | } | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:1246,1252 – 1997/0328/sys/src/9/pc/etherelnk3.c:1325,1331 | ||
| 1996/0607 | x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable); outs(port+MediaStatus, x); | |
| 1997/0327 | if(x & dataRate100){ | |
| 1996/0607 |
| |
| 1997/0328 | ether->mbps = 100; | |
| 1997/0327 | x = inl(port+InternalConfig) & ~ramPartitionMask; outl(port+InternalConfig, x|ramPartition1to1); } | |
| 1997/0327/sys/src/9/pc/etherelnk3.c:1254,1263 – 1997/0328/sys/src/9/pc/etherelnk3.c:1333,1343 | ||
| 1996/0607 | busmaster = 0; switch(xcvr){ | |
| 1997/0328 | case xcvrMii: break; | |
| 1996/0607 | case xcvr100BaseTX: case xcvr100BaseFX: | |
| 1997/0328/sys/src/9/pc/etherelnk3.c:443,454 – 1997/0403/sys/src/9/pc/etherelnk3.c:443,473 (short | long) | ||
| 1996/0607 | promiscuous(void* arg, int on) { int filter, port; | |
| 1997/0403 | Ether *ether; | |
| 1996/0607 |
| |
| 1997/0403 | ether = (Ether*)arg; port = ether->port; | |
| 1997/0328 | ||
| 1996/0607 | filter = receiveBroadcast|receiveIndividual; | |
| 1997/0403 | if(ether->nmaddr) filter |= receiveMulticast; | |
| 1996/0607 | if(on) filter |= receiveAllFrames; | |
| 1997/0403 | COMMAND(port, SetRxFilter, filter); } static void multicast(void* arg, char *addr, int on) { int filter, port; Ether *ether; ether = (Ether*)arg; port = ether->port; filter = receiveBroadcast|receiveIndividual; if(ether->nmaddr) filter |= receiveMulticast; | |
| 1996/0607 | COMMAND(port, SetRxFilter, filter); } | |
| 1997/0403/sys/src/9/pc/etherelnk3.c:457,470 – 1997/0404/sys/src/9/pc/etherelnk3.c:457,473 (short | long) | ||
| 1997/0403 | } static void | |
| 1997/0404 | multicast(void* arg, uchar *addr, int on) | |
| 1997/0403 | { int filter, port; Ether *ether; | |
| 1997/0404 | USED(addr, on); | |
| 1997/0403 | ether = (Ether*)arg; port = ether->port; | |
| 1997/0404 | print("mutlicast nmaddr == %d\n", ether->nmaddr); | |
| 1997/0403 | filter = receiveBroadcast|receiveIndividual; if(ether->nmaddr) filter |= receiveMulticast; | |
| 1997/0403/sys/src/9/pc/etherelnk3.c:1314,1319 – 1997/0404/sys/src/9/pc/etherelnk3.c:1317,1323 | ||
| 1996/0607 | rxstatus9 = 1; | |
| 1997/0328 | break; | |
| 1996/0607 | } | |
| 1997/0404 | USED(did); | |
| 1996/0607 | /* * Check if the adapter's station address is to be overridden. | |
| 1997/0403/sys/src/9/pc/etherelnk3.c:1436,1441 – 1997/0404/sys/src/9/pc/etherelnk3.c:1440,1446 | ||
| 1996/0607 | ether->ifstat = ifstat; ether->promiscuous = promiscuous; | |
| 1997/0404 | ether->multicast = multicast; | |
| 1996/0607 | ether->arg = ether; return 0; | |
| 1997/0404/sys/src/9/pc/etherelnk3.c:467,476 – 1997/0415/sys/src/9/pc/etherelnk3.c:467,478 (short | long) | ||
| 1997/0403 | ether = (Ether*)arg; port = ether->port; | |
| 1997/0404 |
| |
| 1997/0415 | print("multicast nmaddr == %d\n", ether->nmaddr); | |
| 1997/0403 | filter = receiveBroadcast|receiveIndividual; if(ether->nmaddr) filter |= receiveMulticast; | |
| 1997/0415 | if(ether->prom) filter |= receiveAllFrames; | |
| 1996/0607 | COMMAND(port, SetRxFilter, filter); } | |
| 1997/0415/sys/src/9/pc/etherelnk3.c:856,864 – 1997/0417/sys/src/9/pc/etherelnk3.c:856,864 (short | long) | ||
| 1996/0607 | static long ifstat(Ether* ether, void* a, long n, ulong offset) { | |
| 1997/0417 | char *p; | |
| 1996/0607 | int len; | |
| 1997/0417 | Ctlr *ctlr; | |
| 1996/0607 | if(n == 0) return 0; | |
| 1997/0415/sys/src/9/pc/etherelnk3.c:869,890 – 1997/0417/sys/src/9/pc/etherelnk3.c:869,894 | ||
| 1996/0607 | statistics(ether); iunlock(&ctlr->wlock); | |
| 1997/0328 |
| |
| 1997/0417 | p = malloc(READSTR); len = snprint(p, READSTR, "interrupts: %ld\n", ctlr->interrupts); len += snprint(p+len, READSTR-len, "timer: %ld\n", ctlr->timer); len += snprint(p+len, READSTR-len, "carrierlost: %ld\n", ctlr->stats[CarrierLost]); len += snprint(p+len, READSTR-len, "sqeerrors: %ld\n", ctlr->stats[SqeErrors]); len += snprint(p+len, READSTR-len, "multiplecolls: %ld\n", ctlr->stats[MultipleColls]); len += snprint(p+len, READSTR-len, "singlecollframes: %ld\n", ctlr->stats[SingleCollFrames]); len += snprint(p+len, READSTR-len, "latecollisions: %ld\n", ctlr->stats[LateCollisions]); len += snprint(p+len, READSTR-len, "rxoverruns: %ld\n", ctlr->stats[RxOverruns]); len += snprint(p+len, READSTR-len, "framesxmittedok: %ld\n", ctlr->stats[FramesXmittedOk]); len += snprint(p+len, READSTR-len, "framesrcvdok: %ld\n", ctlr->stats[FramesRcvdOk]); len += snprint(p+len, READSTR-len, "framesdeferred: %ld\n", ctlr->stats[FramesDeferred]); len += snprint(p+len, READSTR-len, "bytesrcvdok: %ld\n", ctlr->stats[BytesRcvdOk]); len += snprint(p+len, READSTR-len, "bytesxmittedok: %ld\n", ctlr->stats[BytesRcvdOk+1]); snprint(p+len, READSTR-len, "badssd: %ld\n", ctlr->stats[BytesRcvdOk+2]); | |
| 1996/0607 |
| |
| 1997/0417 | n = readstr(offset, a, n, p); free(p); return n; | |
| 1996/0607 | } | |
| 1997/0327 | typedef struct Adapter { | |
| 1997/0417/sys/src/9/pc/etherelnk3.c:467,473 – 1997/0418/sys/src/9/pc/etherelnk3.c:467,472 (short | long) | ||
| 1997/0403 | ether = (Ether*)arg; port = ether->port; | |
| 1997/0415 |
| |
| 1997/0403 | filter = receiveBroadcast|receiveIndividual; if(ether->nmaddr) filter |= receiveMulticast; | |
| 1997/0418/sys/src/9/pc/etherelnk3.c:1408,1414 – 1997/0614/sys/src/9/pc/etherelnk3.c:1408,1414 (short | long) | ||
| 1996/0607 | ilock(&ctlr->wlock); ctlr->xcvr = xcvr; statistics(ether); | |
| 1997/0614 | memset(ctlr->stats, 0, sizeof(ctlr->stats)); | |
| 1996/0607 | ctlr->busmaster = busmaster; ctlr->xcvr = xcvr; | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:104,113 – 1997/0712/sys/src/9/pc/etherelnk3.c:104,113 (short | long) | ||
| 1996/0607 | }; | |
| 1997/0328 | enum { /* Stall command bits */ | |
| 1997/0712 | upStall = 0x0000, upUnStall = 0x0001, dnStall = 0x0002, dnUnStall = 0x0003, | |
| 1997/0328 | }; | |
| 1996/0607 | enum { /* SetRxFilter command bits */ | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:158,163 – 1997/0712/sys/src/9/pc/etherelnk3.c:158,166 | ||
| 1996/0607 | xcvrMask9 = 0xC000, /* ConfigControl bits */ Ena = 0x0001, | |
| 1997/0712 | base10TAvailable9 = 0x0200, coaxAvailable9 = 0x1000, auiAvailable9 = 0x2000, | |
| 1996/0607 | /* EepromCommand bits */ EepromReadRegister = 0x0080, EepromBusy = 0x8000, | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:346,357 – 1997/0712/sys/src/9/pc/etherelnk3.c:349,360 | ||
| 1997/0328 | dnInProg = 0x00000080, counterSpeed = 0x00000010, /* 0 3.2uS, 1 320nS */ countdownMode = 0x00000020, | |
| 1997/0712 | /* UpPktStatus bits (dpd->control) */ | |
| 1997/0328 | upPktLenMask = 0x00001FFF, upStalled = 0x00002000, upError = 0x00004000, upPktComplete = 0x00008000, | |
| 1997/0712 | upOverrun = 0x00010000, /* RxError<<16 */ | |
| 1997/0328 | upRuntFrame = 0x00020000, upAlignmentError = 0x00040000, upCRCError = 0x00080000, | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:358,363 – 1997/0712/sys/src/9/pc/etherelnk3.c:361,370 | ||
| 1997/0328 | upOversizedFrame = 0x00100000, upDribbleBits = 0x00800000, upOverflow = 0x01000000, | |
| 1997/0712 | dnIndicate = 0x80000000, /* FrameStartHeader (dpd->control) */ updnLastFrag = 0x80000000, /* (dpd->len) */ | |
| 1997/0328 | }; /* | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:364,380 – 1997/0712/sys/src/9/pc/etherelnk3.c:371,397 | ||
| 1997/0328 | * Up/Dn Packet Descriptor. * The hardware info (np, control, addr, len) must be 8-byte aligned. */ | |
| 1997/0712 | typedef struct Dpd Dpd; typedef struct Dpd { ulong np; /* next pointer */ ulong control; /* FSH or UpPktStatus */ ulong addr; ulong len; Dpd* next; | |
| 1997/0328 | Block* bp; | |
| 1997/0712 | void* base; /* base of this allocation */ } Dpd; | |
| 1997/0328 | ||
| 1997/0712 | typedef struct Upd { | |
| 1997/0328 | ulong np; /* next pointer */ ulong control; /* FSH or UpPktStatus */ ulong addr; ulong len; | |
| 1997/0712 | uchar data[sizeof(Etherpkt)]; } Upd; | |
| 1996/0607 | typedef struct { Lock wlock; /* window access */ | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:382,405 – 1997/0712/sys/src/9/pc/etherelnk3.c:399,514 | ||
| 1996/0607 | int busmaster; | |
| 1997/0327 | Block* rbp; /* receive buffer */ | |
| 1996/0607 | ||
| 1997/0327 |
| |
| 1997/0712 | Block* txbp; /* FIFO -based transmission */ | |
| 1996/0607 | int txthreshold; int txbusy; | |
| 1997/0712 | //Lock upqlock; /* full-busmaster -based reception */ Block* upqhead; Block* upqtail; int upalloc; int nupd; Lock dpdlock; /* pool of free Dpd's */ Dpd* dpdpool; Lock dnqlock; /* full-busmaster -based transmission */ Dpd* dnqhead; Dpd* dnqtail; | |
| 1996/0607 | long interrupts; /* statistics */ long timer; | |
| 1997/0328 |
| |
| 1997/0712 | long stats[BytesRcvdOk+3]; | |
| 1996/0607 | int xcvr; /* transceiver type */ int rxstatus9; /* old-style RxStatus register */ | |
| 1997/0327 | int rxearly; /* RxEarlyThreshold */ | |
| 1996/0925 | int ts; /* threshold shift */ | |
| 1997/0712 | int upenabled; int dnenabled; | |
| 1996/0607 | } Ctlr; static Block* | |
| 1997/0327 |
| |
| 1997/0712 | updalloc(ulong np) | |
| 1996/0607 | { Block *bp; | |
| 1997/0712 | Upd *upd; /* * The hardware info (np, control, addr, len) * must be 8-byte aligned. */ if(bp = iallocb(sizeof(Upd)+8)){ bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 8); bp->wp = bp->rp; upd = (Upd*)bp->rp; upd->np = np; upd->control = 0; upd->addr = PADDR(upd->data); upd->len = updnLastFrag|sizeof(Etherpkt); } return bp; } static void init905(Ctlr* ctlr) { int i; ulong np; Block *bp; Upd *upd; np = 0; for(i = 0; i < 16; i++){ bp = updalloc(np); if(ctlr->upqhead == 0) ctlr->upqtail = bp; bp->next = ctlr->upqhead; ctlr->upqhead = bp; np = PADDR(bp->rp); } ctlr->upqtail->next = ctlr->upqhead; upd = (Upd*)ctlr->upqtail->rp; upd->np = PADDR(ctlr->upqhead->rp); } static Dpd* dpdalloc(Ctlr* ctlr) { Dpd *dpd; void *base; ilock(&ctlr->dpdlock); if(dpd = ctlr->dpdpool){ ctlr->dpdpool = dpd->next; iunlock(&ctlr->dpdlock); dpd->next = 0; dpd->bp = 0; } else{ iunlock(&ctlr->dpdlock); base = smalloc(sizeof(Dpd)+8); dpd = (Dpd*)ROUNDUP((ulong)base, 8); dpd->base = base; } return dpd; } static void dpdfree(Ctlr* ctlr, Dpd* dpd) { ilock(&ctlr->dpdlock); dpd->next = ctlr->dpdpool; ctlr->dpdpool = dpd; iunlock(&ctlr->dpdlock); } static Block* rbpalloc(Block* (*f)(int)) { Block *bp; | |
| 1996/0607 | ulong addr; /* | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:498,505 – 1997/0712/sys/src/9/pc/etherelnk3.c:607,620 | ||
| 1996/0607 | promiscuous(ether, ether->prom); | |
| 1997/0327 | x = interruptMask; | |
| 1996/0607 |
| |
| 1997/0712 | if(ctlr->busmaster == 1) | |
| 1996/0607 | x &= ~(rxEarly|rxComplete); | |
| 1997/0712 | else{ if(ctlr->dnenabled) x &= ~transferInt; if(ctlr->upenabled) x &= ~(rxEarly|rxComplete); } | |
| 1996/0607 | COMMAND(port, SetIndicationEnable, x); COMMAND(port, SetInterruptEnable, x); | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:510,517 – 1997/0712/sys/src/9/pc/etherelnk3.c:625,636 | ||
| 1996/0607 | * Prime the busmaster channel for receiving directly into a * receive packet buffer if necessary. */ | |
| 1997/0712 | if(ctlr->busmaster == 1) | |
| 1997/0327 | startdma(ether, PADDR(ctlr->rbp->rp)); | |
| 1997/0712 | else{ if(ctlr->upenabled) outl(port+UpListPtr, PADDR(ctlr->upqhead->rp)); } | |
| 1996/0607 | ctlr->attached = 1; iunlock(&ctlr->wlock); | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:542,551 – 1997/0712/sys/src/9/pc/etherelnk3.c:661,675 | ||
| 1997/0328 | ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF; ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF; | |
| 1996/0607 |
| |
| 1997/0712 | switch(ctlr->xcvr){ case xcvrMii: case xcvr100BaseTX: case xcvr100BaseFX: | |
| 1996/0607 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); STATUS(port); | |
| 1997/0328 | ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD); | |
| 1997/0712 | break; | |
| 1996/0607 | } COMMAND(port, SelectRegisterWindow, w); | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:602,607 – 1997/0712/sys/src/9/pc/etherelnk3.c:726,810 | ||
| 1996/0607 | } | |
| 1997/0327 | static void | |
| 1997/0712 | start905(Ether* ether, Dpd* add) { Ctlr *ctlr; int dnlistptr, port; Dpd *dpd; ctlr = ether->ctlr; port = ether->port; ilock(&ctlr->dnqlock); COMMAND(port, Stall, dnStall); while(STATUS(port) & commandInProgress) ; /* * Free any completed packets. */ dnlistptr = inl(port+DnListPtr); while(dpd = ctlr->dnqhead){ if(PADDR(dpd) == dnlistptr) break; ctlr->dnqhead = dpd->next; if(dpd->bp) freeb(dpd->bp); dpdfree(ctlr, dpd); } /* * Add any new packets to the queue. */ if(add){ if(ctlr->dnqhead){ dpd = ctlr->dnqtail; dpd->next = add; dpd->np = PADDR(&add->np); dpd->control &= ~dnIndicate; } else ctlr->dnqhead = add; ctlr->dnqtail = add; } /* * If the adapter is not currently processing anything * and there is something on the queue, start it processing. */ if(dnlistptr == 0 && ctlr->dnqhead) outl(port+DnListPtr, PADDR(ctlr->dnqhead)); COMMAND(port, Stall, dnUnStall); iunlock(&ctlr->dnqlock); } static void transmit905(Ether* ether) { Ctlr *ctlr; Block *bp; Dpd* dpd; bp = qget(ether->oq); if(bp == nil) return; ctlr = ether->ctlr; dpd = dpdalloc(ctlr); dpd->next = 0; dpd->bp = bp; dpd->np = 0; dpd->control = dnIndicate|BLEN(bp); dpd->addr = PADDR(bp->rp); dpd->len = updnLastFrag|BLEN(bp); start905(ether, dpd); } static void | |
| 1997/0327 | transmit(Ether* ether) | |
| 1996/0607 | { Ctlr *ctlr; | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:610,615 – 1997/0712/sys/src/9/pc/etherelnk3.c:813,823 | ||
| 1996/0607 | port = ether->port; ctlr = ether->ctlr; | |
| 1997/0712 | if(ctlr->dnenabled){ transmit905(ether); return; } | |
| 1996/0607 | ilock(&ctlr->wlock); w = (STATUS(port)>>13) & 0x07; COMMAND(port, SelectRegisterWindow, Wop); | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:619,624 – 1997/0712/sys/src/9/pc/etherelnk3.c:827,888 | ||
| 1996/0607 | } static void | |
| 1997/0712 | receive905(Ether* ether) { Ctlr *ctlr; int port; Block *bp, *xbp; Upd *upd; ctlr = ether->ctlr; port = ether->port; //ilock(&ctlr->upqlock); COMMAND(port, Stall, upStall); while(STATUS(port) & commandInProgress) ; bp = ctlr->upqhead; upd = (Upd*)bp->rp; while(upd->control & upPktComplete){ if(upd->control & upError){ if(upd->control & upOverrun) ether->overflows++; if(upd->control & (upOversizedFrame|upRuntFrame)) ether->buffs++; if(upd->control & upAlignmentError) ether->frames++; if(upd->control & upCRCError) ether->crcs++; upd->control = 0; } else if(xbp = updalloc(upd->np)){ bp->rp += sizeof(Upd)-sizeof(Etherpkt); bp->wp = bp->rp + (upd->control & rxBytes); xbp->next = bp->next; bp->next = 0; etheriq(ether, bp, 1); bp = xbp; } upd = (Upd*)ctlr->upqtail->rp; upd->np = PADDR(bp->rp); ctlr->upqtail->next = bp; ctlr->upqtail = bp; ctlr->upqhead = bp->next; bp = ctlr->upqhead; upd = (Upd*)bp->rp; } COMMAND(port, Stall, upUnStall); //iunlock(&ctlr->upqlock); } static void | |
| 1996/0607 | receive(Ether* ether) { int len, port, rxerror, rxstatus; | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:629,635 – 1997/0712/sys/src/9/pc/etherelnk3.c:893,899 | ||
| 1996/0607 | ctlr = ether->ctlr; while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){ | |
| 1997/0712 | if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress)) | |
| 1996/0607 | break; /* | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:677,688 – 1997/0712/sys/src/9/pc/etherelnk3.c:941,952 | ||
| 1997/0327 | * If there was an error or a new receive buffer can't be * allocated, discard the packet and go on to the next. */ | |
| 1997/0712 | if((rxstatus & rxError) || (bp = rbpalloc(iallocb)) == 0){ | |
| 1996/0607 | COMMAND(port, RxDiscard, 0); while(STATUS(port) & commandInProgress) ; | |
| 1997/0712 | if(ctlr->busmaster == 1) | |
| 1997/0327 | startdma(ether, PADDR(ctlr->rbp->rp)); continue; | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:697,703 – 1997/0712/sys/src/9/pc/etherelnk3.c:961,967 | ||
| 1997/0327 | * end-pointer of the one just received; * pass the packet on to whoever wants it. */ | |
| 1997/0712 | if(ctlr->busmaster == 0 || ctlr->busmaster == 2){ | |
| 1997/0327 | len = (rxstatus & rxBytes9); ctlr->rbp->wp = ctlr->rbp->rp + len; insl(port+Fifo, ctlr->rbp->rp, HOWMANY(len, 4)); | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:707,713 – 1997/0712/sys/src/9/pc/etherelnk3.c:971,977 | ||
| 1997/0327 | while(STATUS(port) & commandInProgress) ; | |
| 1996/0607 | ||
| 1997/0327 |
| |
| 1997/0712 | if(ctlr->busmaster == 1) | |
| 1997/0327 | ctlr->rbp->wp = startdma(ether, PADDR(bp->rp)); | |
| 1996/0607 | ||
| 1997/0327 | etheriq(ether, ctlr->rbp, 1); | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:779,784 – 1997/0712/sys/src/9/pc/etherelnk3.c:1043,1054 | ||
| 1996/0607 | status &= ~(transferInt|rxComplete); } | |
| 1997/0712 | if(status & (upComplete)){ COMMAND(port, AcknowledgeInterrupt, upComplete); receive905(ether); status &= ~upComplete; } | |
| 1996/0607 | if(status & txComplete){ /* * Pop the TxStatus stack, accumulating errors. | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:796,801 – 1997/0712/sys/src/9/pc/etherelnk3.c:1066,1075 | ||
| 1996/0607 | }while(STATUS(port) & txComplete); | |
| 1997/0327 | if(s & txUnderrun){ | |
| 1997/0712 | if(ctlr->dnenabled){ while(inl(port+PktStatus) & dnInProg) ; } | |
| 1996/0607 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); while(ins(port+MediaStatus) & txInProg) ; | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:812,817 – 1997/0712/sys/src/9/pc/etherelnk3.c:1086,1093 | ||
| 1996/0607 | while(STATUS(port) & commandInProgress) ; | |
| 1996/0925 | COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts); | |
| 1997/0712 | if(ctlr->busmaster == 2) outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256)); | |
| 1996/0607 | } COMMAND(port, TxEnable, 0); ether->oerrs++; | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:826,831 – 1997/0712/sys/src/9/pc/etherelnk3.c:1102,1113 | ||
| 1996/0607 | status &= ~txAvailable; } | |
| 1997/0712 | if(status & dnComplete){ COMMAND(port, AcknowledgeInterrupt, dnComplete); start905(ether, 0); status &= ~dnComplete; } | |
| 1996/0607 | if(status & updateStats){ statistics(ether); status &= ~updateStats; | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:869,888 – 1997/0712/sys/src/9/pc/etherelnk3.c:1151,1170 | ||
| 1996/0607 | iunlock(&ctlr->wlock); | |
| 1997/0417 | p = malloc(READSTR); | |
| 1997/0712 | len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts); len += snprint(p+len, READSTR-len, "timer: %lud\n", ctlr->timer); len += snprint(p+len, READSTR-len, "carrierlost: %lud\n", ctlr->stats[CarrierLost]); len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n", ctlr->stats[SqeErrors]); len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n", ctlr->stats[MultipleColls]); len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n", ctlr->stats[SingleCollFrames]); len += snprint(p+len, READSTR-len, "latecollisions: %lud\n", ctlr->stats[LateCollisions]); len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n", ctlr->stats[RxOverruns]); len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n", ctlr->stats[FramesXmittedOk]); len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n", ctlr->stats[FramesRcvdOk]); len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->stats[FramesDeferred]); len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n", ctlr->stats[BytesRcvdOk]); len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n", ctlr->stats[BytesRcvdOk+1]); snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]); | |
| 1996/0607 | ||
| 1997/0417 | n = readstr(offset, a, n, p); free(p); | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1009,1023 – 1997/0712/sys/src/9/pc/etherelnk3.c:1291,1305 | ||
| 1996/0607 | return (acr & 0x1F)*0x10 + 0x200; } | |
| 1997/0712 | static void tcm509isa(void) | |
| 1996/0607 | { int irq, port; /* | |
| 1997/0712 | * Attempt to activate all adapters. If adapter is set for * EISA mode (0x3F0), tag it and ignore. Otherwise, activate * it fully. | |
| 1996/0607 | */ while(port = activate()){ /* | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1051,1080 – 1997/0712/sys/src/9/pc/etherelnk3.c:1333,1354 | ||
| 1996/0607 | COMMAND(port, AcknowledgeInterrupt, 0xFF); irq = (ins(port+ResourceConfig)>>12) & 0x0F; | |
| 1997/0327 | tcmadapter(port, irq, BUSUNKNOWN); | |
| 1996/0607 | } | |
| 1997/0712 | static void tcm5XXeisa(void) | |
| 1996/0607 | { | |
| 1997/0712 | int irq, port, slot; | |
| 1996/0607 | /* | |
| 1997/0712 | * Check if this is an EISA machine. | |
| 1996/0607 | * If not, nothing to do. */ | |
| 1997/0712 | if(strncmp((char*)(KZERO|0xFFFD9), "EISA", 4)) return; | |
| 1996/0607 | /* * Continue through the EISA slots looking for a match on both | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1082,1089 – 1997/0712/sys/src/9/pc/etherelnk3.c:1356,1363 | ||
| 1996/0929 | * If an adapter is found, select window 0, enable it and clear | |
| 1996/0607 | * out any lingering status and interrupts. */ | |
| 1997/0712 | for(slot = 1; slot < MaxEISA; slot++){ port = slot*0x1000; | |
| 1996/0607 | if(ins(port+0xC80+ManufacturerID) != 0x6D50) continue; x = ins(port+0xC80+ProductID); | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1098,1120 – 1997/0712/sys/src/9/pc/etherelnk3.c:1372,1388 | ||
| 1996/0607 | COMMAND(port, AcknowledgeInterrupt, 0xFF); irq = (ins(port+ResourceConfig)>>12) & 0x0F; | |
| 1997/0327 | tcmadapter(port, irq, BUSUNKNOWN); | |
| 1996/0607 | } | |
| 1997/0712 | static void tcm59Xpci(void) | |
| 1996/0607 | { | |
| 1997/0327 |
| |
| 1997/0712 | Pcidev *p; | |
| 1996/0607 | int irq, port; | |
| 1997/0712 | p = nil; | |
| 1997/0327 | while(p = pcimatch(p, 0x10B7, 0)){ port = p->bar[0] & ~0x01; irq = p->intl; | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1121,1136 – 1997/0712/sys/src/9/pc/etherelnk3.c:1389,1397 | ||
| 1997/0328 | COMMAND(port, GlobalReset, 0); while(STATUS(port) & commandInProgress) ; | |
| 1996/0607 |
| |
| 1997/0327 |
| |
| 1996/0607 |
| |
| 1997/0327 | tcmadapter(port, irq, p->tbdf); | |
| 1996/0607 | } | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1142,1149 – 1997/0712/sys/src/9/pc/etherelnk3.c:1403,1452 | ||
| 1996/0607 | return 0; } | |
| 1997/0712 | static void setxcvr(int port, int xcvr, int is9) { int x; if(is9){ COMMAND(port, SelectRegisterWindow, Wsetup); x = ins(port+AddressConfig) & ~xcvrMask9; x |= (xcvr>>20)<<14; outs(port+AddressConfig, x); } else{ COMMAND(port, SelectRegisterWindow, Wfifo); x = inl(port+InternalConfig) & ~xcvrMask; x |= xcvr; outl(port+InternalConfig, x); } COMMAND(port, TxReset, 0); while(STATUS(port) & commandInProgress) ; COMMAND(port, RxReset, 0); while(STATUS(port) & commandInProgress) ; } #ifdef notdef static struct xxx { int available; int next; } xxx[8] = { { base10TAvailable, 1, }, /* xcvr10BaseT -> xcvrAui */ { auiAvailable, 3, }, /* xcvrAui -> xcvr10Base2 */ { 0, -1, }, { coaxAvailable, -1, }, /* xcvr10Base2 -> nowhere */ { baseTXAvailable, 5, }, /* xcvr100BaseTX-> xcvr100BaseFX */ { baseFXAvailable, -1, }, /* xcvr100BaseFX-> nowhere */ { miiConnector, -1, }, /* xcvrMii -> nowhere */ { 0, -1, }, }; #endif /* notdef */ | |
| 1996/0929 | static int | |
| 1997/0712 | autoselect(int port, int xcvr, int is9) | |
| 1996/0929 | { int media, x; | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1151,1190 – 1997/0712/sys/src/9/pc/etherelnk3.c:1454,1507 | ||
| 1996/0929 | * Pathetic attempt at automatic media selection. * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX * cards operational. | |
| 1997/0712 | * It's a bonus if it works for anything else. | |
| 1996/0929 | */ | |
| 1997/0712 | if(is9){ COMMAND(port, SelectRegisterWindow, Wsetup); x = ins(port+ConfigControl); media = 0; if(x & base10TAvailable9) media |= base10TAvailable; if(x & coaxAvailable9) media |= coaxAvailable; if(x & auiAvailable9) media |= auiAvailable; } else{ | |
| 1996/0929 | COMMAND(port, SelectRegisterWindow, Wfifo); media = ins(port+ResetOptions); } | |
| 1997/0712 | //print("autoselect: media %uX\n", media); | |
| 1996/0929 | ||
| 1997/0328 | if(media & miiConnector) return xcvrMii; | |
| 1996/0929 |
| |
| 1997/0712 | //COMMAND(port, SelectRegisterWindow, Wdiagnostic); //print("autoselect: media status %uX\n", ins(port+MediaStatus)); | |
| 1996/0929 | if(media & baseTXAvailable){ /* * Must have InternalConfig register. */ | |
| 1997/0712 | setxcvr(port, xcvr100BaseTX, is9); | |
| 1996/0929 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); | |
| 1997/0712 | x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable); outs(port+MediaStatus, linkBeatEnable|x); delay(10); | |
| 1996/0929 | ||
| 1997/0712 | { int i, v; for(i = 0; i < 2000; i++){ v = ins(port+MediaStatus); if(v & linkBeatDetect){ print("count %d v %uX\n", i, v); return xcvr100BaseTX; } delay(1); } //print("count %d v %uX\n", i, ins(port+MediaStatus)); } | |
| 1996/0929 | if(ins(port+MediaStatus) & linkBeatDetect) return xcvr100BaseTX; outs(port+MediaStatus, x); | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1191,1219 – 1997/0712/sys/src/9/pc/etherelnk3.c:1508,1519 | ||
| 1996/0929 | } if(media & base10TAvailable){ | |
| 1997/0712 | setxcvr(port, xcvr10BaseT, is9); | |
| 1996/0929 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); | |
| 1997/0712 | x = ins(port+MediaStatus) & ~dcConverterEnabled; | |
| 1996/0929 | outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x); | |
| 1997/0712 | delay(100); | |
| 1996/0929 | if(ins(port+MediaStatus) & linkBeatDetect) return xcvr10BaseT; | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1246,1260 – 1997/0712/sys/src/9/pc/etherelnk3.c:1546,1568 | ||
| 1997/0327 | Adapter *ap; | |
| 1996/0607 | uchar ea[Eaddrlen]; Ctlr *ctlr; | |
| 1997/0712 | static int scandone; | |
| 1996/0607 | /* | |
| 1997/0712 | * Scan for adapter on PCI, EISA and finally * using the little ISA configuration dance. | |
| 1996/0607 | */ | |
| 1997/0712 | if(scandone == 0){ tcm59Xpci(); tcm5XXeisa(); tcm509isa(); scandone = 1; } /* * Any adapter matches if no ether->port is supplied, * otherwise the ports must match. */ | |
| 1996/0607 | port = 0; | |
| 1997/0327 | bpp = &adapter; for(bp = *bpp; bp; bp = bp->next){ | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1269,1284 – 1997/0712/sys/src/9/pc/etherelnk3.c:1577,1585 | ||
| 1996/0607 | } | |
| 1997/0327 | bpp = &bp->next; | |
| 1996/0607 | } | |
| 1997/0328 |
| |
| 1997/0712 | if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0) | |
| 1997/0328 | return -1; | |
| 1997/0712 | ||
| 1997/0328 | /* * Read the DeviceID from the EEPROM, it's at offset 0x03, * and do something depending on capabilities. | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1322,1328 – 1997/0712/sys/src/9/pc/etherelnk3.c:1623,1628 | ||
| 1996/0607 | rxstatus9 = 1; | |
| 1997/0328 | break; | |
| 1996/0607 | } | |
| 1997/0404 |
| |
| 1996/0607 | /* * Check if the adapter's station address is to be overridden. | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1347,1381 – 1997/0712/sys/src/9/pc/etherelnk3.c:1647,1700 | ||
| 1996/0607 | * busmastering can be used. Due to bugs in the first revision * of the 3C59[05], don't use busmastering at 10Mbps. */ | |
| 1997/0712 | //print("reset: xcvr %uX\n", xcvr); | |
| 1996/0929 | if(xcvr & autoSelect) | |
| 1996/0607 |
| |
| 1997/0327 |
| |
| 1997/0328 |
| |
| 1997/0327 |
| |
| 1996/0607 |
| |
| 1997/0712 | xcvr = autoselect(port, xcvr, rxstatus9); | |
| 1996/0607 | switch(xcvr){ | |
| 1997/0328 | case xcvrMii: | |
| 1997/0712 | /* * Bug? the 3c905 always seems to have dataRate100 set. */ COMMAND(port, SelectRegisterWindow, Wdiagnostic); if(ins(port+MediaStatus) & dataRate100) ether->mbps = 100; | |
| 1997/0328 | break; | |
| 1996/0607 | case xcvr100BaseTX: case xcvr100BaseFX: | |
| 1997/0712 | COMMAND(port, SelectRegisterWindow, Wfifo); x = inl(port+InternalConfig) & ~ramPartitionMask; outl(port+InternalConfig, x|ramPartition1to1); COMMAND(port, SelectRegisterWindow, Wdiagnostic); x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable); x |= linkBeatEnable; outs(port+MediaStatus, x); if(x & dataRate100) ether->mbps = 100; break; | |
| 1996/0607 | case xcvr10BaseT: /* * Enable Link Beat and Jabber to start the * transceiver. */ | |
| 1997/0712 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); x = ins(port+MediaStatus) & ~dcConverterEnabled; | |
| 1996/0607 | x |= linkBeatEnable|jabberGuardEnable; outs(port+MediaStatus, x); | |
| 1997/0712 | if((did & 0xFF00) == 0x5900) busmaster = 0; | |
| 1996/0607 | break; case xcvr10Base2: | |
| 1997/0712 | COMMAND(port, SelectRegisterWindow, Wdiagnostic); x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable); outs(port+MediaStatus, x); | |
| 1996/0607 | /* * Start the DC-DC converter. * Wait > 800 microseconds. | |
| 1997/0614/sys/src/9/pc/etherelnk3.c:1420,1428 – 1997/0712/sys/src/9/pc/etherelnk3.c:1739,1772 | ||
| 1996/0607 | COMMAND(port, StatisticsEnable, 0); /* | |
| 1997/0327 |
| |
| 1997/0712 | * Allocate any receive buffers. | |
| 1996/0607 | */ | |
| 1997/0327 |
| |
| 1997/0712 | switch(ctlr->busmaster){ case 2: ctlr->dnenabled = 1; /* * Too severe, can use receive busmastering at 100Mbps OK, * but how to tell which rate is actually being used - the * 3c905 always seems to have dataRate100 set? */ x = eepromdata(port, 0x0F); print("software info 2: %uX\n", x); if(x & 0x01) ctlr->upenabled = 1; if(ctlr->upenabled) init905(ctlr); else ctlr->rbp = rbpalloc(allocb); outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256)); break; default: ctlr->rbp = rbpalloc(allocb); break; } | |
| 1996/0607 | /* * Set a base TxStartThresh which will be incremented | |
| 1997/0712/sys/src/9/pc/etherelnk3.c:460,466 – 1997/0715/sys/src/9/pc/etherelnk3.c:460,466 (short | long) | ||
| 1997/0712 | Upd *upd; np = 0; | |
| 1997/0715 | for(i = 0; i < 64; i++){ | |
| 1997/0712 | bp = updalloc(np); if(ctlr->upqhead == 0) ctlr->upqtail = bp; | |
| 1997/0712/sys/src/9/pc/etherelnk3.c:1747,1760 – 1997/0715/sys/src/9/pc/etherelnk3.c:1747,1765 | ||
| 1997/0712 | ctlr->dnenabled = 1; /* | |
| 1997/0715 | * 10MUpldBug. * Disabling is too severe, can use receive busmastering at * 100Mbps OK, but how to tell which rate is actually being used - * the 3c905 always seems to have dataRate100 set? * Believe the bug doesn't apply if upRxEarlyEnable is set * and the threshold is set such that uploads won't start * until the whole packet has been received. | |
| 1997/0712 | */ | |
| 1997/0715 | ctlr->upenabled = 1; | |
| 1997/0712 | x = eepromdata(port, 0x0F); | |
| 1997/0715 | //print("software info 2: %uX\n", x); if(!(x & 0x01)) outl(port+PktStatus, upRxEarlyEnable); | |
| 1997/0712 | if(ctlr->upenabled) init905(ctlr); | |
| 1997/0715/sys/src/9/pc/etherelnk3.c:6,12 – 1997/0806/sys/src/9/pc/etherelnk3.c:6,12 (short | long) | ||
| 1996/0607 | * autoSelect; * PCI latency timer and master enable; | |
| 1997/0327 | * errata list; | |
| 1997/0328 |
| |
| 1997/0806 | * limit 3C90x transmit queue; | |
| 1997/0328 | * rewrite all initialisation. | |
| 1996/0607 | * * Product ID: | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:6,12 – 1997/0919/sys/src/9/pc/etherelnk3.c:6,11 (short | long) | ||
| 1996/0607 | * autoSelect; * PCI latency timer and master enable; | |
| 1997/0327 | * errata list; | |
| 1997/0806 |
| |
| 1997/0328 | * rewrite all initialisation. | |
| 1996/0607 | * * Product ID: | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:365,397 – 1997/0919/sys/src/9/pc/etherelnk3.c:364,390 | ||
| 1997/0712 | dnIndicate = 0x80000000, /* FrameStartHeader (dpd->control) */ updnLastFrag = 0x80000000, /* (dpd->len) */ | |
| 1997/0919 | Nup = 32, Ndn = 16, | |
| 1997/0328 | }; /* | |
| 1997/0919 | * Up/Dn Packet Descriptors. * The hardware info (np, control, addr, len) must be 8-byte aligned * and this structure size must be a multiple of 8. | |
| 1997/0328 | */ | |
| 1997/0712 |
| |
| 1997/0919 | typedef struct Pd Pd; typedef struct Pd { | |
| 1997/0712 | ulong np; /* next pointer */ ulong control; /* FSH or UpPktStatus */ ulong addr; ulong len; | |
| 1997/0919 | Pd* next; | |
| 1997/0328 | Block* bp; | |
| 1997/0712 |
| |
| 1997/0919 | } Pd; | |
| 1997/0328 | ||
| 1997/0712 |
| |
| 1997/0328 |
| |
| 1997/0712 |
| |
| 1996/0607 | typedef struct { Lock wlock; /* window access */ | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:403,425 – 1997/0919/sys/src/9/pc/etherelnk3.c:396,424 | ||
| 1996/0607 | int txthreshold; int txbusy; | |
| 1997/0712 |
| |
| 1997/0919 | int nup; /* full-busmaster -based reception */ void* upbase; Pd* upr; Pd* uphead; | |
| 1997/0712 |
| |
| 1997/0919 | Lock dnlock; /* full-busmaster -based transmission */ int ndn; void* dnbase; Pd* dnr; Pd* dnhead; Pd* dntail; int dnq; | |
| 1997/0712 |
| |
| 1996/0607 | long interrupts; /* statistics */ long timer; | |
| 1997/0712 | long stats[BytesRcvdOk+3]; | |
| 1996/0607 | ||
| 1997/0919 | int upqmax; int upstalls; int dnqmax; long dninterrupts; long dnqueued; | |
| 1996/0607 | int xcvr; /* transceiver type */ int rxstatus9; /* old-style RxStatus register */ | |
| 1997/0327 | int rxearly; /* RxEarlyThreshold */ | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:428,510 – 1997/0919/sys/src/9/pc/etherelnk3.c:427,476 | ||
| 1997/0712 | int dnenabled; | |
| 1996/0607 | } Ctlr; | |
| 1997/0712 |
| |
| 1997/0919 | static void init905(Ctlr* ctlr) | |
| 1996/0607 | { Block *bp; | |
| 1997/0712 |
| |
| 1997/0919 | Pd *pd, *prev; | |
| 1997/0712 | /* | |
| 1997/0919 | * Create rings for the receive and transmit sides. * Take care with alignment: * make sure ring base is 8-byte aligned; * make sure each entry is 8-byte aligned. | |
| 1997/0712 | */ | |
| 1997/0919 | ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd)); ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8); | |
| 1997/0712 |
| |
| 1997/0919 | prev = ctlr->upr; for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){ pd->np = PADDR(&prev->np); pd->control = 0; bp = allocb(sizeof(Etherpkt)); pd->addr = PADDR(bp->rp); pd->len = updnLastFrag|sizeof(Etherpkt); | |
| 1997/0712 |
| |
| 1997/0715 |
| |
| 1997/0712 |
| |
| 1997/0919 | pd->next = prev; prev = pd; pd->bp = bp; | |
| 1997/0712 | } | |
| 1997/0919 | ctlr->uphead = ctlr->upr; | |
| 1997/0712 |
| |
| 1997/0919 | ilock(&ctlr->dnlock); ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd)); ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8); | |
| 1997/0712 |
| |
| 1997/0919 | prev = ctlr->dnr; for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){ pd->next = prev; prev = pd; | |
| 1997/0712 | } | |
| 1997/0919 | ctlr->dnhead = ctlr->dnr; ctlr->dntail = ctlr->dnr; ctlr->dnq = 0; iunlock(&ctlr->dnlock); | |
| 1997/0712 | } | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:629,635 – 1997/0919/sys/src/9/pc/etherelnk3.c:595,601 | ||
| 1997/0327 | startdma(ether, PADDR(ctlr->rbp->rp)); | |
| 1997/0712 | else{ if(ctlr->upenabled) | |
| 1997/0919 | outl(port+UpListPtr, PADDR(&ctlr->uphead->np)); | |
| 1997/0712 | } | |
| 1996/0607 | ctlr->attached = 1; | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:726,741 – 1997/0919/sys/src/9/pc/etherelnk3.c:692,708 | ||
| 1996/0607 | } | |
| 1997/0327 | static void | |
| 1997/0712 |
| |
| 1997/0919 | txstart905(Ether* ether) | |
| 1997/0712 | { Ctlr *ctlr; int dnlistptr, port; | |
| 1997/0919 | Block *bp; Pd *pd; | |
| 1997/0712 | ctlr = ether->ctlr; port = ether->port; | |
| 1997/0919 | ilock(&ctlr->dnlock); | |
| 1997/0712 | COMMAND(port, Stall, dnStall); while(STATUS(port) & commandInProgress) ; | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:744,810 – 1997/0919/sys/src/9/pc/etherelnk3.c:711,766 | ||
| 1997/0712 | * Free any completed packets. */ dnlistptr = inl(port+DnListPtr); | |
| 1997/0919 | pd = ctlr->dntail; while(ctlr->dnq){ if(PADDR(&pd->np) == dnlistptr) | |
| 1997/0712 | break; | |
| 1997/0919 | if(pd->bp){ freeb(pd->bp); pd->bp = nil; } ctlr->dnq--; pd = pd->next; | |
| 1997/0712 | } | |
| 1997/0919 | ctlr->dntail = pd; | |
| 1997/0712 |
| |
| 1997/0919 | while(ctlr->dnq < (ctlr->ndn-1)){ bp = qget(ether->oq); if(bp == nil) break; pd = ctlr->dnhead->next; pd->np = 0; pd->control = dnIndicate|BLEN(bp); pd->addr = PADDR(bp->rp); pd->len = updnLastFrag|BLEN(bp); pd->bp = bp; if(ctlr->dnq == 0) ctlr->dntail = pd; ctlr->dnhead->np = PADDR(&pd->np); ctlr->dnhead->control &= ~dnIndicate; ctlr->dnhead = pd; ctlr->dnq++; ctlr->dnqueued++; | |
| 1997/0712 | } | |
| 1997/0919 | if(ctlr->dnq > ctlr->dnqmax) ctlr->dnqmax = ctlr->dnq; | |
| 1997/0712 | /* * If the adapter is not currently processing anything * and there is something on the queue, start it processing. */ | |
| 1997/0919 | if(dnlistptr == 0 && ctlr->dnq) outl(port+DnListPtr, PADDR(&ctlr->dnhead->np)); | |
| 1997/0712 | COMMAND(port, Stall, dnUnStall); | |
| 1997/0919 | iunlock(&ctlr->dnlock); | |
| 1997/0712 | } static void | |
| 1997/0327 | transmit(Ether* ether) | |
| 1996/0607 | { Ctlr *ctlr; | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:814,820 – 1997/0919/sys/src/9/pc/etherelnk3.c:770,776 | ||
| 1996/0607 | ctlr = ether->ctlr; | |
| 1997/0712 | if(ctlr->dnenabled){ | |
| 1997/0919 | txstart905(ether); | |
| 1997/0712 | return; } | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:830,885 – 1997/0919/sys/src/9/pc/etherelnk3.c:786,829 | ||
| 1997/0712 | receive905(Ether* ether) { Ctlr *ctlr; | |
| 1997/0919 | int len, port, q; Pd *pd; Block *bp; | |
| 1997/0712 | ctlr = ether->ctlr; port = ether->port; | |
| 1997/0919 | if(inl(port+UpPktStatus) & upStalled) ctlr->upstalls++; q = 0; for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){ if(pd->control & upError){ if(pd->control & upOverrun) | |
| 1997/0712 | ether->overflows++; | |
| 1997/0919 | if(pd->control & (upOversizedFrame|upRuntFrame)) | |
| 1997/0712 | ether->buffs++; | |
| 1997/0919 | if(pd->control & upAlignmentError) | |
| 1997/0712 | ether->frames++; | |
| 1997/0919 | if(pd->control & upCRCError) | |
| 1997/0712 | ether->crcs++; | |
| 1997/0919 | else if(bp = iallocb(sizeof(Etherpkt)+4)){ len = pd->control & rxBytes; pd->bp->wp = pd->bp->rp+len; etheriq(ether, pd->bp, 1); pd->bp = bp; pd->addr = PADDR(bp->rp); | |
| 1997/0712 | } | |
| 1997/0919 | pd->control = 0; COMMAND(port, Stall, upUnStall); | |
| 1997/0712 |
| |
| 1997/0919 | q++; | |
| 1997/0712 | } | |
| 1997/0919 | ctlr->uphead = pd; | |
| 1997/0712 |
| |
| 1997/0919 | if(q > ctlr->upqmax) ctlr->upqmax = q; | |
| 1997/0712 | } static void | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:1044,1051 – 1997/0919/sys/src/9/pc/etherelnk3.c:988,995 | ||
| 1996/0607 | } | |
| 1997/0712 | if(status & (upComplete)){ | |
| 1997/0919 | COMMAND(port, AcknowledgeInterrupt, upComplete); | |
| 1997/0712 | status &= ~upComplete; } | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:1103,1111 – 1997/0919/sys/src/9/pc/etherelnk3.c:1047,1056 | ||
| 1996/0607 | } | |
| 1997/0712 | if(status & dnComplete){ | |
| 1997/0919 | txstart905(ether); | |
| 1997/0712 | COMMAND(port, AcknowledgeInterrupt, dnComplete); | |
| 1997/0919 | ctlr->dninterrupts++; | |
| 1997/0712 | } | |
| 1996/0607 | if(status & updateStats){ | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:1164,1169 – 1997/0919/sys/src/9/pc/etherelnk3.c:1109,1120 | ||
| 1997/0712 | len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->stats[FramesDeferred]); len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n", ctlr->stats[BytesRcvdOk]); len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n", ctlr->stats[BytesRcvdOk+1]); | |
| 1997/0919 | len += snprint(p+len, READSTR-len, "up: q %lud s %lud\n", ctlr->upqmax, ctlr->upstalls); ctlr->upqmax = 0; len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d\n", ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax); ctlr->dnqmax = 0; | |
| 1997/0712 | snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]); | |
| 1996/0607 | ||
| 1997/0417 | n = readstr(offset, a, n, p); | |
| 1997/0806/sys/src/9/pc/etherelnk3.c:1761,1768 – 1997/0919/sys/src/9/pc/etherelnk3.c:1712,1722 | ||
| 1997/0715 | if(!(x & 0x01)) outl(port+PktStatus, upRxEarlyEnable); | |
| 1997/0712 |
| |
| 1997/0919 | if(ctlr->upenabled || ctlr->dnenabled){ ctlr->nup = Nup; ctlr->ndn = Ndn; | |
| 1997/0712 | init905(ctlr); | |
| 1997/0919 | } | |
| 1997/0712 | else ctlr->rbp = rbpalloc(allocb); outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256)); | |
| 1997/0919/sys/src/9/pc/etherelnk3.c:1335,1341 – 1997/1011/sys/src/9/pc/etherelnk3.c:1335,1341 (short | long) | ||
| 1996/0607 | ||
| 1997/0712 | p = nil; | |
| 1997/0327 | while(p = pcimatch(p, 0x10B7, 0)){ | |
| 1997/1011 | port = p->mem[0].bar & ~0x01; | |
| 1997/0327 | irq = p->intl; | |
| 1997/0328 | COMMAND(port, GlobalReset, 0); while(STATUS(port) & commandInProgress) | |
| 1997/1011/sys/src/9/pc/etherelnk3.c:401,408 – 1997/1025/sys/src/9/pc/etherelnk3.c:401,407 (short | long) | ||
| 1997/0919 | Pd* upr; Pd* uphead; | |
| 1997/0712 | ||
| 1997/0919 |
| |
| 1997/1025 | int ndn; /* full-busmaster -based transmission */ | |
| 1997/0919 | void* dnbase; Pd* dnr; Pd* dnhead; | |
| 1997/1011/sys/src/9/pc/etherelnk3.c:456,462 – 1997/1025/sys/src/9/pc/etherelnk3.c:455,460 | ||
| 1997/0712 | } | |
| 1997/0919 | ctlr->uphead = ctlr->upr; | |
| 1997/0712 | ||
| 1997/0919 |
| |
| 1997/0712 | ||
| 1997/1011/sys/src/9/pc/etherelnk3.c:468,474 – 1997/1025/sys/src/9/pc/etherelnk3.c:466,471 | ||
| 1997/0919 | ctlr->dnhead = ctlr->dnr; ctlr->dntail = ctlr->dnr; ctlr->dnq = 0; | |
| 1997/0712 | } static Block* | |
| 1997/1011/sys/src/9/pc/etherelnk3.c:702,708 – 1997/1025/sys/src/9/pc/etherelnk3.c:699,704 | ||
| 1997/0712 | ctlr = ether->ctlr; port = ether->port; | |
| 1997/0919 |
| |
| 1997/0712 | COMMAND(port, Stall, dnStall); while(STATUS(port) & commandInProgress) ; | |
| 1997/1011/sys/src/9/pc/etherelnk3.c:757,763 – 1997/1025/sys/src/9/pc/etherelnk3.c:753,758 | ||
| 1997/0919 | outl(port+DnListPtr, PADDR(&ctlr->dnhead->np)); | |
| 1997/0712 | COMMAND(port, Stall, dnUnStall); | |
| 1997/0919 |
| |
| 1997/0712 | } static void | |
| 1997/1011/sys/src/9/pc/etherelnk3.c:769,784 – 1997/1025/sys/src/9/pc/etherelnk3.c:764,778 | ||
| 1996/0607 | port = ether->port; ctlr = ether->ctlr; | |
| 1997/0712 |
| |
| 1997/1025 | ilock(&ctlr->wlock); if(ctlr->dnenabled) | |
| 1997/0919 | txstart905(ether); | |
| 1997/0712 |
| |
| 1997/1025 | else{ w = (STATUS(port)>>13) & 0x07; COMMAND(port, SelectRegisterWindow, Wop); txstart(ether); COMMAND(port, SelectRegisterWindow, w); | |
| 1997/0712 | } | |
| 1996/0607 |
| |
| 1997/0327 |
| |
| 1996/0607 |
| |
| 1997/1011/sys/src/9/pc/etherelnk3.c:1298,1304 – 1997/1025/sys/src/9/pc/etherelnk3.c:1292,1298 | ||
| 1997/0712 | * Check if this is an EISA machine. | |
| 1996/0607 | * If not, nothing to do. */ | |
| 1997/0712 |
| |
| 1997/1025 | if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4)) | |
| 1997/0712 | return; | |
| 1996/0607 | /* | |
| 1997/1025/sys/src/9/pc/etherelnk3.c:413,418 – 1997/1203/sys/src/9/pc/etherelnk3.c:413,420 (short | long) | ||
| 1997/0712 | long stats[BytesRcvdOk+3]; | |
| 1996/0607 | ||
| 1997/0919 | int upqmax; | |
| 1997/1203 | long upinterrupts; long upqueued; | |
| 1997/0919 | int upstalls; int dnqmax; long dninterrupts; | |
| 1997/1025/sys/src/9/pc/etherelnk3.c:816,821 – 1997/1203/sys/src/9/pc/etherelnk3.c:818,824 | ||
| 1997/0712 | } | |
| 1997/0919 | ctlr->uphead = pd; | |
| 1997/0712 | ||
| 1997/1203 | ctlr->upqueued += q; | |
| 1997/0919 | if(q > ctlr->upqmax) ctlr->upqmax = q; | |
| 1997/0712 | } | |
| 1997/1025/sys/src/9/pc/etherelnk3.c:982,990 – 1997/1203/sys/src/9/pc/etherelnk3.c:985,994 | ||
| 1996/0607 | } | |
| 1997/0712 | if(status & (upComplete)){ | |
| 1997/0919 | COMMAND(port, AcknowledgeInterrupt, upComplete); | |
| 1997/1203 | receive905(ether); | |
| 1997/0712 | status &= ~upComplete; | |
| 1997/1203 | ctlr->upinterrupts++; | |
| 1997/0712 | } | |
| 1996/0607 | if(status & txComplete){ | |
| 1997/1025/sys/src/9/pc/etherelnk3.c:1041,1048 – 1997/1203/sys/src/9/pc/etherelnk3.c:1045,1052 | ||
| 1996/0607 | } | |
| 1997/0712 | if(status & dnComplete){ | |
| 1997/0919 |
| |
| 1997/0712 | COMMAND(port, AcknowledgeInterrupt, dnComplete); | |
| 1997/1203 | txstart905(ether); | |
| 1997/0712 | status &= ~dnComplete; | |
| 1997/0919 | ctlr->dninterrupts++; | |
| 1997/0712 | } | |
| 1997/1025/sys/src/9/pc/etherelnk3.c:1103,1114 – 1997/1203/sys/src/9/pc/etherelnk3.c:1107,1124 | ||
| 1997/0712 | len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->stats[FramesDeferred]); len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n", ctlr->stats[BytesRcvdOk]); len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n", ctlr->stats[BytesRcvdOk+1]); | |
| 1997/0919 |
| |
| 1997/1203 | if(ctlr->upenabled){ len += snprint(p+len, READSTR-len, "up: q %lud i %lud m %d s %lud\n", ctlr->upqueued, ctlr->upinterrupts, ctlr->dnqmax, ctlr->upstalls); ctlr->upqmax = 0; } if(ctlr->dnenabled){ len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d\n", ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax); ctlr->dnqmax = 0; } | |
| 1997/0712 | snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]); | |
| 1996/0607 | ||
| 1997/0417 | n = readstr(offset, a, n, p); | |
| 1997/1025/sys/src/9/pc/etherelnk3.c:1729,1734 – 1997/1203/sys/src/9/pc/etherelnk3.c:1739,1746 | ||
| 1997/0327 | ctlr->txthreshold = ETHERMAXTU/2; | |
| 1996/0928 | COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts); | |
| 1996/0925 | COMMAND(port, SetRxEarlyThresh, rxearly>>ctlr->ts); | |
| 1997/1203 | COMMAND(port, AcknowledgeInterrupt, interruptLatch); | |
| 1996/0607 | iunlock(&ctlr->wlock); | |
| 1997/1203/sys/src/9/pc/etherelnk3.c:366,372 – 1997/1207/sys/src/9/pc/etherelnk3.c:366,372 (short | long) | ||
| 1997/0712 | updnLastFrag = 0x80000000, /* (dpd->len) */ | |
| 1997/0919 | Nup = 32, | |
| 1997/1207 | Ndn = 32, | |
| 1997/0328 | }; /* | |
| 1997/1203/sys/src/9/pc/etherelnk3.c:1110,1116 – 1997/1207/sys/src/9/pc/etherelnk3.c:1110,1116 | ||
| 1997/1203 | if(ctlr->upenabled){ len += snprint(p+len, READSTR-len, "up: q %lud i %lud m %d s %lud\n", | |
| 1997/1207 | ctlr->upqueued, ctlr->upinterrupts, ctlr->upqmax, ctlr->upstalls); | |
| 1997/1203 | ctlr->upqmax = 0; } if(ctlr->dnenabled){ | |
| 1997/1207/sys/src/9/pc/etherelnk3.c:366,372 – 1997/1212/sys/src/9/pc/etherelnk3.c:366,372 (short | long) | ||
| 1997/0712 | updnLastFrag = 0x80000000, /* (dpd->len) */ | |
| 1997/0919 | Nup = 32, | |
| 1997/1207 |
| |
| 1997/1212 | Ndn = 64, | |
| 1997/0328 | }; /* | |
| 1997/1207/sys/src/9/pc/etherelnk3.c:694,700 – 1997/1212/sys/src/9/pc/etherelnk3.c:694,700 | ||
| 1997/0919 | txstart905(Ether* ether) | |
| 1997/0712 | { Ctlr *ctlr; | |
| 1997/1212 | int port, stalled, timeo; | |
| 1997/0919 | Block *bp; Pd *pd; | |
| 1997/0712 | ||
| 1997/1207/sys/src/9/pc/etherelnk3.c:701,717 – 1997/1212/sys/src/9/pc/etherelnk3.c:701,712 | ||
| 1997/0712 | ctlr = ether->ctlr; port = ether->port; | |
| 1997/0919 | pd = ctlr->dntail; while(ctlr->dnq){ | |
| 1997/1212 | if(PADDR(&pd->np) == inl(port+DnListPtr)) | |
| 1997/0712 | break; | |
| 1997/0919 | if(pd->bp){ freeb(pd->bp); | |
| 1997/1207/sys/src/9/pc/etherelnk3.c:722,727 – 1997/1212/sys/src/9/pc/etherelnk3.c:717,723 | ||
| 1997/0712 | } | |
| 1997/0919 | ctlr->dntail = pd; | |
| 1997/0712 | ||
| 1997/1212 | stalled = 0; | |
| 1997/0919 | while(ctlr->dnq < (ctlr->ndn-1)){ bp = qget(ether->oq); if(bp == nil) | |
| 1997/1207/sys/src/9/pc/etherelnk3.c:734,744 – 1997/1212/sys/src/9/pc/etherelnk3.c:730,749 | ||
| 1997/0919 | pd->len = updnLastFrag|BLEN(bp); pd->bp = bp; | |
| 1997/1212 | if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){ COMMAND(port, Stall, dnStall); for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--) ; if(timeo == 0) print("#l%d: dnstall %d\n", ether->ctlrno, timeo); stalled = 1; } | |
| 1997/0919 | ctlr->dnhead->np = PADDR(&pd->np); ctlr->dnhead->control &= ~dnIndicate; ctlr->dnhead = pd; | |
| 1997/1212 | if(ctlr->dnq == 0) ctlr->dntail = pd; | |
| 1997/0919 | ctlr->dnq++; ctlr->dnqueued++; | |
| 1997/1207/sys/src/9/pc/etherelnk3.c:751,760 – 1997/1212/sys/src/9/pc/etherelnk3.c:756,765 | ||
| 1997/0712 | * If the adapter is not currently processing anything * and there is something on the queue, start it processing. */ | |
| 1997/0919 |
| |
| 1997/1212 | if(inl(port+DnListPtr) == 0 && ctlr->dnq) | |
| 1997/0919 | outl(port+DnListPtr, PADDR(&ctlr->dnhead->np)); | |
| 1997/0712 |
| |
| 1997/1212 | if(stalled) COMMAND(port, Stall, dnUnStall); | |
| 1997/0712 | } static void | |
| 1997/1207/sys/src/9/pc/etherelnk3.c:1030,1036 – 1997/1212/sys/src/9/pc/etherelnk3.c:1035,1046 | ||
| 1996/0925 | COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts); | |
| 1997/0712 | if(ctlr->busmaster == 2) outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256)); | |
| 1997/1212 | if(ctlr->dnenabled) status |= dnComplete; | |
| 1996/0607 | } | |
| 1997/1212 | print("#l%d: txstatus 0x%uX, threshold %d\n", ether->ctlrno, s, ctlr->txthreshold); | |
| 1996/0607 | COMMAND(port, TxEnable, 0); ether->oerrs++; status &= ~txComplete; | |
| 1997/1207/sys/src/9/pc/etherelnk3.c:1739,1746 – 1997/1212/sys/src/9/pc/etherelnk3.c:1749,1754 | ||
| 1997/0327 | ctlr->txthreshold = ETHERMAXTU/2; | |
| 1996/0928 | COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts); | |
| 1996/0925 | COMMAND(port, SetRxEarlyThresh, rxearly>>ctlr->ts); | |
| 1997/1203 |
| |
| 1996/0607 | iunlock(&ctlr->wlock); | |
| 1997/1212/sys/src/9/pc/etherelnk3.c:1411,1417 – 1998/0319/sys/src/9/pc/etherelnk3.c:1411,1417 (short | long) | ||
|
Anonymize autoselect.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0712 | #endif /* notdef */ | |
| 1996/0929 | static int | |
| 1997/0712 |
| |
| 1998/0319 | autoselect(int port, int , int is9) | |
| 1996/0929 | { int media, x; | |
| Too many diffs (26 > 25). Stopping. | ||