diff --git a/sys/src/9/mtx/devarch.c b/sys/src/9/mtx/devarch.c index cd5eea88f..8f2ad38e6 100644 --- a/sys/src/9/mtx/devarch.c +++ b/sys/src/9/mtx/devarch.c @@ -6,28 +6,8 @@ #include "io.h" #include "../port/error.h" -typedef struct IOMap IOMap; -struct IOMap -{ - IOMap *next; - char tag[13]; - ulong start; - ulong end; -}; - -static struct -{ - Lock; - IOMap *m; - IOMap *free; - IOMap maps[32]; // some initial free maps - - QLock ql; // lock for reading map -} iomap; - enum { Qdir = 0, - Qioalloc = 1, Qiob, Qiow, Qiol, @@ -43,7 +23,6 @@ static Rdwrfn *writefn[Qmax]; static Dirtab archdir[] = { ".", { Qdir, 0, QTDIR }, 0, 0555, - "ioalloc", { Qioalloc, 0 }, 0, 0444, "iob", { Qiob, 0 }, 0, 0660, "iow", { Qiow, 0 }, 0, 0660, "iol", { Qiol, 0 }, 0, 0660, @@ -95,111 +74,12 @@ addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn) void ioinit(void) { - int i; - - for(i = 0; i < nelem(iomap.maps)-1; i++) - iomap.maps[i].next = &iomap.maps[i+1]; - iomap.maps[i].next = nil; - iomap.free = iomap.maps; + iomapinit(IOSIZE-1); // a dummy entry at 2^17 ioalloc(0x20000, 1, 0, "dummy"); } -// -// alloc some io port space and remember who it was -// alloced to. if port < 0, find a free region. -// -int -ioalloc(int port, int size, int align, char *tag) -{ - IOMap *m, **l; - int i; - - lock(&iomap); - if(port < 0){ - // find a free port above 0x400 and below 0x1000 - port = 0x400; - for(l = &iomap.m; *l; l = &(*l)->next){ - m = *l; - i = m->start - port; - if(i > size) - break; - if(align > 0) - port = ((port+align-1)/align)*align; - else - port = m->end; - } - if(*l == nil){ - unlock(&iomap); - return -1; - } - } else { - // see if the space clashes with previously allocated ports - for(l = &iomap.m; *l; l = &(*l)->next){ - m = *l; - if(m->end <= port) - continue; - if(m->start >= port+size) - break; - unlock(&iomap); - return -1; - } - } - m = iomap.free; - if(m == nil){ - print("ioalloc: out of maps"); - unlock(&iomap); - return port; - } - iomap.free = m->next; - m->next = *l; - m->start = port; - m->end = port + size; - strncpy(m->tag, tag, sizeof(m->tag)); - m->tag[sizeof(m->tag)-1] = 0; - *l = m; - - archdir[0].qid.vers++; - - unlock(&iomap); - return m->start; -} - -void -iofree(int port) -{ - IOMap *m, **l; - - lock(&iomap); - for(l = &iomap.m; *l; l = &(*l)->next){ - if((*l)->start == port){ - m = *l; - *l = m->next; - m->next = iomap.free; - iomap.free = m; - break; - } - if((*l)->start > port) - break; - } - archdir[0].qid.vers++; - unlock(&iomap); -} - -int -iounused(int start, int end) -{ - IOMap *m; - - for(m = iomap.m; m; m = m->next){ - if(start >= m->start && start < m->end - || start <= m->start && end > m->start) - return 0; - } - return 1; -} - static void checkport(int start, int end) { @@ -243,16 +123,11 @@ archclose(Chan*) { } -enum -{ - Linelen= 31, -}; - static long archread(Chan *c, void *a, long n, vlong offset) { - char buf[Linelen+1], *p; int port; + uchar *cp; ushort *sp; ulong *lp; IOMap *m; @@ -266,8 +141,8 @@ archread(Chan *c, void *a, long n, vlong offset) case Qiob: port = offset; checkport(offset, offset+n); - for(p = a; port < offset+n; port++) - *p++ = inb(port); + for(cp = a; port < offset+n; port++) + *cp++ = inb(port); return n; case Qiow: @@ -290,40 +165,20 @@ archread(Chan *c, void *a, long n, vlong offset) *lp++ = inl(port); return n*4; - case Qioalloc: - break; - default: if(c->qid.path < narchdir && (fn = readfn[c->qid.path])) return fn(c, a, n, offset); error(Eperm); break; } - - offset = offset/Linelen; - n = n/Linelen; - p = a; - lock(&iomap); - for(m = iomap.m; n > 0 && m != nil; m = m->next){ - if(offset-- > 0) - continue; - if(strcmp(m->tag, "dummy") == 0) - break; - sprint(buf, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag); - memmove(p, buf, Linelen); - p += Linelen; - n--; - } - unlock(&iomap); - - return p - (char*)a; + return 0; } static long archwrite(Chan *c, void *a, long n, vlong offset) { - char *p; int port; + uchar *cp; ushort *sp; ulong *lp; Rdwrfn *fn; @@ -331,10 +186,10 @@ archwrite(Chan *c, void *a, long n, vlong offset) switch((ulong)c->qid.path){ case Qiob: - p = a; + cp = a; checkport(offset, offset+n); for(port = offset; port < offset+n; port++) - outb(port, *p++); + outb(port, *cp++); return n; case Qiow: diff --git a/sys/src/9/mtx/fns.h b/sys/src/9/mtx/fns.h index d63cc6ddb..c34a338fb 100644 --- a/sys/src/9/mtx/fns.h +++ b/sys/src/9/mtx/fns.h @@ -44,8 +44,6 @@ ulong inl(int); void insl(int, void*, int); void intr(Ureg*); void intrenable(int, void (*)(Ureg*, void*), void*, int, char*); -int ioalloc(int, int, int, char*); -void iofree(int); void ioinit(void); int iprint(char*, ...); int isaconfig(char*, int, ISAConf*); diff --git a/sys/src/9/mtx/mkfile b/sys/src/9/mtx/mkfile index df5ba47e8..3fe8e5f57 100644 --- a/sys/src/9/mtx/mkfile +++ b/sys/src/9/mtx/mkfile @@ -17,6 +17,7 @@ PORT=\ dev.$O\ edf.$O\ fault.$O\ + iomap.$O\ log.$O\ mul64fract.$O\ rebootcmd.$O\ diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index 9a845b3ab..cc14b394b 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -7,29 +7,8 @@ #include "ureg.h" #include "../port/error.h" -typedef struct IOMap IOMap; -struct IOMap -{ - IOMap *next; - int reserved; - char tag[13]; - ulong start; - ulong end; -}; - -static struct -{ - Lock; - IOMap *m; - IOMap *free; - IOMap maps[32]; /* some initial free maps */ - - QLock ql; /* lock for reading map */ -} iomap; - enum { Qdir = 0, - Qioalloc = 1, Qiob, Qiow, Qiol, @@ -61,7 +40,6 @@ static Rdwrfn *writefn[Qmax]; static Dirtab archdir[Qmax] = { ".", { Qdir, 0, QTDIR }, 0, 0555, - "ioalloc", { Qioalloc, 0 }, 0, 0444, "iob", { Qiob, 0 }, 0, 0660, "iow", { Qiow, 0 }, 0, 0660, "iol", { Qiol, 0 }, 0, 0660, @@ -116,12 +94,8 @@ void ioinit(void) { char *excluded; - int i; - for(i = 0; i < nelem(iomap.maps)-1; i++) - iomap.maps[i].next = &iomap.maps[i+1]; - iomap.maps[i].next = nil; - iomap.free = iomap.maps; + iomapinit(0xffff); /* * This is necessary to make the IBM X20 boot. @@ -155,160 +129,8 @@ ioinit(void) } } -/* - * Reserve a range to be ioalloced later. - * This is in particular useful for exchangable cards, such - * as pcmcia and cardbus cards. - */ -int -ioreserve(int, int size, int align, char *tag) -{ - IOMap *m, **l; - int i, port; - - lock(&iomap); - /* find a free port above 0x400 and below 0x1000 */ - port = 0x400; - for(l = &iomap.m; *l; l = &(*l)->next){ - m = *l; - if (m->start < 0x400) continue; - i = m->start - port; - if(i > size) - break; - if(align > 0) - port = ((port+align-1)/align)*align; - else - port = m->end; - } - if(*l == nil){ - unlock(&iomap); - return -1; - } - m = iomap.free; - if(m == nil){ - print("ioalloc: out of maps"); - unlock(&iomap); - return port; - } - iomap.free = m->next; - m->next = *l; - m->start = port; - m->end = port + size; - m->reserved = 1; - strncpy(m->tag, tag, sizeof(m->tag)-1); - m->tag[sizeof(m->tag)-1] = 0; - *l = m; - - archdir[0].qid.vers++; - - unlock(&iomap); - return m->start; -} - -/* - * alloc some io port space and remember who it was - * alloced to. if port < 0, find a free region. - */ -int -ioalloc(int port, int size, int align, char *tag) -{ - IOMap *m, **l; - int i; - - lock(&iomap); - if(port < 0){ - /* find a free port above 0x400 and below 0x1000 */ - port = 0x400; - for(l = &iomap.m; (m = *l) != nil; l = &m->next){ - if (m->start < 0x400) continue; - i = m->start - port; - if(i > size) - break; - if(align > 0) - port = ((port+align-1)/align)*align; - else - port = m->end; - } - if(m == nil){ - unlock(&iomap); - return -1; - } - } else { - /* Only 64KB I/O space on the x86. */ - if((port+size) > 0x10000){ - unlock(&iomap); - return -1; - } - /* see if the space clashes with previously allocated ports */ - for(l = &iomap.m; (m = *l) != nil; l = &m->next){ - if(m->end <= port) - continue; - if(m->reserved && m->start == port && m->end >= port + size) { - m->reserved = 0; - unlock(&iomap); - return m->start; - } - if(m->start >= port+size) - break; - unlock(&iomap); - return -1; - } - } - m = iomap.free; - if(m == nil){ - print("ioalloc: out of maps"); - unlock(&iomap); - return port; - } - iomap.free = m->next; - m->next = *l; - m->start = port; - m->end = port + size; - strncpy(m->tag, tag, sizeof(m->tag)-1); - m->tag[sizeof(m->tag)-1] = 0; - *l = m; - - archdir[0].qid.vers++; - - unlock(&iomap); - return m->start; -} - -void -iofree(int port) -{ - IOMap *m, **l; - - lock(&iomap); - for(l = &iomap.m; (m = *l) != nil; l = &m->next){ - if(m->start == port){ - *l = m->next; - m->next = iomap.free; - iomap.free = m; - break; - } - if(m->start > port) - break; - } - archdir[0].qid.vers++; - unlock(&iomap); -} - -int -iounused(int start, int end) -{ - IOMap *m; - - for(m = iomap.m; m != nil; m = m->next){ - if(start >= m->start && start < m->end - || start <= m->start && end > m->start) - return 0; - } - return 1; -} - static void -checkport(uint start, uint end) +checkport(ulong start, ulong end) { if(end < start || end > 0x10000) error(Ebadarg); @@ -356,14 +178,12 @@ archclose(Chan*) static long archread(Chan *c, void *a, long n, vlong offset) { - char buf[32], *p; - uint port, end; + ulong port, end; + uchar *cp; ushort *sp; ulong *lp; vlong *vp; - IOMap *m; Rdwrfn *fn; - int i; port = offset; end = port+n; @@ -373,8 +193,8 @@ archread(Chan *c, void *a, long n, vlong offset) case Qiob: checkport(port, end); - for(p = a; port < end; port++) - *p++ = inb(port); + for(cp = a; port < end; port++) + *cp++ = inb(port); return n; case Qiow: @@ -396,7 +216,7 @@ archread(Chan *c, void *a, long n, vlong offset) case Qmsr: if(n & 7) error(Ebadarg); - if((uint)n/8 > -port) + if((ulong)n/8 > -port) error(Ebadarg); end = port+(n/8); for(vp = a; port != end; port++) @@ -404,25 +224,6 @@ archread(Chan *c, void *a, long n, vlong offset) error(Ebadarg); return n; - case Qioalloc: - lock(&iomap); - i = 0; - for(m = iomap.m; m != nil; m = m->next){ - i = snprint(buf, sizeof(buf), "%8lux %8lux %-12.12s\n", - m->start, m->end-1, m->tag); - offset -= i; - if(offset < 0) - break; - } - unlock(&iomap); - if(offset >= 0) - return 0; - if(n > -offset) - n = -offset; - offset += i; - memmove(a, buf+offset, n); - return n; - default: if(c->qid.path < narchdir && (fn = readfn[c->qid.path])) return fn(c, a, n, offset); @@ -434,8 +235,8 @@ archread(Chan *c, void *a, long n, vlong offset) static long archwrite(Chan *c, void *a, long n, vlong offset) { - uint port, end; - char *p; + ulong port, end; + uchar *cp; ushort *sp; ulong *lp; vlong *vp; @@ -446,8 +247,8 @@ archwrite(Chan *c, void *a, long n, vlong offset) switch((ulong)c->qid.path){ case Qiob: checkport(port, end); - for(p = a; port < end; port++) - outb(port, *p++); + for(cp = a; port < end; port++) + outb(port, *cp++); return n; case Qiow: @@ -469,7 +270,7 @@ archwrite(Chan *c, void *a, long n, vlong offset) case Qmsr: if(n & 7) error(Ebadarg); - if((uint)n/8 > -port) + if((ulong)n/8 > -port) error(Ebadarg); end = port+(n/8); for(vp = a; port != end; port++) diff --git a/sys/src/9/pc/devpccard.c b/sys/src/9/pc/devpccard.c index b6c9bb682..fdfcdd9b7 100644 --- a/sys/src/9/pc/devpccard.c +++ b/sys/src/9/pc/devpccard.c @@ -816,7 +816,7 @@ configure(Cardbus *cb) if(iolen < 512) iolen = 512; - iobase = ioreserve(~0, iolen, 0, "cardbus"); + iobase = ioreserve(-1, iolen, 0, "cardbus"); if(iobase == -1) return; diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index 1bda49c67..669f02ee9 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -85,11 +85,7 @@ void intrenable(int, void (*)(Ureg*, void*), void*, int, char*); void introff(void); void intron(void); void invlpg(ulong); -void iofree(int); void ioinit(void); -int iounused(int, int); -int ioalloc(int, int, int, char*); -int ioreserve(int, int, int, char*); int iprint(char*, ...); int isaconfig(char*, int, ISAConf*); void* kaddr(ulong); diff --git a/sys/src/9/pc/mkfile b/sys/src/9/pc/mkfile index 2c3f6e395..e75948924 100644 --- a/sys/src/9/pc/mkfile +++ b/sys/src/9/pc/mkfile @@ -24,6 +24,8 @@ PORT=\ dev.$O\ edf.$O\ fault.$O\ + iomap.$O\ + memmap.$O\ page.$O\ parse.$O\ pgrp.$O\ @@ -35,7 +37,6 @@ PORT=\ random.$O\ rdb.$O\ rebootcmd.$O\ - memmap.$O\ segment.$O\ syscallfmt.$O\ sysfile.$O\ diff --git a/sys/src/9/pc/pcipc.c b/sys/src/9/pc/pcipc.c index a6850d37f..364fa81d2 100644 --- a/sys/src/9/pc/pcipc.c +++ b/sys/src/9/pc/pcipc.c @@ -528,59 +528,78 @@ pcirouting(void) } static void -pcireservemem(void) +pcireserve(void) { + char tag[64]; Pcidev *p; uvlong pa; + ulong io; int i; /* - * mark all valid physical address space claimed by pci devices - * as in use, so that upaalloc doesn't give it out. + * mark all valid io/mem address space claimed by pci devices + * so that ioreserve/upaalloc doesn't give it out. */ for(p=pciroot; p != nil; p=p->list){ + snprint(tag, sizeof(tag), "%T", p->tbdf); for(i=0; imem); i++){ if(p->mem[i].size == 0) continue; - if(p->mem[i].bar & 1) - continue; - if((p->mem[i].bar & ~0xFULL) == 0) - continue; - upaalloc(p->mem[i].bar&~0xFULL, p->mem[i].size, 0); + if(p->mem[i].bar & 1){ + io = p->mem[i].bar & ~3ULL; + if(io == 0) + continue; + ioreserve(io, p->mem[i].size, 0, tag); + } else { + pa = p->mem[i].bar & ~0xFULL; + if(pa == 0) + continue; + upaalloc(pa, p->mem[i].size, 0); + } } } /* - * allocate physical address space for unassigned membars. + * allocate io/mem address space for unassigned membars. */ for(p=pciroot; p != nil; p=p->list){ + snprint(tag, sizeof(tag), "%T", p->tbdf); for(i=0; imem); i++){ if(p->mem[i].size == 0) continue; - if(p->mem[i].bar & ~0xEULL) - continue; - - if(p->parent == nil){ - pa = upaalloc(-1ULL, - p->mem[i].size, p->mem[i].size); - } else if(p->mem[i].bar & 8){ - pa = upaallocwin(p->parent->prefa.bar, p->parent->prefa.size, - p->mem[i].size, p->mem[i].size); - if(pa == -1ULL) - goto Mem; + if(p->mem[i].bar & 1){ + if(p->mem[i].bar & ~0x3ULL) + continue; + if(p->parent == nil){ + io = ioreserve(-1, p->mem[i].size, p->mem[i].size, tag); + } else { + io = ioreservewin(p->parent->ioa.bar, p->parent->ioa.size, + p->mem[i].size, p->mem[i].size, tag); + } + if(io == -1) + continue; + p->mem[i].bar |= io; } else { - Mem: - pa = upaallocwin(p->parent->mema.bar, p->parent->mema.size, - p->mem[i].size, p->mem[i].size); + if(p->mem[i].bar & ~0xFULL) + continue; + if(p->parent == nil){ + pa = upaalloc(-1ULL, p->mem[i].size, p->mem[i].size); + } else if(p->mem[i].bar & 8){ + pa = upaallocwin(p->parent->prefa.bar, p->parent->prefa.size, + p->mem[i].size, p->mem[i].size); + if(pa == -1ULL) + goto Mem; + } else { + Mem: + pa = upaallocwin(p->parent->mema.bar, p->parent->mema.size, + p->mem[i].size, p->mem[i].size); + } + if(pa == -1ULL) + continue; + p->mem[i].bar |= pa; } - if(pa == -1ULL) - continue; - - p->mem[i].bar |= pa; pcisetbar(p, PciBAR0 + i*4, p->mem[i].bar); - - DBG("%T: bar%d: fixed %.8lluX %d\n", - p->tbdf, i, p->mem[i].bar, p->mem[i].size); + DBG("%s: bar%d: fixed %.8lluX %d\n", tag, i, p->mem[i].bar, p->mem[i].size); } } } @@ -620,6 +639,9 @@ pcicfginit(void) outl(PciADDR, 0x80000000); outb(PciADDR+3, 0); if(inl(PciADDR) & 0x80000000){ + ioalloc(PciADDR, 4, 0, "pcicfg.addr"); + ioalloc(PciDATA, 4, 0, "pcicfg.data"); + pcicfgmode = 1; pcimaxdno = 31; } @@ -634,6 +656,10 @@ pcicfginit(void) if(!(n & 0xF0)){ outb(PciCSE, 0x0E); if(inb(PciCSE) == 0x0E){ + ioalloc(PciCSE, 1, 0, "pcicfg.cse"); + ioalloc(PciFORWARD, 1, 0, "pcicfg.forward"); + ioalloc(0xC000, 0x1000, 0, "pcicfg.io"); + pcicfgmode = 2; pcimaxdno = 15; } @@ -705,16 +731,19 @@ pcicfginit(void) */ mema = upaalloc(-1ULL, mema, mema); if(mema == -1ULL) - panic("pcicfginit: can't allocate pci window"); + panic("pcicfginit: can't allocate pci mem window"); + + ioa = ioreserve(-1, ioa, ioa, "pci"); + if(ioa == -1UL) + panic("pcicfginit: can't allocate pci io window"); - ioa = 0x1000; DBG("Base: mem=%.8llux io=%lux\n", mema, ioa); pcibusmap(pciroot, &mema, &ioa, 1); DBG("Limit: mem=%.8llux io=%lux\n", mema, ioa); goto out; } - pcireservemem(); + pcireserve(); if(!nopcirouting) pcirouting(); diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h index 39afc4864..b3408badb 100644 --- a/sys/src/9/pc64/fns.h +++ b/sys/src/9/pc64/fns.h @@ -83,11 +83,7 @@ void intrenable(int, void (*)(Ureg*, void*), void*, int, char*); void introff(void); void intron(void); void invlpg(uintptr); -void iofree(int); void ioinit(void); -int iounused(int, int); -int ioalloc(int, int, int, char*); -int ioreserve(int, int, int, char*); int iprint(char*, ...); int isaconfig(char*, int, ISAConf*); void* kaddr(uintptr); diff --git a/sys/src/9/pc64/mkfile b/sys/src/9/pc64/mkfile index fa90808a7..8ac22f653 100644 --- a/sys/src/9/pc64/mkfile +++ b/sys/src/9/pc64/mkfile @@ -22,6 +22,7 @@ PORT=\ dev.$O\ edf.$O\ fault.$O\ + iomap.$O\ memmap.$O\ page.$O\ parse.$O\ diff --git a/sys/src/9/port/iomap.c b/sys/src/9/port/iomap.c new file mode 100644 index 000000000..666870b5b --- /dev/null +++ b/sys/src/9/port/iomap.c @@ -0,0 +1,243 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +typedef struct IOMap IOMap; +struct IOMap +{ + IOMap *next; + ulong start; + ulong end; + char reserved; + char tag[13]; +}; + +static struct +{ + Lock; + IOMap *m; + IOMap *free; + IOMap maps[32]; /* some initial free maps */ + + ulong mask; +} iomap; + +static void +insert(IOMap **l, ulong start, ulong end, char *tag, int reserved) +{ + IOMap *m; + + m = iomap.free; + if(m != nil) + iomap.free = m->next; + else + m = malloc(sizeof(IOMap)); + if(m == nil) + panic("ioalloc: out of memory"); + + m->next = *l; + m->start = start; + m->end = end; + m->reserved = reserved; + + strncpy(m->tag, tag, sizeof(m->tag)-1); + m->tag[sizeof(m->tag)-1] = 0; + + *l = m; +} + +/* + * Reserve a range to be ioalloced later. + * If port is -1, look for a free range above 0x400. + */ +int +ioreserve(ulong port, ulong size, ulong align, char *tag) +{ + if(port == -1) + return ioreservewin(0x400, -0x400 & iomap.mask, size, align, tag); + else + return ioreservewin(port, size, size, align, tag); +} + +/* + * Find a free region of length "size" within the window [port, port+win) + * and reserve it to be ioalloced later. + */ +int +ioreservewin(ulong port, ulong win, ulong size, ulong align, char *tag) +{ + IOMap *m, **l; + + if(win == 0 || port & ~iomap.mask || (~port & iomap.mask) < (win-1 & iomap.mask)) + return -1; + + size = (size + ~iomap.mask) & iomap.mask; + if(size == 0 || size > win) + return -1; + + if(align){ + if((align & (align-1)) != 0) + return -1; + align--; + } + + win += port; + port = (port+align) & ~align; + if(port >= win || win - port < size) + return -1; + + lock(&iomap); + for(l = &iomap.m; (m = *l) != nil; l = &m->next){ + if(m->end <= port) + continue; + if(m->start > port && m->start - port >= size) + break; + port = m->end; + port = (port+align) & ~align; + if(port >= win || win - port < size){ + unlock(&iomap); + return -1; + } + } + insert(l, port, port + size, tag, 1); + unlock(&iomap); + + return port; +} + +/* + * Alloc some io port space and remember who it was + * alloced to. If port == -1, find a free region. + */ +int +ioalloc(ulong port, ulong size, ulong align, char *tag) +{ + IOMap *m, **l; + + if(port == -1) + port = ioreserve(port, size, align, tag); + + size = (size + ~iomap.mask) & iomap.mask; + if(size == 0 || port & ~iomap.mask || (~port & iomap.mask) < (size-1 & iomap.mask)) + return -1; + + lock(&iomap); + for(l = &iomap.m; (m = *l) != nil; l = &m->next){ + if(m->end <= port) + continue; + if(m->start > port && m->start - port >= size) + break; + if(m->reserved && m->start <= port && m->end - port >= size){ + if(m->end - port > size) + insert(&m->next, port + size, m->end, m->tag, 1); + if(m->start < port){ + insert(l, m->start, port, m->tag, 1); + l = &(*l)->next; + } + *l = m->next; + m->next = iomap.free; + iomap.free = m; + break; + } + print("ioalloc: %lux - %lux %s: clashes with: %lux - %lux %s\n", + port, port+size-1, tag, + m->start, m->end-1, m->tag); + unlock(&iomap); + return -1; + } + insert(l, port, port + size, tag, 0); + unlock(&iomap); + + return port; +} + +void +iofree(ulong port) +{ + IOMap *m, **l; + + if(port & ~iomap.mask) + return; + + lock(&iomap); + for(l = &iomap.m; (m = *l) != nil; l = &m->next){ + if(m->start == port){ + *l = m->next; + m->next = iomap.free; + iomap.free = m; + break; + } + if(m->start > port) + break; + } + unlock(&iomap); +} + +int +iounused(ulong start, ulong end) +{ + IOMap *m; + + if(start & ~iomap.mask || end < start) + return 0; + + for(m = iomap.m; m != nil; m = m->next){ + if(m->end <= start) + continue; + if(m->start >= end) + break; + if(!m->reserved) + return 0; + } + return 1; +} + +static long +iomapread(Chan*, void *a, long n, vlong offset) +{ + char buf[32]; + IOMap *m; + int i; + + lock(&iomap); + i = 0; + for(m = iomap.m; m != nil; m = m->next){ + i = snprint(buf, sizeof(buf), "%8lux %8lux %-12.12s\n", + m->start, m->end-1, m->tag); + offset -= i; + if(offset < 0) + break; + } + unlock(&iomap); + if(offset >= 0) + return 0; + if(n > -offset) + n = -offset; + offset += i; + memmove(a, buf+offset, n); + return n; +} + +/* + * Initialize the io space port map. + * The mask argument defines the valid bits of + * a port address, so different architectures + * might have different sizes and alignments. + */ +void +iomapinit(ulong mask) +{ + int i; + + assert(mask != 0 && (mask >> 31) == 0); + + for(i = 0; i < nelem(iomap.maps)-1; i++) + iomap.maps[i].next = &iomap.maps[i+1]; + iomap.maps[i].next = nil; + iomap.free = iomap.maps; + iomap.mask = mask; + + addarchfile("ioalloc", 0444, iomapread, nil); +} diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index d50ffb6fb..04550987f 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -138,6 +138,12 @@ ulong imagereclaim(int); long incref(Ref*); void init0(void); void initseg(void); +int ioalloc(ulong, ulong, ulong, char*); +void iofree(ulong); +void iomapinit(ulong); +int ioreserve(ulong, ulong, ulong, char*); +int ioreservewin(ulong, ulong, ulong, ulong, char*); +int iounused(ulong, ulong); int iprint(char*, ...); void isdir(Chan*); int iseve(void); diff --git a/sys/src/9/ppc/fns.h b/sys/src/9/ppc/fns.h index 0606e3b69..68195a729 100644 --- a/sys/src/9/ppc/fns.h +++ b/sys/src/9/ppc/fns.h @@ -50,8 +50,6 @@ int inb(int); void intr(Ureg*); void intrenable(int, void (*)(Ureg*, void*), void*, char*); void intrdisable(int, void (*)(Ureg*, void*), void*, char*); -int ioalloc(int, int, int, char*); -void iofree(int); int iprint(char*, ...); int isaconfig(char*, int, ISAConf*); void kfpinit(void); diff --git a/sys/src/9/xen/fns.h b/sys/src/9/xen/fns.h index 88f5f1916..7289bd570 100644 --- a/sys/src/9/xen/fns.h +++ b/sys/src/9/xen/fns.h @@ -56,7 +56,6 @@ ulong inl(int); void insl(int, void*, int); void intrdisable(int, void (*)(Ureg *, void *), void*, int, char*); void intrenable(int, void (*)(Ureg*, void*), void*, int, char*); -int ioalloc(int, int, int, char*); void ioinit(void); int isaconfig(char*, int, ISAConf*); void kbdenable(void); diff --git a/sys/src/9/xen/mkfile b/sys/src/9/xen/mkfile index 9330581f6..3a3ecc87b 100644 --- a/sys/src/9/xen/mkfile +++ b/sys/src/9/xen/mkfile @@ -22,6 +22,7 @@ PORT=\ dev.$O\ edf.$O\ fault.$O\ + iomap.$O\ page.$O\ parse.$O\ pgrp.$O\