## diffname pc/ether8390.c 1992/1222
## diff -e /dev/null /n/bootesdump/1992/1222/sys/src/9/pc/ether8390.c
0a
/*
* National Semiconductor DP8390
* and SMC 83C90
* Network Interface Controller.
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "devtab.h"
#include "ether.h"
enum {
Cr = 0x00, /* command register, all pages */
Stp = 0x01, /* stop */
Sta = 0x02, /* start */
Txp = 0x04, /* transmit packet */
RDMAread = (1<<3), /* remote DMA read */
RDMAwrite = (2<<3), /* remote DMA write */
RDMAsend = (3<<3), /* remote DMA send packet */
RDMAabort = (4<<3), /* abort/complete remote DMA */
Page0 = (0x00<<6), /* page select */
Page1 = (0x01<<6),
Page2 = (0x02<<6),
};
enum { /* Page 0, read */
Clda0 = 0x01, /* current local DMA address 0 */
Clda1 = 0x02, /* current local DMA address 1 */
Bnry = 0x03, /* boundary pointer (R/W) */
Tsr = 0x04, /* transmit status register */
Ncr = 0x05, /* number of collisions register */
Fifo = 0x06, /* FIFO */
Isr = 0x07, /* interrupt status register (R/W) */
Crda0 = 0x08, /* current remote DMA address 0 */
Crda1 = 0x08, /* current remote DMA address 1 */
Rsr = 0x0C, /* receive status register */
Cntr0 = 0x0D, /* frame alignment errors */
Cntr1 = 0x0E, /* CRC errors */
Cntr2 = 0x0F, /* missed packet errors */
};
enum { /* Page 0, write */
Pstart = 0x01, /* page start register */
Pstop = 0x02, /* page stop register */
Tpsr = 0x04, /* transmit page start address */
Tbcr0 = 0x05, /* transmit byte count register 0 */
Tbcr1 = 0x06, /* transmit byte count register 1 */
Rsar0 = 0x08, /* remote start address register 0 */
Rsar1 = 0x09, /* remote start address register 1 */
Rbcr0 = 0x0A, /* remote byte count register 0 */
Rbcr1 = 0x0B, /* remote byte count register 1 */
Rcr = 0x0C, /* receive configuration register */
Tcr = 0x0D, /* transmit configuration register */
Dcr = 0x0E, /* data configuration register */
Imr = 0x0F, /* interrupt mask */
};
enum { /* Page 1, read/write */
Par0 = 0x01, /* physical address register 0 */
Curr = 0x07, /* current page register */
Mar0 = 0x08, /* multicast address register 0 */
};
enum { /* Interrupt Status Register */
Prx = 0x01, /* packet received */
Ptx = 0x02, /* packet transmitted */
Rxe = 0x04, /* receive error */
Txe = 0x08, /* transmit error */
Ovw = 0x10, /* overwrite warning */
Cnt = 0x20, /* counter overflow */
Rdc = 0x40, /* remote DMA complete */
Rst = 0x80, /* reset status */
};
enum { /* Interrupt Mask Register */
Prxe = 0x01, /* packet received interrupt enable */
Ptxe = 0x02, /* packet transmitted interrupt enable */
Rxee = 0x04, /* receive error interrupt enable */
Txee = 0x08, /* transmit error interrupt enable */
Ovwe = 0x10, /* overwrite warning interrupt enable */
Cnte = 0x20, /* counter overflow interrupt enable */
Rdce = 0x40, /* DMA complete interrupt enable */
};
enum { /* Data Configuration register */
Wts = 0x01, /* word transfer select */
Bos = 0x02, /* byte order select */
Las = 0x04, /* long address select */
Ls = 0x08, /* loopback select */
Arm = 0x10, /* auto-initialise remote */
Ft1 = (0x00<<5), /* FIFO threshhold select 1 byte/word */
Ft2 = (0x01<<5), /* FIFO threshhold select 2 bytes/words */
Ft4 = (0x02<<5), /* FIFO threshhold select 4 bytes/words */
Ft6 = (0x03<<5), /* FIFO threshhold select 6 bytes/words */
};
enum { /* Transmit Configuration Register */
Crc = 0x01, /* inhibit CRC */
Lb = 0x02, /* internal loopback */
Atd = 0x08, /* auto transmit disable */
Ofst = 0x10, /* collision offset enable */
};
enum { /* Transmit Status Register */
Ptxok = 0x01, /* packet transmitted */
Col = 0x04, /* transmit collided */
Abt = 0x08, /* tranmit aborted */
Crs = 0x10, /* carrier sense lost */
Fu = 0x20, /* FIFO underrun */
Cdh = 0x40, /* CD heartbeat */
Owc = 0x80, /* out of window collision */
};
enum { /* Receive Configuration Register */
Sep = 0x01, /* save errored packets */
Ar = 0x02, /* accept runt packets */
Ab = 0x04, /* accept broadcast */
Am = 0x08, /* accept multicast */
Pro = 0x10, /* promiscuous physical */
Mon = 0x20, /* monitor mode */
};
enum { /* Receive Status Register */
Prxok = 0x01, /* packet received intact */
Crce = 0x02, /* CRC error */
Fae = 0x04, /* frame alignment error */
Fo = 0x08, /* FIFO overrun */
Mpa = 0x10, /* missed packet */
Phy = 0x20, /* physical/multicast address */
Dis = 0x40, /* receiver disabled */
Dfr = 0x80, /* deferring */
};
typedef struct {
uchar status;
uchar next;
uchar len0;
uchar len1;
} Hdr;
typedef struct {
Hdr;
uchar data[Dp8390BufSz-sizeof(Hdr)];
} Buf;
static void
dp8390disable(Ctlr *ctlr)
{
Board *board = ctlr->board;
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.
* We need the timeout because there may not be a real
* chip there if this is called when probing for a device
* at boot.
*/
outb(board->dp8390+Cr, Page0|RDMAabort|Stp);
for(timo = 10000; (inb(board->dp8390+Isr) & Rst) == 0 && timo; timo--)
;
}
void
dp8390reset(Ctlr *ctlr)
{
Board *board = ctlr->board;
/*
* This is the initialisation procedure described
* as 'mandatory' in the datasheet.
*/
dp8390disable(ctlr);
if(board->bit16)
outb(board->dp8390+Dcr, Ft4|Ls|Wts);
else
outb(board->dp8390+Dcr, Ft4|Ls);
outb(board->dp8390+Rbcr0, 0);
outb(board->dp8390+Rbcr1, 0);
outb(board->dp8390+Rcr, Ab);
outb(board->dp8390+Tcr, Lb);
outb(board->dp8390+Bnry, board->pstart);
outb(board->dp8390+Pstart, board->pstart);
outb(board->dp8390+Pstop, board->pstop);
outb(board->dp8390+Isr, 0xFF);
outb(board->dp8390+Imr, Ovwe|Txee|Rxee|Ptxe|Prxe);
outb(board->dp8390+Cr, Page1|RDMAabort|Stp);
/*
* Can't initialise ethernet address as we may
* not know it yet.
*/
outb(board->dp8390+Curr, board->pstart+1);
/*
* Leave the chip initialised,
* but in internal loopback mode.
*/
outb(board->dp8390+Cr, Page0|RDMAabort|Sta);
outb(board->dp8390+Tpsr, board->tstart);
}
void
dp8390attach(Ctlr *ctlr)
{
/*
* Enable the chip for transmit/receive.
* The init routine leaves the chip in internal
* loopback.
*/
outb(ctlr->board->dp8390+Tcr, 0);
}
void
dp8390mode(Ctlr *ctlr, int on)
{
if(on)
outb(ctlr->board->dp8390+Rcr, Pro|Ab);
else
outb(ctlr->board->dp8390+Rcr, Ab);
}
void
dp8390setea(Ctlr *ctlr)
{
Board *board = ctlr->board;
uchar cr;
int i;
/*
* 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 = inb(board->dp8390+Cr);
outb(board->dp8390+Cr, Page1|(~Page0 & cr));
for(i = 0; i < sizeof(ctlr->ea); i++)
outb(board->dp8390+Par0+i, ctlr->ea[i]);
outb(board->dp8390+Cr, cr);
}
void*
dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len)
{
Board *board = ctlr->board;
uchar cr;
int timo;
/*
* If the interface has shared memory, just
* do a memmove.
* In this case, 'from' is an index into the shared memory.
*/
if(board->ram){
memmove(to, (void*)(board->ramstart+from), len);
return to;
}
/*
* Read some data at offset 'from' in the board's memory
* using the DP8390 remote DMA facility, and place it at
* 'to' in main memory, via the I/O data port.
*/
cr = inb(board->dp8390+Cr);
outb(board->dp8390+Cr, Page0|RDMAabort|Sta);
outb(board->dp8390+Isr, Rdc);
/*
* Set up the remote DMA address and count.
*/
if(board->bit16)
len = ROUNDUP(len, 2);
outb(board->dp8390+Rbcr0, len & 0xFF);
outb(board->dp8390+Rbcr1, (len>>8) & 0xFF);
outb(board->dp8390+Rsar0, from & 0xFF);
outb(board->dp8390+Rsar1, (from>>8) & 0xFF);
/*
* Start the remote DMA read and suck the data
* out of the I/O port.
*/
outb(board->dp8390+Cr, Page0|RDMAread|Sta);
if(board->bit16)
inss(board->data, to, len/2);
else
insb(board->data, to, len);
/*
* Wait for the remote DMA to complete. The timeout
* is necessary because we may call this routine on
* a non-existent chip during initialisation and, due
* to the miracles of the bus, we could get this far
* and still be talking to a slot full of nothing.
*/
for(timo = 10000; (inb(board->dp8390+Isr) & Rdc) == 0 && timo; timo--)
;
outb(board->dp8390+Isr, Rdc);
outb(board->dp8390+Cr, cr);
return to;
}
void*
dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len)
{
Board *board = ctlr->board;
uchar cr;
/*
* If the interface has shared memory, just
* do a memmove.
* In this case, 'to' is an index into the shared memory.
*/
if(board->ram){
memmove((void*)(board->ramstart+to), from, len);
return (void*)to;
}
/*
* Write some data to offset 'to' in the board's memory
* using the DP8390 remote DMA facility, reading it at
* 'from' in main memory, via the I/O data port.
*/
cr = inb(board->dp8390+Cr);
outb(board->dp8390+Cr, Page0|RDMAabort|Sta);
outb(board->dp8390+Isr, Rdc);
/*
* Set up the remote DMA address and count.
* This is straight from the datasheet, hence
* the initial write to Rbcr0 and Cr.
*/
outb(board->dp8390+Rbcr0, 0xFF);
outb(board->dp8390+Cr, Page0|RDMAread|Sta);
if(board->bit16)
len = ROUNDUP(len, 2);
outb(board->dp8390+Rbcr0, len & 0xFF);
outb(board->dp8390+Rbcr1, (len>>8) & 0xFF);
outb(board->dp8390+Rsar0, to & 0xFF);
outb(board->dp8390+Rsar1, (to>>8) & 0xFF);
/*
* Start the remote DMA write and pump the data
* into the I/O port.
*/
outb(board->dp8390+Cr, Page0|RDMAwrite|Sta);
if(board->bit16)
outss(board->data, from, len/2);
else
outsb(board->data, from, len);
/*
* Wait for the remote DMA to finish. We'll need
* a timeout here if this ever gets called before
* we know there really is a chip there.
*/
while((inb(board->dp8390+Isr) & Rdc) == 0)
;
outb(board->dp8390+Isr, Rdc);
outb(board->dp8390+Cr, cr);
return (void*)to;
}
void
dp8390receive(Ctlr *ctlr)
{
Board *board = ctlr->board;
RingBuf *ring;
uchar bnry, curr, next;
Hdr hdr;
ulong data;
int i, len;
bnry = inb(board->dp8390+Bnry);
next = bnry+1;
if(next >= board->pstop)
next = board->pstart;
for(i = 0; ; i++){
outb(board->dp8390+Cr, Page1|RDMAabort|Sta);
curr = inb(board->dp8390+Curr);
outb(board->dp8390+Cr, Page0|RDMAabort|Sta);
if(next == curr)
break;
/*
* 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.
*/
if(strcmp(arch->id, "NCRD.0") == 0){
uchar a, b, c;
for(;;delay(10)){
a = inb(board->dp8390+Clda0);
b = inb(board->dp8390+Clda0);
if(a != b)
continue;
c = inb(board->dp8390+Clda0);
if(c != b)
continue;
break;
}
}
ctlr->inpackets++;
data = next*Dp8390BufSz;
dp8390read(ctlr, &hdr, data, sizeof(Hdr));
len = ((hdr.len1<<8)|hdr.len0)-4;
/*
* Chip is badly scrogged, reinitialise it.
* dp8390reset() calls the disable function.
* There's no need to reload the ethernet
* address.
*
* Untested.
*/
if(hdr.next < board->pstart || hdr.next >= board->pstop || len < 60){
print("scrogged\n");
dp8390reset(ctlr);
dp8390attach(ctlr);
return;
}
ring = &ctlr->rb[ctlr->ri];
if(ring->owner == Interface){
ring->len = len;
data += sizeof(Hdr);
if((data+len) >= board->pstop*Dp8390BufSz){
len = board->pstop*Dp8390BufSz - data;
dp8390read(ctlr, ring->pkt+len, board->pstart*Dp8390BufSz,
(data+ring->len) - board->pstop*Dp8390BufSz);
}
dp8390read(ctlr, ring->pkt, data, len);
ring->owner = Host;
ctlr->ri = NEXT(ctlr->ri, ctlr->nrb);
}
next = hdr.next;
bnry = next-1;
if(bnry < board->pstart)
bnry = board->pstop-1;
outb(board->dp8390+Bnry, bnry);
}
}
void
dp8390transmit(Ctlr *ctlr)
{
Board *board;
RingBuf *ring;
int s;
s = splhi();
board = ctlr->board;
ring = &ctlr->tb[ctlr->ti];
if(ring->busy == 0 && ring->owner == Interface){
dp8390write(ctlr, board->tstart*Dp8390BufSz, ring->pkt, ring->len);
outb(board->dp8390+Tbcr0, ring->len & 0xFF);
outb(board->dp8390+Tbcr1, (ring->len>>8) & 0xFF);
outb(board->dp8390+Cr, Page0|RDMAabort|Txp|Sta);
ring->busy = 1;
}
splx(s);
}
void
dp8390intr(Ctlr *ctlr)
{
Board *board = ctlr->board;
RingBuf *ring;
uchar isr;
/*
* While there is something of interest,
* clear all the interrupts and process.
*/
while(isr = inb(board->dp8390+Isr)){
outb(board->dp8390+Isr, isr);
if(isr & Ovw){
/*
* Need to do some work here:
* stop the chip;
* clear out the ring;
* re-enable the chip.
* The procedure to put the chip back on
* an active network is to first put it
* into internal loopback mode, enable it,
* then take it out of loopback.
*
* Untested.
*/
ctlr->overflows++;
dp8390disable(ctlr);
(*ctlr->board->receive)(ctlr);
outb(board->dp8390+Tcr, Lb);
outb(board->dp8390+Cr, Page0|RDMAabort|Sta);
dp8390attach(ctlr);
}
/*
* We have received packets.
* Take a spin round the ring and
* wakeup the kproc.
*/
if(isr & (Rxe|Prx)){
(*ctlr->board->receive)(ctlr);
wakeup(&ctlr->rr);
}
/*
* Log errors and successful transmissions.
*/
if(isr & Txe)
ctlr->oerrs++;
if(isr & Rxe){
ctlr->frames += inb(board->dp8390+Cntr0);
ctlr->crcs += inb(board->dp8390+Cntr1);
ctlr->buffs += inb(board->dp8390+Cntr2);
}
if(isr & Ptx)
ctlr->outpackets++;
/*
* A packet completed transmission, successfully or
* not. Start transmission on the next buffered packet,
* and wake the output routine.
*/
if(isr & (Txe|Ptx)){
ring = &ctlr->tb[ctlr->ti];
ring->owner = Host;
ring->busy = 0;
ctlr->ti = NEXT(ctlr->ti, ctlr->ntb);
(*ctlr->board->transmit)(ctlr);
wakeup(&ctlr->tr);
}
}
}
.
## diffname pc/ether8390.c 1993/0212
## diff -e /n/bootesdump/1992/1222/sys/src/9/pc/ether8390.c /n/bootesdump/1993/0212/sys/src/9/pc/ether8390.c
560a
dp8390outb(ctlr->card.dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
559a
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);
}
.
557c
(*ctlr->card.transmit)(ctlr);
.
555c
ctlr->tbusy = 0;
.
552a
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++;
.
535,547d
530c
(*ctlr->card.receive)(ctlr);
dp8390outb(ctlr->card.dp8390+Isr, Rxe|Prx);
.
516,521d
503,514c
if(ctlr->card.overflow)
(*ctlr->card.overflow)(ctlr);
dp8390outb(ctlr->card.dp8390+Isr, Ovw);
.
499,500c
dp8390outb(ctlr->card.dp8390+Imr, 0x00);
while(isr = dp8390inb(ctlr->card.dp8390+Isr)){
.
493c
uchar isr, r;
.
491d
476,483c
if(ctlr->tbusy){
ctlr->tbusy++;
if(ctlr->tbusy > 1 && ctlr->debug)
print("TB%d|", ctlr->tbusy);
.
474a
/*
* Stub watchdog routine.
* Whine if a transmit takes too long.
*/
.
472a
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)
{
.
471d
467a
/*
* Initiate a transmission. Must be called splhi().
*/
.
460,464c
/*
* 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);
.
455c
if(len)
(*ctlr->card.read)(ctlr, pkt, data, len);
.
450,453c
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;
.
447,448c
if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){
pkt = ring->pkt;
.
445a
/*
* 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.
*/
.
439,442c
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);
.
432,437c
* Don't believe the upper byte count, work it
* out from the software next-page pointer and
* the current next-page pointer.
.
427,429c
data = ctlr->card.nxtpkt*Dp8390BufSz;
(*ctlr->card.read)(ctlr, &hdr, data, sizeof(Hdr));
.
418c
c = dp8390inb(ctlr->card.dp8390+Clda0);
.
414,415c
a = dp8390inb(ctlr->card.dp8390+Clda0);
b = dp8390inb(ctlr->card.dp8390+Clda0);
.
391,402c
for(curr = getcurr(ctlr); ctlr->card.nxtpkt != curr; curr = getcurr(ctlr)){
.
388,389c
ulong data, len;
.
386c
uchar curr, len1, *pkt;
.
384d
380a
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;
}
.
376,377c
dp8390outb(ctlr->card.dp8390+Isr, Rdc);
dp8390outb(ctlr->card.dp8390+Cr, cr);
.
373c
while((dp8390inb(ctlr->card.dp8390+Isr) & Rdc) == 0)
.
366c
outsb(ctlr->card.data, from, len);
.
362,364c
if(ctlr->card.bit16)
outss(ctlr->card.data, from, len/2);
.
359,360c
* Pump the data into the I/O port.
.
357a
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;
}
}
.
351,356c
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);
.
348,349c
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);
.
345,346c
* This is straight from the DP8390[12D] datasheet, hence
* the initial set up for read.
.
342a
if(ctlr->card.bit16)
len = ROUNDUP(len, 2);
.
339,341c
cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp;
dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta);
dp8390outb(ctlr->card.dp8390+Isr, Rdc);
.
325,335c
* Write some data to offset 'to' in the card's memory
.
322a
ulong crda;
.
321d
313,314c
dp8390outb(ctlr->card.dp8390+Isr, Rdc);
dp8390outb(ctlr->card.dp8390+Cr, cr);
.
310c
for(timo = 10000; (dp8390inb(ctlr->card.dp8390+Isr) & Rdc) == 0 && timo; timo--)
.
301c
insb(ctlr->card.data, to, len);
.
297,299c
dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAread|Sta);
if(ctlr->card.bit16)
inss(ctlr->card.data, to, len/2);
.
288,291c
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);
.
286c
if(ctlr->card.bit16)
.
279,281c
cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp;
dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta);
dp8390outb(ctlr->card.dp8390+Isr, Rdc);
.
265,275c
* Read some data at offset 'from' in the card's memory
.
260d
253,254c
dp8390outb(ctlr->card.dp8390+Par0+i, ctlr->ea[i]);
dp8390outb(ctlr->card.dp8390+Cr, cr);
.
250,251c
cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp;
dp8390outb(ctlr->card.dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
.
239d
233c
dp8390outb(ctlr->card.dp8390+Rcr, Ab);
.
231c
dp8390outb(ctlr->card.dp8390+Rcr, Pro|Ab);
.
229a
/*
* Set/reset promiscuous mode.
*/
.
224c
dp8390outb(ctlr->card.dp8390+Rcr, Ab);
.
221,222c
* The init routine leaves the chip in monitor
* mode.
.
211,213c
dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta);
.
206a
dp8390outb(ctlr->card.dp8390+Isr, 0xFF);
dp8390outb(ctlr->card.dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
205c
dp8390ring(ctlr);
dp8390outb(ctlr->card.dp8390+Tpsr, ctlr->card.tstart);
.
202,203c
* Init the ring hardware and software ring pointers.
* Can't initialise ethernet address as we may not know
* it yet.
.
192,200d
189,190c
dp8390outb(ctlr->card.dp8390+Tcr, 0);
dp8390outb(ctlr->card.dp8390+Rcr, Mon);
.
186,187c
dp8390outb(ctlr->card.dp8390+Rbcr0, 0);
dp8390outb(ctlr->card.dp8390+Rbcr1, 0);
.
184c
dp8390outb(ctlr->card.dp8390+Dcr, Ft4|Ls);
.
181,182c
if(ctlr->card.bit16)
dp8390outb(ctlr->card.dp8390+Dcr, Ft4|Ls|Wts);
.
178c
* as 'mandatory' in the datasheet, with references
* to the 3Com503 technical reference manual.
.
174,175d
170a
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;
}
.
166,167c
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--)
.
155d
147,151d
41c
Crda1 = 0x09, /* current remote DMA address 1 */
.
27,29c
Ps0 = 0x40, /* page select */
Ps1 = 0x80, /* page select */
Page0 = 0x00,
Page1 = Ps0,
Page2 = Ps1,
.
## diffname pc/ether8390.c 1993/0213
## diff -e /n/bootesdump/1993/0212/sys/src/9/pc/ether8390.c /n/bootesdump/1993/0213/sys/src/9/pc/ether8390.c
513d
509a
.
508a
ctlr->tbusy = 1;
.
405,425c
if(strcmp(arch->id, "NCRD.0") == 0)
cldaquiet(ctlr);
.
395a
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;
}
}
.
229a
dp8390inb(ctlr->card.dp8390+Cntr2);
.
227c
* mode. Clear the missed-packet counter, it
* increments while in monitor mode.
.
216c
* but in monitor mode.
.
## diffname pc/ether8390.c 1993/0915
## diff -e /n/bootesdump/1993/0213/sys/src/9/pc/ether8390.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/ether8390.c
641c
dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
635,638c
ctlr->frames += dp8390inb(dp8390+Cntr0);
ctlr->crcs += dp8390inb(dp8390+Cntr1);
ctlr->buffs += dp8390inb(dp8390+Cntr2);
dp8390outb(dp8390+Isr, Cnt);
.
621c
dp8390outb(dp8390+Isr, Txe|Ptx);
.
614c
r = dp8390inb(dp8390+Tsr);
.
604c
dp8390outb(dp8390+Isr, Rxe|Prx);
.
593c
dp8390outb(dp8390+Isr, Ovw);
.
587,588c
dp8390outb(dp8390+Imr, 0x00);
while(isr = dp8390inb(dp8390+Isr)){
.
582a
dp8390 = ctlr->card.dp8390;
.
579a
ulong dp8390;
.
556c
dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta);
.
553c
dp8390outb(dp8390+Tcr, 0);
.
551c
dp8390outb(dp8390+Isr, Ovw);
.
548,549c
dp8390outb(dp8390+Tcr, Lb);
dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
.
545c
if(txp && (dp8390inb(dp8390+Isr) & (Txe|Ptx)) == 0)
.
541,542c
dp8390outb(dp8390+Rbcr0, 0);
dp8390outb(dp8390+Rbcr1, 0);
.
538,539c
txp = dp8390inb(dp8390+Cr) & Txp;
dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
.
533a
dp8390 = ctlr->card.dp8390;
.
530a
ulong dp8390;
.
522,524c
dp8390outb(dp8390+Tbcr0, ring->len & 0xFF);
dp8390outb(dp8390+Tbcr1, (ring->len>>8) & 0xFF);
dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta);
.
514a
dp8390 = ctlr->card.dp8390;
.
512a
ulong dp8390;
.
503c
dp8390outb(dp8390+Bnry, hdr.next);
.
463c
dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
.
461c
dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
.
433c
cldaquiet(dp8390);
.
431c
dp8390 = ctlr->card.dp8390;
for(curr = getcurr(dp8390); ctlr->card.nxtpkt != curr; curr = getcurr(dp8390)){
.
429c
ulong dp8390, data, len;
.
416c
c = dp8390inb(dp8390+Clda0);
.
412,413c
a = dp8390inb(dp8390+Clda0);
b = dp8390inb(dp8390+Clda0);
.
399c
cldaquiet(ulong dp8390)
.
391,394c
cr = dp8390inb(dp8390+Cr) & ~Txp;
dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
curr = dp8390inb(dp8390+Curr);
dp8390outb(dp8390+Cr, cr);
.
387c
getcurr(ulong dp8390)
.
381,382c
dp8390outb(dp8390+Isr, Rdc);
dp8390outb(dp8390+Cr, cr);
.
378c
while((dp8390inb(dp8390+Isr) & Rdc) == 0)
.
356,357c
crda = dp8390inb(dp8390+Crda0);
crda |= dp8390inb(dp8390+Crda1)<<8;
.
354c
dp8390outb(dp8390+Cr, Page0|RDMAwrite|Sta);
.
347,348c
crda = dp8390inb(dp8390+Crda0);
crda |= dp8390inb(dp8390+Crda1)<<8;
.
340,344c
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);
.
327,329c
cr = dp8390inb(dp8390+Cr) & ~Txp;
dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
dp8390outb(dp8390+Isr, Rdc);
.
321a
dp8390 = ctlr->card.dp8390;
.
320d
318a
ulong dp8390, crda;
.
311,312c
dp8390outb(dp8390+Isr, Rdc);
dp8390outb(dp8390+Cr, cr);
.
308c
for(timo = 10000; (dp8390inb(dp8390+Isr) & Rdc) == 0 && timo; timo--)
.
295c
dp8390outb(dp8390+Cr, Page0|RDMAread|Sta);
.
286,289c
dp8390outb(dp8390+Rbcr0, len & 0xFF);
dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF);
dp8390outb(dp8390+Rsar0, from & 0xFF);
dp8390outb(dp8390+Rsar1, (from>>8) & 0xFF);
.
277,279c
cr = dp8390inb(dp8390+Cr) & ~Txp;
dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
dp8390outb(dp8390+Isr, Rdc);
.
271a
dp8390 = ctlr->card.dp8390;
.
268a
ulong dp8390;
.
265a
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);
}
.
262,263c
dp8390outb(dp8390+Par0+i, ctlr->ea[i]);
dp8390outb(dp8390+Cr, cr);
.
259,260c
cr = dp8390inb(dp8390+Cr) & ~Txp;
dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
.
251a
dp8390 = ctlr->card.dp8390;
.
248a
ulong dp8390;
.
218c
dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
.
211,212c
dp8390outb(dp8390+Isr, 0xFF);
dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
209c
dp8390outb(dp8390+Tpsr, ctlr->card.tstart);
.
200,201c
dp8390outb(dp8390+Tcr, 0);
dp8390outb(dp8390+Rcr, Mon);
.
197,198c
dp8390outb(dp8390+Rbcr0, 0);
dp8390outb(dp8390+Rbcr1, 0);
.
195c
dp8390outb(dp8390+Dcr, Ft4|Ls);
.
193c
dp8390outb(dp8390+Dcr, Ft4|Ls|Wts);
.
185a
ulong dp8390;
dp8390 = ctlr->card.dp8390;
.
179a
dp8390outb(dp8390+Cr, Page1|RDMAabort|Stp);
dp8390outb(dp8390+Curr, ctlr->card.pstart);
dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
.
176,178c
dp8390 = ctlr->card.dp8390;
dp8390outb(dp8390+Pstart, ctlr->card.pstart);
dp8390outb(dp8390+Pstop, ctlr->card.pstop);
dp8390outb(dp8390+Bnry, ctlr->card.pstop-1);
.
172,174c
ulong dp8390;
.
162,165c
dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
dp8390outb(dp8390+Rbcr0, 0);
dp8390outb(dp8390+Rbcr1, 0);
for(timo = 10000; (dp8390inb(dp8390+Isr) & Rst) == 0 && timo; timo--)
.
153a
dp8390 = ctlr->card.dp8390;
.
151a
ulong dp8390;
.
## diffname pc/ether8390.c 1993/1116
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1993/1116/sys/src/brazil/pc/ether8390.c
683a
}
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;
.
677,679c
ether->frames += dp8390inb(dp8390+Cntr0);
ether->crcs += dp8390inb(dp8390+Cntr1);
ether->buffs += dp8390inb(dp8390+Cntr2);
.
666,673c
ether->outpackets++;
wakeup(ðer->tr);
.
660c
ether->oerrs++;
.
658c
if((r & (Cdh|Fu|Crs|Abt)) && ether->debug)
.
647d
645c
receive(ether);
.
641,642c
* Take a spin round the ring. and
.
636c
ether->overflows++;
.
633,634c
overflow(ether);
.
624c
dp8390 = ether->dp8390;
.
621d
602,619d
599,600c
static void
interrupt(Ether *ether)
.
592c
wakeup(ðer->rr);
.
590c
(*ether->receive)(ether);
.
573c
dp8390 = ether->dp8390;
.
566,567c
static void
overflow(Ether *ether)
.
558c
(*ether->write)(ctlr, ether->tstart*Dp8390BufSz, ring->pkt, ring->len);
.
556c
ether->tbusy = 1;
.
552,554c
dp8390 = ether->dp8390;
ring = ðer->tb[ether->ti];
if(ether->tbusy == 0 && ring->owner == Interface){
.
547c
dp8390transmit(Ether *ether)
.
537,538c
if(hdr.next < ether->pstart)
hdr.next = ether->pstop-1;
.
534c
ether->nxtpkt = hdr.next;
.
526,527c
/*
* 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);
}
.
524c
(*ether->read)(ctlr, pkt, data, len);
.
520c
data = ether->pstart*Dp8390BufSz;
.
518c
(*ether->read)(ctlr, pkt, data, count);
.
515,516c
if((data+len) >= ether->pstop*Dp8390BufSz){
ulong count = ether->pstop*Dp8390BufSz - data;
.
509,511c
if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok){
pkt = ether->rpkt;
.
504,507c
* 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.
.
498c
dp8390ring(ether);
.
493c
if(hdr.next < ether->pstart || hdr.next >= ether->pstop
.
484c
len1 = (ether->pstop-ether->nxtpkt) + (hdr.next-ether->pstart) - 1;
.
481,482c
if(hdr.next > ether->nxtpkt)
len1 = hdr.next - ether->nxtpkt - 1;
.
473,475d
471c
data = ether->nxtpkt*Dp8390BufSz;
(*ether->read)(ctlr, &hdr, data, sizeof(Hdr));
.
466,469c
dp8390 = ether->dp8390;
for(curr = getcurr(dp8390); ether->nxtpkt != curr; curr = getcurr(dp8390)){
ether->inpackets++;
.
464a
ushort type;
Netfile *f, **fp, **ep;
.
436,461d
434c
receive(Ether *ether)
.
406c
outsb(ether->data, from, len);
.
403,404c
if(ether->bit16)
outss(ether->data, from, len/2);
.
374,376c
crda = to-1-ether->bit16;
dp8390outb(dp8390+Rbcr0, (len+1+ether->bit16) & 0xFF);
dp8390outb(dp8390+Rbcr1, ((len+1+ether->bit16)>>8) & 0xFF);
.
366c
if(ether->bit16)
.
356c
dp8390 = ether->dp8390;
.
350,351c
static void*
dp8390write(Ether *ether, ulong to, void *from, ulong len)
.
333c
insb(ether->data, to, len);
.
330,331c
if(ether->bit16)
inss(ether->data, to, len/2);
.
318c
if(ether->bit16)
.
305c
dp8390 = ether->dp8390;
.
298,299c
static void*
dp8390read(Ether *ether, void *to, ulong from, ulong len)
.
293,294c
for(i = 0; i < sizeof(ether->ea); i++)
ether->ea[i] = dp8390inb(dp8390+Par0+i);
.
285c
* Get the ethernet address from the chip.
.
283c
dp8390 = ether->dp8390;
.
277c
dp8390getea(Ether *ether)
.
271,272c
for(i = 0; i < sizeof(ether->ea); i++)
dp8390outb(dp8390+Par0+i, ether->ea[i]);
.
261c
dp8390 = ether->dp8390;
.
192,257d
189c
dp8390setea(Ether *ether)
.
185c
ether->nxtpkt = ether->pstart;
.
182c
dp8390outb(dp8390+Curr, ether->pstart);
.
176,179c
dp8390 = ether->dp8390;
dp8390outb(dp8390+Pstart, ether->pstart);
dp8390outb(dp8390+Pstop, ether->pstop);
dp8390outb(dp8390+Bnry, ether->pstop-1);
.
172c
dp8390ring(Ether *ether)
.
155c
dp8390 = ether->dp8390;
.
150c
dp8390disable(Ether *ether)
.
15c
#include "etherif.h"
.
13c
#include "../port/error.h"
#include "../port/netif.h"
.
11d
## diffname pc/ether8390.c 1993/1117
## diff -e /n/fornaxdump/1993/1116/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1993/1117/sys/src/brazil/pc/ether8390.c
600c
dp8390 = ((Dp8390*)ether->private)->dp8390;
.
584a
ulong dp8390;
dp8390 = ((Dp8390*)ether->private)->dp8390;
.
572a
ulong dp8390;
dp8390 = ((Dp8390*)ether->private)->dp8390;
.
517c
dp8390 = ((Dp8390*)ether->private)->dp8390;
.
485c
dp8390 = ((Dp8390*)ether->private)->dp8390;
.
464c
dp8390 = ((Dp8390*)ether->private)->dp8390;
.
376c
dp8390 = ((Dp8390*)ether->private)->dp8390;
.
290c
dp8390 = ((Dp8390*)ether->private)->dp8390;
.
279,280c
dp8390outb(port+Isr, Rdc);
dp8390outb(port+Cr, cr);
.
276c
for(timo = 10000; (dp8390inb(port+Isr) & Rdc) == 0 && timo; timo--)
.
267c
insb(dp8390->data, to, len);
.
263,265c
dp8390outb(port+Cr, Page0|RDMAread|Sta);
if(dp8390->bit16)
inss(dp8390->data, to, len/2);
.
254,257c
dp8390outb(port+Rbcr0, len & 0xFF);
dp8390outb(port+Rbcr1, (len>>8) & 0xFF);
dp8390outb(port+Rsar0, from & 0xFF);
dp8390outb(port+Rsar1, (from>>8) & 0xFF);
.
252c
if(dp8390->bit16)
.
245,247c
cr = dp8390inb(port+Cr) & ~Txp;
dp8390outb(port+Cr, Page0|RDMAabort|Sta);
dp8390outb(port+Isr, Rdc);
.
239c
port = dp8390->dp8390;
.
235c
ulong port;
.
233c
dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len)
.
228,229c
ether->ea[i] = dp8390inb(port+Par0+i);
dp8390outb(port+Cr, cr);
.
225,226c
cr = dp8390inb(port+Cr) & ~Txp;
dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
.
217c
port = ((Dp8390*)ether->private)->dp8390;
.
213c
ulong port;
.
206,207c
dp8390outb(port+Par0+i, ether->ea[i]);
dp8390outb(port+Cr, cr);
.
203,204c
cr = dp8390inb(port+Cr) & ~Txp;
dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
.
195c
port = ((Dp8390*)ether->private)->dp8390;
.
191c
ulong port;
.
185c
dp8390->nxtpkt = dp8390->pstart;
.
181,183c
dp8390outb(port+Cr, Page1|RDMAabort|Stp);
dp8390outb(port+Curr, dp8390->pstart);
dp8390outb(port+Cr, Page0|RDMAabort|Stp);
.
176,179c
port = dp8390->dp8390;
dp8390outb(port+Pstart, dp8390->pstart);
dp8390outb(port+Pstop, dp8390->pstop);
dp8390outb(port+Bnry, dp8390->pstop-1);
.
174c
ulong port;
.
172c
dp8390ring(Dp8390 *dp8390)
.
164,167c
dp8390outb(port+Cr, Page0|RDMAabort|Stp);
dp8390outb(port+Rbcr0, 0);
dp8390outb(port+Rbcr1, 0);
for(timo = 10000; (dp8390inb(port+Isr) & Rst) == 0 && timo; timo--)
.
155c
port = dp8390->dp8390;
.
152c
ulong port;
.
150c
dp8390disable(Dp8390 *dp8390)
.
## diffname pc/ether8390.c 1993/1118
## diff -e /n/fornaxdump/1993/1117/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1993/1118/sys/src/brazil/pc/ether8390.c
639c
dp8390outb(port+Cr, Page0|RDMAabort|Sta);
.
632,633c
dp8390outb(port+Isr, 0xFF);
dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
629,630c
dp8390ring(dp8390);
dp8390outb(port+Tpsr, dp8390->tstart);
.
621,622c
dp8390outb(port+Tcr, 0);
dp8390outb(port+Rcr, Mon);
.
618,619c
dp8390outb(port+Rbcr0, 0);
dp8390outb(port+Rbcr1, 0);
.
616c
dp8390outb(port+Dcr, Ft4|Ls);
.
612,614c
dp8390disable(dp8390);
if(dp8390->bit16)
dp8390outb(port+Dcr, Ft4|Ls|Wts);
.
606c
dp8390 = ether->private;
port = dp8390->dp8390;
.
604c
Dp8390 *dp8390;
ulong port;
.
601c
int
.
597,598c
dp8390outb(dp8390->dp8390+Rcr, Ab);
dp8390inb(dp8390->dp8390+Cntr2);
.
590d
588c
Dp8390 *dp8390 = ether->private;
.
585,586c
static void
attach(Ether *ether)
.
582c
dp8390outb(dp8390->dp8390+Rcr, Ab);
.
580c
dp8390outb(dp8390->dp8390+Rcr, Pro|Ab);
.
575d
573c
Dp8390 *dp8390 = ((Ether*)arg)->private;
.
571c
promiscuous(void *arg, int on)
.
567c
dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
561,564c
ether->frames += dp8390inb(port+Cntr0);
ether->crcs += dp8390inb(port+Cntr1);
ether->buffs += dp8390inb(port+Cntr2);
dp8390outb(port+Isr, Cnt);
.
556a
dp8390->busy = 0;
.
553c
dp8390outb(port+Isr, Txe|Ptx);
.
548,549c
if((r & (Cdh|Fu|Crs|Abt)))
print("dp8390: Tsr#%2.2ux\n", r);
.
546c
r = dp8390inb(port+Tsr);
.
537c
dp8390outb(port+Isr, Rxe|Prx);
.
527c
dp8390outb(port+Isr, Ovw);
.
522,523c
dp8390outb(port+Imr, 0x00);
while(isr = dp8390inb(port+Isr)){
.
517c
dp8390 = ether->private;
port = dp8390->dp8390;
.
514c
Dp8390 *dp8390;
ulong port;
.
508c
dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta);
.
500,505c
dp8390outb(port+Tcr, Lb);
dp8390outb(port+Cr, Page0|RDMAabort|Sta);
receive(ether);
dp8390outb(port+Isr, Ovw);
dp8390outb(port+Tcr, 0);
.
497c
if(txp && (dp8390inb(port+Isr) & (Txe|Ptx)) == 0)
.
493,494c
dp8390outb(port+Rbcr0, 0);
dp8390outb(port+Rbcr1, 0);
.
490,491c
txp = dp8390inb(port+Cr) & Txp;
dp8390outb(port+Cr, Page0|RDMAabort|Stp);
.
485c
dp8390 = ether->private;
port = dp8390->dp8390;
.
481c
Dp8390 *dp8390;
ulong port;
.
475a
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;
.
470,474c
qlock(ðer->tlock);
if(waserror()) {
qunlock(ðer->tlock);
nexterror();
.
468c
dp8390 = ether->private;
port = dp8390->dp8390;
.
464,466c
static long
write(Ether *ether, void *buf, long n)
{
Dp8390 *dp8390;
ulong port;
.
461,462c
return ((Dp8390*)arg)->busy == 0;
}
.
455,459c
static int
istxbusy(void *arg)
.
449,451c
if(hdr.next < dp8390->pstart)
hdr.next = dp8390->pstop-1;
dp8390outb(port+Bnry, hdr.next);
.
446c
dp8390->nxtpkt = hdr.next;
.
443c
* Finished with this packet, update the
.
427,428c
if(len1){
if(dp8390->ram)
memmove(pkt, (void*)(ether->mem+data), len1);
else
dp8390read(dp8390, pkt, data, len1);
}
.
424,425c
data = dp8390->pstart*Dp8390BufSz;
len1 -= count;
.
422c
if(dp8390->ram)
memmove(pkt, (void*)(ether->mem+data), count);
else
dp8390read(dp8390, pkt, data, count);
.
419,420c
if((data+len1) >= dp8390->pstop*Dp8390BufSz){
ulong count = dp8390->pstop*Dp8390BufSz - data;
.
417c
len1 = len;
.
415c
pkt = (uchar*)ðer->rpkt;
.
404,406c
dp8390outb(port+Cr, Page0|RDMAabort|Stp);
dp8390ring(dp8390);
dp8390outb(port+Cr, Page0|RDMAabort|Sta);
.
402c
print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n",
.
400c
if(hdr.next < dp8390->pstart || hdr.next >= dp8390->pstop
.
391c
len1 = (dp8390->pstop-dp8390->nxtpkt) + (hdr.next-dp8390->pstart) - 1;
.
388,389c
if(hdr.next > dp8390->nxtpkt)
len1 = hdr.next - dp8390->nxtpkt - 1;
.
380,381c
data = dp8390->nxtpkt*Dp8390BufSz;
if(dp8390->ram)
memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr));
else
dp8390read(dp8390, &hdr, data, sizeof(Hdr));
.
376,377c
dp8390 = ether->private;
port = dp8390->dp8390;
for(curr = getcurr(dp8390); dp8390->nxtpkt != curr; curr = getcurr(dp8390)){
.
372c
ulong port, data, len, len1;
.
370c
Dp8390 *dp8390;
uchar curr, *pkt;
.
360,363c
cr = dp8390inb(port+Cr) & ~Txp;
dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
curr = dp8390inb(port+Curr);
dp8390outb(port+Cr, cr);
.
357a
ulong port = dp8390->dp8390;
.
356c
getcurr(Dp8390 *dp8390)
.
350,351c
dp8390outb(port+Isr, Rdc);
dp8390outb(port+Cr, cr);
.
347c
while((dp8390inb(port+Isr) & Rdc) == 0)
.
340c
outsb(dp8390->data, from, len);
.
337,338c
if(dp8390->bit16)
outss(dp8390->data, from, len/2);
.
325,326c
crda = dp8390inb(port+Crda0);
crda |= dp8390inb(port+Crda1)<<8;
.
323c
dp8390outb(port+Cr, Page0|RDMAwrite|Sta);
.
316,317c
crda = dp8390inb(port+Crda0);
crda |= dp8390inb(port+Crda1)<<8;
.
308,313c
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);
.
300c
if(dp8390->bit16)
.
296,298c
cr = dp8390inb(port+Cr) & ~Txp;
dp8390outb(port+Cr, Page0|RDMAabort|Sta);
dp8390outb(port+Isr, Rdc);
.
290d
287c
ulong port = dp8390->dp8390;
ulong crda;
.
285c
dp8390write(Dp8390 *dp8390, ulong to, void *from, ulong len)
.
239d
235c
ulong port = dp8390->dp8390;
.
217d
213c
ulong port = ((Dp8390*)ether->private)->dp8390;
.
195d
191c
ulong port = ((Dp8390*)ether->private)->dp8390;
.
176d
174c
ulong port = dp8390->dp8390;
.
155d
152c
ulong port = dp8390->dp8390;
.
16a
extern int dp8390inb(ulong);
extern void dp8390outb(ulong, uchar);
.
## diffname pc/ether8390.c 1993/1119
## diff -e /n/fornaxdump/1993/1118/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1993/1119/sys/src/brazil/pc/ether8390.c
591c
ether->tlen = 0;
.
557a
print("I%2.2ux|", isr);
.
501,503d
487,491d
485a
ether->tlen = n;
.
481,484c
tsleep(ðer->tr, istxavail, ether, 10000);
if(ether->tlen){
print("dp8390: transmitter jammed\n");
return 0;
.
469c
return ((Ether*)arg)->tlen == 0;
.
467c
istxavail(void *arg)
.
449a
}
.
448a
{
print("Q%d|", len);
.
## diffname pc/ether8390.c 1993/1120
## diff -e /n/fornaxdump/1993/1119/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1993/1120/sys/src/brazil/pc/ether8390.c
554d
500c
return len;
.
496,497c
/*
* 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);
.
494c
pkt = ðer->tpkt;
memmove(pkt, buf, len);
.
492c
pkt = (Etherpkt*)(ether->mem+dp8390->tstart*Dp8390BufSz);
.
490a
/*
* 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.
*/
.
489c
ether->tlen = len;
.
479a
Etherpkt *pkt;
.
476c
write(Ether *ether, void *buf, long len)
.
452d
449,450d
## diffname pc/ether8390.c 1993/1124
## diff -e /n/fornaxdump/1993/1120/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/ether8390.c
562a
USED(ur);
ether = arg;
.
558a
Ether *ether;
.
557c
interrupt(Ureg *ur, void *arg)
.
## diffname pc/ether8390.c 1994/0128
## diff -e /n/fornaxdump/1993/1124/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1994/0128/sys/src/brazil/pc/ether8390.c
282c
void*
.
231c
void*
.
## diffname pc/ether8390.c 1994/0130
## diff -e /n/fornaxdump/1994/0128/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1994/0130/sys/src/brazil/pc/ether8390.c
693c
slowoutb(port+Cr, Page0|RDMAabort|Sta);
.
686,687c
slowoutb(port+Isr, 0xFF);
slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
684c
slowoutb(port+Tpsr, dp8390->tstart);
.
675,676c
slowoutb(port+Tcr, 0);
slowoutb(port+Rcr, Mon);
.
672,673c
slowoutb(port+Rbcr0, 0);
slowoutb(port+Rbcr1, 0);
.
670c
slowoutb(port+Dcr, Ft4|Ls);
.
668c
slowoutb(port+Dcr, Ft4|Ls|Wts);
.
648,649c
slowoutb(dp8390->dp8390+Rcr, Ab);
slowinb(dp8390->dp8390+Cntr2);
.
634c
slowoutb(dp8390->dp8390+Rcr, Ab);
.
632c
slowoutb(dp8390->dp8390+Rcr, Pro|Ab);
.
620c
slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
614,617c
ether->frames += slowinb(port+Cntr0);
ether->crcs += slowinb(port+Cntr1);
ether->buffs += slowinb(port+Cntr2);
slowoutb(port+Isr, Cnt);
.
605c
slowoutb(port+Isr, Txe|Ptx);
.
598c
r = slowinb(port+Tsr);
.
589c
slowoutb(port+Isr, Rxe|Prx);
.
579c
slowoutb(port+Isr, Ovw);
.
574,575c
slowoutb(port+Imr, 0x00);
while(isr = slowinb(port+Isr)){
.
553c
slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta);
.
549,550c
slowoutb(port+Isr, Ovw);
slowoutb(port+Tcr, 0);
.
546,547c
slowoutb(port+Tcr, Lb);
slowoutb(port+Cr, Page0|RDMAabort|Sta);
.
543c
if(txp && (slowinb(port+Isr) & (Txe|Ptx)) == 0)
.
539,540c
slowoutb(port+Rbcr0, 0);
slowoutb(port+Rbcr1, 0);
.
536,537c
txp = slowinb(port+Cr) & Txp;
slowoutb(port+Cr, Page0|RDMAabort|Stp);
.
514,516c
slowoutb(port+Tbcr0, len & 0xFF);
slowoutb(port+Tbcr1, (len>>8) & 0xFF);
slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta);
.
462c
slowoutb(port+Bnry, hdr.next);
.
410c
slowoutb(port+Cr, Page0|RDMAabort|Sta);
.
408c
slowoutb(port+Cr, Page0|RDMAabort|Stp);
.
359,362c
cr = slowinb(port+Cr) & ~Txp;
slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
curr = slowinb(port+Curr);
slowoutb(port+Cr, cr);
.
348,349c
slowoutb(port+Isr, Rdc);
slowoutb(port+Cr, cr);
.
345c
while((slowinb(port+Isr) & Rdc) == 0)
.
323,324c
crda = slowinb(port+Crda0);
crda |= slowinb(port+Crda1)<<8;
.
321c
slowoutb(port+Cr, Page0|RDMAwrite|Sta);
.
314,315c
crda = slowinb(port+Crda0);
crda |= slowinb(port+Crda1)<<8;
.
307,311c
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);
.
294,296c
cr = slowinb(port+Cr) & ~Txp;
slowoutb(port+Cr, Page0|RDMAabort|Sta);
slowoutb(port+Isr, Rdc);
.
277,278c
slowoutb(port+Isr, Rdc);
slowoutb(port+Cr, cr);
.
274c
for(timo = 10000; (slowinb(port+Isr) & Rdc) == 0 && timo; timo--)
.
261c
slowoutb(port+Cr, Page0|RDMAread|Sta);
.
252,255c
slowoutb(port+Rbcr0, len & 0xFF);
slowoutb(port+Rbcr1, (len>>8) & 0xFF);
slowoutb(port+Rsar0, from & 0xFF);
slowoutb(port+Rsar1, (from>>8) & 0xFF);
.
243,245c
cr = slowinb(port+Cr) & ~Txp;
slowoutb(port+Cr, Page0|RDMAabort|Sta);
slowoutb(port+Isr, Rdc);
.
227,228c
ether->ea[i] = slowinb(port+Par0+i);
slowoutb(port+Cr, cr);
.
224,225c
cr = slowinb(port+Cr) & ~Txp;
slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
.
206,207c
slowoutb(port+Par0+i, ether->ea[i]);
slowoutb(port+Cr, cr);
.
203,204c
cr = slowinb(port+Cr) & ~Txp;
slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
.
182,184c
slowoutb(port+Cr, Page1|RDMAabort|Stp);
slowoutb(port+Curr, dp8390->pstart);
slowoutb(port+Cr, Page0|RDMAabort|Stp);
.
178,180c
slowoutb(port+Pstart, dp8390->pstart);
slowoutb(port+Pstop, dp8390->pstop);
slowoutb(port+Bnry, dp8390->pstop-1);
.
166,169c
slowoutb(port+Cr, Page0|RDMAabort|Stp);
slowoutb(port+Rbcr0, 0);
slowoutb(port+Rbcr1, 0);
for(timo = 10000; (slowinb(port+Isr) & Rst) == 0 && timo; timo--)
.
17,18c
extern int slowinb(ulong);
extern void slowoutb(ulong, uchar);
.
## diffname pc/ether8390.c 1994/0201
## diff -e /n/fornaxdump/1994/0130/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1994/0201/sys/src/brazil/pc/ether8390.c
346c
if(tries++ >= 10000000){
print("dp8390write whoops\n");
break;
}
.
344a
tries = 0;
.
338a
splx(s);
.
288a
s = splhi();
.
287a
int s, tries;
.
## diffname pc/ether8390.c 1994/0202
## diff -e /n/fornaxdump/1994/0201/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1994/0202/sys/src/brazil/pc/ether8390.c
451,457c
etherrloop(ether, ðer->rpkt, len);
.
423a
*
* We could conceivably remove the copy into rpkt here by wrapping
* this up with the etherrloop code.
.
380,381d
356a
splx(s);
.
353a
}
.
349,351c
while((slowinb(port+Isr) & Rdc) == 0){
if(tries++ >= 100000){
print("dp8390write dma timed out\n");
.
344,346c
* Wait for the remote DMA to finish. It should
* be almost immediate.
.
341d
290a
.
289a
/*
* Keep out interrupts since reading and writing
* use the same DMA engine.
*/
.
## diffname pc/ether8390.c 1994/0715
## diff -e /n/fornaxdump/1994/0202/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1994/0715/sys/src/brazil/pc/ether8390.c
458c
etherrloop(ether, ðer->rpkt, len, 1);
.
## diffname pc/ether8390.c 1995/0408
## diff -e /n/fornaxdump/1994/0715/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1995/0408/sys/src/brazil/pc/ether8390.c
701c
dp8390outb(port+Cr, Page0|RDMAabort|Sta);
.
694,695c
dp8390outb(port+Isr, 0xFF);
dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
692c
dp8390outb(port+Tpsr, dp8390->tstart);
.
683,684c
dp8390outb(port+Tcr, 0);
dp8390outb(port+Rcr, Mon);
.
680,681c
dp8390outb(port+Rbcr0, 0);
dp8390outb(port+Rbcr1, 0);
.
678c
dp8390outb(port+Dcr, Ft4|Ls);
.
676c
dp8390outb(port+Dcr, Ft4|Ls|Wts);
.
656,657c
dp8390outb(dp8390->dp8390+Rcr, Ab);
dp8390inb(dp8390->dp8390+Cntr2);
.
642c
dp8390outb(dp8390->dp8390+Rcr, Ab);
.
640c
dp8390outb(dp8390->dp8390+Rcr, Pro|Ab);
.
628c
dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
622,625c
ether->frames += dp8390inb(port+Cntr0);
ether->crcs += dp8390inb(port+Cntr1);
ether->buffs += dp8390inb(port+Cntr2);
dp8390outb(port+Isr, Cnt);
.
613c
dp8390outb(port+Isr, Txe|Ptx);
.
606c
r = dp8390inb(port+Tsr);
.
597c
dp8390outb(port+Isr, Rxe|Prx);
.
587c
dp8390outb(port+Isr, Ovw);
.
582,583c
dp8390outb(port+Imr, 0x00);
while(isr = dp8390inb(port+Isr)){
.
561c
dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta);
.
557,558c
dp8390outb(port+Isr, Ovw);
dp8390outb(port+Tcr, 0);
.
554,555c
dp8390outb(port+Tcr, Lb);
dp8390outb(port+Cr, Page0|RDMAabort|Sta);
.
551c
if(txp && (dp8390inb(port+Isr) & (Txe|Ptx)) == 0)
.
547,548c
dp8390outb(port+Rbcr0, 0);
dp8390outb(port+Rbcr1, 0);
.
544,545c
txp = dp8390inb(port+Cr) & Txp;
dp8390outb(port+Cr, Page0|RDMAabort|Stp);
.
522,524c
dp8390outb(port+Tbcr0, len & 0xFF);
dp8390outb(port+Tbcr1, (len>>8) & 0xFF);
dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta);
.
470c
dp8390outb(port+Bnry, hdr.next);
.
421c
dp8390outb(port+Cr, Page0|RDMAabort|Sta);
.
419c
dp8390outb(port+Cr, Page0|RDMAabort|Stp);
.
372,375c
cr = dp8390inb(port+Cr) & ~Txp;
dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
curr = dp8390inb(port+Curr);
dp8390outb(port+Cr, cr);
.
359,360c
dp8390outb(port+Isr, Rdc);
dp8390outb(port+Cr, cr);
.
352c
while((dp8390inb(port+Isr) & Rdc) == 0){
.
330,331c
crda = dp8390inb(port+Crda0);
crda |= dp8390inb(port+Crda1)<<8;
.
328c
dp8390outb(port+Cr, Page0|RDMAwrite|Sta);
.
321,322c
crda = dp8390inb(port+Crda0);
crda |= dp8390inb(port+Crda1)<<8;
.
314,318c
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);
.
301,303c
cr = dp8390inb(port+Cr) & ~Txp;
dp8390outb(port+Cr, Page0|RDMAabort|Sta);
dp8390outb(port+Isr, Rdc);
.
277,278c
dp8390outb(port+Isr, Rdc);
dp8390outb(port+Cr, cr);
.
274c
for(timo = 10000; (dp8390inb(port+Isr) & Rdc) == 0 && timo; timo--)
.
261c
dp8390outb(port+Cr, Page0|RDMAread|Sta);
.
252,255c
dp8390outb(port+Rbcr0, len & 0xFF);
dp8390outb(port+Rbcr1, (len>>8) & 0xFF);
dp8390outb(port+Rsar0, from & 0xFF);
dp8390outb(port+Rsar1, (from>>8) & 0xFF);
.
243,245c
cr = dp8390inb(port+Cr) & ~Txp;
dp8390outb(port+Cr, Page0|RDMAabort|Sta);
dp8390outb(port+Isr, Rdc);
.
227,228c
ether->ea[i] = dp8390inb(port+Par0+i);
dp8390outb(port+Cr, cr);
.
224,225c
cr = dp8390inb(port+Cr) & ~Txp;
dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
.
206,207c
dp8390outb(port+Par0+i, ether->ea[i]);
dp8390outb(port+Cr, cr);
.
203,204c
cr = dp8390inb(port+Cr) & ~Txp;
dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
.
182,184c
dp8390outb(port+Cr, Page1|RDMAabort|Stp);
dp8390outb(port+Curr, dp8390->pstart);
dp8390outb(port+Cr, Page0|RDMAabort|Stp);
.
178,180c
dp8390outb(port+Pstart, dp8390->pstart);
dp8390outb(port+Pstop, dp8390->pstop);
dp8390outb(port+Bnry, dp8390->pstop-1);
.
166,169c
dp8390outb(port+Cr, Page0|RDMAabort|Stp);
dp8390outb(port+Rbcr0, 0);
dp8390outb(port+Rbcr1, 0);
for(timo = 10000; (dp8390inb(port+Isr) & Rst) == 0 && timo; timo--)
.
151a
/*
* 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;
}
.
17,19d
## diffname pc/ether8390.c 1995/0409
## diff -e /n/fornaxdump/1995/0408/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1995/0409/sys/src/brazil/pc/ether8390.c
718c
slowoutb(port+Cr, Page0|RDMAabort|Sta);
.
711,712c
slowoutb(port+Isr, 0xFF);
slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
709c
slowoutb(port+Tpsr, dp8390->tstart);
.
700,701c
slowoutb(port+Tcr, 0);
slowoutb(port+Rcr, Mon);
.
697,698c
slowoutb(port+Rbcr0, 0);
slowoutb(port+Rbcr1, 0);
.
695c
slowoutb(port+Dcr, Ft4|Ls);
.
693c
slowoutb(port+Dcr, Ft4|Ls|Wts);
.
673,674c
slowoutb(dp8390->dp8390+Rcr, Ab);
slowinb(dp8390->dp8390+Cntr2);
.
659c
slowoutb(dp8390->dp8390+Rcr, Ab);
.
657c
slowoutb(dp8390->dp8390+Rcr, Pro|Ab);
.
645c
slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
.
639,642c
ether->frames += slowinb(port+Cntr0);
ether->crcs += slowinb(port+Cntr1);
ether->buffs += slowinb(port+Cntr2);
slowoutb(port+Isr, Cnt);
.
630c
slowoutb(port+Isr, Txe|Ptx);
.
623c
r = slowinb(port+Tsr);
.
614c
slowoutb(port+Isr, Rxe|Prx);
.
604c
slowoutb(port+Isr, Ovw);
.
599,600c
slowoutb(port+Imr, 0x00);
while(isr = slowinb(port+Isr)){
.
578c
slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta);
.
574,575c
slowoutb(port+Isr, Ovw);
slowoutb(port+Tcr, 0);
.
571,572c
slowoutb(port+Tcr, Lb);
slowoutb(port+Cr, Page0|RDMAabort|Sta);
.
568c
if(txp && (slowinb(port+Isr) & (Txe|Ptx)) == 0)
.
564,565c
slowoutb(port+Rbcr0, 0);
slowoutb(port+Rbcr1, 0);
.
561,562c
txp = slowinb(port+Cr) & Txp;
slowoutb(port+Cr, Page0|RDMAabort|Stp);
.
539,541c
slowoutb(port+Tbcr0, len & 0xFF);
slowoutb(port+Tbcr1, (len>>8) & 0xFF);
slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta);
.
487c
slowoutb(port+Bnry, hdr.next);
.
438c
slowoutb(port+Cr, Page0|RDMAabort|Sta);
.
436c
slowoutb(port+Cr, Page0|RDMAabort|Stp);
.
389,392c
cr = slowinb(port+Cr) & ~Txp;
slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
curr = slowinb(port+Curr);
slowoutb(port+Cr, cr);
.
376,377c
slowoutb(port+Isr, Rdc);
slowoutb(port+Cr, cr);
.
369c
while((slowinb(port+Isr) & Rdc) == 0){
.
347,348c
crda = slowinb(port+Crda0);
crda |= slowinb(port+Crda1)<<8;
.
345c
slowoutb(port+Cr, Page0|RDMAwrite|Sta);
.
338,339c
crda = slowinb(port+Crda0);
crda |= slowinb(port+Crda1)<<8;
.
331,335c
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);
.
318,320c
cr = slowinb(port+Cr) & ~Txp;
slowoutb(port+Cr, Page0|RDMAabort|Sta);
slowoutb(port+Isr, Rdc);
.
294,295c
slowoutb(port+Isr, Rdc);
slowoutb(port+Cr, cr);
.
291c
for(timo = 10000; (slowinb(port+Isr) & Rdc) == 0 && timo; timo--)
.
278c
slowoutb(port+Cr, Page0|RDMAread|Sta);
.
269,272c
slowoutb(port+Rbcr0, len & 0xFF);
slowoutb(port+Rbcr1, (len>>8) & 0xFF);
slowoutb(port+Rsar0, from & 0xFF);
slowoutb(port+Rsar1, (from>>8) & 0xFF);
.
260,262c
cr = slowinb(port+Cr) & ~Txp;
slowoutb(port+Cr, Page0|RDMAabort|Sta);
slowoutb(port+Isr, Rdc);
.
244,245c
ether->ea[i] = slowinb(port+Par0+i);
slowoutb(port+Cr, cr);
.
241,242c
cr = slowinb(port+Cr) & ~Txp;
slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
.
223,224c
slowoutb(port+Par0+i, ether->ea[i]);
slowoutb(port+Cr, cr);
.
220,221c
cr = slowinb(port+Cr) & ~Txp;
slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr));
.
199,201c
slowoutb(port+Cr, Page1|RDMAabort|Stp);
slowoutb(port+Curr, dp8390->pstart);
slowoutb(port+Cr, Page0|RDMAabort|Stp);
.
195,197c
slowoutb(port+Pstart, dp8390->pstart);
slowoutb(port+Pstop, dp8390->pstop);
slowoutb(port+Bnry, dp8390->pstop-1);
.
183,186c
slowoutb(port+Cr, Page0|RDMAabort|Stp);
slowoutb(port+Rbcr0, 0);
slowoutb(port+Rbcr1, 0);
for(timo = 10000; (slowinb(port+Isr) & Rst) == 0 && timo; timo--)
.
149,168d
16a
extern int slowinb(ulong);
extern void slowoutb(ulong, uchar);
.
## diffname pc/ether8390.c 1995/0721
## diff -e /n/fornaxdump/1995/0409/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1995/0721/sys/src/brazil/pc/ether8390.c
666c
dp8390 = ether->ctlr;
.
648c
Dp8390 *dp8390 = ether->ctlr;
.
634c
Dp8390 *dp8390 = ((Ether*)arg)->ctlr;
.
575c
dp8390 = ether->ctlr;
.
537c
dp8390 = ether->ctlr;
.
487c
dp8390 = ether->ctlr;
.
458c
etherrloop(ether, ðer->rpkt, len);
.
387c
dp8390 = ether->ctlr;
.
213c
ulong port = ((Dp8390*)ether->ctlr)->dp8390;
.
192c
ulong port = ((Dp8390*)ether->ctlr)->dp8390;
.
## diffname pc/ether8390.c 1995/0801
## diff -e /n/fornaxdump/1995/0721/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1995/0801/sys/src/brazil/pc/ether8390.c
655a
x = Ab;
if(ether->prom)
x |= Pro;
.
648a
int x;
.
## diffname pc/ether8390.c 1995/0829
## diff -e /n/fornaxdump/1995/0801/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1995/0829/sys/src/brazil/pc/ether8390.c
660c
slowoutb(dp8390->dp8390+Rcr, x);
.
583c
while(isr = (slowinb(port+Isr) & (Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe))){
.
572,573d
565c
interrupt(Ureg*, void *arg)
.
## diffname pc/ether8390.c 1996/0420
## diff -e /n/fornaxdump/1995/0829/sys/src/brazil/pc/ether8390.c /n/fornaxdump/1996/0420/sys/src/brazil/pc/ether8390.c
210,230d
## diffname pc/ether8390.c 1997/0327
## diff -e /n/fornaxdump/1996/0420/sys/src/brazil/pc/ether8390.c /n/emeliedump/1997/0327/sys/src/brazil/pc/ether8390.c
689a
ether->ifstat = 0;
.
688c
ether->transmit = transmit;
.
682c
regw(ctlr, Cr, Page0|RdABORT|Sta);
.
675,676c
regw(ctlr, Isr, 0xFF);
regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
.
672,673c
ringinit(ctlr);
regw(ctlr, Tpsr, ctlr->tstart);
.
669,670c
* Can't initialise ethernet address as it may not be
* known yet.
.
664,665c
regw(ctlr, Tcr, 0);
regw(ctlr, Rcr, Mon);
.
661,662c
regw(ctlr, Rbcr0, 0);
regw(ctlr, Rbcr1, 0);
.
659c
regw(ctlr, Dcr, Ft4WORD|Ls);
.
655,657c
disable(ctlr);
if(ctlr->width != 1)
regw(ctlr, Dcr, Ft4WORD|Ls|Wts);
.
653c
* to the 3C503 technical reference manual.
.
647,648c
ctlr = ether->ctlr;
.
644,645c
Dp8390 *ctlr;
.
642c
dp8390reset(Ether* ether)
.
640a
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--)
;
}
.
636,638c
r |= Pro;
ilock(ctlr);
regw(ctlr, Rcr, r);
r = regr(ctlr, Cntr2);
iunlock(ctlr);
USED(r);
.
634c
r = Ab;
.
627a
ctlr = ether->ctlr;
.
625,626c
Dp8390 *ctlr;
uchar r;
.
623c
attach(Ether* ether)
.
617,619c
r |= Pro;
ilock(ctlr);
regw(ctlr, Rcr, r);
iunlock(ctlr);
.
615a
r = Ab;
.
612a
ether = arg;
ctlr = ether->ctlr;
.
611c
Ether *ether;
Dp8390 *ctlr;
uchar r;
.
605c
regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
unlock(ctlr);
.
599,602c
ether->frames += regr(ctlr, Cntr0);
ether->crcs += regr(ctlr, Cntr1);
ether->buffs += regr(ctlr, Cntr2);
regw(ctlr, Isr, Cnt);
.
594,595c
ctlr->txbusy = 0;
txstart(ether);
.
590c
regw(ctlr, Isr, Txe|Ptx);
.
583,586c
r = regr(ctlr, Tsr);
if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){
print("dp8390: Tsr#%2.2ux|", r);
.
574c
regw(ctlr, Isr, Rxe|Prx);
.
569,570c
* Packets have been received.
* Take a spin round the ring.
.
564c
regw(ctlr, Isr, Ovw);
.
559,561c
lock(ctlr);
regw(ctlr, Imr, 0x00);
while(isr = (regr(ctlr, Isr) & (Cnt|Ovw|Txe|Rxe|Ptx|Prx))){
.
552,553c
ctlr = ether->ctlr;
.
547,548c
Dp8390 *ctlr;
.
544c
interrupt(Ureg*, void* arg)
.
540c
regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
.
536,537c
regw(ctlr, Isr, Ovw);
regw(ctlr, Tcr, 0);
.
533,534c
regw(ctlr, Tcr, LpbkNIC);
regw(ctlr, Cr, Page0|RdABORT|Sta);
.
530c
if(txp && (regr(ctlr, Isr) & (Txe|Ptx)) == 0)
.
526,527c
regw(ctlr, Rbcr0, 0);
regw(ctlr, Rbcr1, 0);
.
523,524c
txp = regr(ctlr, Cr) & Txp;
regw(ctlr, Cr, Page0|RdABORT|Stp);
.
516,517c
ctlr = ether->ctlr;
.
511,512c
Dp8390 *ctlr;
.
508a
transmit(Ether* ether)
{
Dp8390 *ctlr;
ctlr = ether->ctlr;
ilock(ctlr);
txstart(ether);
iunlock(ctlr);
}
static void
.
505c
ether->outpackets++;
ctlr->txbusy = 1;
.
501,503c
regw(ctlr, Tbcr0, len & 0xFF);
regw(ctlr, Tbcr1, (len>>8) & 0xFF);
regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
.
498,499c
if(ctlr->ram)
memmove((void*)(ether->mem+ctlr->tstart*Dp8390BufSz), rp, len);
else
dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, rp, len);
freeb(bp);
.
494c
rp = minpkt;
memmove(rp, bp->rp, len);
memset(rp+len, 0, ETHERMINTU-len);
.
492c
len = BLEN(bp);
rp = bp->rp;
.
489,490c
* Make sure the packet is of minimum length;
* copy it to the card's memory by the appropriate means;
* start the transmission.
.
482,486c
if(ctlr->txbusy)
return;
bp = qget(ether->oq);
if(bp == nil)
return;
.
477,480c
* This routine is called both from the top level and from interrupt
* level and expects to be called with ctlr already locked.
.
466,475d
459,464c
ctlr = ether->ctlr;
.
456,457c
int len;
Dp8390 *ctlr;
Block *bp;
uchar minpkt[ETHERMINTU], *rp;
.
453,454c
static void
txstart(Ether* ether)
.
447,449c
if(hdr.next < ctlr->pstart)
hdr.next = ctlr->pstop-1;
regw(ctlr, Bnry, hdr.next);
.
444c
ctlr->nxtpkt = hdr.next;
.
437c
etheriq(ether, bp, 1);
.
431c
_dp8390read(ctlr, p, data, len);
.
427,429c
if(len){
if(ctlr->ram)
memmove(p, (void*)(ether->mem+data), len);
.
422,425c
_dp8390read(ctlr, p, data, count);
p += count;
data = ctlr->pstart*Dp8390BufSz;
len -= count;
.
416,420c
if((data+len) >= ctlr->pstop*Dp8390BufSz){
count = ctlr->pstop*Dp8390BufSz - data;
if(ctlr->ram)
memmove(p, (void*)(ether->mem+data), count);
.
414d
411,412c
if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && (bp = iallocb(len))){
p = bp->rp;
bp->wp = p+len;
.
406,409c
* If the packet wraps round the hardware ring, read it in
* two pieces.
.
398,400c
regw(ctlr, Cr, Page0|RdABORT|Stp);
ringinit(ctlr);
regw(ctlr, Cr, Page0|RdABORT|Sta);
.
394c
if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop
.
389c
len = ((len<<8)|hdr.len0)-4;
.
387c
len--;
.
385c
len = (ctlr->pstop-ctlr->nxtpkt) + (hdr.next-ctlr->pstart) - 1;
.
382,383c
if(hdr.next > ctlr->nxtpkt)
len = hdr.next - ctlr->nxtpkt - 1;
.
375c
_dp8390read(ctlr, &hdr, data, sizeof(Hdr));
.
366,372c
ctlr = ether->ctlr;
for(curr = getcurr(ctlr); ctlr->nxtpkt != curr; curr = getcurr(ctlr)){
data = ctlr->nxtpkt*Dp8390BufSz;
if(ctlr->ram)
.
364c
ulong count, data, len;
Block *bp;
.
361,362c
Dp8390 *ctlr;
uchar curr, *p;
.
359c
receive(Ether* ether)
.
351,354c
cr = regr(ctlr, Cr) & ~Txp;
regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
curr = regr(ctlr, Curr);
regw(ctlr, Cr, cr);
.
348d
346c
getcurr(Dp8390* ctlr)
.
344a
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;
}
.
338,341d
326,336c
regw(ctlr, Isr, Rdc);
regw(ctlr, Cr, cr);
.
321,324c
rdwrite(ctlr, from, len);
for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
;
.
319c
* Pump the data into the I/O port
* then wait for the remote DMA to finish.
.
316a
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);
}
.
292,314c
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;
}
.
289,290c
* 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.
.
284,285c
len = ROUNDUP(len, ctlr->width);
.
280,282c
cr = regr(ctlr, Cr) & ~Txp;
regw(ctlr, Cr, Page0|RdABORT|Sta);
regw(ctlr, Isr, Rdc);
.
270,275d
267c
int timo, width;
.
264c
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)
{
.
262c
dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
.
256,257c
regw(ctlr, Isr, Rdc);
regw(ctlr, Cr, cr);
.
253c
for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
.
250,251c
* to the miracles of the bus, it's possible to get this
* far and still be talking to a slot full of nothing.
.
248c
* is necessary because this routine may be called on
.
240,244c
regw(ctlr, Cr, Page0|RdREAD|Sta);
rdread(ctlr, to, len);
.
229,234c
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);
.
222,224c
cr = regr(ctlr, Cr) & ~Txp;
regw(ctlr, Cr, Page0|RdABORT|Sta);
regw(ctlr, Isr, Rdc);
.
213d
210,211c
static void*
_dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
.
203,207c
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);
.
199,201c
* afterwards. Don't care about multicast
* addresses as multicast is never enabled
* (currently).
.
195a
ctlr = ether->ctlr;
.
194a
uchar cr;
Dp8390 *ctlr;
.
192,193d
190c
dp8390setea(Ether* ether)
.
173,188d
166,170c
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);
.
159,164c
* Get the ethernet address from the chip.
* Take care to restore the command register
* afterwards.
.
157a
ctlr = ether->ctlr;
.
155,156c
Dp8390 *ctlr;
uchar cr;
int i;
.
152,153c
void
dp8390getea(Ether* ether, uchar* ea)
.
134c
enum { /* Rsr */
.
125c
enum { /* Rcr */
.
115c
enum { /* Tsr */
.
110c
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 */
.
108c
enum { /* Tcr */
.
102,105c
Ft0 = 0x20, /* FIFO threshold select */
Ft1 = 0x40,
Ft1WORD = 0x00,
Ft2WORD = Ft0,
Ft4WORD = Ft1,
Ft6WORD = Ft1|Ft0,
.
86,96c
enum { /* Dcr */
.
75c
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 */
.
69c
/* Page 1, read/write */
.
67d
53c
/* Page 0, write */
.
51d
23,37c
/* Page 0, read */
.
17,20c
enum { /* NIC core registers */
.
15a
#include "ether8390.h"
.
2,3c
* National Semiconductor DP8390 and clone
.
## diffname pc/ether8390.c 1997/0415
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/ether8390.c /n/emeliedump/1997/0415/sys/src/brazil/pc/ether8390.c
721a
ether->multicast = multicast;
.
644a
if(ether->nmaddr)
r |= Am;
.
628a
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
.
622a
if(ether->nmaddr)
r |= Am;
.
## diffname pc/ether8390.c 1997/0418
## diff -e /n/emeliedump/1997/0415/sys/src/brazil/pc/ether8390.c /n/emeliedump/1997/0418/sys/src/brazil/pc/ether8390.c
652,677c
setbit(ctlr, reverse[h&0x3f], on);
setfilter(ether, ctlr);
.
648,650d
642a
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);
}
.
639c
USED(on);
.
635d
630a
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
.
626c
setfilter(ether, ctlr);
.
617,624d
613a
USED(on);
.
612d
607a
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
.
606a
static uchar allmar[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
.
## diffname pc/ether8390.c 1998/0129
## diff -e /n/emeliedump/1997/0418/sys/src/brazil/pc/ether8390.c /n/emeliedump/1998/0129/sys/src/brazil/pc/ether8390.c
249c
v = _dp8390read(ctlr, to, from, len);
.
## diffname pc/ether8390.c 1998/0319
## diff -e /n/emeliedump/1998/0129/sys/src/brazil/pc/ether8390.c /n/emeliedump/1998/0319/sys/src/brazil/pc/ether8390.c
678,679d
641,642d
636c
promiscuous(void *arg, int )
.
## diffname pc/ether8390.c 1998/0825
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/ether8390.c /n/emeliedump/1998/0825/sys/src/brazil/pc/ether8390.c
396c
print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%lud\n",
.
## diffname pc/ether8390.c 2000/0604
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/pc/ether8390.c /n/emeliedump/2000/0604/sys/src/9/pc/ether8390.c
774c
regw(ctlr, Imr, 0);
.
772a
/*
* Clear any pending interrupts and mask then all off.
*/
.
762c
regw(ctlr, Tcr, LpbkNIC);
.
716a
regw(ctlr, Tcr, LpbkNORMAL);
.
714a
regw(ctlr, Isr, 0xFF);
regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
.
707a
* Sometimes there's an interrupt pending at this
* point but there's nothing in the Isr, so
* any pending interrupts are cleared and the
* mask of acceptable interrupts is enabled here.
.
604c
iunlock(ctlr);
.
558c
ilock(ctlr);
.
538c
regw(ctlr, Tcr, LpbkNORMAL);
.
## diffname pc/ether8390.c 2002/0114
## diff -e /n/emeliedump/2000/0604/sys/src/9/pc/ether8390.c /n/emeliedump/2002/0114/sys/src/9/pc/ether8390.c
305c
panic("crda write %lud to %lud\n", crda, to);
.
|