## diffname pc/ether509.c 1992/0922 ## diff -e /dev/null /n/bootesdump/1992/0922/sys/src/9/pc/ether509.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "io.h" #include "devtab.h" #define NEXT(x, l) (((x)+1)%(l)) #define OFFSETOF(t, m) ((unsigned)&(((t*)0)->m)) #define HOWMANY(x, y) (((x)+((y)-1))/(y)) #define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) enum { Nrb = 16, /* software receive buffers */ Ntb = 4, /* software transmit buffers */ }; enum { IDport = 0x0100, /* anywhere between 0x0100 and 0x01F0 */ /* Commands */ SelectWindow = 0x01, /* SelectWindow command */ StartCoax = 0x02, /* Start Coaxial Transceiver */ RxDisable = 0x03, /* RX Disable */ RxEnable = 0x04, /* RX Enable */ RxDiscard = 0x08, /* RX Discard Top Packet */ TxEnable = 0x09, /* TX Enable */ TxDisable = 0x0A, /* TX Disable */ AckIntr = 0x0D, /* Acknowledge Interrupt */ SetIntrMask = 0x0E, /* Set Interrupt Mask */ SetReadZeroMask = 0x0F, /* Set Read Zero Mask */ SetRxFilter = 0x10, /* Set RX Filter */ SetTxAvailable = 0x12, /* Set TX Available Threshold */ /* RX Filter Command Bits */ MyEtherAddr = 0x01, /* Individual address */ Multicast = 0x02, /* Group (multicast) addresses */ Broadcast = 0x04, /* Broadcast address */ Promiscuous = 0x08, /* All addresses (promiscuous mode */ /* Window Register Offsets */ Command = 0x0E, /* all windows */ Status = 0x0E, EEPROMdata = 0x0C, /* window 0 */ EEPROMcmd = 0x0A, ResourceConfig = 0x08, ConfigControl = 0x04, TxFreeBytes = 0x0C, /* window 1 */ TxStatus = 0x0B, RxStatus = 0x08, Fifo = 0x00, /* Status/Interrupt Bits */ Latch = 0x0001, /* Interrupt Latch */ TxComplete = 0x0004, /* TX Complete */ TxAvailable = 0x0008, /* TX Available */ RxComplete = 0x0010, /* RX Complete */ AllIntr = 0x00FE, /* All Interrupt Bits */ CmdInProgress = 0x1000, /* Command In Progress */ /* RxStatus Bits */ RxByteMask = 0x07FF, /* RX Bytes (0-1514) */ RxErrMask = 0x3800, /* Type of Error: */ RxErrOverrun = 0x0000, /* Overrrun */ RxErrOversize = 0x0800, /* Oversize Packet (>1514) */ RxErrDribble = 0x1000, /* Dribble Bit(s) */ RxErrRunt = 0x1800, /* Runt Packet */ RxErrFraming = 0x2000, /* Alignment (Framing) */ RxErrCRC = 0x2800, /* CRC */ RxError = 0x4000, /* Error */ RxEmpty = 0x8000, /* Incomplete or FIFO empty */ }; #define COMMAND(hw, cmd, a) outs(hw->addr+Command, ((cmd)<<11)|(a)) /* * get configuration parameters */ static int reset(EtherCtlr *cp) { EtherHw *hw = cp->hw; int i, ea; ushort acr; uchar al; cp->rb = xspanalloc(sizeof(EtherBuf)*Nrb, BY2PG, 0); cp->nrb = Nrb; cp->tb = xspanalloc(sizeof(EtherBuf)*Ntb, BY2PG, 0); cp->ntb = Ntb; /* * Do the little configuration dance. We only look * at the first board that responds, if we ever have more * than one we'll need to modify this sequence. * * 2. Write two 0 bytes then the ID sequence to the IDport. */ outb(IDport, 0); outb(IDport, 0); outb(IDport, 0xc0); delay(100) outb(IDport, 0); outb(IDport, 0); for(al = 0xFF, i = 0; i < 255; i++){ outb(IDport, al); if(al & 0x80){ al <<= 1; al ^= 0xCF; } else al <<= 1; } /* * 3. Read the Product ID from the EEPROM. * This is done by writing the IDPort with 0x83 (0x80 * is the 'read EEPROM command, 0x03 is the offset of * the Product ID field in the EEPROM). * The data comes back 1 bit at a time. * We seem to need a delay here between reading the bits. * * If the ID doesn't match the 3C509 ID code, the adapter * probably isn't there, so barf. */ outb(IDport, 0x83); for(acr = 0, i = 0; i < 16; i++){ delay(5); acr <<= 1; acr |= inb(IDport) & 0x01; } if((acr & 0xF0FF) != 0x9050) return -1; /* * 3. Read the Address Configuration from the EEPROM. * The Address Configuration field is at offset 0x08 in the EEPROM). * 6. Activate the adapter by writing the Activate command * (0xFF). */ outb(IDport, 0x88); for(acr = 0, i = 0; i < 16; i++){ delay(20); acr <<= 1; acr |= inb(IDport) & 0x01; } outb(IDport, 0xFF); /* * 8. Now we can talk to the adapter's I/O base addresses. * We get the I/O base address from the acr just read. * * Enable the adapter. */ hw->addr = (acr & 0x1F)*0x10 + 0x200; outb(hw->addr+ConfigControl, 0x01); /* * Read the IRQ from the Resource Configuration Register * and the ethernet address from the EEPROM. * The EEPROM command is 8bits, the lower 6 bits being * the address offset. */ hw->irq = (ins(hw->addr+ResourceConfig)>>12) & 0x0F; for(ea = 0, i = 0; i < 3; i++, ea += 2){ while(ins(hw->addr+EEPROMcmd) & 0x8000) ; outs(hw->addr+EEPROMcmd, (2<<6)|i); while(ins(hw->addr+EEPROMcmd) & 0x8000) ; acr = ins(hw->addr+EEPROMdata); cp->ea[ea] = (acr>>8) & 0xFF; cp->ea[ea+1] = acr & 0xFF; } /* * Finished with window 0. Now set the ethernet address * in window 2. * Commands have the format 'CCCCCAAAAAAAAAAA' where C * is a bit in the command and A is a bit in the argument. */ COMMAND(hw, SelectWindow, 2); for(i = 0; i < 6; i++) outb(hw->addr+i, cp->ea[i]); /* * Finished with window 2. * Set window 1 for normal operation. */ COMMAND(hw, SelectWindow, 1); /* * If we have a 10BASE2 transceiver, start the DC-DC * converter. Wait > 800 microseconds. */ if(((acr>>14) & 0x03) == 0x03){ COMMAND(hw, StartCoax, 0); delay(1); } print("3C509 I/O addr %lux irq %d:", hw->addr, hw->irq); for(i = 0; i < sizeof(cp->ea); i++) print(" %2.2ux", cp->ea[i]); print("\n"); return 0; } static void mode(EtherCtlr *cp, int on) { EtherHw *hw = cp->hw; qlock(cp); if(on){ cp->prom++; if(cp->prom == 1) COMMAND(hw, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr); } else{ cp->prom--; if(cp->prom == 0) COMMAND(hw, SetRxFilter, Broadcast|MyEtherAddr); } qunlock(cp); } static void online(EtherCtlr *cp, int on) { EtherHw *hw = cp->hw; USED(on); /* BUG */ /* * Set the receiver packet filter for our own and * and broadcast addresses, set the interrupt masks * for all interrupts, and enable the receiver and transmitter. * The only interrupt we should see under normal conditions * is the receiver interrupt. If the transmit FIFO fills up, * we will also see TxAvailable interrupts. */ COMMAND(hw, SetRxFilter, Broadcast|MyEtherAddr); COMMAND(hw, SetReadZeroMask, AllIntr|Latch); COMMAND(hw, SetIntrMask, AllIntr|Latch); COMMAND(hw, RxEnable, 0); COMMAND(hw, TxEnable, 0); } static int getdiag(EtherHw *hw) { int bytes; COMMAND(hw, SelectWindow, 4); bytes = ins(hw->addr+0x04); COMMAND(hw, SelectWindow, 1); return bytes & 0xFFFF; } static void receive(EtherCtlr *cp) { EtherHw *hw = cp->hw; ushort status; EtherBuf *rb; int len; while(((status = ins(hw->addr+RxStatus)) & RxEmpty) == 0){ /* * If we had an error, log it and continue * without updating the ring. */ if(status & RxError){ print("error #%ux, #%ux\n", status, getdiag(hw)); switch(status & RxErrMask){ case RxErrOverrun: /* Overrrun */ cp->overflows++; break; case RxErrOversize: /* Oversize Packet (>1514) */ case RxErrRunt: /* Runt Packet */ cp->buffs++; break; case RxErrFraming: /* Alignment (Framing) */ cp->frames++; break; case RxErrCRC: /* CRC */ cp->crcs++; break; } } else { /* * We have a packet. Read it into the next * free ring buffer, if any. * The CRC is already stripped off. */ rb = &cp->rb[cp->ri]; if(rb->owner == Interface){ len = (status & RxByteMask); rb->len = len; /* * Must read len bytes padded to a * doubleword. We can pick them out 16-bits * at a time (can try 32-bits at a time * later). insl(hw->addr+Fifo, rb->pkt, HOWMANY(len, 4)); */ inss(hw->addr+Fifo, rb->pkt, HOWMANY(len, 2)); /* * Update the ring. */ rb->owner = Host; cp->ri = NEXT(cp->ri, cp->nrb); } } /* * Discard the packet as we're done with it. * Wait for discard to complete. */ COMMAND(hw, RxDiscard, 0); while(ins(hw->addr+Status) & CmdInProgress) ; } } static void transmit(EtherCtlr *cp) { EtherHw *hw = cp->hw; EtherBuf *tb; int s; ushort len; s = splhi(); for(tb = &cp->tb[cp->ti]; tb->owner == Interface; tb = &cp->tb[cp->ti]){ /* * If there's no room in the FIFO for this packet, * set up an interrupt for when space becomes available. */ if(tb->len > ins(hw->addr+TxFreeBytes)){ COMMAND(hw, SetTxAvailable, tb->len); break; } /* * There's room, copy the packet to the FIFO and free * the buffer back to the host. * Output packet muat be a multiple of 4 in length. */ len = ROUNDUP(tb->len, 4)/2; outs(hw->addr+Fifo, tb->len); outs(hw->addr+Fifo, 0); outss(hw->addr+Fifo, tb->pkt, len); tb->owner = Host; cp->ti = NEXT(cp->ti, cp->ntb); } splx(s); } static void interrupt(EtherCtlr *cp) { EtherHw *hw = cp->hw; ushort status; status = ins(hw->addr+Status); if(status & RxComplete){ (*cp->hw->receive)(cp); wakeup(&cp->rr); status &= ~RxComplete; } if(status & TxComplete){ /* * Needs work here. */ print("txstat %ux\n", inb(hw->addr+TxStatus)); } if(status & TxAvailable){ (*cp->hw->transmit)(cp); wakeup(&cp->tr); status &= ~TxAvailable; } /* * Panic if there are any interrupt bits on we haven't * dealt with other than Latch. */ if(status & AllIntr) panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(hw)); /* * Acknowledge the interrupt. */ COMMAND(hw, AckIntr, Latch); } EtherHw ether509 = { reset, 0, /* init */ mode, online, receive, transmit, interrupt, 0, /* tweak */ 0, /* I/O base address */ }; . ## diffname pc/ether509.c 1992/0923 ## diff -e /n/bootesdump/1992/0922/sys/src/9/pc/ether509.c /n/bootesdump/1992/0923/sys/src/9/pc/ether509.c 175,177c x = ins(hw->addr+EEPROMdata); cp->ea[ea] = (x>>8) & 0xFF; cp->ea[ea+1] = x & 0xFF; . 136c if((x & 0xF0FF) != 0x9050) . 133,134c x <<= 1; x |= inb(IDport) & 0x01; . 131c for(x = 0, i = 0; i < 16; i++){ . 103,117c idseq(); outb(IDport, 0xC1); delay(2); idseq(); . 101c * 2. get to cammand state, reset, then return to command state . 88,89c ushort x, acr; . 80a * Write two 0 bytes to idnetify the IDport and them reset the * ID sequence. Then send the ID sequenced to the card to get * the card it into command state. */ void idseq(void) { int i; uchar al; outb(IDport, 0); outb(IDport, 0); for(al = 0xFF, i = 0; i < 255; i++){ outb(IDport, al); if(al & 0x80){ al <<= 1; al ^= 0xCF; } else al <<= 1; } } /* . ## diffname pc/ether509.c 1992/0924 ## diff -e /n/bootesdump/1992/0923/sys/src/9/pc/ether509.c /n/bootesdump/1992/0924/sys/src/9/pc/ether509.c 408c status &= ~(TxAvailable|TxComplete); . 405c if(status & (TxAvailable|TxComplete)){ . 402c txstatus = 0; while(ins(hw->addr+Status) & TxComplete){ txstatus |= inb(hw->addr+TxStatus); outb(hw->addr+TxStatus, 0); } if(txstatus & (TxJabber|TxUnderrun)) COMMAND(hw, TxReset, 0); COMMAND(hw, TxEnable, 0); . 400c * Pop the TX Status stack, accumulating errors. * If there was a Jabber or Underrun error, reset * the transmitter. For all conditions enable * the transmitter. . 388a uchar txstatus; . 64a /* TxStatus Bits */ TxJabber = 0x20, /* Jabber Error */ TxUnderrun = 0x10, /* Underrun */ TxMaxColl = 0x08, /* Maximum Collisions */ . 30a TxReset = 0x0B, /* TX Reset */ . ## diffname pc/ether509.c 1992/0925 ## diff -e /n/bootesdump/1992/0924/sys/src/9/pc/ether509.c /n/bootesdump/1992/0925/sys/src/9/pc/ether509.c 419a cp->oerrs++; . ## diffname pc/ether509.c 1992/0926 ## diff -e /n/bootesdump/1992/0925/sys/src/9/pc/ether509.c /n/bootesdump/1992/0926/sys/src/9/pc/ether509.c 378c * Output packet must be a multiple of 4 in length. . ## diffname pc/ether509.c 1992/1015 ## diff -e /n/bootesdump/1992/0926/sys/src/9/pc/ether509.c /n/bootesdump/1992/1015/sys/src/9/pc/ether509.c 414,415c x = inb(hw->addr+TxStatus); if(x) outb(hw->addr+TxStatus, 0); txstatus |= x; . 395c uchar txstatus, x; . 298d ## diffname pc/ether509.c 1992/1016 ## diff -e /n/bootesdump/1992/1015/sys/src/9/pc/ether509.c /n/bootesdump/1992/1016/sys/src/9/pc/ether509.c 424a /* * Reset the Tx FIFO threshold. */ if(status & TxAvailable) COMMAND(hw, AckIntr, TxAvailable); . 417c }while(ins(hw->addr+Status) & TxComplete); . 412,414c do{ if(x = inb(hw->addr+TxStatus)) . ## diffname pc/ether509.c 1992/1102 ## diff -e /n/bootesdump/1992/1016/sys/src/9/pc/ether509.c /n/bootesdump/1992/1102/sys/src/9/pc/ether509.c 87c * Write two 0 bytes to identify the IDport and them reset the . ## diffname pc/ether509.c 1992/1222 ## diff -e /n/bootesdump/1992/1102/sys/src/9/pc/ether509.c /n/bootesdump/1992/1222/sys/src/9/pc/ether509.c 455,456c 0, /* watch */ . 451,452c 0, /* receive */ . 449c 0, /* init */ attach, . 447c Board ether509 = { . 441,444c COMMAND(board, AckIntr, Latch); . 439c panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(board)); . 436a * Otherwise, acknowledge the interrupt. . 428,430c COMMAND(board, AckIntr, TxAvailable); transmit(ctlr); wakeup(&ctlr->tr); . 418,420c COMMAND(board, TxReset, 0); COMMAND(board, TxEnable, 0); ctlr->oerrs++; . 416c }while(ins(board->io+Status) & TxComplete); . 413,414c if(x = inb(board->io+TxStatus)) outb(board->io+TxStatus, 0); . 399,400c receive(ctlr); wakeup(&ctlr->rr); . 396c status = ins(board->io+Status); . 392c Board *board = ctlr->board; . 390c interrupt(Ctlr *ctlr) . 384c ctlr->ti = NEXT(ctlr->ti, ctlr->ntb); . 380,382c outs(board->io+Fifo, tb->len); outs(board->io+Fifo, 0); outss(board->io+Fifo, tb->pkt, len); . 369,370c if(tb->len > ins(board->io+TxFreeBytes)){ COMMAND(board, SetTxAvailable, tb->len); . 363,364c for(tb = &ctlr->tb[ctlr->ti]; tb->owner == Interface; tb = &ctlr->tb[ctlr->ti]){ . 357,358c Board *board = ctlr->board; RingBuf *tb; . 355c transmit(Ctlr *ctlr) . 348,349c COMMAND(board, RxDiscard, 0); while(ins(board->io+Status) & CmdInProgress) . 343a . 341c ctlr->ri = NEXT(ctlr->ri, ctlr->nrb); . 335c inss(board->io+Fifo, rb->pkt, HOWMANY(len, 2)); . 333c insl(board->io+Fifo, rb->pkt, HOWMANY(len, 4)); . 323c rb = &ctlr->rb[ctlr->ri]; . 313c ctlr->crcs++; . 309c ctlr->frames++; . 306c ctlr->buffs++; . 301c ctlr->overflows++; . 291,292c while(((status = ins(board->io+RxStatus)) & RxEmpty) == 0){ . 288c RingBuf *rb; . 286c Board *board = ctlr->board; . 284c receive(Ctlr *ctlr) . 277,279c COMMAND(board, SelectWindow, 4); bytes = ins(board->io+0x04); COMMAND(board, SelectWindow, 1); . 273c getdiag(Board *board) . 271a if(on) COMMAND(board, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr); else COMMAND(board, SetRxFilter, Broadcast|MyEtherAddr); } . 270a static void mode(Ctlr *ctlr, int on) { Board *board = ctlr->board; . 264,268c COMMAND(board, SetRxFilter, Broadcast|MyEtherAddr); COMMAND(board, SetReadZeroMask, AllIntr|Latch); COMMAND(board, SetIntrMask, AllIntr|Latch); COMMAND(board, RxEnable, 0); COMMAND(board, TxEnable, 0); . 236,255d 234c Board *board = ctlr->board; . 232c attach(Ctlr *ctlr) . 223,225c print("3C509 I/O addr %lux irq %d:", board->io, board->irq); for(i = 0; i < sizeof(ctlr->ea); i++) print(" %2.2ux", ctlr->ea[i]); . 219c COMMAND(board, StartCoax, 0); . 212c COMMAND(board, SelectWindow, 1); . 206c outb(board->io+i, ctlr->ea[i]); . 204c COMMAND(board, SelectWindow, 2); . 193,195c x = ins(board->io+EEPROMdata); ctlr->ea[ea] = (x>>8) & 0xFF; ctlr->ea[ea+1] = x & 0xFF; . 190,191c outs(board->io+EEPROMcmd, (2<<6)|i); while(ins(board->io+EEPROMcmd) & 0x8000) . 188c while(ins(board->io+EEPROMcmd) & 0x8000) . 186c board->irq = (ins(board->io+ResourceConfig)>>12) & 0x0F; . 177,178c board->io = (acr & 0x1F)*0x10 + 0x200; outb(board->io+ConfigControl, 0x01); . 130c * 2. get to command state, reset, then return to command state . 120,124d 116c Board *board = ctlr->board; . 114c reset(Ctlr *ctlr) . 111c * Get configuration parameters. . 91c static void . 87,89c * Write two 0 bytes to identify the IDport and then reset the * ID sequence. Then send the ID sequence to the card to get * the card into command state. . 84c #define COMMAND(board, cmd, a) outs(board->io+Command, ((cmd)<<11)|(a)) . 16,20d 10,13c #include "ether.h" . ## diffname pc/ether509.c 1993/0123 ## diff -e /n/bootesdump/1992/1222/sys/src/9/pc/ether509.c /n/bootesdump/1993/0123/sys/src/9/pc/ether509.c 372a if(status & Failure){ /* * Adapter failure, try to find out why. * Reset if necessary. * What happens if Tx is active and we reset, * need to retransmit? * This probably isn't right. */ diag = getdiag(board); print("ether509: status #%ux, diag #%ux\n", status, diag); if(diag & TxOverrun){ COMMAND(board, TxReset, 0); COMMAND(board, TxEnable, 0); } if(diag & RxUnderrun){ COMMAND(board, RxReset, 0); attach(ctlr); } if(diag & TxOverrun) transmit(ctlr); return; } . 369c ushort status, diag; . 358c outss(board->io+Fifo, tb->pkt, len/2); . 355d 353d 345,346c len = ROUNDUP(tb->len, 4); if(len > ins(board->io+TxFreeBytes)+4){ COMMAND(board, SetTxAvailable, len); . 343a * Output packet must be a multiple of 4 in length and * we need 4 bytes for the preamble. . 255c bytes = ins(board->io+FIFOdiag); . 73a FIFOdiag = 0x04, /* window 4 */ /* FIFOdiag bits */ TxOverrun = 0x0400, /* TX Overrrun */ RxOverrun = 0x0800, /* RX Overrun */ RxStatusOverrun = 0x1000, /* RX Status Overrun */ RxUnderrun = 0x2000, /* RX Underrun */ RxReceiving = 0x8000, /* RX Receiving */ . 51a Failure = 0x0002, /* Adapter Failure */ . 19a RxReset = 0x05, /* RX Reset */ . ## diffname pc/ether509.c 1993/0212 ## diff -e /n/bootesdump/1993/0123/sys/src/9/pc/ether509.c /n/bootesdump/1993/0212/sys/src/9/pc/ether509.c 461,469c Card ether509 = { "3Com509", /* ident */ reset, /* reset */ 0, /* init */ attach, /* attach */ mode, /* mode */ 0, /* read */ 0, /* write */ 0, /* receive */ transmit, /* transmit */ interrupt, /* interrupt */ 0, /* watch */ 0, /* overflow */ . 458c COMMAND(ctlr, AckIntr, Latch); . 456c panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(ctlr)); . 444c COMMAND(ctlr, AckIntr, TxAvailable); . 434,435c COMMAND(ctlr, TxReset, 0); COMMAND(ctlr, TxEnable, 0); . 431c }while(ins(ctlr->card.io+Status) & TxComplete); . 428,429c if(x = inb(ctlr->card.io+TxStatus)) outb(ctlr->card.io+TxStatus, 0); . 403c COMMAND(ctlr, RxReset, 0); . 398,399c COMMAND(ctlr, TxReset, 0); COMMAND(ctlr, TxEnable, 0); . 394c diag = getdiag(ctlr); . 384c status = ins(ctlr->card.io+Status); . 380d 376a static ushort getdiag(Ctlr *ctlr) { ushort bytes; COMMAND(ctlr, SelectWindow, 4); bytes = ins(ctlr->card.io+FIFOdiag); COMMAND(ctlr, SelectWindow, 1); return bytes & 0xFFFF; } . 374d 368,370c outs(ctlr->card.io+Fifo, tb->len); outs(ctlr->card.io+Fifo, 0); outss(ctlr->card.io+Fifo, tb->pkt, len/2); . 359,360c if(len > ins(ctlr->card.io+TxFreeBytes)+4){ COMMAND(ctlr, SetTxAvailable, len); . 350d 347d 345d 336,337c COMMAND(ctlr, RxDiscard, 0); while(ins(ctlr->card.io+Status) & CmdInProgress) . 322c inss(ctlr->card.io+Fifo, rb->pkt, HOWMANY(len, 2)); . 320c insl(ctlr->card.io+Fifo, rb->pkt, HOWMANY(len, 4)); . 279c while(((status = ins(ctlr->card.io+RxStatus)) & RxEmpty) == 0){ . 274d 260,270d 257c COMMAND(ctlr, SetRxFilter, Broadcast|MyEtherAddr); . 255c COMMAND(ctlr, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr); . 252,253d 242,246c COMMAND(ctlr, SetRxFilter, Broadcast|MyEtherAddr); COMMAND(ctlr, SetReadZeroMask, AllIntr|Latch); COMMAND(ctlr, SetIntrMask, AllIntr|Latch); COMMAND(ctlr, RxEnable, 0); COMMAND(ctlr, TxEnable, 0); . 232,233d 221,225d 217c COMMAND(ctlr, StartCoax, 0); . 210c COMMAND(ctlr, SelectWindow, 1); . 204c outb(ctlr->card.io+i, ctlr->ea[i]); . 202c COMMAND(ctlr, SelectWindow, 2); . 191c x = ins(ctlr->card.io+EEPROMdata); . 188,189c outs(ctlr->card.io+EEPROMcmd, (2<<6)|i); while(ins(ctlr->card.io+EEPROMcmd) & 0x8000) . 186c while(ins(ctlr->card.io+EEPROMcmd) & 0x8000) . 184c ctlr->card.irq = (ins(ctlr->card.io+ResourceConfig)>>12) & 0x0F; . 175,176c ctlr->card.io = (acr & 0x1F)*0x10 + 0x200; outb(ctlr->card.io+ConfigControl, 0x01); . 125c * at the first card that responds, if we ever have more . 119d 87c #define COMMAND(ctlr, cmd, a) outs(ctlr->card.io+Command, ((cmd)<<11)|(a)) . ## diffname pc/ether509.c 1993/0427 ## diff -e /n/bootesdump/1993/0212/sys/src/9/pc/ether509.c /n/bootesdump/1993/0427/sys/src/9/pc/ether509.c 334c if(len+4 > ins(ctlr->card.io+TxFreeBytes)){ . ## diffname pc/ether509.c 1993/0915 ## diff -e /n/bootesdump/1993/0427/sys/src/9/pc/ether509.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/ether509.c 456,461c /* * Do the little configuration dance. We only look * at the first card that responds, if we ever have more * than one we'll need to modify this sequence. * * 2. get to command state, reset, then return to command state */ idseq(); outb(IDport, 0xC1); delay(2); idseq(); /* * 3. Read the Product ID from the EEPROM. * This is done by writing the IDPort with 0x83 (0x80 * is the 'read EEPROM command, 0x03 is the offset of * the Product ID field in the EEPROM). * The data comes back 1 bit at a time. * We seem to need a delay here between reading the bits. * * If the ID doesn't match the 3C509 ID code, the adapter * probably isn't there, so barf. */ outb(IDport, 0x83); for(x = 0, i = 0; i < 16; i++){ delay(5); x <<= 1; x |= inb(IDport) & 0x01; } if((x & 0xF0FF) != 0x9050) return -1; /* * 3. Read the Address Configuration from the EEPROM. * The Address Configuration field is at offset 0x08 in the EEPROM). * 6. Activate the adapter by writing the Activate command * (0xFF). */ outb(IDport, 0x88); for(acr = 0, i = 0; i < 16; i++){ delay(20); acr <<= 1; acr |= inb(IDport) & 0x01; } outb(IDport, 0xFF); /* * 8. Now we can talk to the adapter's I/O base addresses. * We get the I/O base address from the acr just read. * * Enable the adapter. */ ctlr->card.port = (acr & 0x1F)*0x10 + 0x200; port = ctlr->card.port; outb(port+ConfigControl, 0x01); /* * Read the IRQ from the Resource Configuration Register * and the ethernet address from the EEPROM. * The EEPROM command is 8bits, the lower 6 bits being * the address offset. */ ctlr->card.irq = (ins(port+ResourceConfig)>>12) & 0x0F; for(ea = 0, i = 0; i < 3; i++, ea += 2){ while(ins(port+EEPROMcmd) & 0x8000) ; outs(port+EEPROMcmd, (2<<6)|i); while(ins(port+EEPROMcmd) & 0x8000) ; x = ins(port+EEPROMdata); ctlr->ea[ea] = (x>>8) & 0xFF; ctlr->ea[ea+1] = x & 0xFF; } /* * Finished with window 0. Now set the ethernet address * in window 2. * Commands have the format 'CCCCCAAAAAAAAAAA' where C * is a bit in the command and A is a bit in the argument. */ COMMAND(port, SelectWindow, 2); for(i = 0; i < 6; i++) outb(port+i, ctlr->ea[i]); /* * Finished with window 2. * Set window 1 for normal operation. */ COMMAND(port, SelectWindow, 1); /* * If we have a 10BASE2 transceiver, start the DC-DC * converter. Wait > 800 microseconds. */ if(((acr>>14) & 0x03) == 0x03){ COMMAND(port, StartCoax, 0); delay(1); } /* * Set up the software configuration. */ ctlr->card.reset = ccc509reset; ctlr->card.attach = attach; ctlr->card.mode = mode; ctlr->card.transmit = transmit; ctlr->card.intr = interrupt; ctlr->card.bit16 = 1; return 0; } void ether509link(void) { addethercard("3C509", ccc509reset); } . 453,454c /* * Get configuration parameters. */ int ccc509reset(Ctlr *ctlr) { int i, ea; ushort x, acr; ulong port; . 448,451c outb(IDport, 0); outb(IDport, 0); for(al = 0xFF, i = 0; i < 255; i++){ outb(IDport, al); if(al & 0x80){ al <<= 1; al ^= 0xCF; } else al <<= 1; } } . 445,446c /* * Write two 0 bytes to identify the IDport and then reset the * ID sequence. Then send the ID sequence to the card to get * the card into command state. */ static void idseq(void) { int i; uchar al; . 442c COMMAND(port, AckIntr, Latch); . 428c COMMAND(port, AckIntr, TxAvailable); . 418,419c COMMAND(port, TxReset, 0); COMMAND(port, TxEnable, 0); . 415c }while(ins(port+Status) & TxComplete); . 412,413c if(x = inb(port+TxStatus)) outb(port+TxStatus, 0); . 387c COMMAND(port, RxReset, 0); . 382,383c COMMAND(port, TxReset, 0); COMMAND(port, TxEnable, 0); . 368c port = ctlr->card.port; status = ins(port+Status); . 366a ulong port; . 356,358c port = ctlr->card.port; COMMAND(port, SelectWindow, 4); bytes = ins(port+FIFOdiag); COMMAND(port, SelectWindow, 1); . 354a ulong port; . 343,345c outs(port+Fifo, tb->len); outs(port+Fifo, 0); outss(port+Fifo, tb->pkt, len/2); . 334,335c if(len+4 > ins(port+TxFreeBytes)){ COMMAND(port, SetTxAvailable, len); . 325a port = ctlr->card.port; . 324a ulong port; . 314,315c COMMAND(port, RxDiscard, 0); while(ins(port+Status) & CmdInProgress) . 300c inss(port+Fifo, rb->pkt, HOWMANY(len, 2)); . 298c insl(port+Fifo, rb->pkt, HOWMANY(len, 4)); . 257c port = ctlr->card.port; while(((status = ins(port+RxStatus)) & RxEmpty) == 0){ . 255a ulong port; . 247c COMMAND(port, SetRxFilter, Broadcast|MyEtherAddr); . 245c COMMAND(port, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr); . 243a ulong port; port = ctlr->card.port; . 234,238c COMMAND(port, SetRxFilter, Broadcast|MyEtherAddr); COMMAND(port, SetReadZeroMask, AllIntr|Latch); COMMAND(port, SetIntrMask, AllIntr|Latch); COMMAND(port, RxEnable, 0); COMMAND(port, TxEnable, 0); . 123,226d 100,121c port = ctlr->card.port; . 97,98c ulong port; . 95c attach(Ctlr *ctlr) . 89,93d 87c #define COMMAND(port, cmd, a) outs(port+Command, ((cmd)<<11)|(a)) . ## diffname pc/ether509.c 1993/1113 ## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/ether509.c /n/fornaxdump/1993/1113/sys/src/brazil/pc/ether509.c 474c addethercard("3C509", reset); . 467a ether->promiscuous = promiscuous; ether->arg = ether; . 461,466c ether->attach = attach; ether->write = write; ether->interrupt = interrupt; . 441c outb(port+i, ether->ea[i]); . 429,430c ether->ea[ea] = (x>>8) & 0xFF; ether->ea[ea+1] = x & 0xFF; . 421c ether->irq = (ins(port+ResourceConfig)>>12) & 0x0F; . 411,412c ether->port = (acr & 0x1F)*0x10 + 0x200; port = ether->port; . 360,362c * Do the little configuration dance: . 352,353c static int reset(Ether *ether) . 320c panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(ether)); . 309,310c wakeup(ðer->tr); } . 307c if(status & TxAvailable){ . 300c ether->oerrs++; . 278,279c receive(ether); . 271,273d 268c attach(ether); . 263a wakeup(ðer->tr); . 258c diag = getdiag(ether); . 249a print("I%2.2ux|", status); . 247c port = ether->port; . 241c interrupt(Ether *ether) . 233c port = ether->port; . 228c getdiag(Ether *ether) . 224a /* * We know there's room, copy the packet to the FIFO. * To save copying the packet into a local buffer just * so we can set the source address, stuff the packet * into the FIFO in 3 pieces. * Transmission won't start until the entire packet is * in the FIFO, so it's OK to fault here. */ outs(port+Fifo, ether->tlen); outs(port+Fifo, 0); outss(port+Fifo, buf, Eaddrlen/2); outss(port+Fifo, ether->ea, Eaddrlen/2); outss(port+Fifo, (uchar*)buf+2*Eaddrlen, (len-2*Eaddrlen)/2); return n; . 215,223c static long write(Ether *ether, void *buf, long n) { ushort len; ulong port; print("W|"); port = ether->port; ether->tlen = n; len = ROUNDUP(ether->tlen, 4); tsleep(ðer->tr, istxfifo, ether, 10000); if(len+4 > ins(port+TxFreeBytes)){ print("ether509: transmitter jammed\n"); return 0; . 201,213c ether = arg; port = ether->port; /* * If there's no room in the FIFO for this packet, * set up an interrupt for when space becomes available. * Output packet must be a multiple of 4 in length and * we need 4 bytes for the preamble. * Assume here that when we are called (via tsleep) that * we are safe from interrupts. */ len = ROUNDUP(ether->tlen, 4); if(len+4 > ins(port+TxFreeBytes)){ COMMAND(port, SetTxAvailable, len); return 0; } return 1; } . 197c Ether *ether; . 194,195c static int istxfifo(void *arg) . 176,180c /* * Copy the packet to whoever wants it. */ type = (ether->rpkt.type[0]<<8)|ether->rpkt.type[1]; ep = ðer->f[Ntypes]; for(fp = ether->f; fp < ep; fp++) { f = *fp; if(f && (f->type == type || f->type < 0)) qproduce(f->in, ðer->rpkt, len); . 162,174c len = (status & RxByteMask); inss(port+Fifo, ðer->rpkt, HOWMANY(len, 2)); . 158,160c * We have a packet. Read it into the * buffer. The CRC is already stripped off. * Must read len bytes padded to a * doubleword. We can pick them out 16-bits * at a time (can try 32-bits at a time * later). insl(port+Fifo, ether->rpkt, HOWMANY(len, 4)); . 152c ether->crcs++; . 148c ether->frames++; . 145c ether->buffs++; . 140c ether->overflows++; . 130c port = ether->port; . 128a Netfile *f, **fp, **ep; . 125,126c ushort status, type; . 123c receive(Ether *ether) . 115c port = ((Ether*)arg)->port; . 111c promiscuous(void *arg, int on) . 94c port = ether->port; . 90c attach(Ether *ether) . 10c #include "etherif.h" . 8c #include "../port/error.h" #include "../port/netif.h" . 6d ## diffname pc/ether509.c 1993/1116 ## diff -e /n/fornaxdump/1993/1113/sys/src/brazil/pc/ether509.c /n/fornaxdump/1993/1116/sys/src/brazil/pc/ether509.c 270d 222d ## diffname pc/ether509.c 1993/1118 ## diff -e /n/fornaxdump/1993/1116/sys/src/brazil/pc/ether509.c /n/fornaxdump/1993/1118/sys/src/brazil/pc/ether509.c 242a poperror(); qunlock(ðer->tlock); . 228,229c . 226c if(len+4 > ins(port+TxFreeBytes)) . 222a qlock(ðer->tlock); if(waserror()) { qunlock(ðer->tlock); nexterror(); } . ## diffname pc/ether509.c 1993/1119 ## diff -e /n/fornaxdump/1993/1118/sys/src/brazil/pc/ether509.c /n/fornaxdump/1993/1119/sys/src/brazil/pc/ether509.c 249,251d 234a return 0; } . 233c if(len+4 > ins(port+TxFreeBytes)){ . 224,229d ## diffname pc/ether509.c 1993/1124 ## diff -e /n/fornaxdump/1993/1119/sys/src/brazil/pc/ether509.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/ether509.c 269a . 268a USED(ur); ether = arg; . 267a Ether *ether; . 263c interrupt(Ureg *ur, void *arg) . ## diffname pc/ether509.c 1994/0202 ## diff -e /n/fornaxdump/1993/1124/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0202/sys/src/brazil/pc/ether509.c 172,178c etherrloop(ether, ðer->rpkt, len); . 128d 125c ushort status; . ## diffname pc/ether509.c 1994/0205 ## diff -e /n/fornaxdump/1994/0202/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0205/sys/src/brazil/pc/ether509.c 468c if((acr & XcvrTypeMask) == XcvrBNC){ . 455c for(i = 0; i < Eaddrlen; i++) . 453a if((ether->ea[0]|ether->ea[1]|ether->ea[2]|ether->ea[3]|ether->ea[4]|ether->ea[5]) == 0){ for(i = 0; i < sizeof(ether->ea); i++) ether->ea[i] = ea[i]; } . 446a acr = ins(port+AddressConfig); . 444,445c ea[eax] = (x>>8) & 0xFF; ea[eax+1] = x & 0xFF; . 437c for(eax = 0, i = 0; i < 3; i++, eax += 2){ . 431,432c * Read the IRQ from the Resource Configuration Register, * the ethernet address from the EEPROM, and the address configuration. . 428d 426a outb(ether->port+ConfigControl, 0x01); return 0; } /* * Get configuration parameters. */ static int reset(Ether *ether) { int i, eax; uchar ea[Eaddrlen]; ushort x, acr; ulong port; /* * Switch out to 509 activation code if a port is supplied and is * not in the EISA slot space, otherwise check the EISA card is there. */ if(ether->port < 0x1000 && activate(ether) < 0) return -1; else if((ins(ether->port+ProductID) & 0xF0FF) != 0x9050) return -1; . 374d 372c int i; . 366,370c static ulong activate(Ether *ether) . 237c outsl(port+Fifo, (uchar*)buf+2*Eaddrlen, (len-2*Eaddrlen)/4); ether->outpackets++; . 166c insl(port+Fifo, ðer->rpkt, HOWMANY(len, 4)); . 164a ether->inpackets++; . 160,163c * doubleword. We can pick them out 32-bits * at a time. . 132,133c * If we had an error, log it and continue. . 45a /* AddressConfig Bits */ XcvrTypeMask = 0xC000, /* Transceiver Type Select */ Xcvr10BaseT = 0x0000, XcvrAUI = 0x4000, XcvrBNC = 0xC000, . 44a ProductID = 0x02, ManufacturerID = 0x00, . 43a AddressConfig = 0x06, . ## diffname pc/ether509.c 1994/0209 ## diff -e /n/fornaxdump/1994/0205/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0209/sys/src/brazil/pc/ether509.c 475a port = ether->port; . 456,457d 453,454d 451c if(ether->port < 0x1000){ if((port = activate(ether)) < 0) return -1; } else if(ins(ether->port+ManufacturerID) == 0x6D50) port = ether->port+0xC80; else . 449a * Port is set to either the newly activated ISA card address or * the EISA slot configuration info where Window0 is always mapped. . 433c return ether->port; . 407c if((x & 0xF0FF) != 0x6D50) . 401c outb(IDport, 0x87); . 391,394c * 3. Read the Manufacturer ID from the EEPROM. * This is done by writing the IDPort with 0x87 (0x80 * is the 'read EEPROM command, 0x07 is the offset of * the Manufacturer ID field in the EEPROM). . 56a Timer = 0x0A, . ## diffname pc/ether509.c 1994/0211 ## diff -e /n/fornaxdump/1994/0209/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0211/sys/src/brazil/pc/ether509.c 511a ether->port = port; . 482,483d 458,460c if(port == 0) port = tcm579(ether); if(port == 0) port = tcm509(ether); if(port == 0) . 454,456c port = 0; for(app = &adapter, ap = *app; ap; app = &ap->next, ap = ap->next){ if(ether->port == 0 || ether->port == ap->port){ port = ap->port; *app = ap->next; free(ap); break; } . 449,452c * Any adapter matches if no ether->port is supplied, * otherwise the ports must match. * See if we've already found an adapter that fits * the bill. * If no match then try for an EISA card and finally * for an ISA card. . 446a Adapter *ap, **app; . 436a static ulong tcm509(Ether *ether) { USED(ether); return 0; } static ulong tcm579(Ether *ether) { static int slot = 1; ulong port; Adapter *ap; if(slot == 1 && strncmp((char*)(KZERO|0xFFFD9), "EISA", 4)) return 0; while(slot < 8){ port = slot++*0x1000; if(ins(port+0xC80+ManufacturerID) != 0x6D50) continue; COMMAND(port+0xC80, GlobalReset, 0); delay(1000); outb(port+0xC80+ConfigControl, 0x01); COMMAND(port+0xC80, SelectWindow, 0); if(ether->port == 0 || ether->port == port) return port; ap = malloc(sizeof(Adapter)); ap->port = port; ap->next = adapter; adapter = ap; } return 0; } . 399c * If the ID doesn't match, the adapter . 350a typedef struct Adapter Adapter; struct Adapter { Adapter *next; ulong port; }; static Adapter *adapter; . 15a GlobalReset = 0x00, /* Global Reset */ . ## diffname pc/ether509.c 1994/0212 ## diff -e /n/fornaxdump/1994/0211/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0212/sys/src/brazil/pc/ether509.c 461c while(slot < 16){ . 442c return port; . 439,440c port = (acr & 0x1F)*0x10 + 0x200; outb(port+ConfigControl, 0x01); . 416,417c if(x != 0x6D50) return 0; . 402c * is the 'read EEPROM' command, 0x07 is the offset of . 395,397d 392c * 2. write the ID sequence to get to command state. . 387a ulong port; . 384c activate(void) . ## diffname pc/ether509.c 1994/0213 ## diff -e /n/fornaxdump/1994/0212/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0213/sys/src/brazil/pc/ether509.c 447a #ifdef notdef ulong port; Adapter *ap; while(port = activate()){ } return 0; #endif /* notdef */ . ## diffname pc/ether509.c 1994/0215 ## diff -e /n/fornaxdump/1994/0213/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0215/sys/src/brazil/pc/ether509.c 475c outs(port+0xC80+ConfigControl, Ena); . 457d 453a if(ether->port == 0 || ether->port == port) return port; ap = malloc(sizeof(Adapter)); ap->port = port; ap->next = adapter; adapter = ap; . 452a /* * One time only: * write ID sequence to get the attention of all adapters; * global-reset all adapters; * untag all adapters. */ if(reset == 0){ idseq(); outb(IDport, 0xC0); delay(2); outb(IDport, 0xD0); reset = 1; } /* * Attempt to activate adapters until one matches our * address criteria. */ . 446,449c static int reset; . 438c outs(port+ConfigControl, Ena); . 428a outb(IDport, 0xD1); . 419a * 6. Tag the adapter so it won't respond in future. . 405,406c * If the ID doesn't match, there are no more adapters. . 55a /* ConfigControl */ Rst = 0x04, /* Reset Adapter */ Ena = 0x01, /* Enable Adapter */ . 48c ConfigControl = 0x04, AddressConfig = 0x06, ResourceConfig = 0x08, EEPROMcmd = 0x0A, EEPROMdata = 0x0C, . 42,46c ManufacturerID = 0x00, /* window 0 */ . 13,14c IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */ . ## diffname pc/ether509.c 1994/0216 ## diff -e /n/fornaxdump/1994/0215/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0216/sys/src/brazil/pc/ether509.c 587a while(inb(port+TxStatus)) outb(port+TxStatus, 0); . 585a * Clear out any lingering Tx status. . 553c * The EEPROM command is 8 bits, the lower 6 bits being . 547a port = tcm589(ether); if(port == 0) . 531,532c * If no match then try for an EISA card, an ISA card * and finally for a PCMCIA card. . 513a static ulong tcm589(Ether *ether) { USED(ether); return 0; } . 498,501c x = ins(port+0xC80+ProductID); if((x & 0xF0FF) != 0x9050/* || (x != 0x9350 && x != 0x9250)*/) continue; COMMAND(port, SelectWindow, 0); outs(port+ConfigControl, Ena); COMMAND(port, TxReset, 0); COMMAND(port, RxReset, 0); COMMAND(port, AckIntr, 0xFF); . 493a /* * Continue through the EISA slots looking for a match on both * 3COM as the manufacturer and 3C579 or 3C579-TP as the product. * If we find an adapter, select window 0, enable it and clear * out any lingering status and interrupts. * Trying to do a GlobalReset here to re-init the card (as in the * 509 code) doesn't seem to work. */ . 491a /* * First time through, check if this is an EISA machine. * If not, nothing to do. */ . 488a ushort x; . 472c while(port = activate(0)){ if(port == 0x3F0){ outb(IDport, 0xD1); continue; } outb(IDport, 0xC0); if(activate(1) != port) print("activate %d\n"); . 470c * address criteria. If adapter is set for EISA mode, * tag it and ignore. Otherwise, reset the adapter and * activate it fully. . 465c untag = 1; . 462,463d 460c if(untag == 0){ . 458a * If we do a global reset here on all adapters we'll confuse any * ISA cards configured for EISA mode. . 457d 450c static int untag; . 443a if(tag){ /* * 6. Tag the adapter so it won't respond in future. * 6. Activate the adapter by writing the Activate command * (0xFF). */ outb(IDport, 0xD1); outb(IDport, 0xFF); /* * 8. Now we can talk to the adapter's I/O base addresses. * We get the I/O base address from the acr just read. * * Enable the adapter. */ outs(port+ConfigControl, Ena); } . 442d 432,440d 422,424d 387c activate(int tag) . ## diffname pc/ether509.c 1994/0218 ## diff -e /n/fornaxdump/1994/0216/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0218/sys/src/brazil/pc/ether509.c 485c print("tcm509: activate\n"); . 483a delay(2); . ## diffname pc/ether509.c 1994/0628 ## diff -e /n/fornaxdump/1994/0218/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0628/sys/src/brazil/pc/ether509.c 636,644d 629c * Enable the transceiver if necessary. */ switch(acr & XcvrTypeMask){ case Xcvr10BaseT: /* * Enable Link Beat and Jabber to start the * transceiver. */ COMMAND(port, SelectWindow, 4); outb(port+MediaStatus, LinkBeatEna|JabberEna); break; case XcvrBNC: /* * Start the DC-DC converter. * Wait > 800 microseconds. */ COMMAND(port, StartCoax, 0); delay(1); break; } /* . 98a /* MediaStatus bits */ JabberEna = 0x0040, /* Jabber Enabled (writeable) */ LinkBeatEna = 0x0080, /* Link Beat Enabled (writeable) */ . 91a MediaStatus = 0x0A, . ## diffname pc/ether509.c 1994/0715 ## diff -e /n/fornaxdump/1994/0628/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0715/sys/src/brazil/pc/ether509.c 188c etherrloop(ether, ðer->rpkt, len, 1); . ## diffname pc/ether509.c 1994/1124 ## diff -e /n/fornaxdump/1994/0715/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/1124/sys/src/brazil/pc/ether509.c 63c Timer = 0x0A, TxStatus = 0x0B, TxFreeBytes = 0x0C, . 59,61c Fifo = 0x00, /* window 1 */ . ## diffname pc/ether509.c 1994/1207 ## diff -e /n/fornaxdump/1994/1124/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/1207/sys/src/brazil/pc/ether509.c 35c Promiscuous = 0x08, /* All addresses (promiscuous mode) */ . ## diffname pc/ether509.c 1995/0331 ## diff -e /n/fornaxdump/1994/1207/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0331/sys/src/brazil/pc/ether509.c 683c addethercard("3C509", ether509reset); . 606c if(strcmp(ether->type, "3C589") != 0) ether->irq = (ins(port+ResourceConfig)>>12) & 0x0F; . 596,597d 590a if(strcmp(ether->type, "3C589") == 0) port = ether->port; . 565,566c int ether509reset(Ether *ether) . 555,561d 282d ## diffname pc/ether509.c 1995/0401 ## diff -e /n/fornaxdump/1995/0331/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0401/sys/src/brazil/pc/ether509.c 584c port = ether->card.port; . ## diffname pc/ether509.c 1995/0403 ## diff -e /n/fornaxdump/1995/0401/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0403/sys/src/brazil/pc/ether509.c 584c port = ether->port; . ## diffname pc/ether509.c 1995/0419 ## diff -e /n/fornaxdump/1995/0403/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0419/sys/src/brazil/pc/ether509.c 350c * dealt with other than Latch. Should deal with UP (Update * Statistics) for happier coexistence with Windows drivers. . ## diffname pc/ether509.c 1995/0504 ## diff -e /n/fornaxdump/1995/0419/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0504/sys/src/brazil/pc/ether509.c 70a Update = 0x0080, /* Update Statistics */ . ## diffname pc/ether509.c 1995/0506 ## diff -e /n/fornaxdump/1995/0504/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0506/sys/src/brazil/pc/ether509.c 346,358d 325,344c if(status & AllIntr) panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(ether)); . 320,323c * Panic if there are any interrupt bits on we haven't * dealt with. Should deal with UP (Update Statistics) * for happier coexistence with Windows drivers. . 309,318c . 304,307c if(status & (TxAvailable|TxComplete)){ /* * Reset the Tx FIFO threshold. */ if(status & TxAvailable){ COMMAND(port, AckIntr, TxAvailable); wakeup(ðer->tr); } status &= ~(TxAvailable|TxComplete); . 302c ether->oerrs++; . 296,300c COMMAND(port, AckIntr, Latch); status = ins(port+Status); if((status & AllIntr) == 0) break; if(status & Failure){ /* * Adapter failure, try to find out why. * Reset if necessary. * What happens if Tx is active and we reset, * need to retransmit? * This probably isn't right. */ diag = getdiag(ether); print("ether509: status #%ux, diag #%ux\n", status, diag); if(diag & TxOverrun){ COMMAND(port, TxReset, 0); COMMAND(port, TxEnable, 0); wakeup(ðer->tr); } if(diag & RxUnderrun){ COMMAND(port, RxReset, 0); attach(ether); } return; } if(status & RxComplete){ receive(ether); status &= ~RxComplete; } if(status & TxComplete){ /* * Pop the TX Status stack, accumulating errors. * If there was a Jabber or Underrun error, reset * the transmitter. For all conditions enable * the transmitter. */ txstatus = 0; do{ if(x = inb(port+TxStatus)) outb(port+TxStatus, 0); txstatus |= x; }while(ins(port+Status) & TxComplete); if(txstatus & (TxJabber|TxUnderrun)) COMMAND(port, TxReset, 0); . 290,294c * Clear the interrupt latch. * It's possible to receive a packet and for another * to become complete before we exit the interrupt * handler so this must be done first to ensure another * interrupt will occur. . 286,288c for(;;){ . ## diffname pc/ether509.c 1995/0509 ## diff -e /n/fornaxdump/1995/0506/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0509/sys/src/brazil/pc/ether509.c 367c } . ## diffname pc/ether509.c 1995/0517 ## diff -e /n/fornaxdump/1995/0509/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0517/sys/src/brazil/pc/ether509.c 621c if(pcicfg == 0) acr = ins(port+AddressConfig); else{ ether->irq = pcicfg->irq; acr = Xcvr10BaseT; COMMAND(port, SelectWindow, 3); print("internal config = 0x%8.8luX\n", inl(port+0x00)); free(pcicfg); } . 609c if(strcmp(ether->type, "3C589") != 0 && pcicfg == 0) . 595a if(port == 0 && (pcicfg = tcm590(ether))) port = pcicfg->baseaddr[0] & ~0x01; . 588a pcicfg = ap->pcicfg; . 585a pcicfg = 0; . 575a PCIcfg *pcicfg; . 564a static PCIcfg* tcm590(Ether *ether) { PCIcfg* pcicfg; static uchar devno = 0; ulong port; Adapter *ap; pcicfg = malloc(sizeof(PCIcfg)); while(devno < 16){ pcicfg->vid = 0x10B7; pcicfg->did = 0; if(pcimatch(0, devno++, pcicfg) == 0) continue; port = pcicfg->baseaddr[0] & ~0x01; if(ether->port == 0 || ether->port == port) return pcicfg; ap = malloc(sizeof(Adapter)); ap->pcicfg = pcicfg; pcicfg = malloc(sizeof(PCIcfg)); ap->port = port; ap->next = adapter; adapter = ap; } free(pcicfg); return 0; } . 372,373c Adapter* next; ulong port; PCIcfg* pcicfg; . ## diffname pc/ether509.c 1995/0518 ## diff -e /n/fornaxdump/1995/0517/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0518/sys/src/brazil/pc/ether509.c 581a COMMAND(port, GlobalReset, 0); while(ins(port+Status) & CmdInProgress) ; . ## diffname pc/ether509.c 1995/0519 ## diff -e /n/fornaxdump/1995/0518/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0519/sys/src/brazil/pc/ether509.c 696,697c outs(port+MediaStatus, x|LinkBeatEna|JabberEna); . 688a COMMAND(port, SelectWindow, 4); x = ins(port+MediaStatus) & ~(LinkBeatEna|JabberEna); outs(port+MediaStatus, x); . 682d 677a COMMAND(port, SelectWindow, 2); . 668c l = inl(port+InternalCgf); l &= ~0x700000; outl(port+InternalCgf, l); . 649a COMMAND(port, SelectWindow, 0); . 610c ulong l, port; . 594a pcicfg = malloc(sizeof(PCIcfg)); . 591d 539c while(slot < MaxEISA){ . 91a InternalCgf = 0x00, /* window 3 */ . ## diffname pc/ether509.c 1995/0627 ## diff -e /n/fornaxdump/1995/0519/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0627/sys/src/brazil/pc/ether509.c 106a LinkBeatOk = 0x0800, /* Valid link beat detected (ro) */ . ## diffname pc/ether509.c 1995/0706 ## diff -e /n/fornaxdump/1995/0627/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0706/sys/src/brazil/pc/ether509.c 127,128c COMMAND(port, SetReadZeroMask, (AllIntr|Latch) & ~Update); COMMAND(port, SetIntrMask, (AllIntr|Latch) & ~Update); . 124a * Disable Update interrupts for now. . ## diffname pc/ether509.c 1995/0721 ## diff -e /n/fornaxdump/1995/0706/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0721/sys/src/brazil/pc/ether509.c 582,583c if((devno = pcimatch(0, devno, pcicfg)) == -1) break; . 579c for(;;){ . 574,575c static int devno = 0; int port; . 193c etherrloop(ether, ðer->rpkt, len); . ## diffname pc/ether509.c 1995/0801 ## diff -e /n/fornaxdump/1995/0721/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0801/sys/src/brazil/pc/ether509.c 127c x = Broadcast|MyEtherAddr; if(ether->prom) x |= Promiscuous; COMMAND(port, SetRxFilter, x); . 115a int x; . ## diffname pc/ether509.c 1995/1018 ## diff -e /n/fornaxdump/1995/0801/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/1018/sys/src/brazil/pc/ether509.c 682a else acr = ins(port+AddressConfig); . 679,680c switch(l & 0x700000){ case 0x000000: acr = Xcvr10BaseT; break; case 0x300000: acr = XcvrBNC; break; } . 677a acr = XcvrAUI; . 676d 672,674c if(pcicfg){ . ## diffname pc/ether509.c 1995/1019 ## diff -e /n/fornaxdump/1995/1018/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/1019/sys/src/brazil/pc/ether509.c 642,643c if(port == 0) port = tcm589(ether); . 609a static ulong tcm589(ISAConf *isa) { if(strcmp(isa->type, "3C589") != 0) return 0; /* * The 3com manual register description says that this a noop for * PCMCIA but the flow chart at the end shows it. */ COMMAND(isa->port, SelectWindow, 0); outs(isa->port+ConfigControl, Ena); return isa->port; } . ## diffname pc/ether509.c 1996/0227 ## diff -e /n/fornaxdump/1995/1019/sys/src/brazil/pc/ether509.c /n/fornaxdump/1996/0227/sys/src/brazil/pc/ether509.c 506,510c /* * 6. Activate the adapter by writing the Activate command * (0xFF). */ outb(IDport, 0xFF); delay(20); /* * 8. Now we can talk to the adapter's I/O base addresses. * Use the I/O base address from the acr just read. * * Enable the adapter. */ while(ins(port+Status) & CmdInProgress) ; COMMAND(port, SelectWindow, 0); outs(port+ConfigControl, Ena); COMMAND(port, TxReset, 0); COMMAND(port, RxReset, 0); COMMAND(port, AckIntr, 0xFF); . 502,504c while(port = activate()){ /* * 6. Tag the adapter so it won't respond in future. */ outb(IDport, 0xD1); if(port == 0x3F0) . 497,500c * Attempt to activate adapters until one matches the * address criteria. If adapter is set for EISA mode (0x3F0), * tag it and ignore. Otherwise, activate it fully. . 455,473c return (acr & 0x1F)*0x10 + 0x200; . 453d 436c delay(20); . 434a delay(20); . 415d 411c activate(void) . 407a /* * One time only: * write ID sequence to get the attention of all adapters; * untag all adapters. * If we do a global reset here on all adapters we'll confuse any * ISA cards configured for EISA mode. */ if(untag == 0){ outb(IDport, 0xD0); untag = 1; } . 396a /* * One time only: * reset any adapters listening */ if(reset == 0){ outb(IDport, 0); outb(IDport, 0); outb(IDport, 0xC0); delay(20); reset = 1; } . 395a static int reset, untag; . ## diffname pc/ether509.c 1996/0228 ## diff -e /n/fornaxdump/1996/0227/sys/src/brazil/pc/ether509.c /n/fornaxdump/1996/0228/sys/src/brazil/pc/ether509.c 523c * 8. Can now talk to the adapter's I/O base addresses. . 490,502d 485d ## diffname pc/ether509.c 1996/0607 # deleted ## diff -e /n/fornaxdump/1996/0228/sys/src/brazil/pc/ether509.c /n/fornaxdump/1996/0607/sys/src/brazil/pc/ether509.c 1,785d