This commit is contained in:
cinap_lenrek 2020-11-03 20:47:14 +01:00
commit 9cca88895e
16 changed files with 342 additions and 431 deletions

View file

@ -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:

View file

@ -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*);

View file

@ -17,6 +17,7 @@ PORT=\
dev.$O\
edf.$O\
fault.$O\
iomap.$O\
log.$O\
mul64fract.$O\
rebootcmd.$O\

View file

@ -115,17 +115,13 @@ pcicfginit(void)
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 @@ pcicfgrw8(int tbdf, int rno, int data, int read)
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 @@ pcicfgrw16(int tbdf, int rno, int data, int read)
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

View file

@ -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++)

View file

@ -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;

View file

@ -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);

View file

@ -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\

View file

@ -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; 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 @@ 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();

View file

@ -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);

View file

@ -22,6 +22,7 @@ PORT=\
dev.$O\
edf.$O\
fault.$O\
iomap.$O\
memmap.$O\
page.$O\
parse.$O\

243
sys/src/9/port/iomap.c Normal file
View file

@ -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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -22,6 +22,7 @@ PORT=\
dev.$O\
edf.$O\
fault.$O\
iomap.$O\
page.$O\
parse.$O\
pgrp.$O\