@@ 91,13 91,20 @@ mmuinit(void)
}
/*
- * map special use space
+ * map special space, assume that the space isn't already mapped
*/
ulong*
mapspecial(ulong physaddr, int len)
{
ulong *t;
- ulong virtaddr, i;
+ ulong virtaddr, i, base, end, off, entry, candidate;
+
+ base = physaddr & ~(BY2PG-1);
+ end = (physaddr+len-1) & ~(BY2PG-1);
+ if(len > 128*1024)
+ usemeg = 1;
+ off = 0;
+ candidate = 0;
/* first see if we've mapped it somewhere, the first hole means we're done */
for(virtaddr = REGZERO; virtaddr < REGTOP; virtaddr += OneMeg){
@@ 105,14 112,34 @@ mapspecial(ulong physaddr, int len)
/* create a page table and break */
t = xspanalloc(BY2PG, 1024, 0);
memzero(t, BY2PG, 0);
- l1table[virtaddr>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask);
+ l1table[virtaddr>>20] = L1PageTable | L1Domain0 |
+ (((ulong)t) & L1PTBaseMask);
break;
}
t = (ulong*)(l1table[virtaddr>>20] & L1PTBaseMask);
for(i = 0; i < OneMeg; i += BY2PG){
- if((t[(virtaddr+i)>>20] & L2TypeMask) != L2SmallPage)
+ entry = t[(virtaddr+i)>>20];
+
+ /* first hole means nothing left, add map */
+ if((entry & L2TypeMask) != L2SmallPage)
break;
-
+
+ if(candidate == 0){
+ /* look for start of range */
+ if((entry & L2PageBaseMask) != base)
+ continue;
+ candidate = virtaddr+i;
+ } else {
+ /* look for contiunued range */
+ if((entry & L2PageBaseMask) != base + off)
+ candidate = 0;
+ continue;
+ }
+ }
+
+ /* if we're at the end of the range, area is already mapped */
+ if((entry & L2PageBaseMask) == end)
+ return candidate + (physaddr-base);
}
if(i < OneMeg){
virtaddr += i;
@@ 258,9 258,9 @@ etherwrite(Chan* chan, void* buf, long n, vlong)
error(Ebadctl);
}
- if(n > ETHERMAXTU)
+ if(n > ether->maxmtu)
error(Etoobig);
- if(n < ETHERMINTU)
+ if(n < ether->minmtu)
error(Etoosmall);
bp = allocb(n);
@@ 284,16 284,17 @@ etherbwrite(Chan* chan, Block* bp, ulong)
nexterror();
}
n = etherwrite(chan, bp->rp, n, 0);
+ poperror();
freeb(bp);
return n;
}
ether = etherxx[chan->dev];
- if(n > ETHERMAXTU){
+ if(n > ether->maxmtu){
freeb(bp);
- error(Ebadarg);
+ error(Etoobig);
}
- if(n < ETHERMINTU){
+ if(n < ether->minmtu){
freeb(bp);
error(Etoosmall);
}
@@ 355,6 356,8 @@ etherreset(void)
ether->ctlrno = ctlrno;
ether->tbdf = BUSUNKNOWN;
ether->mbps = 10;
+ ether->minmtu = ETHERMINTU;
+ ether->maxmtu = ETHERMAXTU;
if(isaconfig("ether", ctlrno, ether) == 0)
continue;
for(n = 0; cards[n].type; n++){
@@ 396,7 399,7 @@ etherreset(void)
sprint(buf+i, "\n");
print(buf);
- if(ether->mbps == 100){
+ if(ether->mbps >= 100){
netifinit(ether, name, Ntypes, 256*1024);
if(ether->oq == 0)
ether->oq = qopen(256*1024, 1, 0, 0);
@@ 344,6 344,8 @@ enum { /* Window 7 - bus master operations */
};
enum { /* 3C90x extended register set */
+ Timer905 = 0x001A, /* 8-bits */
+ TxStatus905 = 0x001B, /* 8-bits */
PktStatus = 0x0020, /* 32-bits */
DnListPtr = 0x0024, /* 32-bits, 8-byte aligned */
FragAddr = 0x0028, /* 32-bits */
@@ 426,7 428,7 @@ typedef struct {
int dnq;
long interrupts; /* statistics */
- long timer;
+ long timer[2];
long stats[BytesRcvdOk+3];
int upqmax;
@@ 950,7 952,7 @@ static void
interrupt(Ureg*, void* arg)
{
Ether *ether;
- int port, status, s, w, x;
+ int port, status, s, txstatus, w, x;
Ctlr *ctlr;
ether = arg;
@@ 958,12 960,21 @@ interrupt(Ureg*, void* arg)
ctlr = ether->ctlr;
ilock(&ctlr->wlock);
- w = (STATUS(port)>>13) & 0x07;
+ status = STATUS(port);
+ if(!(status & (interruptMask|interruptLatch))){
+ iunlock(&ctlr->wlock);
+ return;
+ }
+ w = (status>>13) & 0x07;
COMMAND(port, SelectRegisterWindow, Wop);
ctlr->interrupts++;
- ctlr->timer += inb(port+Timer) & 0xFF;
- while((status = STATUS(port)) & (interruptMask|interruptLatch)){
+ if(ctlr->busmaster == 2)
+ ctlr->timer[0] += inb(port+Timer905) & 0xFF;
+ else
+ ctlr->timer[0] += inb(port+Timer) & 0xFF;
+
+ do{
if(status & hostError){
/*
* Adapter failure, try to find out why, reset if
@@ 1026,10 1037,14 @@ interrupt(Ureg*, void* arg)
* as a busmaster receive may be in progress.
* For all conditions enable the transmitter.
*/
+ if(ctlr->busmaster == 2)
+ txstatus = port+TxStatus905;
+ else
+ txstatus = port+TxStatus;
s = 0;
do{
- if(x = inb(port+TxStatus))
- outb(port+TxStatus, 0);
+ if(x = inb(txstatus))
+ outb(txstatus, 0);
s |= x;
}while(STATUS(port) & txComplete);
@@ 1111,7 1126,12 @@ interrupt(Ureg*, void* arg)
panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
COMMAND(port, AcknowledgeInterrupt, interruptLatch);
- }
+ }while((status = STATUS(port)) & (interruptMask|interruptLatch));
+
+ if(ctlr->busmaster == 2)
+ ctlr->timer[1] += inb(port+Timer905) & 0xFF;
+ else
+ ctlr->timer[1] += inb(port+Timer) & 0xFF;
COMMAND(port, SelectRegisterWindow, w);
iunlock(&ctlr->wlock);
@@ 1135,18 1155,30 @@ ifstat(Ether* ether, void* a, long n, ulong offset)
p = malloc(READSTR);
len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
- len += snprint(p+len, READSTR-len, "timer: %lud\n", ctlr->timer);
- len += snprint(p+len, READSTR-len, "carrierlost: %lud\n", ctlr->stats[CarrierLost]);
- len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n", ctlr->stats[SqeErrors]);
- len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n", ctlr->stats[MultipleColls]);
- len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n", ctlr->stats[SingleCollFrames]);
- len += snprint(p+len, READSTR-len, "latecollisions: %lud\n", ctlr->stats[LateCollisions]);
- len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n", ctlr->stats[RxOverruns]);
- len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n", ctlr->stats[FramesXmittedOk]);
- len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n", ctlr->stats[FramesRcvdOk]);
- len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->stats[FramesDeferred]);
- len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n", ctlr->stats[BytesRcvdOk]);
- len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n", ctlr->stats[BytesRcvdOk+1]);
+ len += snprint(p+len, READSTR-len, "timer: %lud %lud\n",
+ ctlr->timer[0], ctlr->timer[1]);
+ len += snprint(p+len, READSTR-len, "carrierlost: %lud\n",
+ ctlr->stats[CarrierLost]);
+ len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n",
+ ctlr->stats[SqeErrors]);
+ len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n",
+ ctlr->stats[MultipleColls]);
+ len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n",
+ ctlr->stats[SingleCollFrames]);
+ len += snprint(p+len, READSTR-len, "latecollisions: %lud\n",
+ ctlr->stats[LateCollisions]);
+ len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n",
+ ctlr->stats[RxOverruns]);
+ len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n",
+ ctlr->stats[FramesXmittedOk]);
+ len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n",
+ ctlr->stats[FramesRcvdOk]);
+ len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n",
+ ctlr->stats[FramesDeferred]);
+ len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n",
+ ctlr->stats[BytesRcvdOk]);
+ len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n",
+ ctlr->stats[BytesRcvdOk+1]);
if(ctlr->upenabled){
if(ctlr->upqmax > ctlr->upqmaxhw)
@@ 1925,8 1957,12 @@ XCVRDEBUG("\n");
* Clear out any lingering Tx status.
*/
COMMAND(port, SelectRegisterWindow, Wop);
- while(inb(port+TxStatus))
- outb(port+TxStatus, 0);
+ if(busmaster == 2)
+ x = port+TxStatus905;
+ else
+ x = port+TxStatus;
+ while(inb(x))
+ outb(x, 0);
/*
* Allocate a controller structure, clear out the