| plan 9 kernel history: overview | file list | diff list |
1995/0801/pc/ether8390.c (diff list | history)
| 1992/1222/sys/src/9/pc/ether8390.c:24,32 – 1993/0212/sys/src/9/pc/ether8390.c:24,34 (short | long) | ||
| 1992/1222 | RDMAwrite = (2<<3), /* remote DMA write */ RDMAsend = (3<<3), /* remote DMA send packet */ RDMAabort = (4<<3), /* abort/complete remote DMA */ | |
| 1993/0212 | Ps0 = 0x40, /* page select */ Ps1 = 0x80, /* page select */ Page0 = 0x00, Page1 = Ps0, Page2 = Ps1, | |
| 1992/1222 | }; enum { /* Page 0, read */ | |
| 1992/1222/sys/src/9/pc/ether8390.c:38,44 – 1993/0212/sys/src/9/pc/ether8390.c:40,46 | ||
| 1992/1222 | Fifo = 0x06, /* FIFO */ Isr = 0x07, /* interrupt status register (R/W) */ Crda0 = 0x08, /* current remote DMA address 0 */ | |
| 1993/0212 | Crda1 = 0x09, /* current remote DMA address 1 */ | |
| 1992/1222 | Rsr = 0x0C, /* receive status register */ Cntr0 = 0x0D, /* frame alignment errors */ Cntr1 = 0x0E, /* CRC errors */ | |
| 1992/1222/sys/src/9/pc/ether8390.c:144,158 – 1993/0212/sys/src/9/pc/ether8390.c:146,154 | ||
| 1992/1222 | uchar len1; } Hdr; | |
| 1992/1222/sys/src/9/pc/ether8390.c:163,216 – 1993/0212/sys/src/9/pc/ether8390.c:159,221 | ||
| 1992/1222 | * chip there if this is called when probing for a device * at boot. */ | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); dp8390outb(ctlr->card.dp8390+Rbcr0, 0); dp8390outb(ctlr->card.dp8390+Rbcr1, 0); for(timo = 10000; (dp8390inb(ctlr->card.dp8390+Isr) & Rst) == 0 && timo; timo--) | |
| 1992/1222 | ; } | |
| 1993/0212 | static void dp8390ring(Ctlr *ctlr) { dp8390outb(ctlr->card.dp8390+Pstart, ctlr->card.pstart); dp8390outb(ctlr->card.dp8390+Pstop, ctlr->card.pstop); dp8390outb(ctlr->card.dp8390+Bnry, ctlr->card.pstop-1); dp8390outb(ctlr->card.dp8390+Cr, Page1|RDMAabort|Stp); dp8390outb(ctlr->card.dp8390+Curr, ctlr->card.pstart); dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); ctlr->card.nxtpkt = ctlr->card.pstart; } | |
| 1992/1222 | void dp8390reset(Ctlr *ctlr) { | |
| 1993/0212 | * as 'mandatory' in the datasheet, with references * to the 3Com503 technical reference manual. | |
| 1992/1222 | */ dp8390disable(ctlr); | |
| 1993/0212 | if(ctlr->card.bit16) dp8390outb(ctlr->card.dp8390+Dcr, Ft4|Ls|Wts); | |
| 1992/1222 | else | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Dcr, Ft4|Ls); | |
| 1992/1222 |
| |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Rbcr0, 0); dp8390outb(ctlr->card.dp8390+Rbcr1, 0); | |
| 1992/1222 |
| |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Tcr, 0); dp8390outb(ctlr->card.dp8390+Rcr, Mon); | |
| 1992/1222 |
| |
| 1993/0212 | * Init the ring hardware and software ring pointers. * Can't initialise ethernet address as we may not know * it yet. | |
| 1992/1222 | */ | |
| 1993/0212 | dp8390ring(ctlr); dp8390outb(ctlr->card.dp8390+Tpsr, ctlr->card.tstart); | |
| 1992/1222 | ||
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Isr, 0xFF); dp8390outb(ctlr->card.dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1992/1222 | /* * Leave the chip initialised, * but in internal loopback mode. */ | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); | |
| 1992/1222 | } void | |
| 1992/1222/sys/src/9/pc/ether8390.c:218,242 – 1993/0212/sys/src/9/pc/ether8390.c:223,249 | ||
| 1992/1222 | { /* * Enable the chip for transmit/receive. | |
| 1993/0212 | * The init routine leaves the chip in monitor * mode. | |
| 1992/1222 | */ | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Rcr, Ab); | |
| 1992/1222 | } void dp8390mode(Ctlr *ctlr, int on) { | |
| 1993/0212 | /* * Set/reset promiscuous mode. */ | |
| 1992/1222 | if(on) | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Rcr, Pro|Ab); | |
| 1992/1222 | else | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Rcr, Ab); | |
| 1992/1222 | } void dp8390setea(Ctlr *ctlr) { | |
| 1992/1222/sys/src/9/pc/ether8390.c:247,304 – 1993/0212/sys/src/9/pc/ether8390.c:254,300 | ||
| 1992/1222 | * addresses as we never set the multicast * enable. */ | |
| 1993/0212 | cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; dp8390outb(ctlr->card.dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1992/1222 | for(i = 0; i < sizeof(ctlr->ea); i++) | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Par0+i, ctlr->ea[i]); dp8390outb(ctlr->card.dp8390+Cr, cr); | |
| 1992/1222 | } void* dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len) { | |
| 1993/0212 | * Read some data at offset 'from' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, and place it at * 'to' in main memory, via the I/O data port. */ | |
| 1993/0212 | cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); dp8390outb(ctlr->card.dp8390+Isr, Rdc); | |
| 1992/1222 | /* * Set up the remote DMA address and count. */ | |
| 1993/0212 | if(ctlr->card.bit16) | |
| 1992/1222 | len = ROUNDUP(len, 2); | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Rbcr0, len & 0xFF); dp8390outb(ctlr->card.dp8390+Rbcr1, (len>>8) & 0xFF); dp8390outb(ctlr->card.dp8390+Rsar0, from & 0xFF); dp8390outb(ctlr->card.dp8390+Rsar1, (from>>8) & 0xFF); | |
| 1992/1222 | /* * Start the remote DMA read and suck the data * out of the I/O port. */ | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAread|Sta); if(ctlr->card.bit16) inss(ctlr->card.data, to, len/2); | |
| 1992/1222 | else | |
| 1993/0212 | insb(ctlr->card.data, to, len); | |
| 1992/1222 | /* * Wait for the remote DMA to complete. The timeout | |
| 1992/1222/sys/src/9/pc/ether8390.c:307,317 – 1993/0212/sys/src/9/pc/ether8390.c:303,313 | ||
| 1992/1222 | * to the miracles of the bus, we could get this far * and still be talking to a slot full of nothing. */ | |
| 1993/0212 | for(timo = 10000; (dp8390inb(ctlr->card.dp8390+Isr) & Rdc) == 0 && timo; timo--) | |
| 1992/1222 | ; | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Isr, Rdc); dp8390outb(ctlr->card.dp8390+Cr, cr); | |
| 1992/1222 | return to; } | |
| 1992/1222/sys/src/9/pc/ether8390.c:318,369 – 1993/0212/sys/src/9/pc/ether8390.c:314,372 | ||
| 1992/1222 | void* dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len) { | |
| 1993/0212 | ulong crda; | |
| 1992/1222 | /* | |
| 1993/0212 | * Write some data to offset 'to' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at * 'from' in main memory, via the I/O data port. */ | |
| 1993/0212 | cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); dp8390outb(ctlr->card.dp8390+Isr, Rdc); | |
| 1992/1222 | ||
| 1993/0212 | if(ctlr->card.bit16) len = ROUNDUP(len, 2); | |
| 1992/1222 | /* * Set up the remote DMA address and count. | |
| 1993/0212 | * This is straight from the DP8390[12D] datasheet, hence * the initial set up for read. | |
| 1992/1222 | */ | |
| 1993/0212 | crda = to-1-ctlr->card.bit16; dp8390outb(ctlr->card.dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF); dp8390outb(ctlr->card.dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF); dp8390outb(ctlr->card.dp8390+Rsar0, crda & 0xFF); dp8390outb(ctlr->card.dp8390+Rsar1, (crda>>8) & 0xFF); dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAread|Sta); | |
| 1992/1222 |
| |
| 1993/0212 | for(;;){ crda = dp8390inb(ctlr->card.dp8390+Crda0); crda |= dp8390inb(ctlr->card.dp8390+Crda1)<<8; if(crda == to){ /* * Start the remote DMA write and make sure * the registers are correct. */ dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAwrite|Sta); | |
| 1992/1222 | ||
| 1993/0212 | crda = dp8390inb(ctlr->card.dp8390+Crda0); crda |= dp8390inb(ctlr->card.dp8390+Crda1)<<8; if(crda != to) panic("crda write %d to %d\n", crda, to); break; } } | |
| 1992/1222 | /* | |
| 1993/0212 | * Pump the data into the I/O port. | |
| 1992/1222 | */ | |
| 1993/0212 | if(ctlr->card.bit16) outss(ctlr->card.data, from, len/2); | |
| 1992/1222 | else | |
| 1993/0212 | outsb(ctlr->card.data, from, len); | |
| 1992/1222 | /* * Wait for the remote DMA to finish. We'll need | |
| 1992/1222/sys/src/9/pc/ether8390.c:370,405 – 1993/0212/sys/src/9/pc/ether8390.c:373,407 | ||
| 1992/1222 | * a timeout here if this ever gets called before * we know there really is a chip there. */ | |
| 1993/0212 | while((dp8390inb(ctlr->card.dp8390+Isr) & Rdc) == 0) | |
| 1992/1222 | ; | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Isr, Rdc); dp8390outb(ctlr->card.dp8390+Cr, cr); | |
| 1992/1222 | return (void*)to; } | |
| 1993/0212 | static uchar getcurr(Ctlr *ctlr) { uchar cr, curr; cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; dp8390outb(ctlr->card.dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); curr = dp8390inb(ctlr->card.dp8390+Curr); dp8390outb(ctlr->card.dp8390+Cr, cr); return curr; } | |
| 1992/1222 | void dp8390receive(Ctlr *ctlr) { | |
| 1993/0212 | uchar curr, len1, *pkt; | |
| 1992/1222 | Hdr hdr; | |
| 1993/0212 | ulong data, len; | |
| 1992/1222 |
| |
| 1993/0212 | for(curr = getcurr(ctlr); ctlr->card.nxtpkt != curr; curr = getcurr(ctlr)){ | |
| 1992/1222 | /* * Hack to keep away from the card's memory while it is receiving * a packet. This is only a problem on the NCR 3170 Safari. | |
| 1992/1222/sys/src/9/pc/ether8390.c:411,421 – 1993/0212/sys/src/9/pc/ether8390.c:413,423 | ||
| 1992/1222 | uchar a, b, c; for(;;delay(10)){ | |
| 1993/0212 | a = dp8390inb(ctlr->card.dp8390+Clda0); b = dp8390inb(ctlr->card.dp8390+Clda0); | |
| 1992/1222 | if(a != b) continue; | |
| 1993/0212 | c = dp8390inb(ctlr->card.dp8390+Clda0); | |
| 1992/1222 | if(c != b) continue; break; | |
| 1992/1222/sys/src/9/pc/ether8390.c:424,486 – 1993/0212/sys/src/9/pc/ether8390.c:426,564 | ||
| 1992/1222 | ctlr->inpackets++; | |
| 1993/0212 | data = ctlr->card.nxtpkt*Dp8390BufSz; (*ctlr->card.read)(ctlr, &hdr, data, sizeof(Hdr)); | |
| 1992/1222 | /* | |
| 1993/0212 | * Don't believe the upper byte count, work it * out from the software next-page pointer and * the current next-page pointer. | |
| 1992/1222 | */ | |
| 1993/0212 | if(hdr.next > ctlr->card.nxtpkt) len1 = hdr.next - ctlr->card.nxtpkt - 1; else len1 = (ctlr->card.pstop-ctlr->card.nxtpkt) + (hdr.next-ctlr->card.pstart) - 1; if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr))) len1--; len = ((len1<<8)|hdr.len0)-4; /* * Chip is badly scrogged, reinitialise the ring. */ if(hdr.next < ctlr->card.pstart || hdr.next >= ctlr->card.pstop || len < 60 || len > sizeof(Etherpkt)){ print("H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d|", hdr.status, hdr.next, hdr.len0, hdr.len1, len); dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); dp8390ring(ctlr); dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); | |
| 1992/1222 | return; } | |
| 1993/0212 | /* * If it's a good packet and we have a place to put it, * read it in to the software ring. * If the packet wraps round the hardware ring, read it * in two pieces. */ | |
| 1992/1222 | ring = &ctlr->rb[ctlr->ri]; | |
| 1993/0212 | if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){ pkt = ring->pkt; | |
| 1992/1222 | data += sizeof(Hdr); | |
| 1993/0212 | ring->len = len; if((data+len) >= ctlr->card.pstop*Dp8390BufSz){ ulong count = ctlr->card.pstop*Dp8390BufSz - data; (*ctlr->card.read)(ctlr, pkt, data, count); pkt += count; data = ctlr->card.pstart*Dp8390BufSz; len -= count; | |
| 1992/1222 | } | |
| 1993/0212 | if(len) (*ctlr->card.read)(ctlr, pkt, data, len); | |
| 1992/1222 | ring->owner = Host; ctlr->ri = NEXT(ctlr->ri, ctlr->nrb); } | |
| 1993/0212 | /* * Finished woth this packet, update the * hardware and software ring pointers. */ ctlr->card.nxtpkt = hdr.next; hdr.next--; if(hdr.next < ctlr->card.pstart) hdr.next = ctlr->card.pstop-1; dp8390outb(ctlr->card.dp8390+Bnry, hdr.next); | |
| 1992/1222 | } } | |
| 1993/0212 | /* * Initiate a transmission. Must be called splhi(). */ | |
| 1992/1222 | void dp8390transmit(Ctlr *ctlr) { | |
| 1993/0212 | ring = &ctlr->tb[ctlr->ti]; if(ctlr->tbusy == 0 && ring->owner == Interface){ (*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len); dp8390outb(ctlr->card.dp8390+Tbcr0, ring->len & 0xFF); dp8390outb(ctlr->card.dp8390+Tbcr1, (ring->len>>8) & 0xFF); dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Txp|Sta); ctlr->tbusy = 1; } } void dp8390overflow(Ctlr *ctlr) { uchar txp; int resend; /* * The following procedure is taken from the DP8390[12D] datasheet, * it seems pretty adamant that this is what has to be done. */ txp = dp8390inb(ctlr->card.dp8390+Cr) & Txp; dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); delay(2); dp8390outb(ctlr->card.dp8390+Rbcr0, 0); dp8390outb(ctlr->card.dp8390+Rbcr1, 0); resend = 0; if(txp && (dp8390inb(ctlr->card.dp8390+Isr) & (Txe|Ptx)) == 0) resend = 1; dp8390outb(ctlr->card.dp8390+Tcr, Lb); dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); (*ctlr->card.receive)(ctlr); dp8390outb(ctlr->card.dp8390+Isr, Ovw); wakeup(&ctlr->rr); dp8390outb(ctlr->card.dp8390+Tcr, 0); if(resend) dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Txp|Sta); } void dp8390watch(Ctlr *ctlr) { | |
| 1992/1222 | int s; | |
| 1993/0212 | /* * Stub watchdog routine. * Whine if a transmit takes too long. */ | |
| 1992/1222 | s = splhi(); | |
| 1993/0212 | if(ctlr->tbusy){ ctlr->tbusy++; if(ctlr->tbusy > 1 && ctlr->debug) print("TB%d|", ctlr->tbusy); | |
| 1992/1222 | } splx(s); } | |
| 1992/1222/sys/src/9/pc/ether8390.c:488,524 – 1993/0212/sys/src/9/pc/ether8390.c:566,586 | ||
| 1992/1222 | void dp8390intr(Ctlr *ctlr) { | |
| 1993/0212 | uchar isr, r; | |
| 1992/1222 | /* * While there is something of interest, * clear all the interrupts and process. */ | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Imr, 0x00); while(isr = dp8390inb(ctlr->card.dp8390+Isr)){ | |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/0212 | if(ctlr->card.overflow) (*ctlr->card.overflow)(ctlr); dp8390outb(ctlr->card.dp8390+Isr, Ovw); | |
| 1992/1222 | ctlr->overflows++; | |
| 1992/1222/sys/src/9/pc/ether8390.c:527,561 – 1993/0212/sys/src/9/pc/ether8390.c:589,631 | ||
| 1992/1222 | * wakeup the kproc. */ if(isr & (Rxe|Prx)){ | |
| 1993/0212 | (*ctlr->card.receive)(ctlr); dp8390outb(ctlr->card.dp8390+Isr, Rxe|Prx); | |
| 1992/1222 | wakeup(&ctlr->rr); } /* | |
| 1993/0212 | r = dp8390inb(ctlr->card.dp8390+Tsr); if(isr & Txe){ if((r & (Cdh|Fu|Crs|Abt)) && ctlr->debug) print("Tsr#%2.2ux|", r); ctlr->oerrs++; } dp8390outb(ctlr->card.dp8390+Isr, Txe|Ptx); if(isr & Ptx) ctlr->outpackets++; | |
| 1992/1222 | ring = &ctlr->tb[ctlr->ti]; ring->owner = Host; | |
| 1993/0212 | ctlr->tbusy = 0; | |
| 1992/1222 | ctlr->ti = NEXT(ctlr->ti, ctlr->ntb); | |
| 1993/0212 | (*ctlr->card.transmit)(ctlr); | |
| 1992/1222 | wakeup(&ctlr->tr); } | |
| 1993/0212 | if(isr & Cnt){ ctlr->frames += dp8390inb(ctlr->card.dp8390+Cntr0); ctlr->crcs += dp8390inb(ctlr->card.dp8390+Cntr1); ctlr->buffs += dp8390inb(ctlr->card.dp8390+Cntr2); dp8390outb(ctlr->card.dp8390+Isr, Cnt); } | |
| 1992/1222 | } | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1992/1222 | } | |
| 1993/0212/sys/src/9/pc/ether8390.c:213,219 – 1993/0213/sys/src/9/pc/ether8390.c:213,219 (short | long) | ||
| 1993/0212 | ||
| 1992/1222 | /* * Leave the chip initialised, | |
| 1993/0213 | * but in monitor mode. | |
| 1992/1222 | */ | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); | |
| 1992/1222 | } | |
| 1993/0212/sys/src/9/pc/ether8390.c:224,232 – 1993/0213/sys/src/9/pc/ether8390.c:224,234 | ||
| 1992/1222 | /* * Enable the chip for transmit/receive. | |
| 1993/0212 | * The init routine leaves the chip in monitor | |
| 1993/0213 | * mode. Clear the missed-packet counter, it * increments while in monitor mode. | |
| 1992/1222 | */ | |
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Rcr, Ab); | |
| 1993/0213 | dp8390inb(ctlr->card.dp8390+Cntr2); | |
| 1992/1222 | } void | |
| 1993/0212/sys/src/9/pc/ether8390.c:393,398 – 1993/0213/sys/src/9/pc/ether8390.c:395,425 | ||
| 1993/0212 | return curr; } | |
| 1993/0213 | static void cldaquiet(Ctlr *ctlr) { uchar a, b, c; /* * Hack to keep away from the card's memory while it is receiving * a packet. This is only a problem on the NCR 3170 Safari. * * We peek at the current local DMA registers and, if they are * changing, wait. */ for(;;delay(10)){ a = dp8390inb(ctlr->card.dp8390+Clda0); b = dp8390inb(ctlr->card.dp8390+Clda0); if(a != b) continue; c = dp8390inb(ctlr->card.dp8390+Clda0); if(c != b) continue; break; } } | |
| 1992/1222 | void dp8390receive(Ctlr *ctlr) { | |
| 1993/0212/sys/src/9/pc/ether8390.c:402,428 – 1993/0213/sys/src/9/pc/ether8390.c:429,436 | ||
| 1993/0212 | ulong data, len; | |
| 1992/1222 | ||
| 1993/0212 | for(curr = getcurr(ctlr); ctlr->card.nxtpkt != curr; curr = getcurr(ctlr)){ | |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0213 | if(strcmp(arch->id, "NCRD.0") == 0) cldaquiet(ctlr); | |
| 1992/1222 | ctlr->inpackets++; | |
| 1993/0212/sys/src/9/pc/ether8390.c:506,516 – 1993/0213/sys/src/9/pc/ether8390.c:514,527 | ||
| 1993/0212 | ring = &ctlr->tb[ctlr->ti]; if(ctlr->tbusy == 0 && ring->owner == Interface){ | |
| 1993/0213 | ctlr->tbusy = 1; | |
| 1993/0212 | (*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len); | |
| 1993/0213 | ||
| 1993/0212 | dp8390outb(ctlr->card.dp8390+Tbcr0, ring->len & 0xFF); dp8390outb(ctlr->card.dp8390+Tbcr1, (ring->len>>8) & 0xFF); dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/0213/sys/src/9/pc/ether8390.c:149,156 – 1993/0915/sys/src/9/pc/ether8390.c:149,158 (short | long) | ||
| 1992/1222 | static void dp8390disable(Ctlr *ctlr) { | |
| 1993/0915 | ulong dp8390; | |
| 1992/1222 | int timo; | |
| 1993/0915 | dp8390 = ctlr->card.dp8390; | |
| 1992/1222 | /* * Stop the chip. Set the Stp bit and wait for the chip * to finish whatever was on its tiny mind before it sets | |
| 1993/0213/sys/src/9/pc/ether8390.c:159,168 – 1993/0915/sys/src/9/pc/ether8390.c:161,170 | ||
| 1992/1222 | * chip there if this is called when probing for a device * at boot. */ | |
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); dp8390outb(dp8390+Rbcr0, 0); dp8390outb(dp8390+Rbcr1, 0); for(timo = 10000; (dp8390inb(dp8390+Isr) & Rst) == 0 && timo; timo--) | |
| 1992/1222 | ; } | |
| 1993/0213/sys/src/9/pc/ether8390.c:169,182 – 1993/0915/sys/src/9/pc/ether8390.c:171,187 | ||
| 1993/0212 | static void dp8390ring(Ctlr *ctlr) { | |
| 1993/0915 | ulong dp8390; | |
| 1993/0212 |
| |
| 1993/0915 | dp8390 = ctlr->card.dp8390; dp8390outb(dp8390+Pstart, ctlr->card.pstart); dp8390outb(dp8390+Pstop, ctlr->card.pstop); dp8390outb(dp8390+Bnry, ctlr->card.pstop-1); | |
| 1993/0212 | ||
| 1993/0915 | dp8390outb(dp8390+Cr, Page1|RDMAabort|Stp); dp8390outb(dp8390+Curr, ctlr->card.pstart); dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); | |
| 1993/0212 | ctlr->card.nxtpkt = ctlr->card.pstart; } | |
| 1993/0213/sys/src/9/pc/ether8390.c:183,188 – 1993/0915/sys/src/9/pc/ether8390.c:188,196 | ||
| 1992/1222 | void dp8390reset(Ctlr *ctlr) { | |
| 1993/0915 | ulong dp8390; dp8390 = ctlr->card.dp8390; | |
| 1992/1222 | /* * This is the initialisation procedure described | |
| 1993/0212 | * as 'mandatory' in the datasheet, with references | |
| 1993/0213/sys/src/9/pc/ether8390.c:190,204 – 1993/0915/sys/src/9/pc/ether8390.c:198,212 | ||
| 1992/1222 | */ dp8390disable(ctlr); | |
| 1993/0212 | if(ctlr->card.bit16) | |
| 1993/0915 | dp8390outb(dp8390+Dcr, Ft4|Ls|Wts); | |
| 1992/1222 | else | |
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Dcr, Ft4|Ls); | |
| 1992/1222 | ||
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Rbcr0, 0); dp8390outb(dp8390+Rbcr1, 0); | |
| 1992/1222 | ||
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Tcr, 0); dp8390outb(dp8390+Rcr, Mon); | |
| 1992/1222 | /* | |
| 1993/0212 | * Init the ring hardware and software ring pointers. | |
| 1993/0213/sys/src/9/pc/ether8390.c:206,221 – 1993/0915/sys/src/9/pc/ether8390.c:214,229 | ||
| 1993/0212 | * it yet. | |
| 1992/1222 | */ | |
| 1993/0212 | dp8390ring(ctlr); | |
| 1993/0915 | dp8390outb(dp8390+Tpsr, ctlr->card.tstart); | |
| 1992/1222 | ||
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Isr, 0xFF); dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1993/0212 | ||
| 1992/1222 | /* * Leave the chip initialised, | |
| 1993/0213 | * but in monitor mode. | |
| 1992/1222 | */ | |
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); | |
| 1992/1222 | } void | |
| 1993/0213/sys/src/9/pc/ether8390.c:246,254 – 1993/0915/sys/src/9/pc/ether8390.c:254,264 | ||
| 1992/1222 | void dp8390setea(Ctlr *ctlr) { | |
| 1993/0915 | ulong dp8390; | |
| 1992/1222 | uchar cr; int i; | |
| 1993/0915 | dp8390 = ctlr->card.dp8390; | |
| 1992/1222 | /* * Set the ethernet address into the chip. * Take care to restore the command register | |
| 1993/0213/sys/src/9/pc/ether8390.c:256,282 – 1993/0915/sys/src/9/pc/ether8390.c:266,316 | ||
| 1992/1222 | * addresses as we never set the multicast * enable. */ | |
| 1993/0212 |
| |
| 1993/0915 | cr = dp8390inb(dp8390+Cr) & ~Txp; dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1992/1222 | for(i = 0; i < sizeof(ctlr->ea); i++) | |
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Par0+i, ctlr->ea[i]); dp8390outb(dp8390+Cr, cr); | |
| 1992/1222 | } | |
| 1993/0915 | void dp8390getea(Ctlr *ctlr) { ulong dp8390; uchar cr; int i; dp8390 = ctlr->card.dp8390; /* * Set the ethernet address into the chip. * Take care to restore the command register * afterwards. We don't care about multicast * addresses as we never set the multicast * enable. */ cr = dp8390inb(dp8390+Cr) & ~Txp; dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); for(i = 0; i < sizeof(ctlr->ea); i++) ctlr->ea[i] = dp8390inb(dp8390+Par0+i); dp8390outb(dp8390+Cr, cr); } | |
| 1992/1222 | void* dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len) { | |
| 1993/0915 | ulong dp8390; | |
| 1992/1222 | uchar cr; int timo; | |
| 1993/0915 | dp8390 = ctlr->card.dp8390; | |
| 1992/1222 | /* | |
| 1993/0212 | * Read some data at offset 'from' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, and place it at * 'to' in main memory, via the I/O data port. */ | |
| 1993/0212 |
| |
| 1993/0915 | cr = dp8390inb(dp8390+Cr) & ~Txp; dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); dp8390outb(dp8390+Isr, Rdc); | |
| 1992/1222 | /* * Set up the remote DMA address and count. | |
| 1993/0213/sys/src/9/pc/ether8390.c:283,298 – 1993/0915/sys/src/9/pc/ether8390.c:317,332 | ||
| 1992/1222 | */ | |
| 1993/0212 | if(ctlr->card.bit16) | |
| 1992/1222 | len = ROUNDUP(len, 2); | |
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Rbcr0, len & 0xFF); dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF); dp8390outb(dp8390+Rsar0, from & 0xFF); dp8390outb(dp8390+Rsar1, (from>>8) & 0xFF); | |
| 1992/1222 | /* * Start the remote DMA read and suck the data * out of the I/O port. */ | |
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); | |
| 1993/0212 | if(ctlr->card.bit16) inss(ctlr->card.data, to, len/2); | |
| 1992/1222 | else | |
| 1993/0213/sys/src/9/pc/ether8390.c:305,315 – 1993/0915/sys/src/9/pc/ether8390.c:339,349 | ||
| 1992/1222 | * to the miracles of the bus, we could get this far * and still be talking to a slot full of nothing. */ | |
| 1993/0212 |
| |
| 1993/0915 | for(timo = 10000; (dp8390inb(dp8390+Isr) & Rdc) == 0 && timo; timo--) | |
| 1992/1222 | ; | |
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Isr, Rdc); dp8390outb(dp8390+Cr, cr); | |
| 1992/1222 | return to; } | |
| 1993/0213/sys/src/9/pc/ether8390.c:316,332 – 1993/0915/sys/src/9/pc/ether8390.c:350,367 | ||
| 1992/1222 | void* dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len) { | |
| 1993/0915 | ulong dp8390, crda; | |
| 1992/1222 | uchar cr; | |
| 1993/0212 |
| |
| 1992/1222 | ||
| 1993/0915 | dp8390 = ctlr->card.dp8390; | |
| 1992/1222 | /* | |
| 1993/0212 | * Write some data to offset 'to' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at * 'from' in main memory, via the I/O data port. */ | |
| 1993/0212 |
| |
| 1993/0915 | cr = dp8390inb(dp8390+Cr) & ~Txp; dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); dp8390outb(dp8390+Isr, Rdc); | |
| 1992/1222 | ||
| 1993/0212 | if(ctlr->card.bit16) len = ROUNDUP(len, 2); | |
| 1993/0213/sys/src/9/pc/ether8390.c:337,360 – 1993/0915/sys/src/9/pc/ether8390.c:372,395 | ||
| 1993/0212 | * the initial set up for read. | |
| 1992/1222 | */ | |
| 1993/0212 | crda = to-1-ctlr->card.bit16; | |
| 1993/0915 | dp8390outb(dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF); dp8390outb(dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF); dp8390outb(dp8390+Rsar0, crda & 0xFF); dp8390outb(dp8390+Rsar1, (crda>>8) & 0xFF); dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); | |
| 1992/1222 | ||
| 1993/0212 | for(;;){ | |
| 1993/0915 | crda = dp8390inb(dp8390+Crda0); crda |= dp8390inb(dp8390+Crda1)<<8; | |
| 1993/0212 | if(crda == to){ /* * Start the remote DMA write and make sure * the registers are correct. */ | |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAwrite|Sta); | |
| 1992/1222 | ||
| 1993/0212 |
| |
| 1993/0915 | crda = dp8390inb(dp8390+Crda0); crda |= dp8390inb(dp8390+Crda1)<<8; | |
| 1993/0212 | if(crda != to) panic("crda write %d to %d\n", crda, to); | |
| 1993/0213/sys/src/9/pc/ether8390.c:375,402 – 1993/0915/sys/src/9/pc/ether8390.c:410,437 | ||
| 1992/1222 | * a timeout here if this ever gets called before * we know there really is a chip there. */ | |
| 1993/0212 |
| |
| 1993/0915 | while((dp8390inb(dp8390+Isr) & Rdc) == 0) | |
| 1992/1222 | ; | |
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Isr, Rdc); dp8390outb(dp8390+Cr, cr); | |
| 1992/1222 | return (void*)to; } | |
| 1993/0212 | static uchar | |
| 1993/0915 | getcurr(ulong dp8390) | |
| 1993/0212 | { uchar cr, curr; | |
| 1993/0915 | cr = dp8390inb(dp8390+Cr) & ~Txp; dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); curr = dp8390inb(dp8390+Curr); dp8390outb(dp8390+Cr, cr); | |
| 1993/0212 | return curr; } | |
| 1993/0213 | static void | |
| 1993/0915 | cldaquiet(ulong dp8390) | |
| 1993/0213 | { uchar a, b, c; | |
| 1993/0213/sys/src/9/pc/ether8390.c:409,419 – 1993/0915/sys/src/9/pc/ether8390.c:444,454 | ||
| 1993/0213 | */ for(;;delay(10)){ | |
| 1993/0915 | a = dp8390inb(dp8390+Clda0); b = dp8390inb(dp8390+Clda0); | |
| 1993/0213 | if(a != b) continue; | |
| 1993/0915 | c = dp8390inb(dp8390+Clda0); | |
| 1993/0213 | if(c != b) continue; break; | |
| 1993/0213/sys/src/9/pc/ether8390.c:426,436 – 1993/0915/sys/src/9/pc/ether8390.c:461,472 | ||
| 1992/1222 | RingBuf *ring; | |
| 1993/0212 | uchar curr, len1, *pkt; | |
| 1992/1222 | Hdr hdr; | |
| 1993/0212 |
| |
| 1993/0915 | ulong dp8390, data, len; | |
| 1992/1222 | ||
| 1993/0212 |
| |
| 1993/0915 | dp8390 = ctlr->card.dp8390; for(curr = getcurr(dp8390); ctlr->card.nxtpkt != curr; curr = getcurr(dp8390)){ | |
| 1993/0213 | if(strcmp(arch->id, "NCRD.0") == 0) | |
| 1993/0915 | cldaquiet(dp8390); | |
| 1992/1222 | ctlr->inpackets++; | |
| 1993/0213/sys/src/9/pc/ether8390.c:458,466 – 1993/0915/sys/src/9/pc/ether8390.c:494,502 | ||
| 1993/0212 | || len < 60 || len > sizeof(Etherpkt)){ print("H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d|", hdr.status, hdr.next, hdr.len0, hdr.len1, len); | |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); | |
| 1993/0212 | dp8390ring(ctlr); | |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); | |
| 1992/1222 | return; } | |
| 1993/0213/sys/src/9/pc/ether8390.c:500,506 – 1993/0915/sys/src/9/pc/ether8390.c:536,542 | ||
| 1993/0212 | hdr.next--; if(hdr.next < ctlr->card.pstart) hdr.next = ctlr->card.pstop-1; | |
| 1993/0915 | dp8390outb(dp8390+Bnry, hdr.next); | |
| 1992/1222 | } } | |
| 1993/0213/sys/src/9/pc/ether8390.c:510,517 – 1993/0915/sys/src/9/pc/ether8390.c:546,555 | ||
| 1992/1222 | void dp8390transmit(Ctlr *ctlr) { | |
| 1993/0915 | ulong dp8390; | |
| 1992/1222 | RingBuf *ring; | |
| 1993/0212 | ||
| 1993/0915 | dp8390 = ctlr->card.dp8390; | |
| 1993/0212 | ring = &ctlr->tb[ctlr->ti]; if(ctlr->tbusy == 0 && ring->owner == Interface){ | |
| 1993/0213 | ||
| 1993/0213/sys/src/9/pc/ether8390.c:519,527 – 1993/0915/sys/src/9/pc/ether8390.c:557,565 | ||
| 1993/0213 | ||
| 1993/0212 | (*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len); | |
| 1993/0213 | ||
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Tbcr0, ring->len & 0xFF); dp8390outb(dp8390+Tbcr1, (ring->len>>8) & 0xFF); dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/0212 | } } | |
| 1993/0213/sys/src/9/pc/ether8390.c:528,559 – 1993/0915/sys/src/9/pc/ether8390.c:566,599 | ||
| 1993/0212 | void dp8390overflow(Ctlr *ctlr) { | |
| 1993/0915 | ulong dp8390; | |
| 1993/0212 | uchar txp; int resend; | |
| 1993/0915 | dp8390 = ctlr->card.dp8390; | |
| 1993/0212 | /* * The following procedure is taken from the DP8390[12D] datasheet, * it seems pretty adamant that this is what has to be done. */ | |
| 1993/0915 | txp = dp8390inb(dp8390+Cr) & Txp; dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); | |
| 1993/0212 | delay(2); | |
| 1993/0915 | dp8390outb(dp8390+Rbcr0, 0); dp8390outb(dp8390+Rbcr1, 0); | |
| 1993/0212 | resend = 0; | |
| 1993/0915 | if(txp && (dp8390inb(dp8390+Isr) & (Txe|Ptx)) == 0) | |
| 1993/0212 | resend = 1; | |
| 1993/0915 | dp8390outb(dp8390+Tcr, Lb); dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); | |
| 1993/0212 | (*ctlr->card.receive)(ctlr); | |
| 1993/0915 | dp8390outb(dp8390+Isr, Ovw); | |
| 1993/0212 | wakeup(&ctlr->rr); | |
| 1993/0915 | dp8390outb(dp8390+Tcr, 0); | |
| 1993/0212 | if(resend) | |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/0212 | } void | |
| 1993/0213/sys/src/9/pc/ether8390.c:577,596 – 1993/0915/sys/src/9/pc/ether8390.c:617,638 | ||
| 1992/1222 | void dp8390intr(Ctlr *ctlr) { | |
| 1993/0915 | ulong dp8390; | |
| 1992/1222 | RingBuf *ring; | |
| 1993/0212 | uchar isr, r; | |
| 1992/1222 | ||
| 1993/0915 | dp8390 = ctlr->card.dp8390; | |
| 1992/1222 | /* * While there is something of interest, * clear all the interrupts and process. */ | |
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Imr, 0x00); while(isr = dp8390inb(dp8390+Isr)){ | |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/0212 | if(ctlr->card.overflow) (*ctlr->card.overflow)(ctlr); | |
| 1993/0915 | dp8390outb(dp8390+Isr, Ovw); | |
| 1992/1222 | ctlr->overflows++; } | |
| 1993/0213/sys/src/9/pc/ether8390.c:601,607 – 1993/0915/sys/src/9/pc/ether8390.c:643,649 | ||
| 1992/1222 | */ if(isr & (Rxe|Prx)){ | |
| 1993/0212 | (*ctlr->card.receive)(ctlr); | |
| 1993/0915 | dp8390outb(dp8390+Isr, Rxe|Prx); | |
| 1992/1222 | wakeup(&ctlr->rr); } | |
| 1993/0213/sys/src/9/pc/ether8390.c:611,617 – 1993/0915/sys/src/9/pc/ether8390.c:653,659 | ||
| 1992/1222 | * and wake the output routine. */ if(isr & (Txe|Ptx)){ | |
| 1993/0212 |
| |
| 1993/0915 | r = dp8390inb(dp8390+Tsr); | |
| 1993/0212 | if(isr & Txe){ if((r & (Cdh|Fu|Crs|Abt)) && ctlr->debug) print("Tsr#%2.2ux|", r); | |
| 1993/0213/sys/src/9/pc/ether8390.c:618,624 – 1993/0915/sys/src/9/pc/ether8390.c:660,666 | ||
| 1993/0212 | ctlr->oerrs++; } | |
| 1993/0915 | dp8390outb(dp8390+Isr, Txe|Ptx); | |
| 1993/0212 | if(isr & Ptx) ctlr->outpackets++; | |
| 1993/0213/sys/src/9/pc/ether8390.c:632,642 – 1993/0915/sys/src/9/pc/ether8390.c:674,684 | ||
| 1992/1222 | } | |
| 1993/0212 | if(isr & Cnt){ | |
| 1993/0915 | ctlr->frames += dp8390inb(dp8390+Cntr0); ctlr->crcs += dp8390inb(dp8390+Cntr1); ctlr->buffs += dp8390inb(dp8390+Cntr2); dp8390outb(dp8390+Isr, Cnt); | |
| 1993/0212 | } | |
| 1992/1222 | } | |
| 1993/0212 |
| |
| 1993/0915 | dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1992/1222 | } | |
| 1993/0915/sys/src/9/pc/ether8390.c:8,18 – 1993/1116/sys/src/9/pc/ether8390.c:8,18 (short | long) | ||
| 1992/1222 | #include "mem.h" #include "dat.h" #include "fns.h" | |
| 1993/1116 | #include "../port/error.h" #include "../port/netif.h" | |
| 1992/1222 |
| |
| 1993/1116 | #include "etherif.h" | |
| 1992/1222 | enum { Cr = 0x00, /* command register, all pages */ | |
| 1993/0915/sys/src/9/pc/ether8390.c:147,158 – 1993/1116/sys/src/9/pc/ether8390.c:147,158 | ||
| 1992/1222 | } Hdr; static void | |
| 1993/1116 | dp8390disable(Ether *ether) | |
| 1992/1222 | { | |
| 1993/0915 | ulong dp8390; | |
| 1992/1222 | int timo; | |
| 1993/0915 |
| |
| 1993/1116 | dp8390 = ether->dp8390; | |
| 1992/1222 | /* * Stop the chip. Set the Stp bit and wait for the chip * to finish whatever was on its tiny mind before it sets | |
| 1993/0915/sys/src/9/pc/ether8390.c:169,264 – 1993/1116/sys/src/9/pc/ether8390.c:169,198 | ||
| 1992/1222 | } | |
| 1993/0212 | static void | |
| 1993/1116 | dp8390ring(Ether *ether) | |
| 1993/0212 | { | |
| 1993/0915 | ulong dp8390; | |
| 1993/0212 | ||
| 1993/0915 |
| |
| 1993/1116 | dp8390 = ether->dp8390; dp8390outb(dp8390+Pstart, ether->pstart); dp8390outb(dp8390+Pstop, ether->pstop); dp8390outb(dp8390+Bnry, ether->pstop-1); | |
| 1993/0212 | ||
| 1993/0915 | dp8390outb(dp8390+Cr, Page1|RDMAabort|Stp); | |
| 1993/1116 | dp8390outb(dp8390+Curr, ether->pstart); | |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); | |
| 1993/0212 |
| |
| 1993/1116 | ether->nxtpkt = ether->pstart; | |
| 1993/0212 | } | |
| 1992/1222 | void | |
| 1993/1116 | dp8390setea(Ether *ether) | |
| 1992/1222 | { | |
| 1993/0915 | ulong dp8390; | |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1993/0915 |
| |
| 1992/1222 |
| |
| 1993/0915 |
| |
| 1992/1222 | ||
| 1993/0915 |
| |
| 1992/1222 | ||
| 1993/0915 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1993/0915 |
| |
| 1992/1222 | ||
| 1993/0915 |
| |
| 1993/0212 | ||
| 1992/1222 |
| |
| 1993/0213 |
| |
| 1992/1222 |
| |
| 1993/0915 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1993/0213 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1993/0213 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0915 |
| |
| 1992/1222 | uchar cr; int i; | |
| 1993/0915 |
| |
| 1993/1116 | dp8390 = ether->dp8390; | |
| 1992/1222 | /* * Set the ethernet address into the chip. * Take care to restore the command register | |
| 1993/0915/sys/src/9/pc/ether8390.c:268,288 – 1993/1116/sys/src/9/pc/ether8390.c:202,222 | ||
| 1992/1222 | */ | |
| 1993/0915 | cr = dp8390inb(dp8390+Cr) & ~Txp; dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1992/1222 |
| |
| 1993/0915 |
| |
| 1993/1116 | for(i = 0; i < sizeof(ether->ea); i++) dp8390outb(dp8390+Par0+i, ether->ea[i]); | |
| 1993/0915 | dp8390outb(dp8390+Cr, cr); | |
| 1992/1222 | } | |
| 1993/0915 | void | |
| 1993/1116 | dp8390getea(Ether *ether) | |
| 1993/0915 | { ulong dp8390; uchar cr; int i; | |
| 1993/1116 | dp8390 = ether->dp8390; | |
| 1993/0915 | /* | |
| 1993/1116 | * Get the ethernet address from the chip. | |
| 1993/0915 | * Take care to restore the command register * afterwards. We don't care about multicast * addresses as we never set the multicast | |
| 1993/0915/sys/src/9/pc/ether8390.c:290,308 – 1993/1116/sys/src/9/pc/ether8390.c:224,242 | ||
| 1993/0915 | */ cr = dp8390inb(dp8390+Cr) & ~Txp; dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1993/1116 | for(i = 0; i < sizeof(ether->ea); i++) ether->ea[i] = dp8390inb(dp8390+Par0+i); | |
| 1993/0915 | dp8390outb(dp8390+Cr, cr); } | |
| 1992/1222 |
| |
| 1993/1116 | static void* dp8390read(Ether *ether, void *to, ulong from, ulong len) | |
| 1992/1222 | { | |
| 1993/0915 | ulong dp8390; | |
| 1992/1222 | uchar cr; int timo; | |
| 1993/0915 |
| |
| 1993/1116 | dp8390 = ether->dp8390; | |
| 1992/1222 | /* | |
| 1993/0212 | * Read some data at offset 'from' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, and place it at | |
| 1993/0915/sys/src/9/pc/ether8390.c:315,321 – 1993/1116/sys/src/9/pc/ether8390.c:249,255 | ||
| 1992/1222 | /* * Set up the remote DMA address and count. */ | |
| 1993/0212 |
| |
| 1993/1116 | if(ether->bit16) | |
| 1992/1222 | len = ROUNDUP(len, 2); | |
| 1993/0915 | dp8390outb(dp8390+Rbcr0, len & 0xFF); dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF); | |
| 1993/0915/sys/src/9/pc/ether8390.c:327,336 – 1993/1116/sys/src/9/pc/ether8390.c:261,270 | ||
| 1992/1222 | * out of the I/O port. */ | |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); | |
| 1993/0212 |
| |
| 1993/1116 | if(ether->bit16) inss(ether->data, to, len/2); | |
| 1992/1222 | else | |
| 1993/0212 |
| |
| 1993/1116 | insb(ether->data, to, len); | |
| 1992/1222 | /* * Wait for the remote DMA to complete. The timeout | |
| 1993/0915/sys/src/9/pc/ether8390.c:347,359 – 1993/1116/sys/src/9/pc/ether8390.c:281,293 | ||
| 1992/1222 | return to; } | |
| 1993/1116 | static void* dp8390write(Ether *ether, ulong to, void *from, ulong len) | |
| 1992/1222 | { | |
| 1993/0915 | ulong dp8390, crda; | |
| 1992/1222 | uchar cr; | |
| 1993/0915 |
| |
| 1993/1116 | dp8390 = ether->dp8390; | |
| 1992/1222 | /* | |
| 1993/0212 | * Write some data to offset 'to' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at | |
| 1993/0915/sys/src/9/pc/ether8390.c:363,369 – 1993/1116/sys/src/9/pc/ether8390.c:297,303 | ||
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); dp8390outb(dp8390+Isr, Rdc); | |
| 1992/1222 | ||
| 1993/0212 |
| |
| 1993/1116 | if(ether->bit16) | |
| 1993/0212 | len = ROUNDUP(len, 2); | |
| 1992/1222 | /* | |
| 1993/0915/sys/src/9/pc/ether8390.c:371,379 – 1993/1116/sys/src/9/pc/ether8390.c:305,313 | ||
| 1993/0212 | * This is straight from the DP8390[12D] datasheet, hence * the initial set up for read. | |
| 1992/1222 | */ | |
| 1993/0212 |
| |
| 1993/0915 |
| |
| 1993/1116 | crda = to-1-ether->bit16; dp8390outb(dp8390+Rbcr0, (len+1+ether->bit16) & 0xFF); dp8390outb(dp8390+Rbcr1, ((len+1+ether->bit16)>>8) & 0xFF); | |
| 1993/0915 | dp8390outb(dp8390+Rsar0, crda & 0xFF); dp8390outb(dp8390+Rsar1, (crda>>8) & 0xFF); dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); | |
| 1993/0915/sys/src/9/pc/ether8390.c:400,409 – 1993/1116/sys/src/9/pc/ether8390.c:334,343 | ||
| 1992/1222 | /* | |
| 1993/0212 | * Pump the data into the I/O port. | |
| 1992/1222 | */ | |
| 1993/0212 |
| |
| 1993/1116 | if(ether->bit16) outss(ether->data, from, len/2); | |
| 1992/1222 | else | |
| 1993/0212 |
| |
| 1993/1116 | outsb(ether->data, from, len); | |
| 1992/1222 | /* * Wait for the remote DMA to finish. We'll need | |
| 1993/0915/sys/src/9/pc/ether8390.c:431,487 – 1993/1116/sys/src/9/pc/ether8390.c:365,394 | ||
| 1993/0212 | } | |
| 1993/0213 | static void | |
| 1993/0915 |
| |
| 1993/1116 | receive(Ether *ether) | |
| 1993/0213 | { | |
| 1993/0915 |
| |
| 1993/0213 |
| |
| 1993/0915 |
| |
| 1993/0213 |
| |
| 1992/1222 |
| |
| 1993/0212 | uchar curr, len1, *pkt; | |
| 1992/1222 | Hdr hdr; | |
| 1993/0915 | ulong dp8390, data, len; | |
| 1993/1116 | ushort type; Netfile *f, **fp, **ep; | |
| 1992/1222 | ||
| 1993/0915 |
| |
| 1993/0213 |
| |
| 1993/0915 |
| |
| 1993/1116 | dp8390 = ether->dp8390; for(curr = getcurr(dp8390); ether->nxtpkt != curr; curr = getcurr(dp8390)){ ether->inpackets++; | |
| 1992/1222 |
| |
| 1993/1116 | data = ether->nxtpkt*Dp8390BufSz; (*ether->read)(ctlr, &hdr, data, sizeof(Hdr)); | |
| 1992/1222 | ||
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0212 | * Don't believe the upper byte count, work it * out from the software next-page pointer and * the current next-page pointer. | |
| 1992/1222 | */ | |
| 1993/0212 |
| |
| 1993/1116 | if(hdr.next > ether->nxtpkt) len1 = hdr.next - ether->nxtpkt - 1; | |
| 1993/0212 | else | |
| 1993/1116 | len1 = (ether->pstop-ether->nxtpkt) + (hdr.next-ether->pstart) - 1; | |
| 1993/0212 | if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr))) len1--; | |
| 1993/0915/sys/src/9/pc/ether8390.c:490,530 – 1993/1116/sys/src/9/pc/ether8390.c:397,442 | ||
| 1993/0212 | /* * Chip is badly scrogged, reinitialise the ring. */ | |
| 1993/1116 | if(hdr.next < ether->pstart || hdr.next >= ether->pstop | |
| 1993/0212 | || len < 60 || len > sizeof(Etherpkt)){ print("H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d|", hdr.status, hdr.next, hdr.len0, hdr.len1, len); | |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); | |
| 1993/0212 |
| |
| 1993/1116 | dp8390ring(ether); | |
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); | |
| 1992/1222 | return; } | |
| 1993/0212 | /* | |
| 1993/1116 | * If it's a good packet read it in to the software buffer. * If the packet wraps round the hardware ring, read it in two pieces. | |
| 1993/0212 | */ | |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1993/1116 | if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok){ pkt = ether->rpkt; | |
| 1992/1222 | data += sizeof(Hdr); | |
| 1993/0212 | ring->len = len; | |
| 1993/1116 | if((data+len) >= ether->pstop*Dp8390BufSz){ ulong count = ether->pstop*Dp8390BufSz - data; | |
| 1993/0212 |
| |
| 1993/1116 | (*ether->read)(ctlr, pkt, data, count); | |
| 1993/0212 | pkt += count; | |
| 1993/1116 | data = ether->pstart*Dp8390BufSz; | |
| 1993/0212 | len -= count; | |
| 1992/1222 | } | |
| 1993/0212 | if(len) | |
| 1993/1116 | (*ether->read)(ctlr, pkt, data, len); | |
| 1993/0212 | ||
| 1992/1222 |
| |
| 1993/1116 | /* * 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); } | |
| 1992/1222 | } | |
| 1993/0212 | /* | |
| 1993/0915/sys/src/9/pc/ether8390.c:531,541 – 1993/1116/sys/src/9/pc/ether8390.c:443,453 | ||
| 1993/0212 | * Finished woth this packet, update the * hardware and software ring pointers. */ | |
| 1993/1116 | ether->nxtpkt = hdr.next; | |
| 1993/0212 | hdr.next--; | |
| 1993/1116 | if(hdr.next < ether->pstart) hdr.next = ether->pstop-1; | |
| 1993/0915 | dp8390outb(dp8390+Bnry, hdr.next); | |
| 1992/1222 | } } | |
| 1993/0915/sys/src/9/pc/ether8390.c:544,561 – 1993/1116/sys/src/9/pc/ether8390.c:456,473 | ||
| 1993/0212 | * Initiate a transmission. Must be called splhi(). */ | |
| 1992/1222 | void | |
| 1993/1116 | dp8390transmit(Ether *ether) | |
| 1992/1222 | { | |
| 1993/0915 | ulong dp8390; | |
| 1992/1222 | RingBuf *ring; | |
| 1993/0212 | ||
| 1993/0915 |
| |
| 1993/0212 |
| |
| 1993/1116 | dp8390 = ether->dp8390; ring = ðer->tb[ether->ti]; if(ether->tbusy == 0 && ring->owner == Interface){ | |
| 1993/0213 |
| |
| 1993/1116 | ether->tbusy = 1; | |
| 1993/0213 | ||
| 1993/0212 |
| |
| 1993/1116 | (*ether->write)(ctlr, ether->tstart*Dp8390BufSz, ring->pkt, ring->len); | |
| 1993/0213 | ||
| 1993/0915 | dp8390outb(dp8390+Tbcr0, ring->len & 0xFF); dp8390outb(dp8390+Tbcr1, (ring->len>>8) & 0xFF); | |
| 1993/0915/sys/src/9/pc/ether8390.c:563,576 – 1993/1116/sys/src/9/pc/ether8390.c:475,488 | ||
| 1993/0212 | } } | |
| 1993/1116 | static void overflow(Ether *ether) | |
| 1993/0212 | { | |
| 1993/0915 | ulong dp8390; | |
| 1993/0212 | uchar txp; int resend; | |
| 1993/0915 |
| |
| 1993/1116 | dp8390 = ether->dp8390; | |
| 1993/0212 | /* * The following procedure is taken from the DP8390[12D] datasheet, * it seems pretty adamant that this is what has to be done. | |
| 1993/0915/sys/src/9/pc/ether8390.c:587,595 – 1993/1116/sys/src/9/pc/ether8390.c:499,507 | ||
| 1993/0212 | ||
| 1993/0915 | dp8390outb(dp8390+Tcr, Lb); dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); | |
| 1993/0212 |
| |
| 1993/1116 | (*ether->receive)(ether); | |
| 1993/0915 | dp8390outb(dp8390+Isr, Ovw); | |
| 1993/0212 |
| |
| 1993/1116 | wakeup(ðer->rr); | |
| 1993/0915 | dp8390outb(dp8390+Tcr, 0); | |
| 1993/0212 | if(resend) | |
| 1993/0915/sys/src/9/pc/ether8390.c:596,627 – 1993/1116/sys/src/9/pc/ether8390.c:508,520 | ||
| 1993/0915 | dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/0212 | } | |
| 1993/1116 | static void interrupt(Ether *ether) | |
| 1993/0212 | { | |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0915 | ulong dp8390; | |
| 1992/1222 |
| |
| 1993/0212 | uchar isr, r; | |
| 1992/1222 | ||
| 1993/0915 |
| |
| 1993/1116 | dp8390 = ether->dp8390; | |
| 1992/1222 | /* * While there is something of interest, * clear all the interrupts and process. | |
| 1993/0915/sys/src/9/pc/ether8390.c:630,650 – 1993/1116/sys/src/9/pc/ether8390.c:523,540 | ||
| 1993/0915 | while(isr = dp8390inb(dp8390+Isr)){ | |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/0212 |
| |
| 1993/1116 | overflow(ether); | |
| 1993/0915 | dp8390outb(dp8390+Isr, Ovw); | |
| 1992/1222 |
| |
| 1993/1116 | ether->overflows++; | |
| 1992/1222 | } /* * We have received packets. | |
| 1993/1116 | * Take a spin round the ring. and | |
| 1992/1222 | */ if(isr & (Rxe|Prx)){ | |
| 1993/0212 |
| |
| 1993/1116 | receive(ether); | |
| 1993/0915 | dp8390outb(dp8390+Isr, Rxe|Prx); | |
| 1992/1222 |
| |
| 1993/0915/sys/src/9/pc/ether8390.c:655,684 – 1993/1116/sys/src/9/pc/ether8390.c:545,646 | ||
| 1992/1222 | if(isr & (Txe|Ptx)){ | |
| 1993/0915 | r = dp8390inb(dp8390+Tsr); | |
| 1993/0212 | if(isr & Txe){ | |
| 1993/1116 | if((r & (Cdh|Fu|Crs|Abt)) && ether->debug) | |
| 1993/0212 | print("Tsr#%2.2ux|", r); | |
| 1993/1116 | ether->oerrs++; | |
| 1993/0212 | } | |
| 1993/0915 | dp8390outb(dp8390+Isr, Txe|Ptx); | |
| 1993/0212 | if(isr & Ptx) | |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/1116 | ether->outpackets++; wakeup(ðer->tr); | |
| 1992/1222 | } | |
| 1993/0212 | if(isr & Cnt){ | |
| 1993/0915 |
| |
| 1993/1116 | ether->frames += dp8390inb(dp8390+Cntr0); ether->crcs += dp8390inb(dp8390+Cntr1); ether->buffs += dp8390inb(dp8390+Cntr2); | |
| 1993/0915 | dp8390outb(dp8390+Isr, Cnt); | |
| 1993/0212 | } | |
| 1992/1222 | } | |
| 1993/0915 | dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1993/1116 | } static void promiscuous(Ether *ether, int on) { /* * Set/reset promiscuous mode. */ if(on) dp8390outb(ether->dp8390+Rcr, Pro|Ab); else dp8390outb(ether->dp8390+Rcr, Ab); } void dp8390attach(Ether *ether) { /* * Enable the chip for transmit/receive. * The init routine leaves the chip in monitor * mode. Clear the missed-packet counter, it * increments while in monitor mode. */ dp8390outb(ether->dp8390+Rcr, Ab); dp8390inb(ether->dp8390+Cntr2); } static int dp8390reset(Ether *ether) { ulong dp8390; dp8390 = ether->dp8390; /* * This is the initialisation procedure described * as 'mandatory' in the datasheet, with references * to the 3Com503 technical reference manual. */ dp8390disable(ether); if(ether->bit16) dp8390outb(dp8390+Dcr, Ft4|Ls|Wts); else dp8390outb(dp8390+Dcr, Ft4|Ls); dp8390outb(dp8390+Rbcr0, 0); dp8390outb(dp8390+Rbcr1, 0); dp8390outb(dp8390+Tcr, 0); dp8390outb(dp8390+Rcr, Mon); /* * Init the ring hardware and software ring pointers. * Can't initialise ethernet address as we may not know * it yet. */ dp8390ring(ether); dp8390outb(dp8390+Tpsr, ether->tstart); dp8390outb(dp8390+Isr, 0xFF); dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); /* * Leave the chip initialised, * but in monitor mode. */ dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); /* * Set up the software configuration. */ ether->attach = attach; ether->write = write; ether->interrupt = interrupt; ether->promiscuous = promiscuous; ether->arg = ether; return 0; | |
| 1992/1222 | } | |
| 1993/1116/sys/src/9/pc/ether8390.c:147,158 – 1993/1117/sys/src/9/pc/ether8390.c:147,158 (short | long) | ||
| 1992/1222 | } Hdr; static void | |
| 1993/1116 |
| |
| 1993/1117 | dp8390disable(Dp8390 *dp8390) | |
| 1992/1222 | { | |
| 1993/0915 |
| |
| 1993/1117 | ulong port; | |
| 1992/1222 | int timo; | |
| 1993/1116 |
| |
| 1993/1117 | port = dp8390->dp8390; | |
| 1992/1222 | /* * Stop the chip. Set the Stp bit and wait for the chip * to finish whatever was on its tiny mind before it sets | |
| 1993/1116/sys/src/9/pc/ether8390.c:161,198 – 1993/1117/sys/src/9/pc/ether8390.c:161,198 | ||
| 1992/1222 | * chip there if this is called when probing for a device * at boot. */ | |
| 1993/0915 |
| |
| 1993/1117 | dp8390outb(port+Cr, Page0|RDMAabort|Stp); dp8390outb(port+Rbcr0, 0); dp8390outb(port+Rbcr1, 0); for(timo = 10000; (dp8390inb(port+Isr) & Rst) == 0 && timo; timo--) | |
| 1992/1222 | ; } | |
| 1993/0212 | static void | |
| 1993/1116 |
| |
| 1993/1117 | dp8390ring(Dp8390 *dp8390) | |
| 1993/0212 | { | |
| 1993/0915 |
| |
| 1993/1117 | ulong port; | |
| 1993/0212 | ||
| 1993/1116 |
| |
| 1993/1117 | port = dp8390->dp8390; dp8390outb(port+Pstart, dp8390->pstart); dp8390outb(port+Pstop, dp8390->pstop); dp8390outb(port+Bnry, dp8390->pstop-1); | |
| 1993/0212 | ||
| 1993/0915 |
| |
| 1993/1116 |
| |
| 1993/0915 |
| |
| 1993/1117 | dp8390outb(port+Cr, Page1|RDMAabort|Stp); dp8390outb(port+Curr, dp8390->pstart); dp8390outb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/0915 | ||
| 1993/1116 |
| |
| 1993/1117 | dp8390->nxtpkt = dp8390->pstart; | |
| 1993/0212 | } | |
| 1992/1222 | void | |
| 1993/1116 | dp8390setea(Ether *ether) | |
| 1992/1222 | { | |
| 1993/0915 |
| |
| 1993/1117 | ulong port; | |
| 1992/1222 | uchar cr; int i; | |
| 1993/1116 |
| |
| 1993/1117 | port = ((Dp8390*)ether->private)->dp8390; | |
| 1992/1222 | /* * Set the ethernet address into the chip. * Take care to restore the command register | |
| 1993/1116/sys/src/9/pc/ether8390.c:200,220 – 1993/1117/sys/src/9/pc/ether8390.c:200,220 | ||
| 1992/1222 | * addresses as we never set the multicast * enable. */ | |
| 1993/0915 |
| |
| 1993/1117 | cr = dp8390inb(port+Cr) & ~Txp; dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1993/1116 | for(i = 0; i < sizeof(ether->ea); i++) | |
| 1993/0915 |
| |
| 1993/1117 | dp8390outb(port+Par0+i, ether->ea[i]); dp8390outb(port+Cr, cr); | |
| 1992/1222 | } | |
| 1993/0915 | void | |
| 1993/1116 | dp8390getea(Ether *ether) | |
| 1993/0915 | { | |
| 1993/1117 | ulong port; | |
| 1993/0915 | uchar cr; int i; | |
| 1993/1116 |
| |
| 1993/1117 | port = ((Dp8390*)ether->private)->dp8390; | |
| 1993/0915 | /* | |
| 1993/1116 | * Get the ethernet address from the chip. | |
| 1993/0915 | * Take care to restore the command register | |
| 1993/1116/sys/src/9/pc/ether8390.c:222,270 – 1993/1117/sys/src/9/pc/ether8390.c:222,270 | ||
| 1993/0915 | * addresses as we never set the multicast * enable. */ | |
| 1993/1117 | cr = dp8390inb(port+Cr) & ~Txp; dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1993/1116 | for(i = 0; i < sizeof(ether->ea); i++) | |
| 1993/0915 |
| |
| 1993/1117 | ether->ea[i] = dp8390inb(port+Par0+i); dp8390outb(port+Cr, cr); | |
| 1993/0915 | } | |
| 1993/1116 | static void* | |
| 1993/1117 | dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) | |
| 1992/1222 | { | |
| 1993/0915 |
| |
| 1993/1117 | ulong port; | |
| 1992/1222 | uchar cr; int timo; | |
| 1993/1116 |
| |
| 1993/1117 | port = dp8390->dp8390; | |
| 1992/1222 | /* | |
| 1993/0212 | * Read some data at offset 'from' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, and place it at * 'to' in main memory, via the I/O data port. */ | |
| 1993/0915 |
| |
| 1993/1117 | cr = dp8390inb(port+Cr) & ~Txp; dp8390outb(port+Cr, Page0|RDMAabort|Sta); dp8390outb(port+Isr, Rdc); | |
| 1992/1222 | /* * Set up the remote DMA address and count. */ | |
| 1993/1116 |
| |
| 1993/1117 | if(dp8390->bit16) | |
| 1992/1222 | len = ROUNDUP(len, 2); | |
| 1993/0915 |
| |
| 1993/1117 | dp8390outb(port+Rbcr0, len & 0xFF); dp8390outb(port+Rbcr1, (len>>8) & 0xFF); dp8390outb(port+Rsar0, from & 0xFF); dp8390outb(port+Rsar1, (from>>8) & 0xFF); | |
| 1992/1222 | /* * Start the remote DMA read and suck the data * out of the I/O port. */ | |
| 1993/0915 |
| |
| 1993/1116 |
| |
| 1993/1117 | dp8390outb(port+Cr, Page0|RDMAread|Sta); if(dp8390->bit16) inss(dp8390->data, to, len/2); | |
| 1992/1222 | else | |
| 1993/1116 |
| |
| 1993/1117 | insb(dp8390->data, to, len); | |
| 1992/1222 | /* * Wait for the remote DMA to complete. The timeout | |
| 1993/1116/sys/src/9/pc/ether8390.c:273,283 – 1993/1117/sys/src/9/pc/ether8390.c:273,283 | ||
| 1992/1222 | * to the miracles of the bus, we could get this far * and still be talking to a slot full of nothing. */ | |
| 1993/0915 |
| |
| 1993/1117 | for(timo = 10000; (dp8390inb(port+Isr) & Rdc) == 0 && timo; timo--) | |
| 1992/1222 | ; | |
| 1993/0915 |
| |
| 1993/1117 | dp8390outb(port+Isr, Rdc); dp8390outb(port+Cr, cr); | |
| 1992/1222 | return to; } | |
| 1993/1116/sys/src/9/pc/ether8390.c:287,293 – 1993/1117/sys/src/9/pc/ether8390.c:287,293 | ||
| 1993/0915 | ulong dp8390, crda; | |
| 1992/1222 | uchar cr; | |
| 1993/1116 |
| |
| 1993/1117 | dp8390 = ((Dp8390*)ether->private)->dp8390; | |
| 1992/1222 | /* | |
| 1993/0212 | * Write some data to offset 'to' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at | |
| 1993/1116/sys/src/9/pc/ether8390.c:373,379 – 1993/1117/sys/src/9/pc/ether8390.c:373,379 | ||
| 1993/1116 | ushort type; Netfile *f, **fp, **ep; | |
| 1992/1222 | ||
| 1993/1116 |
| |
| 1993/1117 | dp8390 = ((Dp8390*)ether->private)->dp8390; | |
| 1993/1116 | for(curr = getcurr(dp8390); ether->nxtpkt != curr; curr = getcurr(dp8390)){ ether->inpackets++; | |
| 1992/1222 | ||
| 1993/1116/sys/src/9/pc/ether8390.c:461,467 – 1993/1117/sys/src/9/pc/ether8390.c:461,467 | ||
| 1993/0915 | ulong dp8390; | |
| 1992/1222 | RingBuf *ring; | |
| 1993/0212 | ||
| 1993/1116 |
| |
| 1993/1117 | dp8390 = ((Dp8390*)ether->private)->dp8390; | |
| 1993/1116 | ring = ðer->tb[ether->ti]; if(ether->tbusy == 0 && ring->owner == Interface){ | |
| 1993/0213 | ||
| 1993/1116/sys/src/9/pc/ether8390.c:482,488 – 1993/1117/sys/src/9/pc/ether8390.c:482,488 | ||
| 1993/0212 | uchar txp; int resend; | |
| 1993/1116 |
| |
| 1993/1117 | dp8390 = ((Dp8390*)ether->private)->dp8390; | |
| 1993/0212 | /* * The following procedure is taken from the DP8390[12D] datasheet, * it seems pretty adamant that this is what has to be done. | |
| 1993/1116/sys/src/9/pc/ether8390.c:514,520 – 1993/1117/sys/src/9/pc/ether8390.c:514,520 | ||
| 1993/0915 | ulong dp8390; | |
| 1993/0212 | uchar isr, r; | |
| 1992/1222 | ||
| 1993/1116 |
| |
| 1993/1117 | dp8390 = ((Dp8390*)ether->private)->dp8390; | |
| 1992/1222 | /* * While there is something of interest, * clear all the interrupts and process. | |
| 1993/1116/sys/src/9/pc/ether8390.c:570,575 – 1993/1117/sys/src/9/pc/ether8390.c:570,578 | ||
| 1993/1116 | static void promiscuous(Ether *ether, int on) { | |
| 1993/1117 | ulong dp8390; dp8390 = ((Dp8390*)ether->private)->dp8390; | |
| 1993/1116 | /* * Set/reset promiscuous mode. */ | |
| 1993/1116/sys/src/9/pc/ether8390.c:582,587 – 1993/1117/sys/src/9/pc/ether8390.c:585,593 | ||
| 1993/1116 | void dp8390attach(Ether *ether) { | |
| 1993/1117 | ulong dp8390; dp8390 = ((Dp8390*)ether->private)->dp8390; | |
| 1993/1116 | /* * Enable the chip for transmit/receive. * The init routine leaves the chip in monitor | |
| 1993/1116/sys/src/9/pc/ether8390.c:597,603 – 1993/1117/sys/src/9/pc/ether8390.c:603,609 | ||
| 1993/1116 | { ulong dp8390; | |
| 1993/1117 | dp8390 = ((Dp8390*)ether->private)->dp8390; | |
| 1993/1116 | /* * This is the initialisation procedure described * as 'mandatory' in the datasheet, with references | |
| 1993/1117/sys/src/9/pc/ether8390.c:14,19 – 1993/1118/sys/src/9/pc/ether8390.c:14,22 (short | long) | ||
| 1992/1222 | ||
| 1993/1116 | #include "etherif.h" | |
| 1992/1222 | ||
| 1993/1118 | extern int dp8390inb(ulong); extern void dp8390outb(ulong, uchar); | |
| 1992/1222 | enum { Cr = 0x00, /* command register, all pages */ | |
| 1993/1117/sys/src/9/pc/ether8390.c:149,158 – 1993/1118/sys/src/9/pc/ether8390.c:152,160 | ||
| 1992/1222 | static void | |
| 1993/1117 | dp8390disable(Dp8390 *dp8390) | |
| 1992/1222 | { | |
| 1993/1117 |
| |
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1992/1222 | int timo; | |
| 1993/1117 |
| |
| 1992/1222 | /* * Stop the chip. Set the Stp bit and wait for the chip * to finish whatever was on its tiny mind before it sets | |
| 1993/1117/sys/src/9/pc/ether8390.c:171,179 – 1993/1118/sys/src/9/pc/ether8390.c:173,180 | ||
| 1993/0212 | static void | |
| 1993/1117 | dp8390ring(Dp8390 *dp8390) | |
| 1993/0212 | { | |
| 1993/1117 |
| |
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1993/0212 | ||
| 1993/1117 |
| |
| 1993/1117/sys/src/9/pc/ether8390.c:188,198 – 1993/1118/sys/src/9/pc/ether8390.c:189,198 | ||
| 1992/1222 | void | |
| 1993/1116 | dp8390setea(Ether *ether) | |
| 1992/1222 | { | |
| 1993/1117 |
| |
| 1993/1118 | ulong port = ((Dp8390*)ether->private)->dp8390; | |
| 1992/1222 | uchar cr; int i; | |
| 1993/1117 |
| |
| 1992/1222 | /* * Set the ethernet address into the chip. * Take care to restore the command register | |
| 1993/1117/sys/src/9/pc/ether8390.c:210,220 – 1993/1118/sys/src/9/pc/ether8390.c:210,219 | ||
| 1993/0915 | void | |
| 1993/1116 | dp8390getea(Ether *ether) | |
| 1993/0915 | { | |
| 1993/1117 |
| |
| 1993/1118 | ulong port = ((Dp8390*)ether->private)->dp8390; | |
| 1993/0915 | uchar cr; int i; | |
| 1993/1117 |
| |
| 1993/0915 | /* | |
| 1993/1116 | * Get the ethernet address from the chip. | |
| 1993/0915 | * Take care to restore the command register | |
| 1993/1117/sys/src/9/pc/ether8390.c:232,242 – 1993/1118/sys/src/9/pc/ether8390.c:231,240 | ||
| 1993/1116 | static void* | |
| 1993/1117 | dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) | |
| 1992/1222 | { | |
| 1993/1117 |
| |
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1992/1222 | uchar cr; int timo; | |
| 1993/1117 |
| |
| 1992/1222 | /* | |
| 1993/0212 | * Read some data at offset 'from' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, and place it at | |
| 1993/1117/sys/src/9/pc/ether8390.c:282,303 – 1993/1118/sys/src/9/pc/ether8390.c:280,301 | ||
| 1992/1222 | } | |
| 1993/1116 | static void* | |
| 1993/1118 | dp8390write(Dp8390 *dp8390, ulong to, void *from, ulong len) | |
| 1992/1222 | { | |
| 1993/0915 |
| |
| 1993/1118 | ulong port = dp8390->dp8390; ulong crda; | |
| 1992/1222 | uchar cr; | |
| 1993/1117 |
| |
| 1992/1222 | /* | |
| 1993/0212 | * Write some data to offset 'to' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at * 'from' in main memory, via the I/O data port. */ | |
| 1993/0915 |
| |
| 1993/1118 | cr = dp8390inb(port+Cr) & ~Txp; dp8390outb(port+Cr, Page0|RDMAabort|Sta); dp8390outb(port+Isr, Rdc); | |
| 1992/1222 | ||
| 1993/1116 |
| |
| 1993/1118 | if(dp8390->bit16) | |
| 1993/0212 | len = ROUNDUP(len, 2); | |
| 1992/1222 | /* | |
| 1993/1117/sys/src/9/pc/ether8390.c:305,329 – 1993/1118/sys/src/9/pc/ether8390.c:303,327 | ||
| 1993/0212 | * This is straight from the DP8390[12D] datasheet, hence * the initial set up for read. | |
| 1992/1222 | */ | |
| 1993/1116 |
| |
| 1993/0915 |
| |
| 1993/1118 | crda = to-1-dp8390->bit16; dp8390outb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); dp8390outb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); dp8390outb(port+Rsar0, crda & 0xFF); dp8390outb(port+Rsar1, (crda>>8) & 0xFF); dp8390outb(port+Cr, Page0|RDMAread|Sta); | |
| 1992/1222 | ||
| 1993/0212 | for(;;){ | |
| 1993/0915 |
| |
| 1993/1118 | crda = dp8390inb(port+Crda0); crda |= dp8390inb(port+Crda1)<<8; | |
| 1993/0212 | if(crda == to){ /* * Start the remote DMA write and make sure * the registers are correct. */ | |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Cr, Page0|RDMAwrite|Sta); | |
| 1992/1222 | ||
| 1993/0915 |
| |
| 1993/1118 | crda = dp8390inb(port+Crda0); crda |= dp8390inb(port+Crda1)<<8; | |
| 1993/0212 | if(crda != to) panic("crda write %d to %d\n", crda, to); | |
| 1993/1117/sys/src/9/pc/ether8390.c:334,343 – 1993/1118/sys/src/9/pc/ether8390.c:332,341 | ||
| 1992/1222 | /* | |
| 1993/0212 | * Pump the data into the I/O port. | |
| 1992/1222 | */ | |
| 1993/1116 |
| |
| 1993/1118 | if(dp8390->bit16) outss(dp8390->data, from, len/2); | |
| 1992/1222 | else | |
| 1993/1116 |
| |
| 1993/1118 | outsb(dp8390->data, from, len); | |
| 1992/1222 | /* * Wait for the remote DMA to finish. We'll need | |
| 1993/1117/sys/src/9/pc/ether8390.c:344,366 – 1993/1118/sys/src/9/pc/ether8390.c:342,365 | ||
| 1992/1222 | * a timeout here if this ever gets called before * we know there really is a chip there. */ | |
| 1993/0915 |
| |
| 1993/1118 | while((dp8390inb(port+Isr) & Rdc) == 0) | |
| 1992/1222 | ; | |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Isr, Rdc); dp8390outb(port+Cr, cr); | |
| 1992/1222 | return (void*)to; } | |
| 1993/0212 | static uchar | |
| 1993/0915 |
| |
| 1993/1118 | getcurr(Dp8390 *dp8390) | |
| 1993/0212 | { | |
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1993/0212 | uchar cr, curr; | |
| 1993/0915 |
| |
| 1993/1118 | cr = dp8390inb(port+Cr) & ~Txp; dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); curr = dp8390inb(port+Curr); dp8390outb(port+Cr, cr); | |
| 1993/0212 | return curr; } | |
| 1993/1117/sys/src/9/pc/ether8390.c:367,384 – 1993/1118/sys/src/9/pc/ether8390.c:366,388 | ||
| 1993/0213 | static void | |
| 1993/1116 | receive(Ether *ether) | |
| 1993/0213 | { | |
| 1993/0212 |
| |
| 1993/1118 | Dp8390 *dp8390; uchar curr, *pkt; | |
| 1992/1222 | Hdr hdr; | |
| 1993/0915 |
| |
| 1993/1118 | ulong port, data, len, len1; | |
| 1993/1116 | ushort type; Netfile *f, **fp, **ep; | |
| 1992/1222 | ||
| 1993/1117 |
| |
| 1993/1116 |
| |
| 1993/1118 | dp8390 = ether->private; port = dp8390->dp8390; for(curr = getcurr(dp8390); dp8390->nxtpkt != curr; curr = getcurr(dp8390)){ | |
| 1993/1116 | ether->inpackets++; | |
| 1992/1222 | ||
| 1993/1116 |
| |
| 1993/1118 | data = dp8390->nxtpkt*Dp8390BufSz; if(dp8390->ram) memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr)); else dp8390read(dp8390, &hdr, data, sizeof(Hdr)); | |
| 1992/1222 | /* | |
| 1993/0212 | * Don't believe the upper byte count, work it | |
| 1993/1117/sys/src/9/pc/ether8390.c:385,394 – 1993/1118/sys/src/9/pc/ether8390.c:389,398 | ||
| 1993/0212 | * out from the software next-page pointer and * the current next-page pointer. | |
| 1992/1222 | */ | |
| 1993/1116 |
| |
| 1993/1118 | if(hdr.next > dp8390->nxtpkt) len1 = hdr.next - dp8390->nxtpkt - 1; | |
| 1993/0212 | else | |
| 1993/1116 |
| |
| 1993/1118 | len1 = (dp8390->pstop-dp8390->nxtpkt) + (hdr.next-dp8390->pstart) - 1; | |
| 1993/0212 | if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr))) len1--; | |
| 1993/1117/sys/src/9/pc/ether8390.c:397,409 – 1993/1118/sys/src/9/pc/ether8390.c:401,413 | ||
| 1993/0212 | /* * Chip is badly scrogged, reinitialise the ring. */ | |
| 1993/1116 |
| |
| 1993/1118 | if(hdr.next < dp8390->pstart || hdr.next >= dp8390->pstop | |
| 1993/0212 | || len < 60 || len > sizeof(Etherpkt)){ | |
| 1993/1118 | print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n", | |
| 1993/0212 | hdr.status, hdr.next, hdr.len0, hdr.len1, len); | |
| 1993/0915 |
| |
| 1993/1116 |
| |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Cr, Page0|RDMAabort|Stp); dp8390ring(dp8390); dp8390outb(port+Cr, Page0|RDMAabort|Sta); | |
| 1992/1222 | return; } | |
| 1993/1117/sys/src/9/pc/ether8390.c:412,431 – 1993/1118/sys/src/9/pc/ether8390.c:416,442 | ||
| 1993/1116 | * If the packet wraps round the hardware ring, read it in two pieces. | |
| 1993/0212 | */ | |
| 1993/1116 | if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok){ | |
| 1993/1118 | pkt = (uchar*)ðer->rpkt; | |
| 1992/1222 | data += sizeof(Hdr); | |
| 1993/0212 |
| |
| 1993/1118 | len1 = len; | |
| 1993/0212 | ||
| 1993/1116 |
| |
| 1993/1118 | if((data+len1) >= dp8390->pstop*Dp8390BufSz){ ulong count = dp8390->pstop*Dp8390BufSz - data; | |
| 1993/0212 | ||
| 1993/1116 |
| |
| 1993/1118 | if(dp8390->ram) memmove(pkt, (void*)(ether->mem+data), count); else dp8390read(dp8390, pkt, data, count); | |
| 1993/0212 | pkt += count; | |
| 1993/1116 |
| |
| 1993/0212 |
| |
| 1993/1118 | data = dp8390->pstart*Dp8390BufSz; len1 -= count; | |
| 1992/1222 | } | |
| 1993/0212 |
| |
| 1993/1116 |
| |
| 1993/1118 | if(len1){ if(dp8390->ram) memmove(pkt, (void*)(ether->mem+data), len1); else dp8390read(dp8390, pkt, data, len1); } | |
| 1993/0212 | ||
| 1993/1116 | /* * Copy the packet to whoever wants it. | |
| 1993/1117/sys/src/9/pc/ether8390.c:440,530 – 1993/1118/sys/src/9/pc/ether8390.c:451,564 | ||
| 1992/1222 | } | |
| 1993/0212 | /* | |
| 1993/1118 | * Finished with this packet, update the | |
| 1993/0212 | * hardware and software ring pointers. */ | |
| 1993/1116 |
| |
| 1993/1118 | dp8390->nxtpkt = hdr.next; | |
| 1993/0212 | hdr.next--; | |
| 1993/1116 |
| |
| 1993/0915 |
| |
| 1993/1118 | if(hdr.next < dp8390->pstart) hdr.next = dp8390->pstop-1; dp8390outb(port+Bnry, hdr.next); | |
| 1992/1222 | } } | |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1993/1116 |
| |
| 1993/1118 | static int istxbusy(void *arg) | |
| 1992/1222 | { | |
| 1993/0915 |
| |
| 1992/1222 |
| |
| 1993/1118 | return ((Dp8390*)arg)->busy == 0; } | |
| 1993/0212 | ||
| 1993/1117 |
| |
| 1993/1116 |
| |
| 1993/1118 | static long write(Ether *ether, void *buf, long n) { Dp8390 *dp8390; ulong port; | |
| 1993/0213 | ||
| 1993/1116 |
| |
| 1993/1118 | dp8390 = ether->private; port = dp8390->dp8390; | |
| 1993/0213 | ||
| 1993/1116 |
| |
| 1993/0213 | ||
| 1993/0915 |
| |
| 1993/1118 | qlock(ðer->tlock); if(waserror()) { qunlock(ðer->tlock); nexterror(); | |
| 1993/0212 | } | |
| 1993/1118 | tsleep(ðer->tr, istxbusy, dp8390, 10000); if(dp8390->busy) print("dp8390: transmitter jammed\n"); dp8390->busy = 1; if(dp8390->ram) memmove((void*)(ether->mem+dp8390->tstart*Dp8390BufSz), buf, n); else dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, buf, n); dp8390outb(port+Tbcr0, n & 0xFF); dp8390outb(port+Tbcr1, (n>>8) & 0xFF); dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); poperror(); qunlock(ðer->tlock); return n; | |
| 1993/0212 | } | |
| 1993/1116 | static void overflow(Ether *ether) | |
| 1993/0212 | { | |
| 1993/0915 |
| |
| 1993/1118 | Dp8390 *dp8390; ulong port; | |
| 1993/0212 | uchar txp; int resend; | |
| 1993/1117 |
| |
| 1993/1118 | dp8390 = ether->private; port = dp8390->dp8390; | |
| 1993/0212 | /* * The following procedure is taken from the DP8390[12D] datasheet, * it seems pretty adamant that this is what has to be done. */ | |
| 1993/0915 |
| |
| 1993/1118 | txp = dp8390inb(port+Cr) & Txp; dp8390outb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/0212 | delay(2); | |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Rbcr0, 0); dp8390outb(port+Rbcr1, 0); | |
| 1993/0212 | resend = 0; | |
| 1993/0915 |
| |
| 1993/1118 | if(txp && (dp8390inb(port+Isr) & (Txe|Ptx)) == 0) | |
| 1993/0212 | resend = 1; | |
| 1993/0915 |
| |
| 1993/1116 |
| |
| 1993/0915 |
| |
| 1993/1116 |
| |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Tcr, Lb); dp8390outb(port+Cr, Page0|RDMAabort|Sta); receive(ether); dp8390outb(port+Isr, Ovw); dp8390outb(port+Tcr, 0); | |
| 1993/0212 | if(resend) | |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/0212 | } | |
| 1993/1116 | static void interrupt(Ether *ether) | |
| 1993/0212 | { | |
| 1993/0915 |
| |
| 1993/1118 | Dp8390 *dp8390; ulong port; | |
| 1993/0212 | uchar isr, r; | |
| 1992/1222 | ||
| 1993/1117 |
| |
| 1993/1118 | dp8390 = ether->private; port = dp8390->dp8390; | |
| 1992/1222 | /* * While there is something of interest, * clear all the interrupts and process. */ | |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Imr, 0x00); while(isr = dp8390inb(port+Isr)){ | |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/1116 | overflow(ether); | |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Isr, Ovw); | |
| 1993/1116 | ether->overflows++; | |
| 1992/1222 | } | |
| 1993/1117/sys/src/9/pc/ether8390.c:534,540 – 1993/1118/sys/src/9/pc/ether8390.c:568,574 | ||
| 1992/1222 | */ if(isr & (Rxe|Prx)){ | |
| 1993/1116 | receive(ether); | |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Isr, Rxe|Prx); | |
| 1992/1222 | } /* | |
| 1993/1117/sys/src/9/pc/ether8390.c:543,593 – 1993/1118/sys/src/9/pc/ether8390.c:577,626 | ||
| 1992/1222 | * and wake the output routine. */ if(isr & (Txe|Ptx)){ | |
| 1993/0915 |
| |
| 1993/1118 | r = dp8390inb(port+Tsr); | |
| 1993/0212 | if(isr & Txe){ | |
| 1993/1116 |
| |
| 1993/0212 |
| |
| 1993/1118 | if((r & (Cdh|Fu|Crs|Abt))) print("dp8390: Tsr#%2.2ux\n", r); | |
| 1993/1116 | ether->oerrs++; | |
| 1993/0212 | } | |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Isr, Txe|Ptx); | |
| 1993/0212 | if(isr & Ptx) | |
| 1993/1116 | ether->outpackets++; | |
| 1993/1118 | dp8390->busy = 0; | |
| 1993/1116 | wakeup(ðer->tr); | |
| 1992/1222 | } | |
| 1993/0212 | if(isr & Cnt){ | |
| 1993/1116 |
| |
| 1993/0915 |
| |
| 1993/1118 | ether->frames += dp8390inb(port+Cntr0); ether->crcs += dp8390inb(port+Cntr1); ether->buffs += dp8390inb(port+Cntr2); dp8390outb(port+Isr, Cnt); | |
| 1993/0212 | } | |
| 1992/1222 | } | |
| 1993/0915 |
| |
| 1993/1118 | dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1993/1116 | } static void | |
| 1993/1118 | promiscuous(void *arg, int on) | |
| 1993/1116 | { | |
| 1993/1117 |
| |
| 1993/1118 | Dp8390 *dp8390 = ((Ether*)arg)->private; | |
| 1993/1117 |
| |
| 1993/1116 | /* * Set/reset promiscuous mode. */ if(on) | |
| 1993/1118 | dp8390outb(dp8390->dp8390+Rcr, Pro|Ab); | |
| 1993/1116 | else | |
| 1993/1118 | dp8390outb(dp8390->dp8390+Rcr, Ab); | |
| 1993/1116 | } | |
| 1993/1118 | static void attach(Ether *ether) | |
| 1993/1116 | { | |
| 1993/1117 |
| |
| 1993/1118 | Dp8390 *dp8390 = ether->private; | |
| 1993/1117 |
| |
| 1993/1116 | /* * Enable the chip for transmit/receive. * The init routine leaves the chip in monitor | |
| 1993/1117/sys/src/9/pc/ether8390.c:594,625 – 1993/1118/sys/src/9/pc/ether8390.c:627,661 | ||
| 1993/1116 | * mode. Clear the missed-packet counter, it * increments while in monitor mode. */ | |
| 1993/1118 | dp8390outb(dp8390->dp8390+Rcr, Ab); dp8390inb(dp8390->dp8390+Cntr2); | |
| 1993/1116 | } | |
| 1993/1118 | int | |
| 1993/1116 | dp8390reset(Ether *ether) { | |
| 1993/1118 | Dp8390 *dp8390; ulong port; | |
| 1993/1116 | ||
| 1993/1117 |
| |
| 1993/1118 | dp8390 = ether->private; port = dp8390->dp8390; | |
| 1993/1116 | /* * This is the initialisation procedure described * as 'mandatory' in the datasheet, with references * to the 3Com503 technical reference manual. */ | |
| 1993/1118 | dp8390disable(dp8390); if(dp8390->bit16) dp8390outb(port+Dcr, Ft4|Ls|Wts); | |
| 1993/1116 | else | |
| 1993/1118 | dp8390outb(port+Dcr, Ft4|Ls); | |
| 1993/1116 |
| |
| 1993/1118 | dp8390outb(port+Rbcr0, 0); dp8390outb(port+Rbcr1, 0); | |
| 1993/1116 |
| |
| 1993/1118 | dp8390outb(port+Tcr, 0); dp8390outb(port+Rcr, Mon); | |
| 1993/1116 | /* * Init the ring hardware and software ring pointers. | |
| 1993/1117/sys/src/9/pc/ether8390.c:626,642 – 1993/1118/sys/src/9/pc/ether8390.c:662,678 | ||
| 1993/1116 | * Can't initialise ethernet address as we may not know * it yet. */ | |
| 1993/1118 | dp8390ring(dp8390); dp8390outb(port+Tpsr, dp8390->tstart); | |
| 1993/1116 |
| |
| 1993/1118 | dp8390outb(port+Isr, 0xFF); dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1993/1116 | /* * Leave the chip initialised, * but in monitor mode. */ | |
| 1993/1118 | dp8390outb(port+Cr, Page0|RDMAabort|Sta); | |
| 1993/1116 | /* * Set up the software configuration. | |
| 1993/1118/sys/src/9/pc/ether8390.c:446,452 – 1993/1119/sys/src/9/pc/ether8390.c:446,455 (short | long) | ||
| 1993/1116 | for(fp = ether->f; fp < ep; fp++) { f = *fp; if(f && (f->type == type || f->type < 0)) | |
| 1993/1119 | { print("Q%d|", len); | |
| 1993/1116 | qproduce(f->in, ðer->rpkt, len); | |
| 1993/1119 | } | |
| 1993/1116 | } | |
| 1992/1222 | } | |
| 1993/1118/sys/src/9/pc/ether8390.c:464,472 – 1993/1119/sys/src/9/pc/ether8390.c:467,475 | ||
| 1992/1222 | } | |
| 1993/1118 | static int | |
| 1993/1119 | istxavail(void *arg) | |
| 1992/1222 | { | |
| 1993/1118 |
| |
| 1993/1119 | return ((Ether*)arg)->tlen == 0; | |
| 1993/1118 | } | |
| 1993/0212 | ||
| 1993/1118 | static long | |
| 1993/1118/sys/src/9/pc/ether8390.c:478,494 – 1993/1119/sys/src/9/pc/ether8390.c:481,493 | ||
| 1993/1118 | dp8390 = ether->private; port = dp8390->dp8390; | |
| 1993/0213 | ||
| 1993/1118 |
| |
| 1993/1119 | tsleep(ðer->tr, istxavail, ether, 10000); if(ether->tlen){ print("dp8390: transmitter jammed\n"); return 0; | |
| 1993/0212 | } | |
| 1993/1119 | ether->tlen = n; | |
| 1993/1118 |
| |
| 1993/1118/sys/src/9/pc/ether8390.c:498,506 – 1993/1119/sys/src/9/pc/ether8390.c:497,502 | ||
| 1993/1118 | dp8390outb(port+Tbcr1, (n>>8) & 0xFF); dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/0212 | } | |
| 1993/1118/sys/src/9/pc/ether8390.c:555,560 – 1993/1119/sys/src/9/pc/ether8390.c:551,557 | ||
| 1992/1222 | */ | |
| 1993/1118 | dp8390outb(port+Imr, 0x00); while(isr = dp8390inb(port+Isr)){ | |
| 1993/1119 | print("I%2.2ux|", isr); | |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/1116 | overflow(ether); | |
| 1993/1118/sys/src/9/pc/ether8390.c:588,594 – 1993/1119/sys/src/9/pc/ether8390.c:585,591 | ||
| 1993/0212 | if(isr & Ptx) | |
| 1993/1116 | ether->outpackets++; | |
| 1993/1118 |
| |
| 1993/1119 | ether->tlen = 0; | |
| 1993/1116 | wakeup(ðer->tr); | |
| 1992/1222 | } | |
| 1993/0212 | ||
| 1993/1119/sys/src/9/pc/ether8390.c:446,455 – 1993/1120/sys/src/9/pc/ether8390.c:446,452 (short | long) | ||
| 1993/1116 | for(fp = ether->f; fp < ep; fp++) { f = *fp; if(f && (f->type == type || f->type < 0)) | |
| 1993/1119 |
| |
| 1993/1116 | qproduce(f->in, ðer->rpkt, len); | |
| 1993/1119 |
| |
| 1993/1116 | } | |
| 1992/1222 | } | |
| 1993/1119/sys/src/9/pc/ether8390.c:473,482 – 1993/1120/sys/src/9/pc/ether8390.c:470,480 | ||
| 1993/1118 | } | |
| 1993/0212 | ||
| 1993/1118 | static long | |
| 1993/1120 | write(Ether *ether, void *buf, long len) | |
| 1993/1118 | { Dp8390 *dp8390; ulong port; | |
| 1993/1120 | Etherpkt *pkt; | |
| 1993/0213 | ||
| 1993/1118 | dp8390 = ether->private; port = dp8390->dp8390; | |
| 1993/1119/sys/src/9/pc/ether8390.c:486,503 – 1993/1120/sys/src/9/pc/ether8390.c:484,521 | ||
| 1993/1119 | print("dp8390: transmitter jammed\n"); return 0; | |
| 1993/0212 | } | |
| 1993/1119 |
| |
| 1993/1120 | ether->tlen = len; | |
| 1993/1118 | ||
| 1993/1120 | /* * If it's a shared-memory interface, copy the packet * directly to the shared-memory area. Otherwise, copy * it to a staging buffer so the I/O-port write can be * done in one. */ | |
| 1993/1118 | if(dp8390->ram) | |
| 1993/1120 | pkt = (Etherpkt*)(ether->mem+dp8390->tstart*Dp8390BufSz); | |
| 1993/1118 | else | |
| 1993/1120 | pkt = ðer->tpkt; memmove(pkt, buf, len); | |
| 1993/1118 |
| |
| 1993/1120 | /* * Give the packet a source address and make sure it * is of minimum length. */ memmove(pkt->s, ether->ea, sizeof(ether->ea)); if(len < ETHERMINTU){ memset(pkt->d+len, 0, ETHERMINTU-len); len = ETHERMINTU; } if(dp8390->ram == 0) dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, pkt, len); dp8390outb(port+Tbcr0, len & 0xFF); dp8390outb(port+Tbcr1, (len>>8) & 0xFF); | |
| 1993/1118 | dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/1120 | return len; | |
| 1993/0212 | } | |
| 1993/1116 | static void | |
| 1993/1119/sys/src/9/pc/ether8390.c:551,557 – 1993/1120/sys/src/9/pc/ether8390.c:569,574 | ||
| 1992/1222 | */ | |
| 1993/1118 | dp8390outb(port+Imr, 0x00); while(isr = dp8390inb(port+Isr)){ | |
| 1993/1119 |
| |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/1116 | overflow(ether); | |
| 1993/1120/sys/src/9/pc/ether8390.c:554,565 – 1993/1124/sys/src/9/pc/ether8390.c:554,569 (short | long) | ||
| 1993/0212 | } | |
| 1993/1116 | static void | |
| 1993/1124 | interrupt(Ureg *ur, void *arg) | |
| 1993/0212 | { | |
| 1993/1124 | Ether *ether; | |
| 1993/1118 | Dp8390 *dp8390; ulong port; | |
| 1993/0212 | uchar isr, r; | |
| 1992/1222 | ||
| 1993/1124 | USED(ur); ether = arg; | |
| 1993/1118 | dp8390 = ether->private; port = dp8390->dp8390; | |
| 1993/1124/sys/src/9/pc/ether8390.c:228,234 – 1994/0128/sys/src/9/pc/ether8390.c:228,234 (short | long) | ||
| 1993/1117 | dp8390outb(port+Cr, cr); | |
| 1993/0915 | } | |
| 1993/1116 |
| |
| 1994/0128 | void* | |
| 1993/1117 | dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) | |
| 1992/1222 | { | |
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1993/1124/sys/src/9/pc/ether8390.c:279,285 – 1994/0128/sys/src/9/pc/ether8390.c:279,285 | ||
| 1992/1222 | return to; } | |
| 1993/1116 |
| |
| 1994/0128 | void* | |
| 1993/1118 | dp8390write(Dp8390 *dp8390, ulong to, void *from, ulong len) | |
| 1992/1222 | { | |
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1994/0128/sys/src/9/pc/ether8390.c:14,21 – 1994/0130/sys/src/9/pc/ether8390.c:14,21 (short | long) | ||
| 1992/1222 | ||
| 1993/1116 | #include "etherif.h" | |
| 1992/1222 | ||
| 1993/1118 |
| |
| 1994/0130 | extern int slowinb(ulong); extern void slowoutb(ulong, uchar); | |
| 1993/1118 | ||
| 1992/1222 | enum { Cr = 0x00, /* command register, all pages */ | |
| 1994/0128/sys/src/9/pc/ether8390.c:163,172 – 1994/0130/sys/src/9/pc/ether8390.c:163,172 | ||
| 1992/1222 | * chip there if this is called when probing for a device * at boot. */ | |
| 1993/1117 |
| |
| 1994/0130 | slowoutb(port+Cr, Page0|RDMAabort|Stp); slowoutb(port+Rbcr0, 0); slowoutb(port+Rbcr1, 0); for(timo = 10000; (slowinb(port+Isr) & Rst) == 0 && timo; timo--) | |
| 1992/1222 | ; } | |
| 1994/0128/sys/src/9/pc/ether8390.c:175,187 – 1994/0130/sys/src/9/pc/ether8390.c:175,187 | ||
| 1993/0212 | { | |
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1993/0212 | ||
| 1993/1117 |
| |
| 1994/0130 | slowoutb(port+Pstart, dp8390->pstart); slowoutb(port+Pstop, dp8390->pstop); slowoutb(port+Bnry, dp8390->pstop-1); | |
| 1993/0212 | ||
| 1993/1117 |
| |
| 1994/0130 | slowoutb(port+Cr, Page1|RDMAabort|Stp); slowoutb(port+Curr, dp8390->pstart); slowoutb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/0915 | ||
| 1993/1117 | dp8390->nxtpkt = dp8390->pstart; | |
| 1993/0212 | } | |
| 1994/0128/sys/src/9/pc/ether8390.c:200,210 – 1994/0130/sys/src/9/pc/ether8390.c:200,210 | ||
| 1992/1222 | * addresses as we never set the multicast * enable. */ | |
| 1993/1117 |
| |
| 1994/0130 | cr = slowinb(port+Cr) & ~Txp; slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1993/1116 | for(i = 0; i < sizeof(ether->ea); i++) | |
| 1993/1117 |
| |
| 1994/0130 | slowoutb(port+Par0+i, ether->ea[i]); slowoutb(port+Cr, cr); | |
| 1992/1222 | } | |
| 1993/0915 | void | |
| 1994/0128/sys/src/9/pc/ether8390.c:221,231 – 1994/0130/sys/src/9/pc/ether8390.c:221,231 | ||
| 1993/0915 | * addresses as we never set the multicast * enable. */ | |
| 1993/1117 |
| |
| 1994/0130 | cr = slowinb(port+Cr) & ~Txp; slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1993/1116 | for(i = 0; i < sizeof(ether->ea); i++) | |
| 1993/1117 |
| |
| 1994/0130 | ether->ea[i] = slowinb(port+Par0+i); slowoutb(port+Cr, cr); | |
| 1993/0915 | } | |
| 1994/0128 | void* | |
| 1994/0128/sys/src/9/pc/ether8390.c:240,248 – 1994/0130/sys/src/9/pc/ether8390.c:240,248 | ||
| 1992/1222 | * using the DP8390 remote DMA facility, and place it at * 'to' in main memory, via the I/O data port. */ | |
| 1993/1117 |
| |
| 1994/0130 | cr = slowinb(port+Cr) & ~Txp; slowoutb(port+Cr, Page0|RDMAabort|Sta); slowoutb(port+Isr, Rdc); | |
| 1992/1222 | /* * Set up the remote DMA address and count. | |
| 1994/0128/sys/src/9/pc/ether8390.c:249,264 – 1994/0130/sys/src/9/pc/ether8390.c:249,264 | ||
| 1992/1222 | */ | |
| 1993/1117 | if(dp8390->bit16) | |
| 1992/1222 | len = ROUNDUP(len, 2); | |
| 1993/1117 |
| |
| 1994/0130 | slowoutb(port+Rbcr0, len & 0xFF); slowoutb(port+Rbcr1, (len>>8) & 0xFF); slowoutb(port+Rsar0, from & 0xFF); slowoutb(port+Rsar1, (from>>8) & 0xFF); | |
| 1992/1222 | /* * Start the remote DMA read and suck the data * out of the I/O port. */ | |
| 1993/1117 |
| |
| 1994/0130 | slowoutb(port+Cr, Page0|RDMAread|Sta); | |
| 1993/1117 | if(dp8390->bit16) inss(dp8390->data, to, len/2); | |
| 1992/1222 | else | |
| 1994/0128/sys/src/9/pc/ether8390.c:271,281 – 1994/0130/sys/src/9/pc/ether8390.c:271,281 | ||
| 1992/1222 | * to the miracles of the bus, we could get this far * and still be talking to a slot full of nothing. */ | |
| 1993/1117 |
| |
| 1994/0130 | for(timo = 10000; (slowinb(port+Isr) & Rdc) == 0 && timo; timo--) | |
| 1992/1222 | ; | |
| 1993/1117 |
| |
| 1994/0130 | slowoutb(port+Isr, Rdc); slowoutb(port+Cr, cr); | |
| 1992/1222 | return to; } | |
| 1994/0128/sys/src/9/pc/ether8390.c:291,299 – 1994/0130/sys/src/9/pc/ether8390.c:291,299 | ||
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at * 'from' in main memory, via the I/O data port. */ | |
| 1993/1118 |
| |
| 1994/0130 | cr = slowinb(port+Cr) & ~Txp; slowoutb(port+Cr, Page0|RDMAabort|Sta); slowoutb(port+Isr, Rdc); | |
| 1992/1222 | ||
| 1993/1118 | if(dp8390->bit16) | |
| 1993/0212 | len = ROUNDUP(len, 2); | |
| 1994/0128/sys/src/9/pc/ether8390.c:304,327 – 1994/0130/sys/src/9/pc/ether8390.c:304,327 | ||
| 1993/0212 | * the initial set up for read. | |
| 1992/1222 | */ | |
| 1993/1118 | crda = to-1-dp8390->bit16; | |
| 1994/0130 | slowoutb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); slowoutb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); slowoutb(port+Rsar0, crda & 0xFF); slowoutb(port+Rsar1, (crda>>8) & 0xFF); slowoutb(port+Cr, Page0|RDMAread|Sta); | |
| 1992/1222 | ||
| 1993/0212 | for(;;){ | |
| 1993/1118 |
| |
| 1994/0130 | crda = slowinb(port+Crda0); crda |= slowinb(port+Crda1)<<8; | |
| 1993/0212 | if(crda == to){ /* * Start the remote DMA write and make sure * the registers are correct. */ | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Cr, Page0|RDMAwrite|Sta); | |
| 1992/1222 | ||
| 1993/1118 |
| |
| 1994/0130 | crda = slowinb(port+Crda0); crda |= slowinb(port+Crda1)<<8; | |
| 1993/0212 | if(crda != to) panic("crda write %d to %d\n", crda, to); | |
| 1994/0128/sys/src/9/pc/ether8390.c:342,352 – 1994/0130/sys/src/9/pc/ether8390.c:342,352 | ||
| 1992/1222 | * a timeout here if this ever gets called before * we know there really is a chip there. */ | |
| 1993/1118 |
| |
| 1994/0130 | while((slowinb(port+Isr) & Rdc) == 0) | |
| 1992/1222 | ; | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Isr, Rdc); slowoutb(port+Cr, cr); | |
| 1992/1222 | return (void*)to; } | |
| 1994/0128/sys/src/9/pc/ether8390.c:356,365 – 1994/0130/sys/src/9/pc/ether8390.c:356,365 | ||
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1993/0212 | uchar cr, curr; | |
| 1993/1118 |
| |
| 1994/0130 | cr = slowinb(port+Cr) & ~Txp; slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); curr = slowinb(port+Curr); slowoutb(port+Cr, cr); | |
| 1993/0212 | return curr; } | |
| 1994/0128/sys/src/9/pc/ether8390.c:405,413 – 1994/0130/sys/src/9/pc/ether8390.c:405,413 | ||
| 1993/0212 | || len < 60 || len > sizeof(Etherpkt)){ | |
| 1993/1118 | print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n", | |
| 1993/0212 | hdr.status, hdr.next, hdr.len0, hdr.len1, len); | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/1118 | dp8390ring(dp8390); | |
| 1994/0130 | slowoutb(port+Cr, Page0|RDMAabort|Sta); | |
| 1992/1222 | return; } | |
| 1994/0128/sys/src/9/pc/ether8390.c:459,465 – 1994/0130/sys/src/9/pc/ether8390.c:459,465 | ||
| 1993/0212 | hdr.next--; | |
| 1993/1118 | if(hdr.next < dp8390->pstart) hdr.next = dp8390->pstop-1; | |
| 1994/0130 | slowoutb(port+Bnry, hdr.next); | |
| 1992/1222 | } } | |
| 1994/0128/sys/src/9/pc/ether8390.c:511,519 – 1994/0130/sys/src/9/pc/ether8390.c:511,519 | ||
| 1993/1120 | if(dp8390->ram == 0) dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, pkt, len); | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Tbcr0, len & 0xFF); slowoutb(port+Tbcr1, (len>>8) & 0xFF); slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/1118 | ||
| 1993/1120 | return len; | |
| 1993/0212 | } | |
| 1994/0128/sys/src/9/pc/ether8390.c:533,556 – 1994/0130/sys/src/9/pc/ether8390.c:533,556 | ||
| 1993/0212 | * The following procedure is taken from the DP8390[12D] datasheet, * it seems pretty adamant that this is what has to be done. */ | |
| 1993/1118 |
| |
| 1994/0130 | txp = slowinb(port+Cr) & Txp; slowoutb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/0212 | delay(2); | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Rbcr0, 0); slowoutb(port+Rbcr1, 0); | |
| 1993/0212 | resend = 0; | |
| 1993/1118 |
| |
| 1994/0130 | if(txp && (slowinb(port+Isr) & (Txe|Ptx)) == 0) | |
| 1993/0212 | resend = 1; | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Tcr, Lb); slowoutb(port+Cr, Page0|RDMAabort|Sta); | |
| 1993/1118 | receive(ether); | |
| 1994/0130 | slowoutb(port+Isr, Ovw); slowoutb(port+Tcr, 0); | |
| 1993/0212 | if(resend) | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/0212 | } | |
| 1993/1116 | static void | |
| 1994/0128/sys/src/9/pc/ether8390.c:571,582 – 1994/0130/sys/src/9/pc/ether8390.c:571,582 | ||
| 1992/1222 | * While there is something of interest, * clear all the interrupts and process. */ | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Imr, 0x00); while(isr = slowinb(port+Isr)){ | |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/1116 | overflow(ether); | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Isr, Ovw); | |
| 1993/1116 | ether->overflows++; | |
| 1992/1222 | } | |
| 1994/0128/sys/src/9/pc/ether8390.c:586,592 – 1994/0130/sys/src/9/pc/ether8390.c:586,592 | ||
| 1992/1222 | */ if(isr & (Rxe|Prx)){ | |
| 1993/1116 | receive(ether); | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Isr, Rxe|Prx); | |
| 1992/1222 | } /* | |
| 1994/0128/sys/src/9/pc/ether8390.c:595,601 – 1994/0130/sys/src/9/pc/ether8390.c:595,601 | ||
| 1992/1222 | * and wake the output routine. */ if(isr & (Txe|Ptx)){ | |
| 1993/1118 |
| |
| 1994/0130 | r = slowinb(port+Tsr); | |
| 1993/0212 | if(isr & Txe){ | |
| 1993/1118 | if((r & (Cdh|Fu|Crs|Abt))) print("dp8390: Tsr#%2.2ux\n", r); | |
| 1994/0128/sys/src/9/pc/ether8390.c:602,608 – 1994/0130/sys/src/9/pc/ether8390.c:602,608 | ||
| 1993/1116 | ether->oerrs++; | |
| 1993/0212 | } | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Isr, Txe|Ptx); | |
| 1993/0212 | if(isr & Ptx) | |
| 1993/1116 | ether->outpackets++; | |
| 1994/0128/sys/src/9/pc/ether8390.c:611,623 – 1994/0130/sys/src/9/pc/ether8390.c:611,623 | ||
| 1992/1222 | } | |
| 1993/0212 | if(isr & Cnt){ | |
| 1993/1118 |
| |
| 1994/0130 | ether->frames += slowinb(port+Cntr0); ether->crcs += slowinb(port+Cntr1); ether->buffs += slowinb(port+Cntr2); slowoutb(port+Isr, Cnt); | |
| 1993/0212 | } | |
| 1992/1222 | } | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1993/1116 | } static void | |
| 1994/0128/sys/src/9/pc/ether8390.c:629,637 – 1994/0130/sys/src/9/pc/ether8390.c:629,637 | ||
| 1993/1116 | * Set/reset promiscuous mode. */ if(on) | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(dp8390->dp8390+Rcr, Pro|Ab); | |
| 1993/1116 | else | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(dp8390->dp8390+Rcr, Ab); | |
| 1993/1116 | } | |
| 1993/1118 | static void | |
| 1994/0128/sys/src/9/pc/ether8390.c:645,652 – 1994/0130/sys/src/9/pc/ether8390.c:645,652 | ||
| 1993/1116 | * mode. Clear the missed-packet counter, it * increments while in monitor mode. */ | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(dp8390->dp8390+Rcr, Ab); slowinb(dp8390->dp8390+Cntr2); | |
| 1993/1116 | } | |
| 1993/1118 | int | |
| 1994/0128/sys/src/9/pc/ether8390.c:665,679 – 1994/0130/sys/src/9/pc/ether8390.c:665,679 | ||
| 1993/1116 | */ | |
| 1993/1118 | dp8390disable(dp8390); if(dp8390->bit16) | |
| 1994/0130 | slowoutb(port+Dcr, Ft4|Ls|Wts); | |
| 1993/1116 | else | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Dcr, Ft4|Ls); | |
| 1993/1116 | ||
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Rbcr0, 0); slowoutb(port+Rbcr1, 0); | |
| 1993/1116 | ||
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Tcr, 0); slowoutb(port+Rcr, Mon); | |
| 1993/1116 | /* * Init the ring hardware and software ring pointers. | |
| 1994/0128/sys/src/9/pc/ether8390.c:681,696 – 1994/0130/sys/src/9/pc/ether8390.c:681,696 | ||
| 1993/1116 | * it yet. */ | |
| 1993/1118 | dp8390ring(dp8390); | |
| 1994/0130 | slowoutb(port+Tpsr, dp8390->tstart); | |
| 1993/1116 | ||
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Isr, 0xFF); slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1993/1116 | /* * Leave the chip initialised, * but in monitor mode. */ | |
| 1993/1118 |
| |
| 1994/0130 | slowoutb(port+Cr, Page0|RDMAabort|Sta); | |
| 1993/1116 | /* * Set up the software configuration. | |
| 1994/0130/sys/src/9/pc/ether8390.c:285,291 – 1994/0201/sys/src/9/pc/ether8390.c:285,293 (short | long) | ||
| 1993/1118 | ulong port = dp8390->dp8390; ulong crda; | |
| 1992/1222 | uchar cr; | |
| 1994/0201 | int s, tries; | |
| 1992/1222 | ||
| 1994/0201 | s = splhi(); | |
| 1992/1222 | /* | |
| 1993/0212 | * Write some data to offset 'to' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at | |
| 1994/0130/sys/src/9/pc/ether8390.c:336,341 – 1994/0201/sys/src/9/pc/ether8390.c:338,344 | ||
| 1993/1118 | outss(dp8390->data, from, len/2); | |
| 1992/1222 | else | |
| 1993/1118 | outsb(dp8390->data, from, len); | |
| 1994/0201 | splx(s); | |
| 1992/1222 | /* * Wait for the remote DMA to finish. We'll need | |
| 1994/0130/sys/src/9/pc/ether8390.c:342,349 – 1994/0201/sys/src/9/pc/ether8390.c:345,356 | ||
| 1992/1222 | * a timeout here if this ever gets called before * we know there really is a chip there. */ | |
| 1994/0201 | tries = 0; | |
| 1994/0130 | while((slowinb(port+Isr) & Rdc) == 0) | |
| 1992/1222 |
| |
| 1994/0201 | if(tries++ >= 10000000){ print("dp8390write whoops\n"); break; } | |
| 1992/1222 | ||
| 1994/0130 | slowoutb(port+Isr, Rdc); slowoutb(port+Cr, cr); | |
| 1994/0201/sys/src/9/pc/ether8390.c:287,293 – 1994/0202/sys/src/9/pc/ether8390.c:287,298 (short | long) | ||
| 1992/1222 | uchar cr; | |
| 1994/0201 | int s, tries; | |
| 1992/1222 | ||
| 1994/0202 | /* * Keep out interrupts since reading and writing * use the same DMA engine. */ | |
| 1994/0201 | s = splhi(); | |
| 1994/0202 | ||
| 1992/1222 | /* | |
| 1993/0212 | * Write some data to offset 'to' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at | |
| 1994/0201/sys/src/9/pc/ether8390.c:338,359 – 1994/0202/sys/src/9/pc/ether8390.c:343,365 | ||
| 1993/1118 | outss(dp8390->data, from, len/2); | |
| 1992/1222 | else | |
| 1993/1118 | outsb(dp8390->data, from, len); | |
| 1994/0201 |
| |
| 1992/1222 | /* | |
| 1994/0202 | * Wait for the remote DMA to finish. It should * be almost immediate. | |
| 1992/1222 | */ | |
| 1994/0201 | tries = 0; | |
| 1994/0130 |
| |
| 1994/0201 |
| |
| 1994/0202 | while((slowinb(port+Isr) & Rdc) == 0){ if(tries++ >= 100000){ print("dp8390write dma timed out\n"); | |
| 1994/0201 | break; } | |
| 1994/0202 | } | |
| 1992/1222 | ||
| 1994/0130 | slowoutb(port+Isr, Rdc); slowoutb(port+Cr, cr); | |
| 1994/0202 | splx(s); | |
| 1992/1222 | return (void*)to; } | |
| 1994/0201/sys/src/9/pc/ether8390.c:377,384 – 1994/0202/sys/src/9/pc/ether8390.c:383,388 | ||
| 1993/1118 | uchar curr, *pkt; | |
| 1992/1222 | Hdr hdr; | |
| 1993/1118 | ulong port, data, len, len1; | |
| 1993/1116 |
| |
| 1992/1222 | ||
| 1993/1118 | dp8390 = ether->private; port = dp8390->dp8390; | |
| 1994/0201/sys/src/9/pc/ether8390.c:421,426 – 1994/0202/sys/src/9/pc/ether8390.c:425,433 | ||
| 1993/0212 | /* | |
| 1993/1116 | * If it's a good packet read it in to the software buffer. * If the packet wraps round the hardware ring, read it in two pieces. | |
| 1994/0202 | * * We could conceivably remove the copy into rpkt here by wrapping * this up with the etherrloop code. | |
| 1993/0212 | */ | |
| 1993/1116 | if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok){ | |
| 1993/1118 | pkt = (uchar*)ðer->rpkt; | |
| 1994/0201/sys/src/9/pc/ether8390.c:448,460 – 1994/0202/sys/src/9/pc/ether8390.c:455,461 | ||
| 1993/1116 | /* * Copy the packet to whoever wants it. */ | |
| 1994/0202 | etherrloop(ether, ðer->rpkt, len); | |
| 1992/1222 | } | |
| 1993/0212 | /* | |
| 1994/0202/sys/src/9/pc/ether8390.c:455,461 – 1994/0715/sys/src/9/pc/ether8390.c:455,461 (short | long) | ||
| 1993/1116 | /* * Copy the packet to whoever wants it. */ | |
| 1994/0202 |
| |
| 1994/0715 | etherrloop(ether, ðer->rpkt, len, 1); | |
| 1992/1222 | } | |
| 1993/0212 | /* | |
| 1994/0715/sys/src/9/pc/ether8390.c:14,22 – 1995/0408/sys/src/9/pc/ether8390.c:14,19 (short | long) | ||
| 1992/1222 | ||
| 1993/1116 | #include "etherif.h" | |
| 1992/1222 | ||
| 1994/0130 |
| |
| 1993/1118 | ||
| 1992/1222 | enum { Cr = 0x00, /* command register, all pages */ | |
| 1994/0715/sys/src/9/pc/ether8390.c:149,154 – 1995/0408/sys/src/9/pc/ether8390.c:146,171 | ||
| 1992/1222 | uchar len1; } Hdr; | |
| 1995/0408 | /* * the 8390 register accesses must not be too close together */ void dp8390outb(ulong port, uchar x) { outb(port, x); microdelay(0); } long dp8390inb(ulong port) { long x; x = inb(port); microdelay(0); return x; } | |
| 1992/1222 | static void | |
| 1993/1117 | dp8390disable(Dp8390 *dp8390) | |
| 1992/1222 | { | |
| 1994/0715/sys/src/9/pc/ether8390.c:163,172 – 1995/0408/sys/src/9/pc/ether8390.c:180,189 | ||
| 1992/1222 | * chip there if this is called when probing for a device * at boot. */ | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Cr, Page0|RDMAabort|Stp); dp8390outb(port+Rbcr0, 0); dp8390outb(port+Rbcr1, 0); for(timo = 10000; (dp8390inb(port+Isr) & Rst) == 0 && timo; timo--) | |
| 1992/1222 | ; } | |
| 1994/0715/sys/src/9/pc/ether8390.c:175,187 – 1995/0408/sys/src/9/pc/ether8390.c:192,204 | ||
| 1993/0212 | { | |
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1993/0212 | ||
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Pstart, dp8390->pstart); dp8390outb(port+Pstop, dp8390->pstop); dp8390outb(port+Bnry, dp8390->pstop-1); | |
| 1993/0212 | ||
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Cr, Page1|RDMAabort|Stp); dp8390outb(port+Curr, dp8390->pstart); dp8390outb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/0915 | ||
| 1993/1117 | dp8390->nxtpkt = dp8390->pstart; | |
| 1993/0212 | } | |
| 1994/0715/sys/src/9/pc/ether8390.c:200,210 – 1995/0408/sys/src/9/pc/ether8390.c:217,227 | ||
| 1992/1222 | * addresses as we never set the multicast * enable. */ | |
| 1994/0130 |
| |
| 1995/0408 | cr = dp8390inb(port+Cr) & ~Txp; dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1993/1116 | for(i = 0; i < sizeof(ether->ea); i++) | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Par0+i, ether->ea[i]); dp8390outb(port+Cr, cr); | |
| 1992/1222 | } | |
| 1993/0915 | void | |
| 1994/0715/sys/src/9/pc/ether8390.c:221,231 – 1995/0408/sys/src/9/pc/ether8390.c:238,248 | ||
| 1993/0915 | * addresses as we never set the multicast * enable. */ | |
| 1994/0130 |
| |
| 1995/0408 | cr = dp8390inb(port+Cr) & ~Txp; dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1993/1116 | for(i = 0; i < sizeof(ether->ea); i++) | |
| 1994/0130 |
| |
| 1995/0408 | ether->ea[i] = dp8390inb(port+Par0+i); dp8390outb(port+Cr, cr); | |
| 1993/0915 | } | |
| 1994/0128 | void* | |
| 1994/0715/sys/src/9/pc/ether8390.c:240,248 – 1995/0408/sys/src/9/pc/ether8390.c:257,265 | ||
| 1992/1222 | * using the DP8390 remote DMA facility, and place it at * 'to' in main memory, via the I/O data port. */ | |
| 1994/0130 |
| |
| 1995/0408 | cr = dp8390inb(port+Cr) & ~Txp; dp8390outb(port+Cr, Page0|RDMAabort|Sta); dp8390outb(port+Isr, Rdc); | |
| 1992/1222 | /* * Set up the remote DMA address and count. | |
| 1994/0715/sys/src/9/pc/ether8390.c:249,264 – 1995/0408/sys/src/9/pc/ether8390.c:266,281 | ||
| 1992/1222 | */ | |
| 1993/1117 | if(dp8390->bit16) | |
| 1992/1222 | len = ROUNDUP(len, 2); | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Rbcr0, len & 0xFF); dp8390outb(port+Rbcr1, (len>>8) & 0xFF); dp8390outb(port+Rsar0, from & 0xFF); dp8390outb(port+Rsar1, (from>>8) & 0xFF); | |
| 1992/1222 | /* * Start the remote DMA read and suck the data * out of the I/O port. */ | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Cr, Page0|RDMAread|Sta); | |
| 1993/1117 | if(dp8390->bit16) inss(dp8390->data, to, len/2); | |
| 1992/1222 | else | |
| 1994/0715/sys/src/9/pc/ether8390.c:271,281 – 1995/0408/sys/src/9/pc/ether8390.c:288,298 | ||
| 1992/1222 | * to the miracles of the bus, we could get this far * and still be talking to a slot full of nothing. */ | |
| 1994/0130 |
| |
| 1995/0408 | for(timo = 10000; (dp8390inb(port+Isr) & Rdc) == 0 && timo; timo--) | |
| 1992/1222 | ; | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Isr, Rdc); dp8390outb(port+Cr, cr); | |
| 1992/1222 | return to; } | |
| 1994/0715/sys/src/9/pc/ether8390.c:298,306 – 1995/0408/sys/src/9/pc/ether8390.c:315,323 | ||
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at * 'from' in main memory, via the I/O data port. */ | |
| 1994/0130 |
| |
| 1995/0408 | cr = dp8390inb(port+Cr) & ~Txp; dp8390outb(port+Cr, Page0|RDMAabort|Sta); dp8390outb(port+Isr, Rdc); | |
| 1992/1222 | ||
| 1993/1118 | if(dp8390->bit16) | |
| 1993/0212 | len = ROUNDUP(len, 2); | |
| 1994/0715/sys/src/9/pc/ether8390.c:311,334 – 1995/0408/sys/src/9/pc/ether8390.c:328,351 | ||
| 1993/0212 | * the initial set up for read. | |
| 1992/1222 | */ | |
| 1993/1118 | crda = to-1-dp8390->bit16; | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); dp8390outb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); dp8390outb(port+Rsar0, crda & 0xFF); dp8390outb(port+Rsar1, (crda>>8) & 0xFF); dp8390outb(port+Cr, Page0|RDMAread|Sta); | |
| 1992/1222 | ||
| 1993/0212 | for(;;){ | |
| 1994/0130 |
| |
| 1995/0408 | crda = dp8390inb(port+Crda0); crda |= dp8390inb(port+Crda1)<<8; | |
| 1993/0212 | if(crda == to){ /* * Start the remote DMA write and make sure * the registers are correct. */ | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Cr, Page0|RDMAwrite|Sta); | |
| 1992/1222 | ||
| 1994/0130 |
| |
| 1995/0408 | crda = dp8390inb(port+Crda0); crda |= dp8390inb(port+Crda1)<<8; | |
| 1993/0212 | if(crda != to) panic("crda write %d to %d\n", crda, to); | |
| 1994/0715/sys/src/9/pc/ether8390.c:349,355 – 1995/0408/sys/src/9/pc/ether8390.c:366,372 | ||
| 1994/0202 | * be almost immediate. | |
| 1992/1222 | */ | |
| 1994/0201 | tries = 0; | |
| 1994/0202 |
| |
| 1995/0408 | while((dp8390inb(port+Isr) & Rdc) == 0){ | |
| 1994/0202 | if(tries++ >= 100000){ print("dp8390write dma timed out\n"); | |
| 1994/0201 | break; | |
| 1994/0715/sys/src/9/pc/ether8390.c:356,363 – 1995/0408/sys/src/9/pc/ether8390.c:373,380 | ||
| 1994/0201 | } | |
| 1994/0202 | } | |
| 1992/1222 | ||
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Isr, Rdc); dp8390outb(port+Cr, cr); | |
| 1994/0202 | splx(s); | |
| 1992/1222 | return (void*)to; | |
| 1994/0715/sys/src/9/pc/ether8390.c:369,378 – 1995/0408/sys/src/9/pc/ether8390.c:386,395 | ||
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1993/0212 | uchar cr, curr; | |
| 1994/0130 |
| |
| 1995/0408 | cr = dp8390inb(port+Cr) & ~Txp; dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); curr = dp8390inb(port+Curr); dp8390outb(port+Cr, cr); | |
| 1993/0212 | return curr; } | |
| 1994/0715/sys/src/9/pc/ether8390.c:416,424 – 1995/0408/sys/src/9/pc/ether8390.c:433,441 | ||
| 1993/0212 | || len < 60 || len > sizeof(Etherpkt)){ | |
| 1993/1118 | print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n", | |
| 1993/0212 | hdr.status, hdr.next, hdr.len0, hdr.len1, len); | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/1118 | dp8390ring(dp8390); | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Cr, Page0|RDMAabort|Sta); | |
| 1992/1222 | return; } | |
| 1994/0715/sys/src/9/pc/ether8390.c:467,473 – 1995/0408/sys/src/9/pc/ether8390.c:484,490 | ||
| 1993/0212 | hdr.next--; | |
| 1993/1118 | if(hdr.next < dp8390->pstart) hdr.next = dp8390->pstop-1; | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Bnry, hdr.next); | |
| 1992/1222 | } } | |
| 1994/0715/sys/src/9/pc/ether8390.c:519,527 – 1995/0408/sys/src/9/pc/ether8390.c:536,544 | ||
| 1993/1120 | if(dp8390->ram == 0) dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, pkt, len); | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Tbcr0, len & 0xFF); dp8390outb(port+Tbcr1, (len>>8) & 0xFF); dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/1118 | ||
| 1993/1120 | return len; | |
| 1993/0212 | } | |
| 1994/0715/sys/src/9/pc/ether8390.c:541,564 – 1995/0408/sys/src/9/pc/ether8390.c:558,581 | ||
| 1993/0212 | * The following procedure is taken from the DP8390[12D] datasheet, * it seems pretty adamant that this is what has to be done. */ | |
| 1994/0130 |
| |
| 1995/0408 | txp = dp8390inb(port+Cr) & Txp; dp8390outb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/0212 | delay(2); | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Rbcr0, 0); dp8390outb(port+Rbcr1, 0); | |
| 1993/0212 | resend = 0; | |
| 1994/0130 |
| |
| 1995/0408 | if(txp && (dp8390inb(port+Isr) & (Txe|Ptx)) == 0) | |
| 1993/0212 | resend = 1; | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Tcr, Lb); dp8390outb(port+Cr, Page0|RDMAabort|Sta); | |
| 1993/1118 | receive(ether); | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Isr, Ovw); dp8390outb(port+Tcr, 0); | |
| 1993/0212 | if(resend) | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/0212 | } | |
| 1993/1116 | static void | |
| 1994/0715/sys/src/9/pc/ether8390.c:579,590 – 1995/0408/sys/src/9/pc/ether8390.c:596,607 | ||
| 1992/1222 | * While there is something of interest, * clear all the interrupts and process. */ | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Imr, 0x00); while(isr = dp8390inb(port+Isr)){ | |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/1116 | overflow(ether); | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Isr, Ovw); | |
| 1993/1116 | ether->overflows++; | |
| 1992/1222 | } | |
| 1994/0715/sys/src/9/pc/ether8390.c:594,600 – 1995/0408/sys/src/9/pc/ether8390.c:611,617 | ||
| 1992/1222 | */ if(isr & (Rxe|Prx)){ | |
| 1993/1116 | receive(ether); | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Isr, Rxe|Prx); | |
| 1992/1222 | } /* | |
| 1994/0715/sys/src/9/pc/ether8390.c:603,609 – 1995/0408/sys/src/9/pc/ether8390.c:620,626 | ||
| 1992/1222 | * and wake the output routine. */ if(isr & (Txe|Ptx)){ | |
| 1994/0130 |
| |
| 1995/0408 | r = dp8390inb(port+Tsr); | |
| 1993/0212 | if(isr & Txe){ | |
| 1993/1118 | if((r & (Cdh|Fu|Crs|Abt))) print("dp8390: Tsr#%2.2ux\n", r); | |
| 1994/0715/sys/src/9/pc/ether8390.c:610,616 – 1995/0408/sys/src/9/pc/ether8390.c:627,633 | ||
| 1993/1116 | ether->oerrs++; | |
| 1993/0212 | } | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Isr, Txe|Ptx); | |
| 1993/0212 | if(isr & Ptx) | |
| 1993/1116 | ether->outpackets++; | |
| 1994/0715/sys/src/9/pc/ether8390.c:619,631 – 1995/0408/sys/src/9/pc/ether8390.c:636,648 | ||
| 1992/1222 | } | |
| 1993/0212 | if(isr & Cnt){ | |
| 1994/0130 |
| |
| 1995/0408 | ether->frames += dp8390inb(port+Cntr0); ether->crcs += dp8390inb(port+Cntr1); ether->buffs += dp8390inb(port+Cntr2); dp8390outb(port+Isr, Cnt); | |
| 1993/0212 | } | |
| 1992/1222 | } | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1993/1116 | } static void | |
| 1994/0715/sys/src/9/pc/ether8390.c:637,645 – 1995/0408/sys/src/9/pc/ether8390.c:654,662 | ||
| 1993/1116 | * Set/reset promiscuous mode. */ if(on) | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(dp8390->dp8390+Rcr, Pro|Ab); | |
| 1993/1116 | else | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(dp8390->dp8390+Rcr, Ab); | |
| 1993/1116 | } | |
| 1993/1118 | static void | |
| 1994/0715/sys/src/9/pc/ether8390.c:653,660 – 1995/0408/sys/src/9/pc/ether8390.c:670,677 | ||
| 1993/1116 | * mode. Clear the missed-packet counter, it * increments while in monitor mode. */ | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(dp8390->dp8390+Rcr, Ab); dp8390inb(dp8390->dp8390+Cntr2); | |
| 1993/1116 | } | |
| 1993/1118 | int | |
| 1994/0715/sys/src/9/pc/ether8390.c:673,687 – 1995/0408/sys/src/9/pc/ether8390.c:690,704 | ||
| 1993/1116 | */ | |
| 1993/1118 | dp8390disable(dp8390); if(dp8390->bit16) | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Dcr, Ft4|Ls|Wts); | |
| 1993/1116 | else | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Dcr, Ft4|Ls); | |
| 1993/1116 | ||
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Rbcr0, 0); dp8390outb(port+Rbcr1, 0); | |
| 1993/1116 | ||
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Tcr, 0); dp8390outb(port+Rcr, Mon); | |
| 1993/1116 | /* * Init the ring hardware and software ring pointers. | |
| 1994/0715/sys/src/9/pc/ether8390.c:689,704 – 1995/0408/sys/src/9/pc/ether8390.c:706,721 | ||
| 1993/1116 | * it yet. */ | |
| 1993/1118 | dp8390ring(dp8390); | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Tpsr, dp8390->tstart); | |
| 1993/1116 | ||
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Isr, 0xFF); dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1993/1116 | /* * Leave the chip initialised, * but in monitor mode. */ | |
| 1994/0130 |
| |
| 1995/0408 | dp8390outb(port+Cr, Page0|RDMAabort|Sta); | |
| 1993/1116 | /* * Set up the software configuration. | |
| 1995/0408/sys/src/9/pc/ether8390.c:14,19 – 1995/0409/sys/src/9/pc/ether8390.c:14,22 (short | long) | ||
| 1992/1222 | ||
| 1993/1116 | #include "etherif.h" | |
| 1992/1222 | ||
| 1995/0409 | extern int slowinb(ulong); extern void slowoutb(ulong, uchar); | |
| 1992/1222 | enum { Cr = 0x00, /* command register, all pages */ | |
| 1995/0408/sys/src/9/pc/ether8390.c:146,171 – 1995/0409/sys/src/9/pc/ether8390.c:149,154 | ||
| 1992/1222 | uchar len1; } Hdr; | |
| 1995/0408 |
| |
| 1992/1222 | static void | |
| 1993/1117 | dp8390disable(Dp8390 *dp8390) | |
| 1992/1222 | { | |
| 1995/0408/sys/src/9/pc/ether8390.c:180,189 – 1995/0409/sys/src/9/pc/ether8390.c:163,172 | ||
| 1992/1222 | * chip there if this is called when probing for a device * at boot. */ | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Cr, Page0|RDMAabort|Stp); slowoutb(port+Rbcr0, 0); slowoutb(port+Rbcr1, 0); for(timo = 10000; (slowinb(port+Isr) & Rst) == 0 && timo; timo--) | |
| 1992/1222 | ; } | |
| 1995/0408/sys/src/9/pc/ether8390.c:192,204 – 1995/0409/sys/src/9/pc/ether8390.c:175,187 | ||
| 1993/0212 | { | |
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1993/0212 | ||
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Pstart, dp8390->pstart); slowoutb(port+Pstop, dp8390->pstop); slowoutb(port+Bnry, dp8390->pstop-1); | |
| 1993/0212 | ||
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Cr, Page1|RDMAabort|Stp); slowoutb(port+Curr, dp8390->pstart); slowoutb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/0915 | ||
| 1993/1117 | dp8390->nxtpkt = dp8390->pstart; | |
| 1993/0212 | } | |
| 1995/0408/sys/src/9/pc/ether8390.c:217,227 – 1995/0409/sys/src/9/pc/ether8390.c:200,210 | ||
| 1992/1222 | * addresses as we never set the multicast * enable. */ | |
| 1995/0408 |
| |
| 1995/0409 | cr = slowinb(port+Cr) & ~Txp; slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1993/1116 | for(i = 0; i < sizeof(ether->ea); i++) | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Par0+i, ether->ea[i]); slowoutb(port+Cr, cr); | |
| 1992/1222 | } | |
| 1993/0915 | void | |
| 1995/0408/sys/src/9/pc/ether8390.c:238,248 – 1995/0409/sys/src/9/pc/ether8390.c:221,231 | ||
| 1993/0915 | * addresses as we never set the multicast * enable. */ | |
| 1995/0408 |
| |
| 1995/0409 | cr = slowinb(port+Cr) & ~Txp; slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); | |
| 1993/1116 | for(i = 0; i < sizeof(ether->ea); i++) | |
| 1995/0408 |
| |
| 1995/0409 | ether->ea[i] = slowinb(port+Par0+i); slowoutb(port+Cr, cr); | |
| 1993/0915 | } | |
| 1994/0128 | void* | |
| 1995/0408/sys/src/9/pc/ether8390.c:257,265 – 1995/0409/sys/src/9/pc/ether8390.c:240,248 | ||
| 1992/1222 | * using the DP8390 remote DMA facility, and place it at * 'to' in main memory, via the I/O data port. */ | |
| 1995/0408 |
| |
| 1995/0409 | cr = slowinb(port+Cr) & ~Txp; slowoutb(port+Cr, Page0|RDMAabort|Sta); slowoutb(port+Isr, Rdc); | |
| 1992/1222 | /* * Set up the remote DMA address and count. | |
| 1995/0408/sys/src/9/pc/ether8390.c:266,281 – 1995/0409/sys/src/9/pc/ether8390.c:249,264 | ||
| 1992/1222 | */ | |
| 1993/1117 | if(dp8390->bit16) | |
| 1992/1222 | len = ROUNDUP(len, 2); | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Rbcr0, len & 0xFF); slowoutb(port+Rbcr1, (len>>8) & 0xFF); slowoutb(port+Rsar0, from & 0xFF); slowoutb(port+Rsar1, (from>>8) & 0xFF); | |
| 1992/1222 | /* * Start the remote DMA read and suck the data * out of the I/O port. */ | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Cr, Page0|RDMAread|Sta); | |
| 1993/1117 | if(dp8390->bit16) inss(dp8390->data, to, len/2); | |
| 1992/1222 | else | |
| 1995/0408/sys/src/9/pc/ether8390.c:288,298 – 1995/0409/sys/src/9/pc/ether8390.c:271,281 | ||
| 1992/1222 | * to the miracles of the bus, we could get this far * and still be talking to a slot full of nothing. */ | |
| 1995/0408 |
| |
| 1995/0409 | for(timo = 10000; (slowinb(port+Isr) & Rdc) == 0 && timo; timo--) | |
| 1992/1222 | ; | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Isr, Rdc); slowoutb(port+Cr, cr); | |
| 1992/1222 | return to; } | |
| 1995/0408/sys/src/9/pc/ether8390.c:315,323 – 1995/0409/sys/src/9/pc/ether8390.c:298,306 | ||
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at * 'from' in main memory, via the I/O data port. */ | |
| 1995/0408 |
| |
| 1995/0409 | cr = slowinb(port+Cr) & ~Txp; slowoutb(port+Cr, Page0|RDMAabort|Sta); slowoutb(port+Isr, Rdc); | |
| 1992/1222 | ||
| 1993/1118 | if(dp8390->bit16) | |
| 1993/0212 | len = ROUNDUP(len, 2); | |
| 1995/0408/sys/src/9/pc/ether8390.c:328,351 – 1995/0409/sys/src/9/pc/ether8390.c:311,334 | ||
| 1993/0212 | * the initial set up for read. | |
| 1992/1222 | */ | |
| 1993/1118 | crda = to-1-dp8390->bit16; | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); slowoutb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); slowoutb(port+Rsar0, crda & 0xFF); slowoutb(port+Rsar1, (crda>>8) & 0xFF); slowoutb(port+Cr, Page0|RDMAread|Sta); | |
| 1992/1222 | ||
| 1993/0212 | for(;;){ | |
| 1995/0408 |
| |
| 1995/0409 | crda = slowinb(port+Crda0); crda |= slowinb(port+Crda1)<<8; | |
| 1993/0212 | if(crda == to){ /* * Start the remote DMA write and make sure * the registers are correct. */ | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Cr, Page0|RDMAwrite|Sta); | |
| 1992/1222 | ||
| 1995/0408 |
| |
| 1995/0409 | crda = slowinb(port+Crda0); crda |= slowinb(port+Crda1)<<8; | |
| 1993/0212 | if(crda != to) panic("crda write %d to %d\n", crda, to); | |
| 1995/0408/sys/src/9/pc/ether8390.c:366,372 – 1995/0409/sys/src/9/pc/ether8390.c:349,355 | ||
| 1994/0202 | * be almost immediate. | |
| 1992/1222 | */ | |
| 1994/0201 | tries = 0; | |
| 1995/0408 |
| |
| 1995/0409 | while((slowinb(port+Isr) & Rdc) == 0){ | |
| 1994/0202 | if(tries++ >= 100000){ print("dp8390write dma timed out\n"); | |
| 1994/0201 | break; | |
| 1995/0408/sys/src/9/pc/ether8390.c:373,380 – 1995/0409/sys/src/9/pc/ether8390.c:356,363 | ||
| 1994/0201 | } | |
| 1994/0202 | } | |
| 1992/1222 | ||
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Isr, Rdc); slowoutb(port+Cr, cr); | |
| 1994/0202 | splx(s); | |
| 1992/1222 | return (void*)to; | |
| 1995/0408/sys/src/9/pc/ether8390.c:386,395 – 1995/0409/sys/src/9/pc/ether8390.c:369,378 | ||
| 1993/1118 | ulong port = dp8390->dp8390; | |
| 1993/0212 | uchar cr, curr; | |
| 1995/0408 |
| |
| 1995/0409 | cr = slowinb(port+Cr) & ~Txp; slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); curr = slowinb(port+Curr); slowoutb(port+Cr, cr); | |
| 1993/0212 | return curr; } | |
| 1995/0408/sys/src/9/pc/ether8390.c:433,441 – 1995/0409/sys/src/9/pc/ether8390.c:416,424 | ||
| 1993/0212 | || len < 60 || len > sizeof(Etherpkt)){ | |
| 1993/1118 | print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n", | |
| 1993/0212 | hdr.status, hdr.next, hdr.len0, hdr.len1, len); | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/1118 | dp8390ring(dp8390); | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Cr, Page0|RDMAabort|Sta); | |
| 1992/1222 | return; } | |
| 1995/0408/sys/src/9/pc/ether8390.c:484,490 – 1995/0409/sys/src/9/pc/ether8390.c:467,473 | ||
| 1993/0212 | hdr.next--; | |
| 1993/1118 | if(hdr.next < dp8390->pstart) hdr.next = dp8390->pstop-1; | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Bnry, hdr.next); | |
| 1992/1222 | } } | |
| 1995/0408/sys/src/9/pc/ether8390.c:536,544 – 1995/0409/sys/src/9/pc/ether8390.c:519,527 | ||
| 1993/1120 | if(dp8390->ram == 0) dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, pkt, len); | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Tbcr0, len & 0xFF); slowoutb(port+Tbcr1, (len>>8) & 0xFF); slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/1118 | ||
| 1993/1120 | return len; | |
| 1993/0212 | } | |
| 1995/0408/sys/src/9/pc/ether8390.c:558,581 – 1995/0409/sys/src/9/pc/ether8390.c:541,564 | ||
| 1993/0212 | * The following procedure is taken from the DP8390[12D] datasheet, * it seems pretty adamant that this is what has to be done. */ | |
| 1995/0408 |
| |
| 1995/0409 | txp = slowinb(port+Cr) & Txp; slowoutb(port+Cr, Page0|RDMAabort|Stp); | |
| 1993/0212 | delay(2); | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Rbcr0, 0); slowoutb(port+Rbcr1, 0); | |
| 1993/0212 | resend = 0; | |
| 1995/0408 |
| |
| 1995/0409 | if(txp && (slowinb(port+Isr) & (Txe|Ptx)) == 0) | |
| 1993/0212 | resend = 1; | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Tcr, Lb); slowoutb(port+Cr, Page0|RDMAabort|Sta); | |
| 1993/1118 | receive(ether); | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Isr, Ovw); slowoutb(port+Tcr, 0); | |
| 1993/0212 | if(resend) | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); | |
| 1993/0212 | } | |
| 1993/1116 | static void | |
| 1995/0408/sys/src/9/pc/ether8390.c:596,607 – 1995/0409/sys/src/9/pc/ether8390.c:579,590 | ||
| 1992/1222 | * While there is something of interest, * clear all the interrupts and process. */ | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Imr, 0x00); while(isr = slowinb(port+Isr)){ | |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/1116 | overflow(ether); | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Isr, Ovw); | |
| 1993/1116 | ether->overflows++; | |
| 1992/1222 | } | |
| 1995/0408/sys/src/9/pc/ether8390.c:611,617 – 1995/0409/sys/src/9/pc/ether8390.c:594,600 | ||
| 1992/1222 | */ if(isr & (Rxe|Prx)){ | |
| 1993/1116 | receive(ether); | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Isr, Rxe|Prx); | |
| 1992/1222 | } /* | |
| 1995/0408/sys/src/9/pc/ether8390.c:620,626 – 1995/0409/sys/src/9/pc/ether8390.c:603,609 | ||
| 1992/1222 | * and wake the output routine. */ if(isr & (Txe|Ptx)){ | |
| 1995/0408 |
| |
| 1995/0409 | r = slowinb(port+Tsr); | |
| 1993/0212 | if(isr & Txe){ | |
| 1993/1118 | if((r & (Cdh|Fu|Crs|Abt))) print("dp8390: Tsr#%2.2ux\n", r); | |
| 1995/0408/sys/src/9/pc/ether8390.c:627,633 – 1995/0409/sys/src/9/pc/ether8390.c:610,616 | ||
| 1993/1116 | ether->oerrs++; | |
| 1993/0212 | } | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Isr, Txe|Ptx); | |
| 1993/0212 | if(isr & Ptx) | |
| 1993/1116 | ether->outpackets++; | |
| 1995/0408/sys/src/9/pc/ether8390.c:636,648 – 1995/0409/sys/src/9/pc/ether8390.c:619,631 | ||
| 1992/1222 | } | |
| 1993/0212 | if(isr & Cnt){ | |
| 1995/0408 |
| |
| 1995/0409 | ether->frames += slowinb(port+Cntr0); ether->crcs += slowinb(port+Cntr1); ether->buffs += slowinb(port+Cntr2); slowoutb(port+Isr, Cnt); | |
| 1993/0212 | } | |
| 1992/1222 | } | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1993/1116 | } static void | |
| 1995/0408/sys/src/9/pc/ether8390.c:654,662 – 1995/0409/sys/src/9/pc/ether8390.c:637,645 | ||
| 1993/1116 | * Set/reset promiscuous mode. */ if(on) | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(dp8390->dp8390+Rcr, Pro|Ab); | |
| 1993/1116 | else | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(dp8390->dp8390+Rcr, Ab); | |
| 1993/1116 | } | |
| 1993/1118 | static void | |
| 1995/0408/sys/src/9/pc/ether8390.c:670,677 – 1995/0409/sys/src/9/pc/ether8390.c:653,660 | ||
| 1993/1116 | * mode. Clear the missed-packet counter, it * increments while in monitor mode. */ | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(dp8390->dp8390+Rcr, Ab); slowinb(dp8390->dp8390+Cntr2); | |
| 1993/1116 | } | |
| 1993/1118 | int | |
| 1995/0408/sys/src/9/pc/ether8390.c:690,704 – 1995/0409/sys/src/9/pc/ether8390.c:673,687 | ||
| 1993/1116 | */ | |
| 1993/1118 | dp8390disable(dp8390); if(dp8390->bit16) | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Dcr, Ft4|Ls|Wts); | |
| 1993/1116 | else | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Dcr, Ft4|Ls); | |
| 1993/1116 | ||
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Rbcr0, 0); slowoutb(port+Rbcr1, 0); | |
| 1993/1116 | ||
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Tcr, 0); slowoutb(port+Rcr, Mon); | |
| 1993/1116 | /* * Init the ring hardware and software ring pointers. | |
| 1995/0408/sys/src/9/pc/ether8390.c:706,721 – 1995/0409/sys/src/9/pc/ether8390.c:689,704 | ||
| 1993/1116 | * it yet. */ | |
| 1993/1118 | dp8390ring(dp8390); | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Tpsr, dp8390->tstart); | |
| 1993/1116 | ||
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Isr, 0xFF); slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); | |
| 1993/1116 | /* * Leave the chip initialised, * but in monitor mode. */ | |
| 1995/0408 |
| |
| 1995/0409 | slowoutb(port+Cr, Page0|RDMAabort|Sta); | |
| 1993/1116 | /* * Set up the software configuration. | |
| 1995/0409/sys/src/9/pc/ether8390.c:189,195 – 1995/0721/sys/src/9/pc/ether8390.c:189,195 (short | long) | ||
| 1992/1222 | void | |
| 1993/1116 | dp8390setea(Ether *ether) | |
| 1992/1222 | { | |
| 1993/1118 |
| |
| 1995/0721 | ulong port = ((Dp8390*)ether->ctlr)->dp8390; | |
| 1992/1222 | uchar cr; int i; | |
| 1995/0409/sys/src/9/pc/ether8390.c:210,216 – 1995/0721/sys/src/9/pc/ether8390.c:210,216 | ||
| 1993/0915 | void | |
| 1993/1116 | dp8390getea(Ether *ether) | |
| 1993/0915 | { | |
| 1993/1118 |
| |
| 1995/0721 | ulong port = ((Dp8390*)ether->ctlr)->dp8390; | |
| 1993/0915 | uchar cr; int i; | |
| 1995/0409/sys/src/9/pc/ether8390.c:384,390 – 1995/0721/sys/src/9/pc/ether8390.c:384,390 | ||
| 1992/1222 | Hdr hdr; | |
| 1993/1118 | ulong port, data, len, len1; | |
| 1992/1222 | ||
| 1993/1118 |
| |
| 1995/0721 | dp8390 = ether->ctlr; | |
| 1993/1118 | port = dp8390->dp8390; for(curr = getcurr(dp8390); dp8390->nxtpkt != curr; curr = getcurr(dp8390)){ | |
| 1993/1116 | ether->inpackets++; | |
| 1995/0409/sys/src/9/pc/ether8390.c:455,461 – 1995/0721/sys/src/9/pc/ether8390.c:455,461 | ||
| 1993/1116 | /* * Copy the packet to whoever wants it. */ | |
| 1994/0715 |
| |
| 1995/0721 | etherrloop(ether, ðer->rpkt, len); | |
| 1992/1222 | } | |
| 1993/0212 | /* | |
| 1995/0409/sys/src/9/pc/ether8390.c:484,490 – 1995/0721/sys/src/9/pc/ether8390.c:484,490 | ||
| 1993/1118 | ulong port; | |
| 1993/1120 | Etherpkt *pkt; | |
| 1993/0213 | ||
| 1993/1118 |
| |
| 1995/0721 | dp8390 = ether->ctlr; | |
| 1993/1118 | port = dp8390->dp8390; | |
| 1993/0213 | ||
| 1993/1119 | tsleep(ðer->tr, istxavail, ether, 10000); | |
| 1995/0409/sys/src/9/pc/ether8390.c:534,540 – 1995/0721/sys/src/9/pc/ether8390.c:534,540 | ||
| 1993/0212 | uchar txp; int resend; | |
| 1993/1118 |
| |
| 1995/0721 | dp8390 = ether->ctlr; | |
| 1993/1118 | port = dp8390->dp8390; | |
| 1993/0212 | /* | |
| 1995/0409/sys/src/9/pc/ether8390.c:572,578 – 1995/0721/sys/src/9/pc/ether8390.c:572,578 | ||
| 1993/1124 | USED(ur); ether = arg; | |
| 1993/1118 |
| |
| 1995/0721 | dp8390 = ether->ctlr; | |
| 1993/1118 | port = dp8390->dp8390; | |
| 1992/1222 | /* | |
| 1995/0409/sys/src/9/pc/ether8390.c:631,637 – 1995/0721/sys/src/9/pc/ether8390.c:631,637 | ||
| 1993/1116 | static void | |
| 1993/1118 | promiscuous(void *arg, int on) | |
| 1993/1116 | { | |
| 1993/1118 |
| |
| 1995/0721 | Dp8390 *dp8390 = ((Ether*)arg)->ctlr; | |
| 1993/1117 | ||
| 1993/1116 | /* * Set/reset promiscuous mode. | |
| 1995/0409/sys/src/9/pc/ether8390.c:645,651 – 1995/0721/sys/src/9/pc/ether8390.c:645,651 | ||
| 1993/1118 | static void attach(Ether *ether) | |
| 1993/1116 | { | |
| 1993/1118 |
| |
| 1995/0721 | Dp8390 *dp8390 = ether->ctlr; | |
| 1993/1117 | ||
| 1993/1116 | /* * Enable the chip for transmit/receive. | |
| 1995/0409/sys/src/9/pc/ether8390.c:663,669 – 1995/0721/sys/src/9/pc/ether8390.c:663,669 | ||
| 1993/1118 | Dp8390 *dp8390; ulong port; | |
| 1993/1116 | ||
| 1993/1118 |
| |
| 1995/0721 | dp8390 = ether->ctlr; | |
| 1993/1118 | port = dp8390->dp8390; | |
| 1993/1116 | /* | |
| 1995/0721/sys/src/9/pc/ether8390.c:646,651 – 1995/0801/sys/src/9/pc/ether8390.c:646,652 (short | long) | ||
| 1993/1118 | attach(Ether *ether) | |
| 1993/1116 | { | |
| 1995/0721 | Dp8390 *dp8390 = ether->ctlr; | |
| 1995/0801 | int x; | |
| 1993/1117 | ||
| 1993/1116 | /* * Enable the chip for transmit/receive. | |
| 1995/0721/sys/src/9/pc/ether8390.c:653,658 – 1995/0801/sys/src/9/pc/ether8390.c:654,662 | ||
| 1993/1116 | * mode. Clear the missed-packet counter, it * increments while in monitor mode. */ | |
| 1995/0801 | x = Ab; if(ether->prom) x |= Pro; | |
| 1995/0409 | slowoutb(dp8390->dp8390+Rcr, Ab); slowinb(dp8390->dp8390+Cntr2); | |
| 1993/1116 | } | |
| 1995/0801/sys/src/9/pc/ether8390.c:562,568 – 1995/0829/sys/src/9/pc/ether8390.c:562,568 (short | long) | ||
| 1993/0212 | } | |
| 1993/1116 | static void | |
| 1993/1124 |
| |
| 1995/0829 | interrupt(Ureg*, void *arg) | |
| 1993/0212 | { | |
| 1993/1124 | Ether *ether; | |
| 1993/1118 | Dp8390 *dp8390; | |
| 1995/0801/sys/src/9/pc/ether8390.c:569,576 – 1995/0829/sys/src/9/pc/ether8390.c:569,574 | ||
| 1993/1118 | ulong port; | |
| 1993/0212 | uchar isr, r; | |
| 1992/1222 | ||
| 1993/1124 |
| |
| 1995/0721 | dp8390 = ether->ctlr; | |
| 1993/1118 | port = dp8390->dp8390; | |
| 1995/0801/sys/src/9/pc/ether8390.c:580,586 – 1995/0829/sys/src/9/pc/ether8390.c:578,584 | ||
| 1992/1222 | * clear all the interrupts and process. */ | |
| 1995/0409 | slowoutb(port+Imr, 0x00); | |
| 1995/0829 | while(isr = (slowinb(port+Isr) & (Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe))){ | |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/1116 | overflow(ether); | |
| 1995/0801/sys/src/9/pc/ether8390.c:657,663 – 1995/0829/sys/src/9/pc/ether8390.c:655,661 | ||
| 1995/0801 | x = Ab; if(ether->prom) x |= Pro; | |
| 1995/0409 |
| |
| 1995/0829 | slowoutb(dp8390->dp8390+Rcr, x); | |
| 1995/0409 | slowinb(dp8390->dp8390+Cntr2); | |
| 1993/1116 | } | |
| 1995/0829/sys/src/9/pc/ether8390.c:207,233 – 1996/0420/sys/src/9/pc/ether8390.c:207,212 (short | long) | ||
| 1995/0409 | slowoutb(port+Cr, cr); | |
| 1992/1222 | } | |
| 1993/0915 |
| |
| 1993/1116 |
| |
| 1993/0915 |
| |
| 1995/0721 |
| |
| 1993/0915 |
| |
| 1993/1116 |
| |
| 1993/0915 |
| |
| 1995/0409 |
| |
| 1993/1116 |
| |
| 1995/0409 |
| |
| 1993/0915 |
| |
| 1994/0128 | void* | |
| 1993/1117 | dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) | |
| 1992/1222 | { | |
| 1996/0420/sys/src/9/pc/ether8390.c:1,6 – 1997/0327/sys/src/9/pc/ether8390.c:1,5 (short | long) | ||
| 1992/1222 | /* | |
| 1997/0327 | * National Semiconductor DP8390 and clone | |
| 1992/1222 | * Network Interface Controller. */ #include "u.h" | |
| 1996/0420/sys/src/9/pc/ether8390.c:13,40 – 1997/0327/sys/src/9/pc/ether8390.c:12,23 | ||
| 1993/1116 | #include "../port/netif.h" | |
| 1992/1222 | ||
| 1993/1116 | #include "etherif.h" | |
| 1997/0327 | #include "ether8390.h" | |
| 1992/1222 | ||
| 1995/0409 |
| |
| 1992/1222 |
| |
| 1997/0327 | enum { /* NIC core registers */ | |
| 1992/1222 | Cr = 0x00, /* command register, all pages */ | |
| 1993/0212 |
| |
| 1992/1222 |
| |
| 1997/0327 | /* Page 0, read */ | |
| 1992/1222 | Clda0 = 0x01, /* current local DMA address 0 */ Clda1 = 0x02, /* current local DMA address 1 */ Bnry = 0x03, /* boundary pointer (R/W) */ | |
| 1996/0420/sys/src/9/pc/ether8390.c:48,56 – 1997/0327/sys/src/9/pc/ether8390.c:31,38 | ||
| 1992/1222 | Cntr0 = 0x0D, /* frame alignment errors */ Cntr1 = 0x0E, /* CRC errors */ Cntr2 = 0x0F, /* missed packet errors */ | |
| 1997/0327 | /* Page 0, write */ | |
| 1992/1222 | Pstart = 0x01, /* page start register */ Pstop = 0x02, /* page stop register */ Tpsr = 0x04, /* transmit page start address */ | |
| 1996/0420/sys/src/9/pc/ether8390.c:64,78 – 1997/0327/sys/src/9/pc/ether8390.c:46,77 | ||
| 1992/1222 | Tcr = 0x0D, /* transmit configuration register */ Dcr = 0x0E, /* data configuration register */ Imr = 0x0F, /* interrupt mask */ | |
| 1997/0327 | /* Page 1, read/write */ | |
| 1992/1222 | Par0 = 0x01, /* physical address register 0 */ Curr = 0x07, /* current page register */ Mar0 = 0x08, /* multicast address register 0 */ }; | |
| 1997/0327 | enum { /* Cr */ Stp = 0x01, /* stop */ Sta = 0x02, /* start */ Txp = 0x04, /* transmit packet */ Rd0 = 0x08, /* remote DMA command */ Rd1 = 0x10, Rd2 = 0x20, RdREAD = Rd0, /* remote read */ RdWRITE = Rd1, /* remote write */ RdSEND = Rd1|Rd0, /* send packet */ RdABORT = Rd2, /* abort/complete remote DMA */ Ps0 = 0x40, /* page select */ Ps1 = 0x80, Page0 = 0x00, Page1 = Ps0, Page2 = Ps1, }; enum { /* Isr/Imr */ | |
| 1992/1222 | Prx = 0x01, /* packet received */ Ptx = 0x02, /* packet transmitted */ Rxe = 0x04, /* receive error */ | |
| 1996/0420/sys/src/9/pc/ether8390.c:83,118 – 1997/0327/sys/src/9/pc/ether8390.c:82,114 | ||
| 1992/1222 | Rst = 0x80, /* reset status */ }; | |
| 1997/0327 | enum { /* Dcr */ | |
| 1992/1222 | Wts = 0x01, /* word transfer select */ Bos = 0x02, /* byte order select */ Las = 0x04, /* long address select */ Ls = 0x08, /* loopback select */ Arm = 0x10, /* auto-initialise remote */ | |
| 1997/0327 | Ft0 = 0x20, /* FIFO threshold select */ Ft1 = 0x40, Ft1WORD = 0x00, Ft2WORD = Ft0, Ft4WORD = Ft1, Ft6WORD = Ft1|Ft0, | |
| 1992/1222 | }; | |
| 1997/0327 | enum { /* Tcr */ | |
| 1992/1222 | Crc = 0x01, /* inhibit CRC */ | |
| 1997/0327 | Lb0 = 0x02, /* encoded loopback control */ Lb1 = 0x04, LpbkNORMAL = 0x00, /* normal operation */ LpbkNIC = Lb0, /* internal NIC module loopback */ LpbkENDEC = Lb1, /* internal ENDEC module loopback */ LpbkEXTERNAL = Lb1|Lb0, /* external loopback */ | |
| 1992/1222 | Atd = 0x08, /* auto transmit disable */ Ofst = 0x10, /* collision offset enable */ }; | |
| 1997/0327 | enum { /* Tsr */ | |
| 1992/1222 | Ptxok = 0x01, /* packet transmitted */ Col = 0x04, /* transmit collided */ Abt = 0x08, /* tranmit aborted */ | |
| 1996/0420/sys/src/9/pc/ether8390.c:122,128 – 1997/0327/sys/src/9/pc/ether8390.c:118,124 | ||
| 1992/1222 | Owc = 0x80, /* out of window collision */ }; | |
| 1997/0327 | enum { /* Rcr */ | |
| 1992/1222 | Sep = 0x01, /* save errored packets */ Ar = 0x02, /* accept runt packets */ Ab = 0x04, /* accept broadcast */ | |
| 1996/0420/sys/src/9/pc/ether8390.c:131,137 – 1997/0327/sys/src/9/pc/ether8390.c:127,133 | ||
| 1992/1222 | Mon = 0x20, /* monitor mode */ }; | |
| 1997/0327 | enum { /* Rsr */ | |
| 1992/1222 | Prxok = 0x01, /* packet received intact */ Crce = 0x02, /* CRC error */ Fae = 0x04, /* frame alignment error */ | |
| 1996/0420/sys/src/9/pc/ether8390.c:149,216 – 1997/0327/sys/src/9/pc/ether8390.c:145,201 | ||
| 1992/1222 | uchar len1; } Hdr; | |
| 1993/1117 |
| |
| 1997/0327 | void dp8390getea(Ether* ether, uchar* ea) | |
| 1992/1222 | { | |
| 1993/1118 |
| |
| 1992/1222 |
| |
| 1997/0327 | Dp8390 *ctlr; uchar cr; int i; | |
| 1992/1222 | ||
| 1997/0327 | ctlr = ether->ctlr; | |
| 1992/1222 | /* | |
| 1997/0327 | * Get the ethernet address from the chip. * Take care to restore the command register * afterwards. | |
| 1992/1222 | */ | |
| 1995/0409 |
| |
| 1992/1222 |
| |
| 1997/0327 | ilock(ctlr); cr = regr(ctlr, Cr) & ~Txp; regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr)); for(i = 0; i < Eaddrlen; i++) ea[i] = regr(ctlr, Par0+i); regw(ctlr, Cr, cr); iunlock(ctlr); | |
| 1992/1222 | } | |
| 1993/0212 |
| |
| 1993/1117 |
| |
| 1993/0212 |
| |
| 1993/1118 |
| |
| 1993/0212 | ||
| 1995/0409 |
| |
| 1993/0212 | ||
| 1995/0409 |
| |
| 1993/0915 | ||
| 1993/1117 |
| |
| 1993/0212 |
| |
| 1992/1222 | void | |
| 1993/1116 |
| |
| 1997/0327 | dp8390setea(Ether* ether) | |
| 1992/1222 | { | |
| 1995/0721 |
| |
| 1992/1222 |
| |
| 1997/0327 | uchar cr; Dp8390 *ctlr; | |
| 1992/1222 | ||
| 1997/0327 | ctlr = ether->ctlr; | |
| 1992/1222 | /* * Set the ethernet address into the chip. * Take care to restore the command register | |
| 1997/0327 | * afterwards. Don't care about multicast * addresses as multicast is never enabled * (currently). | |
| 1992/1222 | */ | |
| 1995/0409 |
| |
| 1993/1116 |
| |
| 1995/0409 |
| |
| 1997/0327 | ilock(ctlr); cr = regr(ctlr, Cr) & ~Txp; regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr)); for(i = 0; i < Eaddrlen; i++) regw(ctlr, Par0+i, ether->ea[i]); regw(ctlr, Cr, cr); iunlock(ctlr); | |
| 1992/1222 | } | |
| 1994/0128 |
| |
| 1993/1117 |
| |
| 1997/0327 | static void* _dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len) | |
| 1992/1222 | { | |
| 1993/1118 |
| |
| 1992/1222 | uchar cr; int timo; | |
| 1996/0420/sys/src/9/pc/ether8390.c:219,378 – 1997/0327/sys/src/9/pc/ether8390.c:204,378 | ||
| 1992/1222 | * using the DP8390 remote DMA facility, and place it at * 'to' in main memory, via the I/O data port. */ | |
| 1995/0409 |
| |
| 1997/0327 | cr = regr(ctlr, Cr) & ~Txp; regw(ctlr, Cr, Page0|RdABORT|Sta); regw(ctlr, Isr, Rdc); | |
| 1992/1222 | /* * Set up the remote DMA address and count. */ | |
| 1993/1117 |
| |
| 1992/1222 |
| |
| 1995/0409 |
| |
| 1997/0327 | len = ROUNDUP(len, ctlr->width); regw(ctlr, Rbcr0, len & 0xFF); regw(ctlr, Rbcr1, (len>>8) & 0xFF); regw(ctlr, Rsar0, from & 0xFF); regw(ctlr, Rsar1, (from>>8) & 0xFF); | |
| 1992/1222 | /* * Start the remote DMA read and suck the data * out of the I/O port. */ | |
| 1995/0409 |
| |
| 1993/1117 |
| |
| 1992/1222 |
| |
| 1993/1117 |
| |
| 1997/0327 | regw(ctlr, Cr, Page0|RdREAD|Sta); rdread(ctlr, to, len); | |
| 1992/1222 | /* * Wait for the remote DMA to complete. The timeout | |
| 1997/0327 | * is necessary because this routine may be called on | |
| 1992/1222 | * a non-existent chip during initialisation and, due | |
| 1997/0327 | * to the miracles of the bus, it's possible to get this * far and still be talking to a slot full of nothing. | |
| 1992/1222 | */ | |
| 1995/0409 |
| |
| 1997/0327 | for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--) | |
| 1992/1222 | ; | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Isr, Rdc); regw(ctlr, Cr, cr); | |
| 1992/1222 | return to; } | |
| 1994/0128 | void* | |
| 1993/1118 |
| |
| 1997/0327 | dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len) | |
| 1992/1222 | { | |
| 1993/1118 |
| |
| 1997/0327 | void *v; ilock(ctlr); v = dp8390read(ctlr, to, from, len); iunlock(ctlr); return v; } static void* dp8390write(Dp8390* ctlr, ulong to, void* from, ulong len) { | |
| 1993/1118 | ulong crda; | |
| 1992/1222 | uchar cr; | |
| 1994/0201 |
| |
| 1997/0327 | int timo, width; | |
| 1992/1222 | ||
| 1994/0202 | /* | |
| 1994/0201 |
| |
| 1994/0202 | ||
| 1992/1222 |
| |
| 1993/0212 | * Write some data to offset 'to' in the card's memory | |
| 1992/1222 | * using the DP8390 remote DMA facility, reading it at * 'from' in main memory, via the I/O data port. */ | |
| 1995/0409 |
| |
| 1997/0327 | cr = regr(ctlr, Cr) & ~Txp; regw(ctlr, Cr, Page0|RdABORT|Sta); regw(ctlr, Isr, Rdc); | |
| 1992/1222 | ||
| 1993/1118 |
| |
| 1993/0212 |
| |
| 1997/0327 | len = ROUNDUP(len, ctlr->width); | |
| 1993/0212 | ||
| 1992/1222 | /* * Set up the remote DMA address and count. | |
| 1993/0212 |
| |
| 1997/0327 | * This is straight from the DP8390[12D] datasheet, * hence the initial set up for read. * Assumption here that the A7000 EtherV card will * never need a dummyrr. | |
| 1992/1222 | */ | |
| 1993/1118 |
| |
| 1995/0409 |
| |
| 1992/1222 | ||
| 1993/0212 |
| |
| 1995/0409 |
| |
| 1993/0212 |
| |
| 1995/0409 |
| |
| 1992/1222 | ||
| 1995/0409 |
| |
| 1993/0212 |
| |
| 1997/0327 | if(ctlr->dummyrr && (ctlr->width == 1 || ctlr->width == 2)){ if(ctlr->width == 2) width = 1; else width = 0; crda = to-1-width; regw(ctlr, Rbcr0, (len+1+width) & 0xFF); regw(ctlr, Rbcr1, ((len+1+width)>>8) & 0xFF); regw(ctlr, Rsar0, crda & 0xFF); regw(ctlr, Rsar1, (crda>>8) & 0xFF); regw(ctlr, Cr, Page0|RdREAD|Sta); for(;;){ crda = regr(ctlr, Crda0); crda |= regr(ctlr, Crda1)<<8; if(crda == to){ /* * Start the remote DMA write and make sure * the registers are correct. */ regw(ctlr, Cr, Page0|RdWRITE|Sta); crda = regr(ctlr, Crda0); crda |= regr(ctlr, Crda1)<<8; if(crda != to) panic("crda write %d to %d\n", crda, to); break; } | |
| 1993/0212 | } } | |
| 1997/0327 | else{ regw(ctlr, Rsar0, to & 0xFF); regw(ctlr, Rsar1, (to>>8) & 0xFF); regw(ctlr, Rbcr0, len & 0xFF); regw(ctlr, Rbcr1, (len>>8) & 0xFF); regw(ctlr, Cr, Page0|RdWRITE|Sta); } | |
| 1993/0212 | ||
| 1992/1222 | /* | |
| 1993/0212 |
| |
| 1997/0327 | * Pump the data into the I/O port * then wait for the remote DMA to finish. | |
| 1992/1222 | */ | |
| 1993/1118 |
| |
| 1992/1222 |
| |
| 1993/1118 |
| |
| 1997/0327 | rdwrite(ctlr, from, len); for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--) ; | |
| 1992/1222 |
| |
| 1994/0202 |
| |
| 1992/1222 |
| |
| 1994/0201 |
| |
| 1995/0409 |
| |
| 1994/0202 |
| |
| 1994/0201 |
| |
| 1994/0202 |
| |
| 1997/0327 | regw(ctlr, Isr, Rdc); regw(ctlr, Cr, cr); | |
| 1992/1222 | ||
| 1995/0409 |
| |
| 1994/0202 |
| |
| 1992/1222 | return (void*)to; } | |
| 1997/0327 | static void ringinit(Dp8390* ctlr) { regw(ctlr, Pstart, ctlr->pstart); regw(ctlr, Pstop, ctlr->pstop); regw(ctlr, Bnry, ctlr->pstop-1); regw(ctlr, Cr, Page1|RdABORT|Stp); regw(ctlr, Curr, ctlr->pstart); regw(ctlr, Cr, Page0|RdABORT|Stp); ctlr->nxtpkt = ctlr->pstart; } | |
| 1993/0212 | static uchar | |
| 1993/1118 |
| |
| 1997/0327 | getcurr(Dp8390* ctlr) | |
| 1993/0212 | { | |
| 1993/1118 |
| |
| 1993/0212 | uchar cr, curr; | |
| 1995/0409 |
| |
| 1997/0327 | cr = regr(ctlr, Cr) & ~Txp; regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr)); curr = regr(ctlr, Curr); regw(ctlr, Cr, cr); | |
| 1993/0212 | return curr; } | |
| 1993/0213 | static void | |
| 1993/1116 |
| |
| 1997/0327 | receive(Ether* ether) | |
| 1993/0213 | { | |
| 1993/1118 |
| |
| 1997/0327 | Dp8390 *ctlr; uchar curr, *p; | |
| 1992/1222 | Hdr hdr; | |
| 1993/1118 |
| |
| 1997/0327 | ulong count, data, len; Block *bp; | |
| 1992/1222 | ||
| 1995/0721 |
| |
| 1993/1118 |
| |
| 1993/1116 |
| |
| 1992/1222 | ||
| 1993/1118 |
| |
| 1997/0327 | ctlr = ether->ctlr; for(curr = getcurr(ctlr); ctlr->nxtpkt != curr; curr = getcurr(ctlr)){ data = ctlr->nxtpkt*Dp8390BufSz; if(ctlr->ram) | |
| 1993/1118 | memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr)); else | |
| 1997/0327 | _dp8390read(ctlr, &hdr, data, sizeof(Hdr)); | |
| 1992/1222 | /* | |
| 1993/0212 | * Don't believe the upper byte count, work it | |
| 1996/0420/sys/src/9/pc/ether8390.c:379,440 – 1997/0327/sys/src/9/pc/ether8390.c:379,438 | ||
| 1993/0212 | * out from the software next-page pointer and * the current next-page pointer. | |
| 1992/1222 | */ | |
| 1993/1118 |
| |
| 1997/0327 | if(hdr.next > ctlr->nxtpkt) len = hdr.next - ctlr->nxtpkt - 1; | |
| 1993/0212 | else | |
| 1993/1118 |
| |
| 1997/0327 | len = (ctlr->pstop-ctlr->nxtpkt) + (hdr.next-ctlr->pstart) - 1; | |
| 1993/0212 | if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr))) | |
| 1997/0327 | len--; | |
| 1993/0212 |
| |
| 1997/0327 | len = ((len<<8)|hdr.len0)-4; | |
| 1993/0212 | /* * Chip is badly scrogged, reinitialise the ring. */ | |
| 1993/1118 |
| |
| 1997/0327 | if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop | |
| 1993/0212 | || len < 60 || len > sizeof(Etherpkt)){ | |
| 1993/1118 | print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n", | |
| 1993/0212 | hdr.status, hdr.next, hdr.len0, hdr.len1, len); | |
| 1995/0409 |
| |
| 1993/1118 |
| |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Cr, Page0|RdABORT|Stp); ringinit(ctlr); regw(ctlr, Cr, Page0|RdABORT|Sta); | |
| 1992/1222 | return; } | |
| 1993/0212 | /* | |
| 1993/1116 | * If it's a good packet read it in to the software buffer. | |
| 1994/0202 |
| |
| 1997/0327 | * If the packet wraps round the hardware ring, read it in * two pieces. | |
| 1993/0212 | */ | |
| 1993/1116 |
| |
| 1993/1118 |
| |
| 1997/0327 | if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && (bp = iallocb(len))){ p = bp->rp; bp->wp = p+len; | |
| 1992/1222 | data += sizeof(Hdr); | |
| 1993/1118 |
| |
| 1993/0212 | ||
| 1993/1118 |
| |
| 1993/0212 | ||
| 1993/1118 |
| |
| 1997/0327 | if((data+len) >= ctlr->pstop*Dp8390BufSz){ count = ctlr->pstop*Dp8390BufSz - data; if(ctlr->ram) memmove(p, (void*)(ether->mem+data), count); | |
| 1993/1118 | else | |
| 1993/0212 |
| |
| 1993/1118 |
| |
| 1997/0327 | _dp8390read(ctlr, p, data, count); p += count; data = ctlr->pstart*Dp8390BufSz; len -= count; | |
| 1992/1222 | } | |
| 1993/1118 |
| |
| 1997/0327 | if(len){ if(ctlr->ram) memmove(p, (void*)(ether->mem+data), len); | |
| 1993/1118 | else | |
| 1997/0327 | _dp8390read(ctlr, p, data, len); | |
| 1993/1118 | } | |
| 1993/0212 | ||
| 1993/1116 | /* * Copy the packet to whoever wants it. */ | |
| 1995/0721 |
| |
| 1997/0327 | etheriq(ether, bp, 1); | |
| 1992/1222 | } | |
| 1993/0212 | /* | |
| 1996/0420/sys/src/9/pc/ether8390.c:441,577 – 1997/0327/sys/src/9/pc/ether8390.c:439,576 | ||
| 1993/1118 | * Finished with this packet, update the | |
| 1993/0212 | * hardware and software ring pointers. */ | |
| 1993/1118 |
| |
| 1997/0327 | ctlr->nxtpkt = hdr.next; | |
| 1993/0212 | hdr.next--; | |
| 1993/1118 |
| |
| 1995/0409 |
| |
| 1997/0327 | if(hdr.next < ctlr->pstart) hdr.next = ctlr->pstop-1; regw(ctlr, Bnry, hdr.next); | |
| 1992/1222 | } } | |
| 1993/1118 |
| |
| 1993/1119 |
| |
| 1997/0327 | static void txstart(Ether* ether) | |
| 1992/1222 | { | |
| 1993/1119 |
| |
| 1993/1118 |
| |
| 1997/0327 | int len; Dp8390 *ctlr; Block *bp; uchar minpkt[ETHERMINTU], *rp; | |
| 1993/0212 | ||
| 1993/1118 |
| |
| 1993/1120 |
| |
| 1993/1118 |
| |
| 1993/1120 |
| |
| 1997/0327 | ctlr = ether->ctlr; | |
| 1993/0213 | ||
| 1995/0721 |
| |
| 1993/1118 |
| |
| 1993/0213 | ||
| 1993/1119 |
| |
| 1993/0212 |
| |
| 1993/1120 |
| |
| 1993/1118 | ||
| 1993/1120 | /* | |
| 1997/0327 | * This routine is called both from the top level and from interrupt * level and expects to be called with ctlr already locked. | |
| 1993/1120 | */ | |
| 1993/1118 |
| |
| 1993/1120 |
| |
| 1993/1118 |
| |
| 1993/1120 |
| |
| 1997/0327 | if(ctlr->txbusy) return; bp = qget(ether->oq); if(bp == nil) return; | |
| 1993/1118 | ||
| 1993/1120 | /* | |
| 1997/0327 | * Make sure the packet is of minimum length; * copy it to the card's memory by the appropriate means; * start the transmission. | |
| 1993/1120 | */ | |
| 1997/0327 | len = BLEN(bp); rp = bp->rp; | |
| 1993/1120 | if(len < ETHERMINTU){ | |
| 1997/0327 | rp = minpkt; memmove(rp, bp->rp, len); memset(rp+len, 0, ETHERMINTU-len); | |
| 1993/1120 | len = ETHERMINTU; } | |
| 1997/0327 | if(ctlr->ram) memmove((void*)(ether->mem+ctlr->tstart*Dp8390BufSz), rp, len); else dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, rp, len); freeb(bp); | |
| 1993/1120 | ||
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Tbcr0, len & 0xFF); regw(ctlr, Tbcr1, (len>>8) & 0xFF); regw(ctlr, Cr, Page0|RdABORT|Txp|Sta); | |
| 1993/1118 | ||
| 1993/1120 |
| |
| 1997/0327 | ether->outpackets++; ctlr->txbusy = 1; | |
| 1993/0212 | } | |
| 1993/1116 | static void | |
| 1997/0327 | transmit(Ether* ether) { Dp8390 *ctlr; ctlr = ether->ctlr; ilock(ctlr); txstart(ether); iunlock(ctlr); } static void | |
| 1993/1116 | overflow(Ether *ether) | |
| 1993/0212 | { | |
| 1993/1118 |
| |
| 1997/0327 | Dp8390 *ctlr; | |
| 1993/0212 | uchar txp; int resend; | |
| 1995/0721 |
| |
| 1993/1118 |
| |
| 1997/0327 | ctlr = ether->ctlr; | |
| 1993/1118 | ||
| 1993/0212 | /* * The following procedure is taken from the DP8390[12D] datasheet, * it seems pretty adamant that this is what has to be done. */ | |
| 1995/0409 |
| |
| 1997/0327 | txp = regr(ctlr, Cr) & Txp; regw(ctlr, Cr, Page0|RdABORT|Stp); | |
| 1993/0212 | delay(2); | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Rbcr0, 0); regw(ctlr, Rbcr1, 0); | |
| 1993/0212 | resend = 0; | |
| 1995/0409 |
| |
| 1997/0327 | if(txp && (regr(ctlr, Isr) & (Txe|Ptx)) == 0) | |
| 1993/0212 | resend = 1; | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Tcr, LpbkNIC); regw(ctlr, Cr, Page0|RdABORT|Sta); | |
| 1993/1118 | receive(ether); | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Isr, Ovw); regw(ctlr, Tcr, 0); | |
| 1993/0212 | if(resend) | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Cr, Page0|RdABORT|Txp|Sta); | |
| 1993/0212 | } | |
| 1993/1116 | static void | |
| 1995/0829 |
| |
| 1997/0327 | interrupt(Ureg*, void* arg) | |
| 1993/0212 | { | |
| 1993/1124 | Ether *ether; | |
| 1993/1118 |
| |
| 1997/0327 | Dp8390 *ctlr; | |
| 1993/0212 | uchar isr, r; | |
| 1992/1222 | ||
| 1993/1124 | ether = arg; | |
| 1995/0721 |
| |
| 1993/1118 |
| |
| 1997/0327 | ctlr = ether->ctlr; | |
| 1993/1118 | ||
| 1992/1222 | /* * While there is something of interest, * clear all the interrupts and process. */ | |
| 1995/0409 |
| |
| 1995/0829 |
| |
| 1992/1222 | ||
| 1997/0327 | lock(ctlr); regw(ctlr, Imr, 0x00); while(isr = (regr(ctlr, Isr) & (Cnt|Ovw|Txe|Rxe|Ptx|Prx))){ | |
| 1992/1222 | if(isr & Ovw){ | |
| 1993/1116 | overflow(ether); | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Isr, Ovw); | |
| 1993/1116 | ether->overflows++; | |
| 1992/1222 | } /* | |
| 1993/1116 |
| |
| 1997/0327 | * Packets have been received. * Take a spin round the ring. | |
| 1992/1222 | */ if(isr & (Rxe|Prx)){ | |
| 1993/1116 | receive(ether); | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Isr, Rxe|Prx); | |
| 1992/1222 | } /* | |
| 1996/0420/sys/src/9/pc/ether8390.c:580,630 – 1997/0327/sys/src/9/pc/ether8390.c:579,638 | ||
| 1992/1222 | * and wake the output routine. */ if(isr & (Txe|Ptx)){ | |
| 1995/0409 |
| |
| 1993/0212 |
| |
| 1993/1118 |
| |
| 1997/0327 | r = regr(ctlr, Tsr); if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){ print("dp8390: Tsr#%2.2ux|", r); | |
| 1993/1116 | ether->oerrs++; | |
| 1993/0212 | } | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Isr, Txe|Ptx); | |
| 1993/0212 | if(isr & Ptx) | |
| 1993/1116 | ether->outpackets++; | |
| 1993/1119 |
| |
| 1993/1116 |
| |
| 1997/0327 | ctlr->txbusy = 0; txstart(ether); | |
| 1992/1222 | } | |
| 1993/0212 | if(isr & Cnt){ | |
| 1995/0409 |
| |
| 1997/0327 | ether->frames += regr(ctlr, Cntr0); ether->crcs += regr(ctlr, Cntr1); ether->buffs += regr(ctlr, Cntr2); regw(ctlr, Isr, Cnt); | |
| 1993/0212 | } | |
| 1992/1222 | } | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx); unlock(ctlr); | |
| 1993/1116 | } static void | |
| 1993/1118 | promiscuous(void *arg, int on) | |
| 1993/1116 | { | |
| 1995/0721 |
| |
| 1997/0327 | Ether *ether; Dp8390 *ctlr; uchar r; | |
| 1993/1117 | ||
| 1997/0327 | ether = arg; ctlr = ether->ctlr; | |
| 1993/1116 | /* * Set/reset promiscuous mode. */ | |
| 1997/0327 | r = Ab; | |
| 1993/1116 | if(on) | |
| 1995/0409 |
| |
| 1993/1116 |
| |
| 1995/0409 |
| |
| 1997/0327 | r |= Pro; ilock(ctlr); regw(ctlr, Rcr, r); iunlock(ctlr); | |
| 1993/1116 | } | |
| 1993/1118 | static void | |
| 1997/0327 | attach(Ether* ether) | |
| 1993/1116 | { | |
| 1995/0721 |
| |
| 1995/0801 |
| |
| 1997/0327 | Dp8390 *ctlr; uchar r; | |
| 1993/1117 | ||
| 1997/0327 | ctlr = ether->ctlr; | |
| 1993/1116 | /* * Enable the chip for transmit/receive. * The init routine leaves the chip in monitor | |
| 1996/0420/sys/src/9/pc/ether8390.c:631,692 – 1997/0327/sys/src/9/pc/ether8390.c:639,722 | ||
| 1993/1116 | * mode. Clear the missed-packet counter, it * increments while in monitor mode. */ | |
| 1995/0801 |
| |
| 1997/0327 | r = Ab; | |
| 1995/0801 | if(ether->prom) | |
| 1995/0829 |
| |
| 1995/0409 |
| |
| 1997/0327 | r |= Pro; ilock(ctlr); regw(ctlr, Rcr, r); r = regr(ctlr, Cntr2); iunlock(ctlr); USED(r); | |
| 1993/1116 | } | |
| 1997/0327 | static void disable(Dp8390* ctlr) { int timo; /* * Stop the chip. Set the Stp bit and wait for the chip * to finish whatever was on its tiny mind before it sets * the Rst bit. * The timeout is needed because there may not be a real * chip there if this is called when probing for a device * at boot. */ regw(ctlr, Cr, Page0|RdABORT|Stp); regw(ctlr, Rbcr0, 0); regw(ctlr, Rbcr1, 0); for(timo = 10000; (regr(ctlr, Isr) & Rst) == 0 && timo; timo--) ; } | |
| 1993/1118 | int | |
| 1993/1116 |
| |
| 1997/0327 | dp8390reset(Ether* ether) | |
| 1993/1116 | { | |
| 1993/1118 |
| |
| 1997/0327 | Dp8390 *ctlr; | |
| 1993/1116 | ||
| 1995/0721 |
| |
| 1993/1118 |
| |
| 1997/0327 | ctlr = ether->ctlr; | |
| 1993/1118 | ||
| 1993/1116 | /* * This is the initialisation procedure described * as 'mandatory' in the datasheet, with references | |
| 1997/0327 | * to the 3C503 technical reference manual. | |
| 1993/1116 | */ | |
| 1993/1118 |
| |
| 1995/0409 |
| |
| 1997/0327 | disable(ctlr); if(ctlr->width != 1) regw(ctlr, Dcr, Ft4WORD|Ls|Wts); | |
| 1993/1116 | else | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Dcr, Ft4WORD|Ls); | |
| 1993/1116 | ||
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Rbcr0, 0); regw(ctlr, Rbcr1, 0); | |
| 1993/1116 | ||
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Tcr, 0); regw(ctlr, Rcr, Mon); | |
| 1993/1116 | /* * Init the ring hardware and software ring pointers. | |
| 1997/0327 | * Can't initialise ethernet address as it may not be * known yet. | |
| 1993/1116 | */ | |
| 1993/1118 |
| |
| 1995/0409 |
| |
| 1997/0327 | ringinit(ctlr); regw(ctlr, Tpsr, ctlr->tstart); | |
| 1993/1116 | ||
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Isr, 0xFF); regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx); | |
| 1993/1116 | /* * Leave the chip initialised, * but in monitor mode. */ | |
| 1995/0409 |
| |
| 1997/0327 | regw(ctlr, Cr, Page0|RdABORT|Sta); | |
| 1993/1116 | /* * Set up the software configuration. */ ether->attach = attach; | |
| 1997/0327 | ether->transmit = transmit; | |
| 1993/1116 | ether->interrupt = interrupt; | |
| 1997/0327 | ether->ifstat = 0; | |
| 1993/1116 | ether->promiscuous = promiscuous; ether->arg = ether; | |
| 1997/0327/sys/src/9/pc/ether8390.c:620,625 – 1997/0415/sys/src/9/pc/ether8390.c:620,627 (short | long) | ||
| 1997/0327 | r = Ab; | |
| 1993/1116 | if(on) | |
| 1997/0327 | r |= Pro; | |
| 1997/0415 | if(ether->nmaddr) r |= Am; | |
| 1997/0327 | ilock(ctlr); regw(ctlr, Rcr, r); iunlock(ctlr); | |
| 1997/0327/sys/src/9/pc/ether8390.c:626,631 – 1997/0415/sys/src/9/pc/ether8390.c:628,684 | ||
| 1993/1116 | } | |
| 1993/1118 | static void | |
| 1997/0415 | multicast(void* arg, uchar *addr, int on) { Ether *ether; Dp8390 *ctlr; uchar r, cr; int i; ulong h; USED(addr, on); ether = arg; ctlr = ether->ctlr; /* * change filter bits */ h = ethercrc(addr, 6); h = h>>(32-6); i = h/8; h = h%8; ilock(ctlr); cr = regr(ctlr, Cr) & ~Txp; regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr)); r = regr(ctlr, Mar0+i); if(on){ if(++(ctlr->mref[h]) == 1) r |= 1<<h; } else { if(--(ctlr->mref[h]) <= 0){ ctlr->mref[h] = 0; r &= ~(1<<h); } } regw(ctlr, Mar0+i, r); regw(ctlr, Cr, cr); iunlock(ctlr); /* * Set/reset promiscuous mode. */ r = Ab; if(ether->nmaddr) r |= Am; if(ether->prom) r |= Pro; ilock(ctlr); regw(ctlr, Rcr, r); iunlock(ctlr); } static void | |
| 1997/0327 | attach(Ether* ether) | |
| 1993/1116 | { | |
| 1997/0327 | Dp8390 *ctlr; | |
| 1997/0327/sys/src/9/pc/ether8390.c:642,647 – 1997/0415/sys/src/9/pc/ether8390.c:695,702 | ||
| 1997/0327 | r = Ab; | |
| 1995/0801 | if(ether->prom) | |
| 1997/0327 | r |= Pro; | |
| 1997/0415 | if(ether->nmaddr) r |= Am; | |
| 1997/0327 | ilock(ctlr); regw(ctlr, Rcr, r); r = regr(ctlr, Cntr2); | |
| 1997/0327/sys/src/9/pc/ether8390.c:719,724 – 1997/0415/sys/src/9/pc/ether8390.c:774,780 | ||
| 1997/0327 | ether->ifstat = 0; | |
| 1993/1116 | ether->promiscuous = promiscuous; | |
| 1997/0415 | ether->multicast = multicast; | |
| 1993/1116 | ether->arg = ether; return 0; | |
| 1997/0415/sys/src/9/pc/ether8390.c:604,680 – 1997/0418/sys/src/9/pc/ether8390.c:604,698 (short | long) | ||
| 1997/0327 | unlock(ctlr); | |
| 1993/1116 | } | |
| 1997/0418 | static uchar allmar[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | |
| 1993/1116 | static void | |
| 1997/0418 | setfilter(Ether *ether, Dp8390 *ctlr) { uchar r, cr; int i; uchar *mar; r = Ab; mar = 0; if(ether->prom){ r |= Pro|Am; mar = allmar; } else if(ether->nmaddr){ r |= Am; mar = ctlr->mar; } if(mar){ cr = regr(ctlr, Cr) & ~Txp; regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr)); for(i = 0; i < 8; i++) regw(ctlr, Mar0+i, *(mar++)); regw(ctlr, Cr, cr); } regw(ctlr, Rcr, r); } static void | |
| 1993/1118 | promiscuous(void *arg, int on) | |
| 1993/1116 | { | |
| 1997/0327 | Ether *ether; Dp8390 *ctlr; | |
| 1993/1117 | ||
| 1997/0418 | USED(on); | |
| 1997/0327 | ether = arg; ctlr = ether->ctlr; | |
| 1993/1116 |
| |
| 1997/0327 |
| |
| 1993/1116 |
| |
| 1997/0327 |
| |
| 1997/0415 |
| |
| 1997/0327 | ilock(ctlr); | |
| 1997/0418 | setfilter(ether, ctlr); | |
| 1997/0327 | iunlock(ctlr); | |
| 1993/1116 | } | |
| 1993/1118 | static void | |
| 1997/0418 | setbit(Dp8390 *ctlr, int bit, int on) { int i, h; i = bit/8; h = bit%8; if(on){ if(++(ctlr->mref[bit]) == 1) ctlr->mar[i] |= 1<<h; } else { if(--(ctlr->mref[bit]) <= 0){ ctlr->mref[bit] = 0; ctlr->mar[i] &= ~(1<<h); } } } static uchar reverse[64]; static void | |
| 1997/0415 | multicast(void* arg, uchar *addr, int on) { Ether *ether; Dp8390 *ctlr; | |
| 1997/0418 | USED(on); | |
| 1997/0415 | ether = arg; ctlr = ether->ctlr; | |
| 1997/0418 | if(reverse[1] == 0){ for(i = 0; i < 64; i++) reverse[i] = ((i&1)<<5) | ((i&2)<<3) | ((i&4)<<1) | ((i&8)>>1) | ((i&16)>>3) | ((i&32)>>5); } | |
| 1997/0415 | /* * change filter bits */ h = ethercrc(addr, 6); | |
| 1997/0418 | setbit(ctlr, reverse[h&0x3f], on); setfilter(ether, ctlr); | |
| 1997/0415 | iunlock(ctlr); } | |
| 1997/0418/sys/src/9/pc/ether8390.c:246,252 – 1998/0129/sys/src/9/pc/ether8390.c:246,252 (short | long) | ||
| 1997/0327 | void *v; ilock(ctlr); | |
| 1998/0129 | v = _dp8390read(ctlr, to, from, len); | |
| 1997/0327 | iunlock(ctlr); return v; | |
| 1998/0129/sys/src/9/pc/ether8390.c:633,645 – 1998/0319/sys/src/9/pc/ether8390.c:633,643 (short | long) | ||
|
Change dev read and write to use vlong offset. Formatting edits.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0418 | } static void | |
| 1993/1118 |
| |
| 1998/0319 | promiscuous(void *arg, int ) | |
| 1993/1116 | { | |
| 1997/0327 | Ether *ether; Dp8390 *ctlr; | |
| 1993/1117 | ||
| 1997/0418 |
| |
| 1997/0327 | ether = arg; ctlr = ether->ctlr; | |
| 1998/0129/sys/src/9/pc/ether8390.c:675,682 – 1998/0319/sys/src/9/pc/ether8390.c:673,678 | ||
| 1997/0415 | Dp8390 *ctlr; int i; ulong h; | |
| 1997/0418 |
| |
| 1997/0415 | ether = arg; ctlr = ether->ctlr; | |
| Too many diffs (26 > 25). Stopping. | ||