# HG changeset patch # User David du Colombier <0intro@gmail.com> # Date 1331073587 -3600 # Node ID dd5286addc1a67c9f71ee3690d07d737e8ae6f75 # Parent 5f9e0e495d4312f62a849ea58c4743a48e85eb0c 9: sync with plan 9 R=nixiedev CC=nix-dev http://codereview.appspot.com/5757055 Committer: Francisco J Ballesteros diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/bitsy/dat.h --- a/sys/src/9/bitsy/dat.h Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/bitsy/dat.h Tue Mar 06 23:39:47 2012 +0100 @@ -57,6 +57,9 @@ FPinit, FPactive, FPinactive, + + /* bit or'd with the state */ + FPillegal= 0x100, }; struct FPsave { diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/boot/parts.c --- a/sys/src/9/boot/parts.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/boot/parts.c Tue Mar 06 23:39:47 2012 +0100 @@ -112,27 +112,30 @@ /* update devsd's in-memory partition table */ if (fprint(unit->ctl, "part %s %lld %lld\n", name, start, end) < 0) fprint(2, "can't update devsd's partition table\n"); + if (debugboot) + print("part %s %lld %lld\n", name, start, end); } static long sdread(SDunit *unit, SDpart *pp, void* va, long len, vlong off) { - long l; + long l, secsize; uvlong bno, nb; /* * Check the request is within partition bounds. */ - if (unit->secsize == 0) + secsize = unit->secsize; + if (secsize == 0) sysfatal("sdread: zero sector size"); - bno = (off/unit->secsize) + pp->start; - nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno; + bno = off/secsize + pp->start; + nb = (off+len+secsize-1)/secsize + pp->start - bno; if(bno+nb > pp->end) nb = pp->end - bno; if(bno >= pp->end || nb == 0) return 0; - seek(unit->data, off, 0); + seek(unit->data, bno * secsize, 0); assert(va); /* "sdread" */ l = read(unit->data, va, len); if (l < 0) @@ -172,7 +175,8 @@ { SDpart *pp; char *field[3], *line[Npart+1]; - ulong n, start, end; + ulong n; + uvlong start, end; int i; /* @@ -188,6 +192,8 @@ pp->start = unit->sectors - 2; pp->end = unit->sectors - 1; + if(debugboot) + print("oldp9part %s\n", unit->name); if(sdreadblk(unit, pp, partbuf, 0, 0) < 0) return; @@ -230,7 +236,7 @@ int i; if(parttrace) - print("findpart %d %s %s\t\n", unit->npart, unit->name, name); + print("findpart %d %s %s: ", unit->npart, unit->name, name); for(i=0; inpart; i++) { if(parttrace) print("%s...", unit->part[i].name); @@ -245,6 +251,11 @@ return nil; } +/* + * look for a plan 9 partition table on drive `unit' in the second + * sector (sector 1) of partition `name'. + * if found, add the partitions defined in the table. + */ static void p9part(SDunit *unit, char *name) { @@ -253,6 +264,8 @@ uvlong start, end; int i, n; + if(debugboot) + print("p9part %s %s\n", unit->name, name); p = sdfindpart(unit, name); if(p == nil) return; @@ -300,8 +313,8 @@ mbrpart(SDunit *unit) { Dospart *dp; - ulong taboffset, start, end; - ulong firstxpart, nxtxpart; + uvlong taboffset, start, end; + uvlong firstxpart, nxtxpart; int havedos, i, nplan9; char name[10]; @@ -337,7 +350,7 @@ return -1; if(trace) { if(firstxpart) - print("%s ext %lud ", unit->name, taboffset); + print("%s ext %llud ", unit->name, taboffset); else print("%s mbr ", unit->name); } @@ -373,7 +386,7 @@ if(isextend(dp[i].type)){ nxtxpart = start-taboffset+firstxpart; if(trace) - print("link %lud...", nxtxpart); + print("link %llud...", nxtxpart); } } if(trace) diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/ip/netlog.c --- a/sys/src/9/ip/netlog.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/ip/netlog.c Tue Mar 06 23:39:47 2012 +0100 @@ -202,10 +202,11 @@ else f->alog->iponlyset = 1; free(cb); + poperror(); return; default: - cmderror(cb, "unknown ip control message"); + cmderror(cb, "unknown netlog control message"); } for(i = 1; i < cb->nf; i++){ diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/ip/tcp.c --- a/sys/src/9/ip/tcp.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/ip/tcp.c Tue Mar 06 23:39:47 2012 +0100 @@ -1345,6 +1345,7 @@ return commonerror(); if(ipcmp(s->raddr, IPnoaddr) != 0) { if(!waserror()){ + memset(&seg, 0, sizeof seg); seg.flags = RST | ACK; seg.ack = tcb->rcv.nxt; tcb->rcv.una = 0; @@ -1413,6 +1414,7 @@ panic("sndrst: version %d", lp->version); } + memset(&seg, 0, sizeof seg); seg.seq = lp->iss; seg.ack = lp->irs+1; seg.flags = SYN|ACK; @@ -1960,6 +1962,7 @@ h4 = (Tcp4hdr*)(bp->rp); h6 = (Tcp6hdr*)(bp->rp); + memset(&seg, 0, sizeof seg); if((h4->vihl&0xF0)==IP_VER4) { version = V4; @@ -2445,6 +2448,7 @@ f = s->p->f; tpriv = s->p->priv; version = s->ipversion; + memset(&seg, 0, sizeof seg); for(msgs = 0; msgs < 100; msgs++) { tcb = (Tcpctl*)s->ptcl; @@ -2657,6 +2661,7 @@ tcb = (Tcpctl*)s->ptcl; dbp = nil; + memset(&seg, 0, sizeof seg); seg.urg = 0; seg.source = s->lport; seg.dest = s->rport; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/kw/dat.h --- a/sys/src/9/kw/dat.h Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/kw/dat.h Tue Mar 06 23:39:47 2012 +0100 @@ -65,6 +65,9 @@ FPinit, FPactive, FPinactive, + + /* bit or'd with the state */ + FPillegal= 0x100, }; struct Confmem diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/kw/ethermii.c --- a/sys/src/9/kw/ethermii.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/kw/ethermii.c Tue Mar 06 23:39:47 2012 +0100 @@ -81,14 +81,18 @@ int miireset(Mii* mii) { - int bmcr; + int bmcr, phyno; if(mii == nil || mii->ctlr == nil || mii->curphy == nil) return -1; - bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr); + phyno = mii->curphy->phyno; + bmcr = mii->mir(mii, phyno, Bmcr); bmcr |= BmcrR; - mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr); - microdelay(1); + mii->miw(mii, phyno, Bmcr, bmcr); + +// microdelay(1); + while(mii->mir(mii, phyno, Bmcr) & BmcrR) + ; return 0; } diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/kw/mkfile --- a/sys/src/9/kw/mkfile Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/kw/mkfile Tue Mar 06 23:39:47 2012 +0100 @@ -69,6 +69,7 @@ /$objtype/lib/libdraw.a\ /$objtype/lib/libip.a\ /$objtype/lib/libsec.a\ + /$objtype/lib/libmp.a\ /$objtype/lib/libc.a\ 9:V: $p$CONF s$p$CONF diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/kw/ucalloc.c --- a/sys/src/9/kw/ucalloc.c Tue Mar 06 23:34:10 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/* - * allocate uncached memory - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" - -#include - -typedef struct Private Private; -struct Private { - Lock; - char msg[256]; - char* cur; -}; - -static Private ucprivate; - -static void -ucpoolpanic(Pool* p, char* fmt, ...) -{ - va_list v; - Private *pv; - char msg[sizeof pv->msg]; - - pv = p->private; - va_start(v, fmt); - vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v); - va_end(v); - memmove(msg, pv->msg, sizeof msg); - iunlock(pv); - panic("%s", msg); -} - -static void -ucpoolprint(Pool* p, char* fmt, ...) -{ - va_list v; - Private *pv; - - pv = p->private; - va_start(v, fmt); - pv->cur = vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v); - va_end(v); -} - -static void -ucpoolunlock(Pool* p) -{ - Private *pv; - char msg[sizeof pv->msg]; - - pv = p->private; - if(pv->cur == pv->msg){ - iunlock(pv); - return; - } - - memmove(msg, pv->msg, sizeof msg); - pv->cur = pv->msg; - iunlock(pv); - - iprint("%.*s", sizeof pv->msg, msg); -} - -static void -ucpoollock(Pool* p) -{ - Private *pv; - - pv = p->private; - ilock(pv); - pv->pc = getcallerpc(&p); - pv->cur = pv->msg; -} - -static void* -ucarena(usize size) -{ - void *uv, *v; - - assert(size == 1*MiB); - - mainmem->maxsize += 1*MiB; - if((v = mallocalign(1*MiB, 1*MiB, 0, 0)) == nil || - (uv = mmuuncache(v, 1*MiB)) == nil){ - free(v); - mainmem->maxsize -= 1*MiB; - return nil; - } - return uv; -} - -static Pool ucpool = { - .name = "Uncached", - .maxsize = 4*MiB, - .minarena = 1*MiB-32, - .quantum = 32, - .alloc = ucarena, - .merge = nil, - .flags = /*POOL_TOLERANCE|POOL_ANTAGONISM|POOL_PARANOIA|*/0, - - .lock = ucpoollock, - .unlock = ucpoolunlock, - .print = ucpoolprint, - .panic = ucpoolpanic, - - .private = &ucprivate, -}; - -void -ucfree(void* v) -{ - if(v == nil) - return; - poolfree(&ucpool, v); -} - -void* -ucalloc(usize size) -{ - assert(size < ucpool.minarena-128); - - return poolallocalign(&ucpool, size, 32, 0, 0); -} - -void* -ucallocalign(usize size, int align, int span) -{ - assert(size < ucpool.minarena-128); - - return poolallocalign(&ucpool, size, align, 0, span); -} diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/kw/usbehcikw.c --- a/sys/src/9/kw/usbehcikw.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/kw/usbehcikw.c Tue Mar 06 23:39:47 2012 +0100 @@ -273,7 +273,9 @@ return; already = 1; - ctlr = smalloc(sizeof(Ctlr)); + ctlr = malloc(sizeof(Ctlr)); + if (ctlr == nil) + panic("ehci: out of memory"); /* the sheeva's usb 2.0 otg uses a superset of the ehci registers */ ctlr->capio = (Ecapio *)(soc.ehci + 0x100); ctlr->opio = (Eopio *) (soc.ehci + 0x140); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/mtx/dat.h --- a/sys/src/9/mtx/dat.h Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/mtx/dat.h Tue Mar 06 23:39:47 2012 +0100 @@ -53,6 +53,9 @@ FPinit, FPactive, FPinactive, + + /* bit or'd with the state */ + FPillegal= 0x100, }; /* diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/omap/cache.v7.s --- a/sys/src/9/omap/cache.v7.s Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/omap/cache.v7.s Tue Mar 06 23:39:47 2012 +0100 @@ -26,13 +26,13 @@ /* set cache size select */ TEXT setcachelvl(SB), $-4 - MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDid), 0 + MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDidct), 0 ISB RET /* return cache sizes */ TEXT getwayssets(SB), $-4 - MRC CpSC, CpIDcsize, R0, C(CpID), C(CpIDid), 0 + MRC CpSC, CpIDcsize, R0, C(CpID), C(CpIDidct), 0 RET /* @@ -152,9 +152,9 @@ /* get cache sizes */ SLL $1, R8, R0 /* R0 = (cache - 1) << 1 */ - MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDid), 0 /* set cache size select */ + MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDidct), 0 /* set cache size select */ ISB - MRC CpSC, CpIDcsize, R0, C(CpID), C(CpIDid), 0 /* get cache sizes */ + MRC CpSC, CpIDcsize, R0, C(CpID), C(CpIDidct), 0 /* get cache sizes */ /* compute # of ways and sets for this cache level */ SRA $3, R0, R5 /* R5 (ways) = R0 >> 3 */ diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/omap/dat.h --- a/sys/src/9/omap/dat.h Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/omap/dat.h Tue Mar 06 23:39:47 2012 +0100 @@ -89,6 +89,9 @@ FPinit, FPactive, FPinactive, + + /* bit or'd with the state */ + FPillegal= 0x100, }; struct Confmem diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/omap/ucalloc.c --- a/sys/src/9/omap/ucalloc.c Tue Mar 06 23:34:10 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/* - * allocate uncached memory - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" - -#include - -typedef struct Private Private; -struct Private { - Lock; - char msg[256]; - char* cur; -}; - -static Private ucprivate; - -static void -ucpoolpanic(Pool* p, char* fmt, ...) -{ - va_list v; - Private *pv; - char msg[sizeof pv->msg]; - - pv = p->private; - va_start(v, fmt); - vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v); - va_end(v); - memmove(msg, pv->msg, sizeof msg); - iunlock(pv); - panic("%s", msg); -} - -static void -ucpoolprint(Pool* p, char* fmt, ...) -{ - va_list v; - Private *pv; - - pv = p->private; - va_start(v, fmt); - pv->cur = vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v); - va_end(v); -} - -static void -ucpoolunlock(Pool* p) -{ - Private *pv; - char msg[sizeof pv->msg]; - - pv = p->private; - if(pv->cur == pv->msg){ - iunlock(pv); - return; - } - - memmove(msg, pv->msg, sizeof msg); - pv->cur = pv->msg; - iunlock(pv); - - iprint("%.*s", sizeof pv->msg, msg); -} - -static void -ucpoollock(Pool* p) -{ - Private *pv; - - pv = p->private; - ilock(pv); - pv->pc = getcallerpc(&p); - pv->cur = pv->msg; -} - -static void* -ucarena(usize size) -{ - void *uv, *v; - - assert(size == 1*MiB); - - mainmem->maxsize += 1*MiB; - if((v = mallocalign(1*MiB, 1*MiB, 0, 0)) == nil || - (uv = mmuuncache(v, 1*MiB)) == nil){ - free(v); - mainmem->maxsize -= 1*MiB; - return nil; - } - return uv; -} - -static Pool ucpool = { - .name = "Uncached", - .maxsize = 4*MiB, - .minarena = 1*MiB-32, - .quantum = 32, - .alloc = ucarena, - .merge = nil, - .flags = /*POOL_TOLERANCE|POOL_ANTAGONISM|POOL_PARANOIA|*/0, - - .lock = ucpoollock, - .unlock = ucpoolunlock, - .print = ucpoolprint, - .panic = ucpoolpanic, - - .private = &ucprivate, -}; - -void -ucfree(void* v) -{ - if(v == nil) - return; - poolfree(&ucpool, v); -} - -void* -ucalloc(usize size) -{ - assert(size < ucpool.minarena-128); - - return poolallocalign(&ucpool, size, 32, 0, 0); -} - -void* -ucallocalign(usize size, int align, int span) -{ - assert(size < ucpool.minarena-128); - - return poolallocalign(&ucpool, size, align, 0, span); -} diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/omap/ucallocb.c --- a/sys/src/9/omap/ucallocb.c Tue Mar 06 23:34:10 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -/* - * allocate Blocks from uncached memory - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -enum -{ - Hdrspc = 64, /* leave room for high-level headers */ - Bdead = 0x51494F42, /* "QIOB" */ -}; - -struct -{ - Lock; - ulong bytes; -} ucialloc; - -static Block* -_ucallocb(int size) -{ - Block *b; - ulong addr; - - if((b = ucalloc(sizeof(Block)+size+Hdrspc)) == nil) - return nil; - - b->next = nil; - b->list = nil; - b->free = 0; - b->flag = 0; - b->ref = 0; - _xinc(&b->ref); - - /* align start of data portion by rounding up */ - addr = (ulong)b; - addr = ROUND(addr + sizeof(Block), BLOCKALIGN); - b->base = (uchar*)addr; - - /* align end of data portion by rounding down */ - b->lim = ((uchar*)b) + msize(b); - addr = (ulong)(b->lim); - addr = addr & ~(BLOCKALIGN-1); - b->lim = (uchar*)addr; - - /* leave sluff at beginning for added headers */ - b->rp = b->lim - ROUND(size, BLOCKALIGN); - if(b->rp < b->base) - panic("_ucallocb"); - b->wp = b->rp; - - return b; -} - -Block* -ucallocb(int size) -{ - Block *b; - - /* - * Check in a process and wait until successful. - * Can still error out of here, though. - */ - if(up == nil) - panic("ucallocb without up: %#p", getcallerpc(&size)); - if((b = _ucallocb(size)) == nil) - panic("ucallocb: no memory for %d bytes", size); - setmalloctag(b, getcallerpc(&size)); - - return b; -} - -Block* -uciallocb(int size) -{ - Block *b; - static int m1, m2, mp; - - if(0 && ucialloc.bytes > conf.ialloc){ - if((m1++%10000)==0){ - if(mp++ > 1000){ - active.exiting = 1; - exit(0); - } - iprint("uciallocb: limited %lud/%lud\n", - ucialloc.bytes, conf.ialloc); - } - return nil; - } - - if((b = _ucallocb(size)) == nil){ - if(0 && (m2++%10000)==0){ - if(mp++ > 1000){ - active.exiting = 1; - exit(0); - } - iprint("uciallocb: no memory %lud/%lud\n", - ucialloc.bytes, conf.ialloc); - } - return nil; - } - setmalloctag(b, getcallerpc(&size)); - b->flag = BINTR; - - ilock(&ucialloc); - ucialloc.bytes += b->lim - b->base; - iunlock(&ucialloc); - - return b; -} - -void -ucfreeb(Block *b) -{ - void *dead = (void*)Bdead; - long ref; - - if(b == nil || (ref = _xdec(&b->ref)) > 0) - return; - - if(ref < 0){ - dumpstack(); - panic("ucfreeb: ref %ld; caller pc %#p", ref, getcallerpc(&b)); - } - - /* - * drivers which perform non cache coherent DMA manage their own buffer - * pool of uncached buffers and provide their own free routine. - */ - if(b->free) { - b->free(b); - return; - } - if(b->flag & BINTR) { - ilock(&ucialloc); - ucialloc.bytes -= b->lim - b->base; - iunlock(&ucialloc); - } - - /* poison the block in case someone is still holding onto it */ - b->next = dead; - b->rp = dead; - b->wp = dead; - b->lim = dead; - b->base = dead; - - ucfree(b); -} diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/apic.c --- a/sys/src/9/pc/apic.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/apic.c Tue Mar 06 23:39:47 2012 +0100 @@ -100,12 +100,14 @@ static ulong lapicr(int r) { + assert(lapicbase != 0); return *(lapicbase+(r/sizeof(*lapicbase))); } static void lapicw(int r, ulong data) { + assert(lapicbase != 0); *(lapicbase+(r/sizeof(*lapicbase))) = data; data = *(lapicbase+(LapicID/sizeof(*lapicbase))); USED(data); @@ -156,6 +158,7 @@ lapictimer.hz, hz); lapictimer.hz = hz; } + assert(lapictimer.hz != 0); lapictimer.div = hz/lapictimer.hz; } } @@ -372,6 +375,8 @@ period = lapictimer.max; if(next != 0){ period = next - fastticks(nil); + if (lapictimer.div == 0) + panic("lapictimerset: zero lapictimer.div"); period /= lapictimer.div; if(period < lapictimer.min) diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/archmp.c --- a/sys/src/9/pc/archmp.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/archmp.c Tue Mar 06 23:39:47 2012 +0100 @@ -96,12 +96,20 @@ * if correct, check the version. * To do: check extended table checksum. */ - if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0) + if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0) { + /* + * we can easily get processor info from acpi, but + * interrupt routing, etc. would require interpreting aml. + */ + print("archmp: no mp table found, assuming uniprocessor\n"); return 1; + } pcmp = KADDR(_mp_->physaddr); - if(memcmp(pcmp, "PCMP", 4)) + if(memcmp(pcmp, "PCMP", 4) != 0) { + print("archmp: mp table has bad magic"); return 1; + } length = pcmp->length; sum = 0; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/audio.h --- a/sys/src/9/pc/audio.h Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/audio.h Tue Mar 06 23:39:47 2012 +0100 @@ -8,7 +8,6 @@ }; #define seteisadma(a, b) dmainit(a, Bufsize); -#define CACHELINESZ 8 #define UNCACHED(type, v) (type*)((ulong)(v)) #define Int0vec diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/bios32.c --- a/sys/src/9/pc/bios32.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/bios32.c Tue Mar 06 23:39:47 2012 +0100 @@ -7,12 +7,8 @@ #define VFLAG(...) if(vflag) print(__VA_ARGS__) -#define BIOSSEG(a) KADDR(((uint)(a))<<4) #define UPTR2INT(p) ((uintptr)(p)) -#define l16get(p) (((p)[1]<<8)|(p)[0]) -#define l32get(p) (((u32int)l16get(p+2)<<16)|l16get(p)) - static int vflag = 0; typedef struct BIOS32sdh { /* BIOS32 Service Directory Header */ @@ -90,9 +86,9 @@ return -1; if(rsdchecksum(sdh, sizeof(BIOS32sdh)) == nil) return -1; - VFLAG("sdh @ %#p, entry %#ux\n", sdh, l32get(sdh->physaddr)); + VFLAG("sdh @ %#p, entry %#ux\n", sdh, L32GET(sdh->physaddr)); - bios32entry = vmap(l32get(sdh->physaddr), 4096+1); + bios32entry = vmap(L32GET(sdh->physaddr), 4096+1); VFLAG("entry @ %#p\n", bios32entry); ptr = UPTR2INT(bios32entry); bios32ptr[0] = ptr & 0xffff; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/cga.c --- a/sys/src/9/pc/cga.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/cga.c Tue Mar 06 23:39:47 2012 +0100 @@ -29,9 +29,14 @@ Attr = (Black<<4)|Grey, /* high nibble background * low foreground */ + + Poststrlen = 0, + Postcodelen = 2, + Postlen = Poststrlen+Postcodelen, }; #define CGASCREENBASE ((uchar*)KADDR(0xB8000)) +#define CGA CGASCREENBASE static int cgapos; static Lock cgascreenlock; @@ -115,6 +120,20 @@ unlock(&cgascreenlock); } +char hex[] = "0123456789ABCDEF"; + +void +cgapost(int code) +{ + uchar *cga; + + cga = CGA; + cga[Width*Height-Postcodelen*2] = hex[(code>>4) & 0x0F]; + cga[Width*Height-Postcodelen*2+1] = Attr; + cga[Width*Height-Postcodelen*2+2] = hex[code & 0x0F]; + cga[Width*Height-Postcodelen*2+3] = Attr; +} + void screeninit(void) { diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/dat.h --- a/sys/src/9/pc/dat.h Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/dat.h Tue Mar 06 23:39:47 2012 +0100 @@ -27,6 +27,9 @@ #define MAXSYSARG 5 /* for mount(fd, afd, mpt, flag, arg) */ +#define KMESGSIZE (256*1024) /* lots, for acpi debugging */ +#define STAGESIZE 2048 + /* * parameters for sysproc.c */ diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/devarch.c --- a/sys/src/9/pc/devarch.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/devarch.c Tue Mar 06 23:39:47 2012 +0100 @@ -586,6 +586,7 @@ char* name; }; +/* cpuid ax is 0x0ffMTFmS, where 0xffF is family, 0xMm is model */ static X86type x86intel[] = { { 4, 0, 22, "486DX", }, /* known chips */ @@ -610,13 +611,22 @@ { 6, 7, 16, "PentiumIII/Xeon", }, { 6, 8, 16, "PentiumIII/Xeon", }, { 6, 0xB, 16, "PentiumIII/Xeon", }, - { 6, 0xF, 16, "Xeon5000-series", }, + { 6, 0xF, 16, "Core 2/Xeon", }, { 6, 0x16, 16, "Celeron", }, { 6, 0x17, 16, "Core 2/Xeon", }, { 6, 0x1A, 16, "Core i7/Xeon", }, { 6, 0x1C, 16, "Atom", }, { 6, 0x1D, 16, "Xeon MP", }, - { 6, 0x25, 16, "Core i5", }, + { 6, 0x1E, 16, "Core i5/i7/Xeon", }, + { 6, 0x1F, 16, "Core i7/Xeon", }, + { 6, 0x22, 16, "Core i7", }, + { 6, 0x25, 16, "Core i3/i5/i7", }, + { 6, 0x2A, 16, "Core i7", }, + { 6, 0x2C, 16, "Core i7/Xeon", }, + { 6, 0x2D, 16, "Core i7", }, + { 6, 0x2E, 16, "Xeon MP", }, + { 6, 0x2F, 16, "Xeon MP", }, + { 6, 0x3A, 16, "Core i7", }, { 0xF, 1, 16, "P4", }, /* P4 */ { 0xF, 2, 16, "PentiumIV/Xeon", }, { 0xF, 6, 16, "PentiumIV/Xeon", }, @@ -707,7 +717,8 @@ int i; char buf[128]; - i = sprint(buf, "cpu%d: %dMHz ", m->machno, m->cpumhz); + i = sprint(buf, "cpu%d: %s%dMHz ", m->machno, m->machno < 10? " ": "", + m->cpumhz); if(m->cpuidid[0]) i += sprint(buf+i, "%12.12s ", m->cpuidid); seprint(buf+i, buf + sizeof buf - 1, @@ -1020,6 +1031,12 @@ addarchfile("archctl", 0664, archctlread, archctlwrite); } +void +archrevert(void) +{ + arch = &archgeneric; +} + /* * call either the pcmcia or pccard device setup */ diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/devether.c --- a/sys/src/9/pc/devether.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/devether.c Tue Mar 06 23:39:47 2012 +0100 @@ -447,26 +447,32 @@ sprint(buf+i, "\n"); print(buf); + /* + * input queues are allocated by ../port/netif.c:/^openfile. + * the size will be the last argument to netifinit() below. + * + * output queues should be small, to minimise `bufferbloat', + * which confuses tcp's feedback loop. at 1Gb/s, it only takes + * ~15µs to transmit a full-sized non-jumbo packet. + */ + /* compute log10(ether->mbps) into lg */ for(lg = 0, mb = ether->mbps; mb >= 10; lg++) mb /= 10; - if (lg > 0) - lg--; - if (lg > 14) /* 2^(14+17) = 2⁳ⁱ */ + if (lg > 14) /* sanity cap; 2**(14+15) = 2²⁹ */ lg = 14; - /* allocate larger output queues for higher-speed interfaces */ - bsz = 1UL << (lg + 17); /* 2ⁱ⁷ = 128K, bsz = 2ⁿ × 128K */ - while (bsz > mainmem->maxsize / 8 && bsz > 128*1024) + + /* allocate larger input queues for higher-speed interfaces */ + bsz = 1UL << (lg + 15); /* 2ⁱ⁵ = 32K, bsz = 2ⁿ × 32K */ + while (bsz > mainmem->maxsize / 8 && bsz > 128*1024) /* sanity */ bsz /= 2; + netifinit(ether, name, Ntypes, bsz); - netifinit(ether, name, Ntypes, bsz); - if(ether->oq == nil) { - ether->oq = qopen(bsz, Qmsg, 0, 0); - ether->limit = bsz; - } if(ether->oq == nil) - panic("etherreset %s: can't allocate output queue of %ld bytes", - name, bsz); + ether->oq = qopen(1 << (lg + 13), Qmsg, 0, 0); + if(ether->oq == nil) + panic("etherreset %s: can't allocate output queue", name); + ether->alen = Eaddrlen; memmove(ether->addr, ether->ea, Eaddrlen); memset(ether->bcast, 0xFF, Eaddrlen); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ether2114x.c --- a/sys/src/9/pc/ether2114x.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ether2114x.c Tue Mar 06 23:39:47 2012 +0100 @@ -630,7 +630,7 @@ bp->wp += sizeof(bi)*16; ctlr->setupbp = bp; - ether->oq = qopen(256*1024, Qmsg, 0, 0); + ether->oq = qopen(64*1024, Qmsg, 0, 0); transmit(ether); } diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ether8139.c --- a/sys/src/9/pc/ether8139.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ether8139.c Tue Mar 06 23:39:47 2012 +0100 @@ -351,6 +351,11 @@ { int timeo; + /* stop interrupts */ + csr16w(ctlr, Imr, 0); + csr16w(ctlr, Isr, ~0); + csr32w(ctlr, TimerInt, 0); + /* * Soft reset the controller. */ @@ -372,6 +377,7 @@ csr8w(ctlr, Cr, 0); csr16w(ctlr, Imr, 0); csr16w(ctlr, Isr, ~0); + csr32w(ctlr, TimerInt, 0); for(i = 0; i < Ntd; i++){ if(ctlr->td[i].bp == nil) @@ -438,13 +444,6 @@ ctlr->etxth = 128/32; /* - * Interrupts. - */ - csr32w(ctlr, TimerInt, 0); - csr16w(ctlr, Imr, Serr|Timerbit|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok); - csr32w(ctlr, Mpc, 0); - - /* * Enable receiver/transmitter. * Need to enable before writing the Rcr or it won't take. */ @@ -455,6 +454,13 @@ csr32w(ctlr, Mar0+4, 0); ctlr->mchash = 0; + /* + * Interrupts. + */ + csr32w(ctlr, TimerInt, 0); + csr16w(ctlr, Imr, Serr|Timerbit|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok); + csr32w(ctlr, Mpc, 0); + iunlock(&ctlr->ilock); } @@ -463,11 +469,19 @@ { Ctlr *ctlr; + if(edev == nil) { + print("rtl8139attach: nil edev\n"); + return; + } ctlr = edev->ctlr; + if(ctlr == nil) { + print("rtl8139attach: nil ctlr for Ether %#p\n", edev); + return; + } qlock(&ctlr->alock); if(ctlr->alloc == nil){ ctlr->rblen = 1<<((Rblen>>RblenSHIFT)+13); - ctlr->alloc = mallocz(ctlr->rblen+16 + Ntd*Tdbsz + 32, 0); + ctlr->alloc = malloc(ctlr->rblen+16 + Ntd*Tdbsz + 32); if(ctlr->alloc == nil) { qunlock(&ctlr->alock); error(Enomem); @@ -537,6 +551,8 @@ * Capr is where the host is reading from, * Cbr is where the NIC is currently writing. */ + if(ctlr->rblen == 0) + return; /* not attached yet (shouldn't happen) */ capr = (csr16r(ctlr, Capr)+16) % ctlr->rblen; while(!(csr8r(ctlr, Cr) & Bufe)){ p = ctlr->rbstart+capr; @@ -616,9 +632,19 @@ edev = arg; ctlr = edev->ctlr; + if(ctlr == nil) { /* not attached yet? (shouldn't happen) */ + print("rtl8139interrupt: interrupt for unattached Ether %#p\n", + edev); + return; + } while((isr = csr16r(ctlr, Isr)) != 0){ csr16w(ctlr, Isr, isr); + if(ctlr->alloc == nil) { + print("rtl8139interrupt: interrupt for unattached Ctlr " + "%#p port %#p\n", ctlr, (void *)ctlr->port); + return; /* not attached yet (shouldn't happen) */ + } if(isr & (Fovw|PunLc|Rxovw|Rer|Rok)){ rtl8139receive(edev); if(!(isr & Rok)) @@ -827,12 +853,12 @@ edev->ea[5] = i>>8; } + edev->arg = edev; edev->attach = rtl8139attach; edev->transmit = rtl8139transmit; edev->interrupt = rtl8139interrupt; edev->ifstat = rtl8139ifstat; - edev->arg = edev; edev->promiscuous = rtl8139promiscuous; edev->multicast = rtl8139multicast; edev->shutdown = rtl8139shutdown; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ether8169.c --- a/sys/src/9/pc/ether8169.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ether8169.c Tue Mar 06 23:39:47 2012 +0100 @@ -585,6 +585,7 @@ static void rtl8169halt(Ctlr* ctlr) { + csr32w(ctlr, Timerint, 0); csr8w(ctlr, Cr, 0); csr16w(ctlr, Imr, 0); csr16w(ctlr, Isr, ~0); @@ -655,16 +656,14 @@ static int rtl8169init(Ether* edev) { - int i; u32int r; - Block *bp; Ctlr *ctlr; u8int cplusc; ctlr = edev->ctlr; ilock(&ctlr->ilock); - rtl8169halt(ctlr); + rtl8169reset(ctlr); /* * MAC Address is not settable on some (all?) chips. @@ -687,11 +686,6 @@ ctlr->nrdfree = ctlr->rdh = ctlr->rdt = 0; ctlr->rd[ctlr->nrd-1].control = Eor; - for(i = 0; i < ctlr->nrd; i++) - if((bp = ctlr->rb[i]) != nil){ - ctlr->rb[i] = nil; - freeb(bp); - } rtl8169replenish(ctlr); ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Am|Apm; @@ -855,10 +849,8 @@ } qunlock(&ctlr->alock); - /* - * Wait for link to be ready. - */ - for(timeo = 0; timeo < 35; timeo++){ + /* Don't wait long for link to be ready. */ + for(timeo = 0; timeo < 10; timeo++){ if(miistatus(ctlr->mii) == 0) break; delay(100); /* print fewer miistatus messages */ diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ether82543gc.c --- a/sys/src/9/pc/ether82543gc.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ether82543gc.c Tue Mar 06 23:39:47 2012 +0100 @@ -339,7 +339,7 @@ enum { Nrdesc = 256, /* multiple of 8 */ - Ntdesc = 256, /* multiple of 8 */ + Ntdesc = 64, /* multiple of 8 */ Nblocks = 4098, /* total number of blocks to use */ SBLOCKSIZE = 2048, diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ether82557.c --- a/sys/src/9/pc/ether82557.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ether82557.c Tue Mar 06 23:39:47 2012 +0100 @@ -1300,7 +1300,7 @@ * Load the chip configuration and start it off. */ if(ether->oq == 0) - ether->oq = qopen(256*1024, Qmsg, 0, 0); + ether->oq = qopen(64*1024, Qmsg, 0, 0); configure(ether, 0); command(ctlr, CUstart, PADDR(&ctlr->cbr->status)); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ether82563.c --- a/sys/src/9/pc/ether82563.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ether82563.c Tue Mar 06 23:39:47 2012 +0100 @@ -411,7 +411,7 @@ enum { Nrd = 256, /* power of two */ - Ntd = 128, /* power of two */ + Ntd = 64, /* power of two */ Nrb = 1024, /* private receive buffers per Ctlr */ }; @@ -1250,13 +1250,13 @@ char name[KNAMELEN]; ctlr = edev->ctlr; - ctlr->edev = edev; /* point back to Ether* */ qlock(&ctlr->alock); if(ctlr->attached){ qunlock(&ctlr->alock); return; } + ctlr->edev = edev; /* point back to Ether* */ ctlr->nrd = Nrd; ctlr->ntd = Ntd; @@ -1287,7 +1287,7 @@ for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){ if((bp = allocb(ctlr->rbsz + BY2PG)) == nil) - break; + error(Enomem); bp->free = i82563rbfree; freeb(bp); } @@ -1314,7 +1314,7 @@ { Ctlr *ctlr; Ether *edev; - int icr, im; + int icr, im, i; edev = arg; ctlr = edev->ctlr; @@ -1322,8 +1322,9 @@ ilock(&ctlr->imlock); csr32w(ctlr, Imc, ~0); im = ctlr->im; - - for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){ + i = 1000; /* don't livelock */ + for(icr = csr32r(ctlr, Icr); icr & ctlr->im && i-- > 0; + icr = csr32r(ctlr, Icr)){ if(icr & Lsc){ im &= ~Lsc; ctlr->lim = icr & Lsc; @@ -1342,7 +1343,6 @@ wakeup(&ctlr->trendez); } } - ctlr->im = im; csr32w(ctlr, Ims, im); iunlock(&ctlr->imlock); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ether82598.c --- a/sys/src/9/pc/ether82598.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ether82598.c Tue Mar 06 23:39:47 2012 +0100 @@ -303,7 +303,7 @@ enum { Rbsz = 12*1024, Nrd = 256, - Ntd = 256, + Ntd = 64, Nrb = 256, }; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ether8390.c --- a/sys/src/9/pc/ether8390.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ether8390.c Tue Mar 06 23:39:47 2012 +0100 @@ -752,6 +752,15 @@ ; } +static void +shutdown(Ether *ether) +{ + Dp8390 *ctlr; + + ctlr = ether->ctlr; + disable(ctlr); +} + int dp8390reset(Ether* ether) { @@ -802,6 +811,7 @@ ether->attach = attach; ether->transmit = transmit; ether->interrupt = interrupt; + ether->shutdown = shutdown; ether->ifstat = 0; ether->promiscuous = promiscuous; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/etherdp83820.c --- a/sys/src/9/pc/etherdp83820.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/etherdp83820.c Tue Mar 06 23:39:47 2012 +0100 @@ -338,7 +338,7 @@ Nrd = 256, Nrb = 4*Nrd, Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8), - Ntd = 128, + Ntd = 64, }; typedef struct Ctlr Ctlr; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/etherigbe.c --- a/sys/src/9/pc/etherigbe.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/etherigbe.c Tue Mar 06 23:39:47 2012 +0100 @@ -708,7 +708,7 @@ v = strtol(cb->f[1], &p, 0); if(v < 0 || p == cb->f[1] || v > 0xFFFF) error(Ebadarg); - ctlr->rdtr = v;; + ctlr->rdtr = v; csr32w(ctlr, Rdtr, Fpd|v); break; } @@ -1964,7 +1964,9 @@ break; case 0x00: case 0xFF: - print("igbe: unusable CLS - %d\n", cls*4); + /* bogus value; use a sane default */ + cls = CACHELINESZ/sizeof(long); + pcicfgw8(p, PciCLS, cls); continue; case 0x08: case 0x10: diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ethersmc.c --- a/sys/src/9/pc/ethersmc.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ethersmc.c Tue Mar 06 23:39:47 2012 +0100 @@ -553,7 +553,7 @@ if (status & IntAlloc) { outb(port + IntrMask, mask & ~IntAlloc); - txstart(ether);; + txstart(ether); mask = inb(port + IntrMask); } diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ethervt6102.c --- a/sys/src/9/pc/ethervt6102.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ethervt6102.c Tue Mar 06 23:39:47 2012 +0100 @@ -493,7 +493,7 @@ alloc = malloc((ctlr->nrd+ctlr->ntd)*ctlr->cls + ctlr->ntd*Txcopy + ctlr->cls-1); if(alloc == nil){ qunlock(&ctlr->alock); - return; + error(Enomem); } ctlr->alloc = alloc; alloc = (uchar*)ROUNDUP((ulong)alloc, ctlr->cls); @@ -877,6 +877,14 @@ return 0; } +static void +vt6102shutdown(Ether *ether) +{ + Ctlr *ctlr = ether->ctlr; + + vt6102detach(ctlr); +} + static int vt6102reset(Ctlr* ctlr) { @@ -1039,6 +1047,7 @@ edev->transmit = vt6102transmit; edev->interrupt = vt6102interrupt; edev->ifstat = vt6102ifstat; + edev->shutdown = vt6102shutdown; edev->ctl = nil; edev->arg = edev; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/ethervt6105m.c --- a/sys/src/9/pc/ethervt6105m.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/ethervt6105m.c Tue Mar 06 23:39:47 2012 +0100 @@ -282,7 +282,7 @@ enum { Nrd = 196, - Ntd = 128, + Ntd = 64, Crcsz = 4, Bslop = 48, Rdbsz = ETHERMAXTU+Crcsz+Bslop, @@ -637,7 +637,7 @@ alloc = mallocalign((ctlr->nrd+ctlr->ntd)*dsz, dsz, 0, 0); if(alloc == nil){ qunlock(&ctlr->alock); - return; + error(Enomem); } ctlr->alloc = alloc; @@ -1040,6 +1040,14 @@ return 0; } +static void +vt6105Mshutdown(Ether *ether) +{ + Ctlr *ctlr = ether->ctlr; + + vt6105Mdetach(ctlr); +} + static int vt6105Mreset(Ctlr* ctlr) { @@ -1208,6 +1216,7 @@ edev->transmit = vt6105Mtransmit; edev->interrupt = vt6105Minterrupt; edev->ifstat = vt6105Mifstat; + edev->shutdown = vt6105Mshutdown; edev->ctl = nil; edev->arg = edev; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/fns.h --- a/sys/src/9/pc/fns.h Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/fns.h Tue Mar 06 23:39:47 2012 +0100 @@ -4,12 +4,14 @@ void acpiscan(void (*func)(uchar *)); Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong)); void archinit(void); +void archrevert(void); int bios32call(BIOS32ci*, u16int[3]); int bios32ci(BIOS32si*, BIOS32ci*); void bios32close(BIOS32si*); BIOS32si* bios32open(char*); void bootargs(void*); ulong cankaddr(ulong); +void cgapost(int); void clockintr(Ureg*, void*); int (*cmpswap)(long*, long, long); int cmpswap486(long*, long, long); @@ -44,6 +46,7 @@ void i8042auxenable(void (*)(int, int)); void i8042reset(void); void i8250console(void); +void i8250config(char *); void* i8250alloc(int, int, int); void i8250mouse(char*, int (*)(Queue*, int), int); void i8250setmouseputc(char*, int (*)(Queue*, int)); @@ -183,3 +186,8 @@ #define PADDR(a) paddr((void*)(a)) #define dcflush(a, b) + +#define BIOSSEG(a) KADDR(((uint)(a))<<4) + +#define L16GET(p) (((p)[1]<<8)|(p)[0]) +#define L32GET(p) (((u32int)L16GET((p)+2)<<16)|L16GET(p)) diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/kbd.c --- a/sys/src/9/pc/kbd.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/kbd.c Tue Mar 06 23:39:47 2012 +0100 @@ -215,6 +215,19 @@ } /* + * ask 8042 to enable the use of address bit 20 + */ +void +i8042a20(void) +{ + outready(); + outb(Cmd, 0xD1); + outready(); + outb(Data, 0xDF); + outready(); +} + +/* * ask 8042 to reset the machine */ void diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/l.s --- a/sys/src/9/pc/l.s Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/l.s Tue Mar 06 23:39:47 2012 +0100 @@ -708,7 +708,12 @@ JZ _cpu386 /* can't set this bit on 386 */ TESTL $0x200000, AX /* Id */ JZ _cpu486 /* can't toggle this bit on some 486 */ - MOVL fn+0(FP), AX + /* load registers */ + MOVL regs+4(FP), BP + MOVL fn+0(FP), AX /* cpuid function */ + MOVL 4(BP), BX + MOVL 8(BP), CX /* typically an index */ + MOVL 12(BP), DX CPUID JMP _cpuid _cpu486: diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/main.c --- a/sys/src/9/pc/main.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/main.c Tue Mar 06 23:39:47 2012 +0100 @@ -10,6 +10,10 @@ #include "reboot.h" #include "mp.h" +enum { + Less_power_slower = 1, +}; + Mach *m; /* @@ -843,8 +847,6 @@ return 0; } -int less_power_slower; - /* * put the processor in the halt state if we've no processes to run. * an interrupt will get us going again. @@ -857,7 +859,11 @@ * can result in a startup latency for processes that become ready. * if less_power_slower is true, we care more about saving energy * than reducing this latency. + * + * the performance loss of less_power_slower seems to be minute + * and it reduces lock contention (thus system time and real time) + * on many-core systems with large values of NPROC. */ - if(conf.nmach == 1 || less_power_slower) + if(conf.nmach == 1 || Less_power_slower) halt(); } diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/mem.h --- a/sys/src/9/pc/mem.h Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/mem.h Tue Mar 06 23:39:47 2012 +0100 @@ -18,6 +18,7 @@ #define PGSHIFT 12 /* log(BY2PG) */ #define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1)) #define PGROUND(s) ROUND(s, BY2PG) +#define CACHELINESZ 32 /* pentium & later */ #define BLOCKALIGN 8 /* diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/mp.c --- a/sys/src/9/pc/mp.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/mp.c Tue Mar 06 23:39:47 2012 +0100 @@ -9,14 +9,22 @@ #include "mp.h" #include "apbootstrap.h" +#define dprint(...) if(mpdebug) print(__VA_ARGS__); else USED(mpdebug) + +/* from mpacpi.c */ +Apic *bootapic; + +int mpdebug; +void (*mpacpifunc)(void); + static PCMP* mppcmp; static Bus* mpbus; static Bus* mpbuslast; static int mpisabus = -1; static int mpeisabus = -1; extern int i8259elcr; /* mask of level-triggered interrupts */ -static Apic mpapic[MaxAPICNO+1]; -static int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */ +/* static */ Apic mpapic[MaxAPICNO+1]; +/* static */ int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */ static Ref mpvnoref; /* unique vector assignment */ static int mpmachno = 1; static Lock mpphysidlock; @@ -185,7 +193,7 @@ aintr->intr = p; if(0) - print("mkiointr: type %d intr type %d flags %#o " + dprint("mkiointr: type %d intr type %d flags %#o " "bus %d irq %d apicno %d intin %d\n", p->type, p->intr, p->flags, p->busno, p->irq, p->apicno, p->intin); @@ -193,7 +201,7 @@ * Hack for Intel SR1520ML motherboard, which BIOS describes * the i82575 dual ethernet controllers incorrectly. */ - if(memcmp(mppcmp->product, "INTEL X38MLST ", 20) == 0){ + if(mppcmp && memcmp(mppcmp->product, "INTEL X38MLST ", 20) == 0){ if(p->busno == 1 && p->intin == 16 && p->irq == 1){ pcmpintr = malloc(sizeof(PCMPintr)); if(pcmpintr == nil) @@ -207,6 +215,8 @@ aintr->intr = pcmpintr; } } + if ((unsigned)p->apicno >= nelem(mpapic)) + panic("mkiointr: apic %d out of range", p->apicno); aintr->apic = &mpapic[p->apicno]; aintr->next = bus->aintr; bus->aintr = aintr; @@ -320,6 +330,8 @@ } } else{ + if ((unsigned)p->apicno >= nelem(mpapic)) + panic("mklintr: ioapic %d out of range", p->apicno); apic = &mpapic[p->apicno]; if((apic->flags & PcmpEN) && apic->type == PcmpPROCESSOR) apic->lintr[intin] = v; @@ -486,21 +498,41 @@ nvramwrite(0x0F, 0x00); } +static void +trympacpi(void) +{ + if (mpacpifunc != nil) { + print("mpinit: scanning acpi madt for extra cpus\n"); + (*mpacpifunc)(); + } +} + void mpinit(void) { - int ncpu; + int ncpu, cpuson; char *cp; PCMP *pcmp; uchar *e, *p; Apic *apic, *bpapic; void *va; + mpdebug = getconf("*debugmp") != nil; i8259init(); syncclock(); - if(_mp_ == 0) + bpapic = nil; + cpuson = 0; + + if(_mp_ == 0) { + /* + * We can easily get processor info from ACPI, but + * interrupt routing, etc. would require interpreting AML. + */ + print("mpinit: no mp table found, assuming uniprocessor\n"); + archrevert(); return; + } pcmp = KADDR(_mp_->physaddr); /* @@ -509,9 +541,7 @@ if((va = vmap(pcmp->lapicbase, 1024)) == nil) return; mppcmp = pcmp; - print("LAPIC: %.8lux %.8lux\n", pcmp->lapicbase, (ulong)va); - - bpapic = nil; + print("LAPIC: %#lux %#lux\n", pcmp->lapicbase, (ulong)va); /* * Run through the table saving information needed for starting @@ -544,6 +574,7 @@ apic->paddr = pcmp->lapicbase; if(apic->flags & PcmpBP) bpapic = apic; + cpuson++; } p += sizeof(PCMPprocessor); continue; @@ -570,6 +601,14 @@ continue; } + dprint("mpinit: mp table describes %d cpus\n", cpuson); + + /* For now, always scan ACPI's MADT for processors that MP missed. */ + trympacpi(); + + if (bpapic == nil) + bpapic = bootapic; + /* * No bootstrap processor, no need to go further. */ @@ -648,6 +687,14 @@ * to more than one thread in a core, or to use a "noise" core. * But, as usual, Intel make that an onerous task. */ + + /* + * temporary workaround for many-core intel (non-amd) systems: + * always use cpu 0. (TODO) + */ + if(strncmp(m->cpuidid, "AuthenticAMD", 12) != 0 && conf.nmach > 8) + return 0; + lock(&mpphysidlock); for(;;){ i = mpphysid++; @@ -669,6 +716,7 @@ Apic *apic; Pcidev *pcidev; int bno, dno, hi, irq, lo, n, type, vno; + char *typenm; /* * Find the bus. @@ -678,6 +726,7 @@ dno = BUSDNO(tbdf); if(type == BusISA) bno = mpisabus; + vno = -1; for(bus = mpbus; bus != nil; bus = bus->next){ if(bus->type != type) continue; @@ -685,7 +734,9 @@ break; } if(bus == nil){ - print("ioapicirq: can't find bus type %d\n", type); + typenm = type < 0 || type >= nelem(buses)? "": buses[type]; + panic("mpintrenablex: can't find bus type %d (%s) for " + "irq %d %s busno %d", type, typenm, v->irq, v->name, bno); return -1; } @@ -701,7 +752,7 @@ irq = (dno<<2)|(n-1); else irq = -1; - //print("pcidev %uX: irq %uX v->irq %uX\n", tbdf, irq, v->irq); + //print("pcidev %#uX: irq %#uX v->irq %#uX\n", tbdf, irq, v->irq); } else irq = v->irq; @@ -742,11 +793,7 @@ v->irq, tbdf, lo, n); return -1; } - - v->isr = lapicisr; - v->eoi = lapiceoi; - - return vno; + break; } /* @@ -769,6 +816,7 @@ vno, v->irq, tbdf); return -1; } + hi = mpintrcpu()<<24; lo = mpintrinit(bus, aintr->intr, vno, v->irq); //print("lo 0x%uX: busno %d intr %d vno %d irq %d elcr 0x%uX\n", @@ -776,7 +824,6 @@ // v->irq, i8259elcr); if(lo & ApicIMASK) return -1; - lo |= ApicPHYSICAL; /* no-op */ if((apic->flags & PcmpEN) && apic->type == PcmpIOAPIC) @@ -784,14 +831,13 @@ //else // print("lo not enabled 0x%uX %d\n", // apic->flags, apic->type); - + break; + } + if (aintr) { v->isr = lapicisr; v->eoi = lapiceoi; - - return vno; } - - return -1; + return vno; } int diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/mpacpi.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/9/pc/mpacpi.c Tue Mar 06 23:39:47 2012 +0100 @@ -0,0 +1,287 @@ +/* + * minimal acpi support for multiprocessors. + * + * avoids AML but that's only enough to discover + * the processors, not the interrupt routing details. + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "mp.h" +#include "mpacpi.h" + +/* 8c says: out of fixed registers */ +#define L64GET(p) ((uvlong)L32GET((p)+4) << 32 | L32GET(p)) + +enum { + /* apic types */ + Apiclproc, + Apicio, + Apicintrsrcoverride, + Apicnmisrc, + Apiclnmi, + Apicladdroverride, + Apicios, + Apicls, + Apicintrsrc, + Apiclx2, + Apiclx2nmi, + + PcmpUsed = 1ul<<31, /* Apic->flags addition */ + + Lapicbase = 0x1b, /* msr */ + + Lapicae = 1<<11, /* apic enable in Lapicbase */ +}; + +#define dprint(...) if(mpdebug) print(__VA_ARGS__); else USED(mpdebug) + +/* from mp.c */ +int mpdebug; +int mpmachno; +Apic mpapic[MaxAPICNO+1]; +int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */ + +Apic *bootapic; + +static int nprocid; + +static uvlong +l64get(uchar *p) +{ + return L64GET(p); +} + +int +apicset(Apic *apic, int type, int apicno, int f) +{ + if(apicno > MaxAPICNO) + return -1; + apic->type = type; + apic->apicno = apicno; + apic->flags = f | PcmpEN | PcmpUsed; + return 0; +} + +int +mpnewproc(Apic *apic, int apicno, int f) +{ + if(apic->flags & PcmpUsed) { + print("mpnewproc: apic already enabled\n"); + return -1; + } + if (apicset(apic, PcmpPROCESSOR, apicno, f) < 0) + return -1; + apic->lintr[1] = apic->lintr[0] = ApicIMASK; + /* botch! just enumerate */ + if(apic->flags & PcmpBP) + apic->machno = 0; + else + apic->machno = ++mpmachno; + machno2apicno[apic->machno] = apicno; + return 0; +} + +static int +mpacpiproc(uchar *p, ulong laddr) +{ + int id, f; + ulong *vladdr; + vlong base; + char *already; + Apic *apic; + + /* p bytes: type (0), len (8), cpuid, cpu_lapic id, flags[4] */ + id = p[3]; + /* cpu unusable flag or id out of range? */ + if((L32GET(p+4) & 1) == 0 || id > MaxAPICNO) + return -1; + + vladdr = nil; + already = ""; + f = 0; + apic = &mpapic[id]; + apic->paddr = laddr; + if (nprocid++ == 0) { + f = PcmpBP; + vladdr = vmap(apic->paddr, 1024); + if(apic->addr == nil){ + print("proc apic %d: failed to map %#p\n", id, + apic->paddr); + already = "(fail)"; + } + bootapic = apic; + } + apic->addr = vladdr; + + if(apic->flags & PcmpUsed) + already = "(on)"; + else + mpnewproc(apic, id, f); + + if (0) + dprint("\tapic proc %d/%d apicid %d flags%s%s %s\n", nprocid-1, + apic->machno, id, f & PcmpBP? " boot": "", + f & PcmpEN? " enabled": "", already); + USED(already); + + rdmsr(Lapicbase, &base); + if (!(base & Lapicae)) { + dprint("mpacpiproc: enabling lapic\n"); + wrmsr(Lapicbase, base | Lapicae); + } + return 0; +} + +static void +mpacpicpus(Madt *madt) +{ + int i, n; + ulong laddr; + uchar *p; + + laddr = L32GET(madt->addr); + dprint("APIC mpacpicpus lapic addr %#lux, flags %#ux\n", + laddr, L32GET(madt->flags)); + + n = L32GET(&madt->sdthdr[4]); + p = madt->structures; + /* byte 0 is assumed to be type, 1 is assumed to be length */ + for(i = offsetof(Madt, structures[0]); i < n; i += p[1], p += p[1]) + switch(p[0]){ + case Apiclproc: + mpacpiproc(p, laddr); + break; + } +} + +/* returns nil iff checksum is bad */ +static void * +mpacpirsdchecksum(void* addr, int length) +{ + uchar *p, sum; + + sum = 0; + for(p = addr; length-- > 0; p++) + sum += *p; + return sum == 0? addr: nil; +} + +static void * +mpacpirsdscan(uchar* addr, int len, char* signature) +{ + int sl; + uchar *e, *p; + + sl = strlen(signature); + e = addr + len - sl; + for(p = addr; p < e; p += 16) + if(memcmp(p, signature, sl) == 0) + return p; + return nil; +} + +static void * +mpacpirsdsearch(char* signature) +{ + uintptr p; + uchar *bda; + Rsd *rsd; + + /* + * Search for the data structure signature: + * 1) in the first KB of the EBDA; + * 2) in the BIOS ROM between 0xE0000 and 0xFFFFF. + */ + if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4) == 0){ + bda = BIOSSEG(0x40); + p = bda[0x0F]<<8 | bda[0x0E]; + if(p != 0 && + (rsd = mpacpirsdscan(KADDR(p), 1024, signature)) != nil) + return rsd; + } + return mpacpirsdscan(BIOSSEG(0xE000), 0x20000, signature); +} + +/* call func for each acpi table found */ +static void +mpacpiscan(void (*func)(uchar *)) +{ + int asize, i, tbllen, sdtlen; + uintptr dhpa, sdtpa; + uchar *tbl, *sdt; + Rsd *rsd; + + dprint("ACPI..."); + if((rsd = mpacpirsdsearch("RSD PTR ")) == nil) { + dprint("none\n"); + return; + } + + dprint("rsd %#p physaddr %#ux length %ud %#llux rev %d oem %.6s\n", + rsd, L32GET(rsd->raddr), L32GET(rsd->length), + l64get(rsd->xaddr), rsd->revision, (char*)rsd->oemid); + + if(rsd->revision == 2){ + if(mpacpirsdchecksum(rsd, 36) == nil) + return; + asize = 8; + sdtpa = l64get(rsd->xaddr); + } else { + if(mpacpirsdchecksum(rsd, 20) == nil) + return; + asize = 4; + sdtpa = L32GET(rsd->raddr); + } + + if((sdt = vmap(sdtpa, 8)) == nil) + return; + if((sdt[0] != 'R' && sdt[0] != 'X') || memcmp(sdt+1, "SDT", 3) != 0){ + vunmap(sdt, 8); + return; + } + sdtlen = L32GET(sdt + 4); + vunmap(sdt, 8); + + if((sdt = vmap(sdtpa, sdtlen)) == nil) + return; + if(mpacpirsdchecksum(sdt, sdtlen) != nil) + for(i = 36; i < sdtlen; i += asize){ + if(asize == 8) + dhpa = l64get(sdt+i); + else + dhpa = L32GET(sdt+i); + + if((tbl = vmap(dhpa, 8)) == nil) + continue; + tbllen = L32GET(tbl + 4); + vunmap(tbl, 8); + + if((tbl = vmap(dhpa, tbllen)) == nil) + continue; + if(mpacpirsdchecksum(tbl, tbllen) != nil) + (*func)(tbl); + vunmap(tbl, tbllen); + } + vunmap(sdt, sdtlen); +} + +static void +mpacpitbl(uchar *p) +{ + /* for now, just activate any idle cpus */ + if (memcmp(p, "APIC", 4) == 0) + mpacpicpus((Madt *)p); +} + +static void +mpacpi(void) +{ + mpdebug = getconf("*debugmp") != nil; + mpacpiscan(mpacpitbl); +} + +void (*mpacpifunc)(void) = mpacpi; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/mpacpi.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/9/pc/mpacpi.h Tue Mar 06 23:39:47 2012 +0100 @@ -0,0 +1,62 @@ +/* + * ACPI definitions + * + * A System Descriptor Table starts with a header of 4 bytes of signature + * followed by 4 bytes of total table length then 28 bytes of ID information + * (including the table checksum). + */ +typedef struct Dsdt Dsdt; +typedef struct Facp Facp; +typedef struct Hpet Hpet; +typedef struct Madt Madt; +typedef struct Mcfg Mcfg; +typedef struct Mcfgd Mcfgd; +typedef struct Rsd Rsd; + +struct Dsdt { /* Differentiated System DT */ + uchar sdthdr[36]; /* "DSDT" + length[4] + [28] */ + uchar db[]; /* Definition Block */ +}; +struct Facp { /* Fixed ACPI DT */ + uchar sdthdr[36]; /* "FACP" + length[4] + [28] */ + uchar faddr[4]; /* Firmware Control Address */ + uchar dsdt[4]; /* DSDT Address */ + uchar pad[200]; /* total table is 244 */ +}; +struct Hpet { /* High-Precision Event Timer DT */ + uchar sdthdr[36]; /* "HPET" + length[4] + [28] */ + uchar id[4]; /* Event Timer Block ID */ + uchar addr[12]; /* ACPI Format Address */ + uchar seqno; /* Sequence Number */ + uchar minticks[2]; /* Minimum Clock Tick */ + uchar attr; /* Page Protection */ +}; +struct Madt { /* Multiple APIC DT */ + uchar sdthdr[36]; /* "MADT" + length[4] + [28] */ + uchar addr[4]; /* Local APIC Address */ + uchar flags[4]; + uchar structures[]; +}; +typedef struct Mcfg { /* PCI Memory Mapped Config */ + uchar sdthdr[36]; /* "MCFG" + length[4] + [28] */ + uchar pad[8]; /* reserved */ + Mcfgd mcfgd[]; /* descriptors */ +} Mcfg; +struct Mcfgd { /* MCFG Descriptor */ + uchar addr[8]; /* base address */ + uchar segno[2]; /* segment group number */ + uchar sbno; /* start bus number */ + uchar ebno; /* end bus number */ + uchar pad[4]; /* reserved */ +}; +struct Rsd { /* Root System Description * */ + uchar signature[8]; /* "RSD PTR " */ + uchar rchecksum; + uchar oemid[6]; + uchar revision; + uchar raddr[4]; /* RSDT */ + uchar length[4]; + uchar xaddr[8]; /* XSDT */ + uchar xchecksum; /* XSDT */ + uchar pad[3]; /* reserved */ +}; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/mtrr.c --- a/sys/src/9/pc/mtrr.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/mtrr.c Tue Mar 06 23:39:47 2012 +0100 @@ -290,7 +290,7 @@ qlock(&mtrrlk); slot = -1; vcnt = cap & Capvcnt; - for(i = 0; i < vcnt; i++){ + for(i = 0; i < vcnt && i < Nmtrr; i++){ mtrrget(&mtrr, i); mok = mtrrdec(&mtrr, &mp, &msize, &mtype); /* reuse any entry for addresses above 4GB */ @@ -330,7 +330,7 @@ n += snprint(buf+n, bufsize-n, "cache default %s\n", type2str(def & Deftype)); vcnt = cap & Capvcnt; - for(i = 0; i < vcnt; i++){ + for(i = 0; i < vcnt && i < Nmtrr; i++){ mtrrget(&mtrr, i); if (mtrrdec(&mtrr, &base, &size, &type)) n += snprint(buf+n, bufsize-n, diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/nomtrr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/9/pc/nomtrr.c Tue Mar 06 23:39:47 2012 +0100 @@ -0,0 +1,21 @@ +/* + * dummy support for memory-type region registers. + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +int +mtrr(uvlong, uvlong, char *) +{ + error("mtrr support excluded"); + return 0; +} + +int +mtrrprint(char *, long) +{ + return 0; +} diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/pc --- a/sys/src/9/pc/pc Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/pc Tue Mar 06 23:39:47 2012 +0100 @@ -48,7 +48,7 @@ ether8003 ether8390 ether8139 pci ether8169 pci ethermii - ether82543gc pci +# ether82543gc pci ether82563 pci ether82557 pci ether83815 pci diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/pccpu --- a/sys/src/9/pc/pccpu Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/pccpu Tue Mar 06 23:39:47 2012 +0100 @@ -40,7 +40,7 @@ ether8003 ether8390 ether8139 pci ether8169 pci ethermii - ether82543gc pci +# ether82543gc pci ether82563 pci ether82557 pci ether83815 pci @@ -61,7 +61,7 @@ usbehci usbehcipc misc - archmp mp apic + archmp mp apic mpacpi mtrr uarti8250 diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/pcdisk --- a/sys/src/9/pc/pcdisk Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/pcdisk Tue Mar 06 23:39:47 2012 +0100 @@ -42,6 +42,7 @@ devpccard devi82365 apm apmjump + ether2000 ether8390 ether2114x pci ether589 etherelnk3 @@ -49,7 +50,6 @@ ether8003 ether8390 ether8139 ether8169 pci ethermii - ether82543gc pci ether82563 pci ether82557 pci ether83815 pci @@ -63,10 +63,12 @@ ethersink ethersmc devi82365 cis etherwavelan wavelan devi82365 cis pci + ethermedium pcmciamodem netdevmedium loopbackmedium + usbuhci usbohci usbehci usbehcipc @@ -126,10 +128,9 @@ local bootdir - bootpcdisk.out boot + boot$CONF.out boot /386/bin/ip/ipconfig /386/bin/auth/factotum /386/bin/disk/kfs /386/bin/cfs /386/bin/usb/usbd - /386/bin/disk/partfs diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/pcflop --- a/sys/src/9/pc/pcflop Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/pcflop Tue Mar 06 23:39:47 2012 +0100 @@ -1,4 +1,4 @@ -# tiny kernel used to install from floppy. +# pcflop - tiny kernel used to install from floppy. # has minimal vga drivers, no usb support and only some ether drivers, # and in general no frills. probably only useful in quite old systems. dev @@ -14,10 +14,7 @@ srv dup rtc -# ssl -# tls cap -# kprof ether netif ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno @@ -25,7 +22,6 @@ draw screen vga vgax mouse mouse vga -# kbmap sd floppy dma @@ -48,11 +44,8 @@ # ether82563 pci ether82557 pci ether83815 pci -# etherdp83820 pci etherec2t ether8390 etherelnk3 pci -# has vast firmware -# etherga620 pci etherigbe pci ethermii ethervgbe pci ethermii ethervt6102 pci ethermii @@ -66,7 +59,6 @@ loopbackmedium misc -# archmp mp apic mtrr sdata pci sdscsi @@ -75,10 +67,8 @@ # sdiahci pci sdscsi uarti8250 -# uartpci pci vgavesa -# vgavmware +cur ip tcp @@ -94,6 +84,6 @@ local bootdir - bootpcflop.out boot + boot$CONF.out boot /sys/lib/dist/bin/386/bzfs kfs /sys/lib/dist/pc/root.bz2 bzroot diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/pci.c --- a/sys/src/9/pc/pci.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/pci.c Tue Mar 06 23:39:47 2012 +0100 @@ -13,10 +13,12 @@ struct { - char output[16384]; + char output[PCICONSSIZE]; int ptr; }PCICONS; +int pcivga; + int pcilog(char *fmt, ...) { @@ -365,6 +367,7 @@ } } +/* side effect: if a video controller is seen, set pcivga non-zero */ static int pcilscan(int bno, Pcidev** list) { @@ -425,9 +428,11 @@ * and work out the sizes. */ switch(p->ccrb) { + case 0x03: /* display controller */ + pcivga = 1; + /* fall through */ case 0x01: /* mass storage controller */ case 0x02: /* network controller */ - case 0x03: /* display controller */ case 0x04: /* multimedia device */ case 0x07: /* simple comm. controllers */ case 0x08: /* base system peripherals */ @@ -721,13 +726,16 @@ if(p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R') break; - if(p >= (uchar *)KADDR(0xfffff)) + if(p >= (uchar *)KADDR(0xfffff)) { + // print("no PCI intr routing table found\n"); return; + } r = (Router *)p; - // print("PCI interrupt routing table version %d.%d at %.6uX\n", - // r->version[0], r->version[1], (ulong)r & 0xfffff); + if (0) + print("PCI interrupt routing table version %d.%d at %#.6luX\n", + r->version[0], r->version[1], (ulong)r & 0xfffff); tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8); sbpci = pcimatchtbdf(tbdf); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/sdata.c --- a/sys/src/9/pc/sdata.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/sdata.c Tue Mar 06 23:39:47 2012 +0100 @@ -69,7 +69,7 @@ enum { /* Interrupt Reason */ Cd = 0x01, /* Command/Data */ - Io = 0x02, /* I/O direction */ + Io = 0x02, /* I/O direction: read */ Rel = 0x04, /* Bus Release */ }; @@ -285,6 +285,7 @@ Drive* drive[2]; Prd* prdt; /* physical region descriptor table */ + void (*irqack)(Ctlr*); /* call to extinguish ICH intrs */ QLock; /* current command */ Drive* curdrive; @@ -292,6 +293,11 @@ Rendez; int done; + /* interrupt counts */ + ulong intnil; /* no drive */ + ulong intbusy; /* controller still busy */ + ulong intok; /* normal */ + Lock; /* register access */ } Ctlr; @@ -329,6 +335,11 @@ int status; int error; int flags; /* internal flags */ + + /* interrupt counts */ + ulong intcmd; /* commands */ + ulong intrd; /* reads */ + ulong intwr; /* writes */ } Drive; enum { /* internal flags */ @@ -937,8 +948,10 @@ { Ctlr *ctlr = sdev->ctlr; - return seprint(p, e, "%s ata port %X ctl %X irq %d\n", - sdev->name, ctlr->cmdport, ctlr->ctlport, ctlr->irq); + return seprint(p, e, "%s ata port %X ctl %X irq %d " + "intr-ok %lud intr-busy %lud intr-nil-drive %lud\n", + sdev->name, ctlr->cmdport, ctlr->ctlport, ctlr->irq, + ctlr->intok, ctlr->intbusy, ctlr->intnil); } static SDev* @@ -1203,16 +1216,18 @@ atapktinterrupt(Drive* drive) { Ctlr* ctlr; - int cmdport, len; + int cmdport, len, sts; ctlr = drive->ctlr; cmdport = ctlr->cmdport; - switch(inb(cmdport+Ir) & (/*Rel|*/Io|Cd)){ - case Cd: + sts = inb(cmdport+Ir) & (/*Rel|*/ Io|Cd); + /* a default case is impossible since all cases are enumerated */ + switch(sts){ + case Cd: /* write cmd */ outss(cmdport+Data, drive->pktcmd, drive->pkt/2); break; - case 0: + case 0: /* write data */ len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo); if(drive->data+len > drive->limit){ atanop(drive, 0); @@ -1222,7 +1237,7 @@ drive->data += len; break; - case Io: + case Io: /* read data */ len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo); if(drive->data+len > drive->limit){ atanop(drive, 0); @@ -1232,13 +1247,19 @@ drive->data += len; break; - case Io|Cd: + case Io|Cd: /* read cmd */ if(drive->pktdma) atadmainterrupt(drive, drive->dlen); else ctlr->done = 1; break; } + if(sts & Cd) + drive->intcmd++; + if(sts & Io) + drive->intrd++; + else + drive->intwr++; } static int @@ -1757,6 +1778,17 @@ return SDok; } +/* interrupt ack hack for intel ich controllers */ +static void +ichirqack(Ctlr *ctlr) +{ + int bmiba; + + bmiba = ctlr->bmiba; + if(bmiba) + outb(bmiba+Bmisx, inb(bmiba+Bmisx)); +} + static void atainterrupt(Ureg*, void* arg) { @@ -1768,6 +1800,7 @@ ilock(ctlr); if(inb(ctlr->ctlport+As) & Bsy){ + ctlr->intbusy++; iunlock(ctlr); if(DEBUG & DbgBsy) print("IBsy+"); @@ -1776,12 +1809,17 @@ cmdport = ctlr->cmdport; status = inb(cmdport+Status); if((drive = ctlr->curdrive) == nil){ + ctlr->intnil++; + if(ctlr->irqack != nil) + ctlr->irqack(ctlr); iunlock(ctlr); if((DEBUG & DbgINL) && ctlr->command != Cedd) print("Inil%2.2uX+", ctlr->command); return; } + ctlr->intok++; + if(status & Err) drive->error = inb(cmdport+Error); else switch(drive->command){ @@ -1791,6 +1829,7 @@ case Crs: case Crsm: + drive->intrd++; if(!(status & Drq)){ drive->error = Abrt; break; @@ -1806,6 +1845,7 @@ case Cws: case Cwsm: + drive->intwr++; len = drive->block; if(drive->data+len > drive->limit) len = drive->limit-drive->data; @@ -1829,7 +1869,11 @@ break; case Crd: + drive->intrd++; + /* fall through */ case Cwd: + if (drive->command == Cwd) + drive->intwr++; atadmainterrupt(drive, drive->count*drive->secsize); break; @@ -1837,6 +1881,8 @@ ctlr->done = 1; break; } + if(ctlr->irqack != nil) + ctlr->irqack(ctlr); iunlock(ctlr); if(drive->error){ @@ -1858,7 +1904,9 @@ Pcidev *p; SDev *legacy[2], *sdev, *head, *tail; int channel, ispc87415, maxio, pi, r, span; + void (*irqack)(Ctlr*); + irqack = nil; legacy[0] = legacy[1] = head = tail = nil; if(sdev = ataprobe(0x1F0, 0x3F4, IrqATA0)){ head = tail = sdev; @@ -2003,6 +2051,7 @@ */ /*FALLTHROUGH*/ case (0x4376<<16)|0x1002: /* ATI SB400 PATA */ + case (0x438c<<16)|0x1002: /* ATI SB600 PATA */ break; case (0x0211<<16)|0x1166: /* ServerWorks IB6566 */ { @@ -2024,6 +2073,7 @@ case (0x0646<<16)|0x1095: /* CMD 646 */ case (0x0571<<16)|0x1106: /* VIA 82C686 */ case (0x2363<<16)|0x197b: /* JMicron SATA */ + break; /* TODO: verify that this should be here; wasn't in original patch */ case (0x1230<<16)|0x8086: /* 82371FB (PIIX) */ case (0x7010<<16)|0x8086: /* 82371SB (PIIX3) */ case (0x7111<<16)|0x8086: /* 82371[AE]B (PIIX4[E]) */ @@ -2035,6 +2085,7 @@ case (0x248B<<16)|0x8086: /* 82801CA (ICH3, High-End) */ case (0x24CA<<16)|0x8086: /* 82801DBM (ICH4, Mobile) */ case (0x24CB<<16)|0x8086: /* 82801DB (ICH4, High-End) */ + case (0x24D1<<16)|0x8086: /* 82801EB/ER (ICH5 High-End) */ case (0x24DB<<16)|0x8086: /* 82801EB (ICH5) */ case (0x25A3<<16)|0x8086: /* 6300ESB (E7210) */ case (0x2653<<16)|0x8086: /* 82801FBM (ICH6M) */ @@ -2046,6 +2097,7 @@ case (0x2920<<16)|0x8086: /* 82801(IB)/IR/IH/IO SATA IDE (ICH9) */ case (0x3a20<<16)|0x8086: /* 82801JI (ICH10) */ case (0x3a26<<16)|0x8086: /* 82801JI (ICH10) */ + irqack = ichirqack; break; } @@ -2078,6 +2130,7 @@ ctlr->pcidev = p; ctlr->maxio = maxio; ctlr->span = span; + ctlr->irqack = irqack; if(!(pi & 0x80)) continue; ctlr->bmiba = (p->mem[4].bar & ~0x01) + channel*8; @@ -2198,6 +2251,8 @@ n += snprint(p+n, l-n, " lba48always %s", (drive->flags&Lba48always) ? "on" : "off"); n += snprint(p+n, l-n, "\n"); + n += snprint(p+n, l-n, "interrupts read %lud write %lud cmds %lud\n", + drive->intrd, drive->intwr, drive->intcmd); if(drive->sectors){ n += snprint(p+n, l-n, "geometry %lld %d", drive->sectors, drive->secsize); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/sdiahci.c --- a/sys/src/9/pc/sdiahci.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/sdiahci.c Tue Mar 06 23:39:47 2012 +0100 @@ -21,7 +21,7 @@ #define Intel(x) ((x)->pci->vid == Vintel) enum { - NCtlr = 4, + NCtlr = 16, NCtlrdrv= 32, NDrive = NCtlr*NCtlrdrv, @@ -34,6 +34,12 @@ Mcomrwait= 64*1024/Nms - 1, Obs = 0xa0, /* obsolete device bits */ + + /* + * if we get more than this many interrupts per tick for a drive, + * either the hardware is broken or we've got a bug in this driver. + */ + Maxintrspertick = 1000, }; /* pci space configuration */ @@ -139,11 +145,16 @@ char firmware[8+1]; char model[40+1]; - ushort info[0x200]; + int infosz; + ushort *info; + ushort tinyinfo[2]; /* used iff malloc fails */ int driveno; /* ctlr*NCtlrdrv + unit */ /* controller port # != driveno when not all ports are enabled */ int portno; + + ulong lastintr0; + ulong intrs; }; struct Ctlr { @@ -162,10 +173,13 @@ /* phyical register address */ uchar *physio; - Drive rawdrive[NCtlrdrv]; - Drive* drive[NCtlrdrv]; + Drive *rawdrive; + Drive *drive[NCtlrdrv]; int ndrive; - int mport; + int mport; /* highest drive # (0-origin) on ich9 at least */ + + ulong lastintr0; + ulong intrs; /* not attributable to any drive */ }; struct Asleep { @@ -278,31 +292,43 @@ return -1; } +/* fill in cfis boilerplate */ +static uchar * +cfissetup(Aportc *pc) +{ + uchar *cfis; + + cfis = pc->m->ctab->cfis; + memset(cfis, 0, 0x20); + cfis[0] = 0x27; + cfis[1] = 0x80; + cfis[7] = Obs; + return cfis; +} + +/* initialise pc's list */ +static void +listsetup(Aportc *pc, int flags) +{ + Alist *list; + + list = pc->m->list; + list->flags = flags | 5; + list->len = 0; + list->ctab = PCIWADDR(pc->m->ctab); + list->ctabhi = 0; +} + static int nop(Aportc *pc) { uchar *c; - Actab *t; - Alist *l; if((pc->m->feat & Dnop) == 0) return -1; - - t = pc->m->ctab; - c = t->cfis; - - memset(c, 0, 0x20); - c[0] = 0x27; - c[1] = 0x80; - c[2] = 0x00; - c[7] = Obs; - - l = pc->m->list; - l->flags = Lwrite | 0x5; - l->len = 0; - l->ctab = PCIWADDR(t); - l->ctabhi = 0; - + c = cfissetup(pc); + c[2] = 0; + listsetup(pc, Lwrite); return ahciwait(pc, 3*1000); } @@ -310,25 +336,11 @@ setfeatures(Aportc *pc, uchar f) { uchar *c; - Actab *t; - Alist *l; - t = pc->m->ctab; - c = t->cfis; - - memset(c, 0, 0x20); - c[0] = 0x27; - c[1] = 0x80; + c = cfissetup(pc); c[2] = 0xef; c[3] = f; - c[7] = Obs; - - l = pc->m->list; - l->flags = Lwrite | 0x5; - l->len = 0; - l->ctab = PCIWADDR(t); - l->ctabhi = 0; - + listsetup(pc, Lwrite); return ahciwait(pc, 3*1000); } @@ -336,30 +348,15 @@ setudmamode(Aportc *pc, uchar f) { uchar *c; - Actab *t; - Alist *l; /* hack */ if((pc->p->sig >> 16) == 0xeb14) return 0; - - t = pc->m->ctab; - c = t->cfis; - - memset(c, 0, 0x20); - c[0] = 0x27; - c[1] = 0x80; + c = cfissetup(pc); c[2] = 0xef; c[3] = 3; /* set transfer mode */ - c[7] = Obs; c[12] = 0x40 | f; /* sector count */ - - l = pc->m->list; - l->flags = Lwrite | 0x5; - l->len = 0; - l->ctab = PCIWADDR(t); - l->ctabhi = 0; - + listsetup(pc, Lwrite); return ahciwait(pc, 3*1000); } @@ -396,30 +393,15 @@ smart(Aportc *pc, int n) { uchar *c; - Actab *t; - Alist *l; if((pc->m->feat&Dsmart) == 0) return -1; - - t = pc->m->ctab; - c = t->cfis; - - memset(c, 0, 0x20); - c[0] = 0x27; - c[1] = 0x80; + c = cfissetup(pc); c[2] = 0xb0; c[3] = 0xd8 + n; /* able smart */ c[5] = 0x4f; c[6] = 0xc2; - c[7] = Obs; - - l = pc->m->list; - l->flags = Lwrite | 0x5; - l->len = 0; - l->ctab = PCIWADDR(t); - l->ctabhi = 0; - + listsetup(pc, Lwrite); if(ahciwait(pc, 1000) == -1 || pc->p->task & (1|32)){ dprint("ahci: smart fail %lux\n", pc->p->task); // preg(pc->m->fis.r, 20); @@ -434,26 +416,13 @@ smartrs(Aportc *pc) { uchar *c; - Actab *t; - Alist *l; - t = pc->m->ctab; - c = t->cfis; - - memset(c, 0, 0x20); - c[0] = 0x27; - c[1] = 0x80; + c = cfissetup(pc); c[2] = 0xb0; c[3] = 0xda; /* return smart status */ c[5] = 0x4f; c[6] = 0xc2; - c[7] = Obs; - - l = pc->m->list; - l->flags = Lwrite | 0x5; - l->len = 0; - l->ctab = PCIWADDR(t); - l->ctabhi = 0; + listsetup(pc, Lwrite); c = pc->m->fis.r; if(ahciwait(pc, 1000) == -1 || pc->p->task & (1|32)){ @@ -469,30 +438,14 @@ static int ahciflushcache(Aportc *pc) { - uchar *c, llba; - Actab *t; - Alist *l; - static uchar tab[2] = {0xe7, 0xea}; + uchar *c; - llba = pc->m->feat&Dllba? 1: 0; - t = pc->m->ctab; - c = t->cfis; - - memset(c, 0, 0x20); - c[0] = 0x27; - c[1] = 0x80; - c[2] = tab[llba]; - c[7] = Obs; - - l = pc->m->list; - l->flags = Lwrite | 0x5; - l->len = 0; - l->ctab = PCIWADDR(t); - l->ctabhi = 0; - + c = cfissetup(pc); + c[2] = pc->m->feat & Dllba? 0xea: 0xe7; + listsetup(pc, Lwrite); if(ahciwait(pc, 60000) == -1 || pc->p->task & (1|32)){ dprint("ahciflushcache: fail %lux\n", pc->p->task); -// preg( pc->m->fis.r, 20); +// preg(pc->m->fis.r, 20); return -1; } return 0; @@ -534,32 +487,18 @@ ahciidentify0(Aportc *pc, void *id, int atapi) { uchar *c; - Actab *t; - Alist *l; Aprdt *p; static uchar tab[] = { 0xec, 0xa1, }; - t = pc->m->ctab; - c = t->cfis; - - memset(c, 0, 0x20); - c[0] = 0x27; - c[1] = 0x80; + c = cfissetup(pc); c[2] = tab[atapi]; - c[7] = Obs; - - l = pc->m->list; - l->flags = 1<<16 | 0x5; - l->len = 0; - l->ctab = PCIWADDR(t); - l->ctabhi = 0; + listsetup(pc, 1<<16); memset(id, 0, 0x100); - p = &t->prdt; + p = &pc->m->ctab->prdt; p->dba = PCIWADDR(id); p->dbahi = 0; p->count = 1<<31 | (0x200-2) | 1; - return ahciwait(pc, 3*1000); } @@ -647,8 +586,6 @@ ahcicomreset(Aportc *pc) { uchar *c; - Actab *t; - Alist *l; dprint("ahcicomreset\n"); dreg("ahci: comreset ", pc->p); @@ -658,21 +595,10 @@ } dreg("comreset ", pc->p); - t = pc->m->ctab; - c = t->cfis; - - memset(c, 0, 0x20); - c[0] = 0x27; - c[1] = 0x00; - c[7] = Obs; + c = cfissetup(pc); + c[1] = 0; c[15] = 1<<2; /* srst */ - - l = pc->m->list; - l->flags = Lclear | Lreset | 0x5; - l->len = 0; - l->ctab = PCIWADDR(t); - l->ctabhi = 0; - + listsetup(pc, Lclear | Lreset); if(ahciwait(pc, 500) == -1){ dprint("ahcicomreset: first command failed\n"); return -1; @@ -680,17 +606,9 @@ microdelay(250); dreg("comreset ", pc->p); - memset(c, 0, 0x20); - c[0] = 0x27; - c[1] = 0x00; - c[7] = Obs; - - l = pc->m->list; - l->flags = Lwrite | 0x5; - l->len = 0; - l->ctab = PCIWADDR(t); - l->ctabhi = 0; - + c = cfissetup(pc); + c[1] = 0; + listsetup(pc, Lwrite); if(ahciwait(pc, 150) == -1){ dprint("ahcicomreset: second command failed\n"); return -1; @@ -877,10 +795,10 @@ h->ghc |= Hae; dprint("#S/sd%c: type %s port %#p: sss %ld ncs %ld coal %ld " - "mports %ld led %ld clo %ld ems %ld\n", + "%ld ports, led %ld clo %ld ems %ld\n", ctlr->sdev->idno, tname[ctlr->type], h, - (u>>27) & 1, (u>>8) & 0x1f, (u>>7) & 1, u & 0x1f, (u>>25) & 1, - (u>>24) & 1, (u>>6) & 1); + (u>>27) & 1, (u>>8) & 0x1f, (u>>7) & 1, + (u & 0x1f) + 1, (u>>25) & 1, (u>>24) & 1, (u>>6) & 1); return countbits(h->pi); } @@ -926,6 +844,14 @@ uchar oserial[21]; SDunit *u; + if(d->info == nil) { + d->infosz = 512 * sizeof(ushort); + d->info = malloc(d->infosz); + } + if(d->info == nil) { + d->info = d->tinyinfo; + d->infosz = sizeof d->tinyinfo; + } id = d->info; s = ahciidentify(&d->portc, id); if(s == -1){ @@ -1350,11 +1276,42 @@ for(;;){ tsleep(&up->sleep, return0, 0, Nms); for(i = 0; i < niadrive; i++) - checkdrive(iadrive[i], i); + if(iadrive[i] != nil) + checkdrive(iadrive[i], i); } } static void +isctlrjabbering(Ctlr *c, ulong cause) +{ + ulong now; + + now = TK2MS(MACHP(0)->ticks); + if (now > c->lastintr0) { + c->intrs = 0; + c->lastintr0 = now; + } + if (++c->intrs > Maxintrspertick) + panic("sdiahci: too many intrs per tick for no serviced " + "drive; cause %#lux mport %d", cause, c->mport); +} + +static void +isdrivejabbering(Drive *d) +{ + ulong now; + + now = TK2MS(MACHP(0)->ticks); + if (now > d->lastintr0) { + d->intrs = 0; + d->lastintr0 = now; + } + if (++d->intrs > Maxintrspertick) + panic("sdiahci: too many interrupts per tick for %s", + d->unit->name); +} + +static void iainterrupt(Ureg*, void *a) { int i; @@ -1365,16 +1322,29 @@ c = a; ilock(c); cause = c->hba->isr; - for(i = 0; i < c->mport; i++){ + if (cause == 0) { + isctlrjabbering(c, cause); + // iprint("sdiahci: interrupt for no drive\n"); + iunlock(c); + return; + } + for(i = 0; cause && i <= c->mport; i++){ m = 1 << i; if((cause & m) == 0) continue; d = c->rawdrive + i; ilock(d); + isdrivejabbering(d); if(d->port->isr && c->hba->pi & m) updatedrive(d); c->hba->isr = m; iunlock(d); + + cause &= ~m; + } + if (cause) { + isctlrjabbering(c, cause); + iprint("sdiachi: intr cause unserviced: %#lux\n", cause); } iunlock(c); } @@ -1408,7 +1378,7 @@ if(!c->enabled) { if(once == 0) { once = 1; - kproc("iasata", satakproc, 0); + kproc("ahci", satakproc, 0); } if(c->ndrive == 0) panic("iaenable: zero s->ctlr->ndrive"); @@ -1656,7 +1626,7 @@ aprint("ahci: iariopkt: %02ux %02ux %c %d %p\n", cmd[0], cmd[2], "rw"[r->write], r->dlen, r->data); if(cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f) - return sdmodesense(r, cmd, d->info, sizeof d->info); + return sdmodesense(r, cmd, d->info, d->infosz); r->rlen = 0; count = r->dlen; max = 65536; @@ -1757,7 +1727,7 @@ return sdsetsense(r, SDcheck, 3, 0xc, 2); } - if((i = sdfakescsi(r, d->info, sizeof d->info)) != SDnostatus){ + if((i = sdfakescsi(r, d->info, d->infosz)) != SDnostatus){ r->status = i; return i; } @@ -1912,13 +1882,60 @@ return -1; } +static int +newctlr(Ctlr *ctlr, SDev *sdev, int nunit) +{ + int i, n; + Drive *drive; + + ctlr->ndrive = sdev->nunit = nunit; + ctlr->mport = ctlr->hba->cap & ((1<<5)-1); + + i = (ctlr->hba->cap >> 20) & ((1<<4)-1); /* iss */ + print("#S/sd%c: %s: %#p %s, %d ports, irq %d\n", sdev->idno, + Tname(ctlr), ctlr->physio, descmode[i], nunit, ctlr->pci->intl); + /* map the drives -- they don't all need to be enabled. */ + n = 0; + ctlr->rawdrive = malloc(NCtlrdrv * sizeof(Drive)); + if(ctlr->rawdrive == nil) { + print("ahci: out of memory\n"); + return -1; + } + for(i = 0; i < NCtlrdrv; i++) { + drive = ctlr->rawdrive + i; + drive->portno = i; + drive->driveno = -1; + drive->sectors = 0; + drive->serial[0] = ' '; + drive->ctlr = ctlr; + if((ctlr->hba->pi & (1<port = (Aport*)(ctlr->mmio + 0x80*i + 0x100); + drive->portc.p = drive->port; + drive->portc.m = &drive->portm; + drive->driveno = n++; + ctlr->drive[drive->driveno] = drive; + iadrive[niadrive + drive->driveno] = drive; + } + for(i = 0; i < n; i++) + if(ahciidle(ctlr->drive[i]->port) == -1){ + dprint("ahci: %s: port %d wedged; abort\n", + Tname(ctlr), i); + return -1; + } + for(i = 0; i < n; i++){ + ctlr->drive[i]->mode = DMsatai; + configdrive(ctlr->drive[i]); + } + return n; +} + static SDev* iapnp(void) { - int i, n, nunit, type; + int n, nunit, type; ulong io; Ctlr *c; - Drive *d; Pcidev *p; SDev *head, *tail, *s; static int done; @@ -1970,42 +1987,9 @@ vunmap(c->mmio, p->mem[Abar].size); continue; } - c->ndrive = s->nunit = nunit; - c->mport = c->hba->cap & ((1<<5)-1); - - i = (c->hba->cap >> 20) & ((1<<4)-1); /* iss */ - print("#S/sd%c: %s: %#p %s, %d ports, irq %d\n", s->idno, - Tname(c), c->physio, descmode[i], nunit, c->pci->intl); - /* map the drives -- they don't all need to be enabled. */ - memset(c->rawdrive, 0, sizeof c->rawdrive); - n = 0; - for(i = 0; i < NCtlrdrv; i++) { - d = c->rawdrive + i; - d->portno = i; - d->driveno = -1; - d->sectors = 0; - d->serial[0] = ' '; - d->ctlr = c; - if((c->hba->pi & (1<port = (Aport*)(c->mmio + 0x80*i + 0x100); - d->portc.p = d->port; - d->portc.m = &d->portm; - d->driveno = n++; - c->drive[d->driveno] = d; - iadrive[niadrive + d->driveno] = d; - } - for(i = 0; i < n; i++) - if(ahciidle(c->drive[i]->port) == -1){ - dprint("ahci: %s: port %d wedged; abort\n", - Tname(c), i); - goto loop; - } - for(i = 0; i < n; i++){ - c->drive[i]->mode = DMsatai; - configdrive(c->drive[i]); - } - + n = newctlr(c, s, nunit); + if(n < 0) + goto loop; niadrive += n; niactlr++; if(head) @@ -2136,6 +2120,23 @@ iunlock(d); } +/* + * force this driver to notice a change of medium if the hardware doesn't + * report it. + */ +static void +changemedia(SDunit *u) +{ + Ctlr *c; + Drive *d; + + c = u->dev->ctlr; + d = c->drive[u->subno]; + ilock(d); + d->mediachange = 1; + u->sectors = 0; + iunlock(d); +} static int iawctl(SDunit *u, Cmdbuf *cmd) @@ -2149,7 +2150,9 @@ d = c->drive[u->subno]; f = cmd->f; - if(strcmp(f[0], "flushcache") == 0) + if(strcmp(f[0], "change") == 0) + changemedia(u); + else if(strcmp(f[0], "flushcache") == 0) runflushcache(d); else if(strcmp(f[0], "identify") == 0){ i = strtoul(f[1]? f[1]: "0", 0, 0); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/uarti8250.c --- a/sys/src/9/pc/uarti8250.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/uarti8250.c Tue Mar 06 23:39:47 2012 +0100 @@ -684,13 +684,13 @@ }; void -i8250console(void) +i8250config(char *p) { Uart *uart; int n; - char *cmd, *p; + char *cmd; - if((p = getconf("console")) == nil) + if(p == nil) return; n = strtoul(p, &cmd, 0); if(p == cmd) @@ -706,7 +706,8 @@ break; } - (*uart->phys->enable)(uart, 0); + if(!uart->enabled) + (*uart->phys->enable)(uart, 0); uartctl(uart, "b9600 l8 pn s1"); if(*cmd != '\0') uartctl(uart, cmd); @@ -716,6 +717,12 @@ } void +i8250console(void) +{ + i8250config(getconf("console")); +} + +void i8250mouse(char* which, int (*putc)(Queue*, int), int setb1200) { char *p; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/usbehcipc.c --- a/sys/src/9/pc/usbehcipc.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/usbehcipc.c Tue Mar 06 23:39:47 2012 +0100 @@ -186,7 +186,9 @@ dprint("usbehci: %#x %#x: port %#lux size %#x irq %d\n", p->vid, p->did, io, p->mem[0].size, p->intl); - ctlr = smalloc(sizeof(Ctlr)); + ctlr = malloc(sizeof(Ctlr)); + if (ctlr == nil) + panic("usbehci: out of memory"); ctlr->pcidev = p; capio = ctlr->capio = vmap(io, p->mem[0].size); ctlr->opio = (Eopio*)((uintptr)capio + (capio->cap & 0xff)); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/usbohci.c --- a/sys/src/9/pc/usbohci.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/usbohci.c Tue Mar 06 23:39:47 2012 +0100 @@ -1133,11 +1133,12 @@ switch(err){ case Tddataovr: /* Overrun is not an error */ + break; case Tdok: - /* can't make this assertion in virtualbox */ -// if(td->cbp != 0) -// panic("ohci: full packet but cbp != 0"); - break; + /* virtualbox doesn't always report underflow on short packets */ + if(td->cbp == 0) + break; + /* fall through */ case Tddataund: /* short input packets are ok */ if(mode == OREAD){ @@ -1326,12 +1327,16 @@ Td *td, *dtd; Block *bp; - if(ep->maxpkt > 0x2000) - panic("ohci: max packet > two pages"); - if(ep->maxpkt < count) - error("maxpkt too short"); - bp = allocb(ep->maxpkt); /* panics if no mem */ - assert(bp != nil); + if(count <= BY2PG) + bp = allocb(count); + else{ + if(count > 2*BY2PG) + panic("ohci: transfer > two pages"); + /* maximum of one physical page crossing allowed */ + bp = allocb(count+BY2PG); + bp->rp = (uchar*)PGROUND((uintptr)bp->rp); + bp->wp = bp->rp; + } dtd = *dtdp; td = dtd; td->bp = bp; @@ -1340,8 +1345,6 @@ td->be = ptr2pa(bp->wp + count - 1); if(a != nil){ /* validaddr((uintptr)a, count, 0); DEBUG */ - assert(bp != nil); - assert(bp->wp != nil); memmove(bp->wp, a, count); } bp->wp += count; @@ -1482,7 +1485,7 @@ ltd = td0 = ed->tds; load = tot = 0; do{ - n = ep->maxpkt; + n = 2*BY2PG; if(count-tot < n) n = count-tot; if(c != nil && io->tok != Tdtokin) @@ -2369,7 +2372,9 @@ continue; } - ctlr = smalloc(sizeof(Ctlr)); + ctlr = malloc(sizeof(Ctlr)); + if (ctlr == nil) + panic("ohci: out of memory"); ctlr->pcidev = p; ctlr->ohci = vmap(mem, p->mem[0].size); dprint("scanpci: ctlr %#p, ohci %#p\n", ctlr, ctlr->ohci); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/pc/usbuhci.c --- a/sys/src/9/pc/usbuhci.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/pc/usbuhci.c Tue Mar 06 23:39:47 2012 +0100 @@ -2112,7 +2112,9 @@ dprint("uhci: %#x %#x: port %#ux size %#x irq %d\n", p->vid, p->did, io, p->mem[4].size, p->intl); - ctlr = smalloc(sizeof(Ctlr)); + ctlr = malloc(sizeof(Ctlr)); + if (ctlr == nil) + panic("uhci: out of memory"); ctlr->pcidev = p; ctlr->port = io; for(i = 0; i < Nhcis; i++) diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/chan.c --- a/sys/src/9/port/chan.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/port/chan.c Tue Mar 06 23:39:47 2012 +0100 @@ -185,14 +185,24 @@ free(prev); } +static int debugstart; + void chandevreset(void) { int i; todinit(); /* avoid later reentry causing infinite recursion */ - for(i=0; devtab[i] != nil; i++) + debugstart = getconf("*debugstart") != nil; + if(debugstart) + iprint("reset:"); + for(i=0; devtab[i] != nil; i++) { + if(debugstart) + iprint(" %s", devtab[i]->name); devtab[i]->reset(); + } + if(debugstart) + iprint("\n"); } void @@ -200,8 +210,15 @@ { int i; - for(i=0; devtab[i] != nil; i++) + if(debugstart) + iprint("init:"); + for(i=0; devtab[i] != nil; i++) { + if(debugstart) + iprint(" %s", devtab[i]->name); devtab[i]->init(); + } + if(debugstart) + iprint("\n"); } void diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/devcons.c --- a/sys/src/9/port/devcons.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/port/devcons.c Tue Mar 06 23:39:47 2012 +0100 @@ -101,8 +101,7 @@ */ struct { Lock lk; -// char buf[16384]; /* normal */ - char buf[256*1024]; /* for acpi debugging */ + char buf[KMESGSIZE]; uint n; } kmesg; diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/devenv.c --- a/sys/src/9/port/devenv.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/port/devenv.c Tue Mar 06 23:39:47 2012 +0100 @@ -146,6 +146,8 @@ if(c->qid.type != QTDIR) error(Eperm); + if(strlen(name) >= sizeof up->genbuf) + error("name too long"); /* protect envgen */ omode = openmode(omode); eg = envgrp(c); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/devsd.c --- a/sys/src/9/port/devsd.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/port/devsd.c Tue Mar 06 23:39:47 2012 +0100 @@ -72,7 +72,7 @@ ((p)<next) + for(u = 0; u < sdev->nunit; u++) /* each drive */ + (*addconf)(sdev->unit[u]); +} + static int sd2gen(Chan* c, int i, Dir* dp) { diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/devssl.c --- a/sys/src/9/port/devssl.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/port/devssl.c Tue Mar 06 23:39:47 2012 +0100 @@ -760,7 +760,7 @@ if(waserror()){ if(b != nil) - free(b); + freeb(b); nexterror(); } diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/devtls.c --- a/sys/src/9/port/devtls.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/port/devtls.c Tue Mar 06 23:39:47 2012 +0100 @@ -234,6 +234,8 @@ static int rc4enc(Secret *sec, uchar *buf, int n); static int des3enc(Secret *sec, uchar *buf, int n); static int des3dec(Secret *sec, uchar *buf, int n); +static int aesenc(Secret *sec, uchar *buf, int n); +static int aesdec(Secret *sec, uchar *buf, int n); static int noenc(Secret *sec, uchar *buf, int n); static int sslunpad(uchar *buf, int n, int block); static int tlsunpad(uchar *buf, int n, int block); @@ -1428,6 +1430,16 @@ } static void +initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv) +{ + s->enckey = smalloc(sizeof(AESstate)); + s->enc = aesenc; + s->dec = aesdec; + s->block = 16; + setupAESstate(s->enckey, p, ea->keylen, iv); +} + +static void initclearenc(Encalg *, Secret *s, uchar *, uchar *) { s->enc = noenc; @@ -1440,6 +1452,8 @@ { "clear", 0, 0, initclearenc }, { "rc4_128", 128/8, 0, initRC4key }, { "3des_ede_cbc", 3 * 8, 8, initDES3key }, + { "aes_128_cbc", 128/8, 16, initAESkey }, + { "aes_256_cbc", 256/8, 16, initAESkey }, { 0 } }; @@ -2000,7 +2014,7 @@ buf[n++] = pad; return nn; } - + static int des3enc(Secret *sec, uchar *buf, int n) { @@ -2015,6 +2029,22 @@ des3CBCdecrypt(buf, n, sec->enckey); return (*sec->unpad)(buf, n, 8); } + +static int +aesenc(Secret *sec, uchar *buf, int n) +{ + n = blockpad(buf, n, 16); + aesCBCencrypt(buf, n, sec->enckey); + return n; +} + +static int +aesdec(Secret *sec, uchar *buf, int n) +{ + aesCBCdecrypt(buf, n, sec->enckey); + return (*sec->unpad)(buf, n, 16); +} + static DigestState* nomac(uchar *, ulong, uchar *, ulong, uchar *, DigestState *) { diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/devuart.c --- a/sys/src/9/port/devuart.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/port/devuart.c Tue Mar 06 23:39:47 2012 +0100 @@ -189,12 +189,15 @@ uartnuart++; } - if(uartnuart) + if(uartnuart) { uart = xalloc(uartnuart*sizeof(Uart*)); + if (uart == nil) + panic("uartreset: no memory"); + } uartndir = 1 + 3*uartnuart; uartdir = xalloc(uartndir * sizeof(Dirtab)); - if (uart == nil || uartdir == nil) + if (uartdir == nil) panic("uartreset: no memory"); dp = uartdir; strcpy(dp->name, "."); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/portdat.h --- a/sys/src/9/port/portdat.h Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/port/portdat.h Tue Mar 06 23:39:47 2012 +0100 @@ -58,6 +58,16 @@ #include +#ifndef KMESGSIZE +#define KMESGSIZE (16*1024) +#endif +#ifndef PCICONSSIZE +#define PCICONSSIZE (16*1024) +#endif +#ifndef STAGESIZE +#define STAGESIZE 64 +#endif + struct Ref { Lock; @@ -853,7 +863,7 @@ }; enum { - Stagesize= 2048 + Stagesize= STAGESIZE }; /* diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/sd.h --- a/sys/src/9/port/sd.h Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/port/sd.h Tue Mar 06 23:39:47 2012 +0100 @@ -126,6 +126,9 @@ /* devsd.c */ extern void sdadddevs(SDev*); +extern void sdaddconf(SDunit*); +extern void sdaddallconfs(void (*f)(SDunit*)); +extern void sdaddpart(SDunit*, char*, uvlong, uvlong); extern int sdsetsense(SDreq*, int, int, int, int); extern int sdmodesense(SDreq*, uchar*, void*, int); extern int sdfakescsi(SDreq*, void*, int); diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/ucalloc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/9/port/ucalloc.c Tue Mar 06 23:39:47 2012 +0100 @@ -0,0 +1,137 @@ +/* + * allocate uncached memory + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +#include + +typedef struct Private Private; +struct Private { + Lock; + char msg[256]; + char* cur; +}; + +static Private ucprivate; + +static void +ucpoolpanic(Pool* p, char* fmt, ...) +{ + va_list v; + Private *pv; + char msg[sizeof pv->msg]; + + pv = p->private; + va_start(v, fmt); + vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v); + va_end(v); + memmove(msg, pv->msg, sizeof msg); + iunlock(pv); + panic("%s", msg); +} + +static void +ucpoolprint(Pool* p, char* fmt, ...) +{ + va_list v; + Private *pv; + + pv = p->private; + va_start(v, fmt); + pv->cur = vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v); + va_end(v); +} + +static void +ucpoolunlock(Pool* p) +{ + Private *pv; + char msg[sizeof pv->msg]; + + pv = p->private; + if(pv->cur == pv->msg){ + iunlock(pv); + return; + } + + memmove(msg, pv->msg, sizeof msg); + pv->cur = pv->msg; + iunlock(pv); + + iprint("%.*s", sizeof pv->msg, msg); +} + +static void +ucpoollock(Pool* p) +{ + Private *pv; + + pv = p->private; + ilock(pv); + pv->pc = getcallerpc(&p); + pv->cur = pv->msg; +} + +static void* +ucarena(usize size) +{ + void *uv, *v; + + assert(size == 1*MiB); + + mainmem->maxsize += 1*MiB; + if((v = mallocalign(1*MiB, 1*MiB, 0, 0)) == nil || + (uv = mmuuncache(v, 1*MiB)) == nil){ + free(v); + mainmem->maxsize -= 1*MiB; + return nil; + } + return uv; +} + +static Pool ucpool = { + .name = "Uncached", + .maxsize = 4*MiB, + .minarena = 1*MiB-32, + .quantum = 32, + .alloc = ucarena, + .merge = nil, + .flags = /*POOL_TOLERANCE|POOL_ANTAGONISM|POOL_PARANOIA|*/0, + + .lock = ucpoollock, + .unlock = ucpoolunlock, + .print = ucpoolprint, + .panic = ucpoolpanic, + + .private = &ucprivate, +}; + +void +ucfree(void* v) +{ + if(v == nil) + return; + poolfree(&ucpool, v); +} + +void* +ucallocalign(usize size, int align, int span) +{ + void *v; + + assert(size < ucpool.minarena-128); + v = poolallocalign(&ucpool, size, align, 0, span); + if(v) + memset(v, 0, size); + return v; +} + +void* +ucalloc(usize size) +{ + return ucallocalign(size, 32, 0); +} diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/ucallocb.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/9/port/ucallocb.c Tue Mar 06 23:39:47 2012 +0100 @@ -0,0 +1,152 @@ +/* + * allocate Blocks from uncached memory + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "error.h" + +enum +{ + Hdrspc = 64, /* leave room for high-level headers */ + Bdead = 0x51494F42, /* "QIOB" */ +}; + +struct +{ + Lock; + ulong bytes; +} ucialloc; + +static Block* +_ucallocb(int size) +{ + Block *b; + ulong addr; + + if((b = ucalloc(sizeof(Block)+size+Hdrspc)) == nil) + return nil; + + b->next = nil; + b->list = nil; + b->free = 0; + b->flag = 0; + b->ref = 0; + _xinc(&b->ref); + + /* align start of data portion by rounding up */ + addr = (ulong)b; + addr = ROUND(addr + sizeof(Block), BLOCKALIGN); + b->base = (uchar*)addr; + + /* align end of data portion by rounding down */ + b->lim = ((uchar*)b) + msize(b); + addr = (ulong)(b->lim); + addr = addr & ~(BLOCKALIGN-1); + b->lim = (uchar*)addr; + + /* leave sluff at beginning for added headers */ + b->rp = b->lim - ROUND(size, BLOCKALIGN); + if(b->rp < b->base) + panic("_ucallocb"); + b->wp = b->rp; + + return b; +} + +Block* +ucallocb(int size) +{ + Block *b; + + /* + * Check in a process and wait until successful. + * Can still error out of here, though. + */ + if(up == nil) + panic("ucallocb without up: %#p", getcallerpc(&size)); + if((b = _ucallocb(size)) == nil) + panic("ucallocb: no memory for %d bytes", size); + setmalloctag(b, getcallerpc(&size)); + + return b; +} + +Block* +uciallocb(int size) +{ + Block *b; + static int m1, m2, mp; + + if(0 && ucialloc.bytes > conf.ialloc){ + if((m1++%10000)==0){ + if(mp++ > 1000){ + active.exiting = 1; + exit(0); + } + iprint("uciallocb: limited %lud/%lud\n", + ucialloc.bytes, conf.ialloc); + } + return nil; + } + + if((b = _ucallocb(size)) == nil){ + if(0 && (m2++%10000)==0){ + if(mp++ > 1000){ + active.exiting = 1; + exit(0); + } + iprint("uciallocb: no memory %lud/%lud\n", + ucialloc.bytes, conf.ialloc); + } + return nil; + } + setmalloctag(b, getcallerpc(&size)); + b->flag = BINTR; + + ilock(&ucialloc); + ucialloc.bytes += b->lim - b->base; + iunlock(&ucialloc); + + return b; +} + +void +ucfreeb(Block *b) +{ + void *dead = (void*)Bdead; + long ref; + + if(b == nil || (ref = _xdec(&b->ref)) > 0) + return; + + if(ref < 0){ + dumpstack(); + panic("ucfreeb: ref %ld; caller pc %#p", ref, getcallerpc(&b)); + } + + /* + * drivers which perform non cache coherent DMA manage their own buffer + * pool of uncached buffers and provide their own free routine. + */ + if(b->free) { + b->free(b); + return; + } + if(b->flag & BINTR) { + ilock(&ucialloc); + ucialloc.bytes -= b->lim - b->base; + iunlock(&ucialloc); + } + + /* poison the block in case someone is still holding onto it */ + b->next = dead; + b->rp = dead; + b->wp = dead; + b->lim = dead; + b->base = dead; + + ucfree(b); +} diff -r 5f9e0e495d43 -r dd5286addc1a sys/src/9/port/xalloc.c --- a/sys/src/9/port/xalloc.c Tue Mar 06 23:34:10 2012 +0100 +++ b/sys/src/9/port/xalloc.c Tue Mar 06 23:39:47 2012 +0100 @@ -84,7 +84,7 @@ pm++; } } - xsummary(); +// xsummary(); /* call it from main if desired */ } void* @@ -263,11 +263,19 @@ for(h = xlists.flist; h; h = h->link) i++; - print("%d holes free\n", i); + print("%d holes free", i); i = 0; for(h = xlists.table; h; h = h->link) { - print("%.8lux %.8lux %lud\n", h->addr, h->top, h->size); + if (0) { + print("addr %#.8lux top %#.8lux size %lud\n", + h->addr, h->top, h->size); + delay(10); + } i += h->size; + if (h == h->link) { + print("xsummary: infinite loop broken\n"); + break; + } } - print("%d bytes free\n", i); + print(" %d bytes free\n", i); }