merge
This commit is contained in:
commit
9cca88895e
16 changed files with 342 additions and 431 deletions
|
@ -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:
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -17,6 +17,7 @@ PORT=\
|
|||
dev.$O\
|
||||
edf.$O\
|
||||
fault.$O\
|
||||
iomap.$O\
|
||||
log.$O\
|
||||
mul64fract.$O\
|
||||
rebootcmd.$O\
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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\
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
243
sys/src/9/port/iomap.c
Normal 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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -22,6 +22,7 @@ PORT=\
|
|||
dev.$O\
|
||||
edf.$O\
|
||||
fault.$O\
|
||||
iomap.$O\
|
||||
page.$O\
|
||||
parse.$O\
|
||||
pgrp.$O\
|
||||
|
|
Loading…
Reference in a new issue