ref: 9cca88895e31c73d4d0793dd83f76ebd24456cdd
parent: 97de3f67c230a34d95778cc16a8c1003148f0b4b
parent: 0ba91ae22a06af3a7561db15973dd98f715cc9eb
author: cinap_lenrek <[email protected]>
date: Tue Nov 3 15:47:14 EST 2020
merge
--- 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 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 @@
void
ioinit(void)
{
- int i;
+ iomapinit(IOSIZE-1);
- 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;
-
// 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 @@
{
}
-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 @@
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,9 +165,6 @@
*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);
@@ -299,31 +171,14 @@
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 @@
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:
--- a/sys/src/9/mtx/fns.h
+++ b/sys/src/9/mtx/fns.h
@@ -44,8 +44,6 @@
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*);
--- a/sys/src/9/mtx/mkfile
+++ b/sys/src/9/mtx/mkfile
@@ -17,6 +17,7 @@
dev.$O\
edf.$O\
fault.$O\
+ iomap.$O\
log.$O\
mul64fract.$O\
rebootcmd.$O\
--- a/sys/src/9/mtx/pcimtx.c
+++ b/sys/src/9/mtx/pcimtx.c
@@ -115,17 +115,13 @@
int
pcicfgrw8(int tbdf, int rno, int data, int read)
{
- int o, type, x;
+ int o, x;
- if(BUSBNO(tbdf))
- type = 0x01;
- else
- type = 0x00;
switch(pcicfgmode){
case 1:
o = rno & 0x03;
rno &= ~0x03;
- outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno);
if(read)
data = inb(PciDATA+o);
else
@@ -151,17 +147,13 @@
int
pcicfgrw16(int tbdf, int rno, int data, int read)
{
- int o, type;
+ int o;
- if(BUSBNO(tbdf))
- type = 0x01;
- else
- type = 0x00;
switch(pcicfgmode){
case 1:
o = rno & 0x02;
rno &= ~0x03;
- outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno);
if(read)
data = ins(PciDATA+o);
else
@@ -186,16 +178,10 @@
int
pcicfgrw32(int tbdf, int rno, int data, int read)
{
- int type;
-
- if(BUSBNO(tbdf))
- type = 0x01;
- else
- type = 0x00;
switch(pcicfgmode){
case 1:
rno &= ~0x03;
- outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno);
if(read)
data = inl(PciDATA);
else
--- 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 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 @@
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 @@
}
}
-/*
- * 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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++)
--- a/sys/src/9/pc/devpccard.c
+++ b/sys/src/9/pc/devpccard.c
@@ -816,7 +816,7 @@
if(iolen < 512)
iolen = 512;
- iobase = ioreserve(~0, iolen, 0, "cardbus");
+ iobase = ioreserve(-1, iolen, 0, "cardbus");
if(iobase == -1)
return;
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -85,11 +85,7 @@
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);
--- a/sys/src/9/pc/mkfile
+++ b/sys/src/9/pc/mkfile
@@ -24,6 +24,8 @@
dev.$O\
edf.$O\
fault.$O\
+ iomap.$O\
+ memmap.$O\
page.$O\
parse.$O\
pgrp.$O\
@@ -35,7 +37,6 @@
random.$O\
rdb.$O\
rebootcmd.$O\
- memmap.$O\
segment.$O\
syscallfmt.$O\
sysfile.$O\
--- a/sys/src/9/pc/pcipc.c
+++ b/sys/src/9/pc/pcipc.c
@@ -528,59 +528,78 @@
}
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; i<nelem(p->mem); 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; i<nelem(p->mem); 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 @@
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 @@
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,9 +731,12 @@
*/
mema = upaalloc(-1ULL, mema, mema);
if(mema == -1ULL)
- panic("pcicfginit: can't allocate pci window");
+ panic("pcicfginit: can't allocate pci mem window");
- ioa = 0x1000;
+ ioa = ioreserve(-1, ioa, ioa, "pci");
+ if(ioa == -1UL)
+ panic("pcicfginit: can't allocate pci io window");
+
DBG("Base: mem=%.8llux io=%lux\n", mema, ioa);
pcibusmap(pciroot, &mema, &ioa, 1);
DBG("Limit: mem=%.8llux io=%lux\n", mema, ioa);
@@ -714,7 +743,7 @@
goto out;
}
- pcireservemem();
+ pcireserve();
if(!nopcirouting)
pcirouting();
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -83,11 +83,7 @@
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);
--- a/sys/src/9/pc64/mkfile
+++ b/sys/src/9/pc64/mkfile
@@ -22,6 +22,7 @@
dev.$O\
edf.$O\
fault.$O\
+ iomap.$O\
memmap.$O\
page.$O\
parse.$O\
--- /dev/null
+++ b/sys/src/9/port/iomap.c
@@ -1,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);
+}
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -138,6 +138,12 @@
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);
--- a/sys/src/9/ppc/fns.h
+++ b/sys/src/9/ppc/fns.h
@@ -50,8 +50,6 @@
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);
--- a/sys/src/9/xen/fns.h
+++ b/sys/src/9/xen/fns.h
@@ -56,7 +56,6 @@
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);
--- a/sys/src/9/xen/mkfile
+++ b/sys/src/9/xen/mkfile
@@ -22,6 +22,7 @@
dev.$O\
edf.$O\
fault.$O\
+ iomap.$O\
page.$O\
parse.$O\
pgrp.$O\