pc, pc64: implement 64-bit pci membar support
This commit is contained in:
parent
93f6ce24f4
commit
3bcc34f276
2 changed files with 57 additions and 46 deletions
|
@ -232,14 +232,6 @@ enum {
|
||||||
PciCapHSW = 0x0c, /* hot swap */
|
PciCapHSW = 0x0c, /* hot swap */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Pcisiz Pcisiz;
|
|
||||||
struct Pcisiz
|
|
||||||
{
|
|
||||||
Pcidev* dev;
|
|
||||||
int siz;
|
|
||||||
int bar;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct Pcidev Pcidev;
|
typedef struct Pcidev Pcidev;
|
||||||
struct Pcidev
|
struct Pcidev
|
||||||
{
|
{
|
||||||
|
@ -257,12 +249,12 @@ struct Pcidev
|
||||||
uchar ltr;
|
uchar ltr;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
ulong bar; /* base address */
|
uvlong bar; /* base address */
|
||||||
int size;
|
int size;
|
||||||
} mem[6];
|
} mem[6];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
ulong bar;
|
uvlong bar;
|
||||||
int size;
|
int size;
|
||||||
} rom;
|
} rom;
|
||||||
uchar intl; /* interrupt line */
|
uchar intl; /* interrupt line */
|
||||||
|
@ -273,7 +265,7 @@ struct Pcidev
|
||||||
Pcidev* parent; /* up a bus */
|
Pcidev* parent; /* up a bus */
|
||||||
Pcidev* bridge; /* down a bus */
|
Pcidev* bridge; /* down a bus */
|
||||||
struct {
|
struct {
|
||||||
ulong bar;
|
uvlong bar;
|
||||||
int size;
|
int size;
|
||||||
} ioa, mema;
|
} ioa, mema;
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,15 @@ enum
|
||||||
SErrEn = (1<<8),
|
SErrEn = (1<<8),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct Pcisiz Pcisiz;
|
||||||
|
struct Pcisiz
|
||||||
|
{
|
||||||
|
Pcidev* dev;
|
||||||
|
int siz;
|
||||||
|
int bar;
|
||||||
|
int typ;
|
||||||
|
};
|
||||||
|
|
||||||
static Lock pcicfglock;
|
static Lock pcicfglock;
|
||||||
static Lock pcicfginitlock;
|
static Lock pcicfginitlock;
|
||||||
static int pcicfgmode = -1;
|
static int pcicfgmode = -1;
|
||||||
|
@ -156,11 +165,12 @@ pcimask(ulong v)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
|
pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg)
|
||||||
{
|
{
|
||||||
Pcidev *p;
|
Pcidev *p;
|
||||||
int ntb, i, size, rno, hole;
|
int ntb, i, size, rno, hole;
|
||||||
ulong v, mema, ioa, sioa, smema, base, limit;
|
uvlong mema, smema, base, limit;
|
||||||
|
ulong ioa, sioa, v;
|
||||||
Pcisiz *table, *tptr, *mtb, *itb;
|
Pcisiz *table, *tptr, *mtb, *itb;
|
||||||
|
|
||||||
if(!nobios)
|
if(!nobios)
|
||||||
|
@ -169,7 +179,7 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
|
||||||
ioa = *pioa;
|
ioa = *pioa;
|
||||||
mema = *pmema;
|
mema = *pmema;
|
||||||
|
|
||||||
DBG("pcibusmap wr=%d %T mem=%luX io=%luX\n",
|
DBG("pcibusmap wr=%d %T mem=%lluX io=%luX\n",
|
||||||
wrreg, root->tbdf, mema, ioa);
|
wrreg, root->tbdf, mema, ioa);
|
||||||
|
|
||||||
ntb = 0;
|
ntb = 0;
|
||||||
|
@ -211,16 +221,18 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
|
||||||
itb->dev = p;
|
itb->dev = p;
|
||||||
itb->bar = -1;
|
itb->bar = -1;
|
||||||
itb->siz = p->ioa.size;
|
itb->siz = p->ioa.size;
|
||||||
|
itb->typ = 0;
|
||||||
itb++;
|
itb++;
|
||||||
|
|
||||||
mtb->dev = p;
|
mtb->dev = p;
|
||||||
mtb->bar = -1;
|
mtb->bar = -1;
|
||||||
mtb->siz = p->mema.size;
|
mtb->siz = p->mema.size;
|
||||||
|
mtb->typ = 0;
|
||||||
mtb++;
|
mtb++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i <= 5; i++) {
|
for(i = 0; i < nelem(p->mem); i++) {
|
||||||
rno = PciBAR0 + i*4;
|
rno = PciBAR0 + i*4;
|
||||||
v = pcicfgrw32(p->tbdf, rno, 0, 1);
|
v = pcicfgrw32(p->tbdf, rno, 0, 1);
|
||||||
size = pcibarsize(p, rno);
|
size = pcibarsize(p, rno);
|
||||||
|
@ -232,16 +244,17 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
|
||||||
itb->dev = p;
|
itb->dev = p;
|
||||||
itb->bar = i;
|
itb->bar = i;
|
||||||
itb->siz = size;
|
itb->siz = size;
|
||||||
|
itb->typ = 1;
|
||||||
itb++;
|
itb++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mtb->dev = p;
|
mtb->dev = p;
|
||||||
mtb->bar = i;
|
mtb->bar = i;
|
||||||
mtb->siz = size;
|
mtb->siz = size;
|
||||||
mtb++;
|
mtb->typ = v & 7;
|
||||||
|
if(mtb->typ & 4)
|
||||||
if((v & 7) == 4)
|
|
||||||
i++;
|
i++;
|
||||||
|
mtb++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,16 +295,23 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
|
||||||
hole = tptr->siz;
|
hole = tptr->siz;
|
||||||
if(tptr->bar == -1)
|
if(tptr->bar == -1)
|
||||||
hole = 1<<20;
|
hole = 1<<20;
|
||||||
mema = (mema+hole-1) & ~(hole-1);
|
mema = (mema+hole-1) & ~((uvlong)hole-1);
|
||||||
|
|
||||||
p = tptr->dev;
|
p = tptr->dev;
|
||||||
if(tptr->bar == -1)
|
if(tptr->bar == -1)
|
||||||
p->mema.bar = mema;
|
p->mema.bar = mema;
|
||||||
else {
|
else {
|
||||||
p->pcr |= MEMen;
|
p->pcr |= MEMen;
|
||||||
p->mem[tptr->bar].bar = mema;
|
p->mem[tptr->bar].bar = mema|tptr->typ;
|
||||||
if(wrreg)
|
if(wrreg){
|
||||||
pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), mema, 0);
|
rno = PciBAR0+(tptr->bar*4);
|
||||||
|
pcicfgrw32(p->tbdf, rno, mema|tptr->typ, 0);
|
||||||
|
if(tptr->bar < nelem(p->mem)-1 && (tptr->typ & 4) != 0){
|
||||||
|
p->mem[tptr->bar+1].bar = 0;
|
||||||
|
p->mem[tptr->bar+1].size = 0;
|
||||||
|
pcicfgrw32(p->tbdf, rno+4, mema>>32, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mema += tptr->siz;
|
mema += tptr->siz;
|
||||||
}
|
}
|
||||||
|
@ -425,21 +445,14 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent)
|
||||||
if((hdt & 0x7F) != 0)
|
if((hdt & 0x7F) != 0)
|
||||||
break;
|
break;
|
||||||
rno = PciBAR0;
|
rno = PciBAR0;
|
||||||
for(i = 0; i <= 5; i++) {
|
for(i = 0; i < nelem(p->mem); i++) {
|
||||||
p->mem[i].bar = pcicfgr32(p, rno);
|
p->mem[i].bar = (ulong)pcicfgr32(p, rno);
|
||||||
p->mem[i].size = pcibarsize(p, rno);
|
p->mem[i].size = pcibarsize(p, rno);
|
||||||
if((p->mem[i].bar & 7) == 4 && i < 5){
|
if((p->mem[i].bar & 7) == 4 && i < nelem(p->mem)-1){
|
||||||
ulong hi;
|
|
||||||
|
|
||||||
rno += 4;
|
rno += 4;
|
||||||
hi = pcicfgr32(p, rno);
|
p->mem[i++].bar |= (uvlong)pcicfgr32(p, rno) << 32;
|
||||||
if(hi != 0){
|
p->mem[i].bar = 0;
|
||||||
print("ignoring 64-bit bar %d: %llux %d from %T\n",
|
p->mem[i].size = 0;
|
||||||
i, (uvlong)hi<<32 | p->mem[i].bar, p->mem[i].size, p->tbdf);
|
|
||||||
p->mem[i].bar = 0;
|
|
||||||
p->mem[i].size = 0;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
rno += 4;
|
rno += 4;
|
||||||
}
|
}
|
||||||
|
@ -923,7 +936,7 @@ pcibiosinit(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pcibussize(Pcidev *root, ulong *msize, ulong *iosize)
|
pcibussize(Pcidev *root, uvlong *msize, ulong *iosize)
|
||||||
{
|
{
|
||||||
*msize = 0;
|
*msize = 0;
|
||||||
*iosize = 0;
|
*iosize = 0;
|
||||||
|
@ -935,7 +948,8 @@ pcicfginit(void)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
Pcidev **list;
|
Pcidev **list;
|
||||||
ulong mema, ioa;
|
uvlong mema;
|
||||||
|
ulong ioa;
|
||||||
int bno, n, pcibios;
|
int bno, n, pcibios;
|
||||||
|
|
||||||
lock(&pcicfginitlock);
|
lock(&pcicfginitlock);
|
||||||
|
@ -1052,10 +1066,10 @@ pcicfginit(void)
|
||||||
ioa = 0x1000;
|
ioa = 0x1000;
|
||||||
mema = 0x90000000;
|
mema = 0x90000000;
|
||||||
|
|
||||||
DBG("Mask sizes: mem=%lux io=%lux\n", mema, ioa);
|
DBG("Mask sizes: mem=%llux io=%lux\n", mema, ioa);
|
||||||
|
|
||||||
pcibusmap(pciroot, &mema, &ioa, 1);
|
pcibusmap(pciroot, &mema, &ioa, 1);
|
||||||
DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
|
DBG("Sizes2: mem=%llux io=%lux\n", mema, ioa);
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1083,8 +1097,8 @@ pcireservemem(void)
|
||||||
*/
|
*/
|
||||||
for(p=pciroot; p; p=p->list)
|
for(p=pciroot; p; p=p->list)
|
||||||
for(i=0; i<nelem(p->mem); i++)
|
for(i=0; i<nelem(p->mem); i++)
|
||||||
if((p->mem[i].bar&~4) != 0 && (p->mem[i].bar&1) == 0)
|
if(p->mem[i].size && (p->mem[i].bar&1) == 0 && (p->mem[i].bar&~0xF) != 0)
|
||||||
upaalloc(p->mem[i].bar&~0x0F, p->mem[i].size, 0);
|
upaalloc(p->mem[i].bar&~0xF, p->mem[i].size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1330,13 +1344,13 @@ pcilhinv(Pcidev* p)
|
||||||
for(i = 0; i < nelem(p->mem); i++) {
|
for(i = 0; i < nelem(p->mem); i++) {
|
||||||
if(t->mem[i].size == 0)
|
if(t->mem[i].size == 0)
|
||||||
continue;
|
continue;
|
||||||
print("%d:%.8lux %d ", i,
|
print("%d:%.8llux %d ", i,
|
||||||
t->mem[i].bar, t->mem[i].size);
|
t->mem[i].bar, t->mem[i].size);
|
||||||
}
|
}
|
||||||
if(t->ioa.bar || t->ioa.size)
|
if(t->ioa.bar || t->ioa.size)
|
||||||
print("ioa:%.8lux %d ", t->ioa.bar, t->ioa.size);
|
print("ioa:%.8llux %d ", t->ioa.bar, t->ioa.size);
|
||||||
if(t->mema.bar || t->mema.size)
|
if(t->mema.bar || t->mema.size)
|
||||||
print("mema:%.8lux %d ", t->mema.bar, t->mema.size);
|
print("mema:%.8llux %d ", t->mema.bar, t->mema.size);
|
||||||
if(t->bridge)
|
if(t->bridge)
|
||||||
print("->%d", BUSBNO(t->bridge->tbdf));
|
print("->%d", BUSBNO(t->bridge->tbdf));
|
||||||
print("\n");
|
print("\n");
|
||||||
|
@ -1589,8 +1603,13 @@ pcienable(Pcidev *p)
|
||||||
delay(100); /* D3: minimum delay 50ms */
|
delay(100); /* D3: minimum delay 50ms */
|
||||||
|
|
||||||
/* restore registers */
|
/* restore registers */
|
||||||
for(i = 0; i < 6; i++)
|
for(i = 0; i < nelem(p->mem); i++){
|
||||||
pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
|
pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
|
||||||
|
if((p->mem[i].bar&7) == 4 && i < nelem(p->mem)-1){
|
||||||
|
pcicfgw32(p, PciBAR0+i*4+4, p->mem[i].bar>>32);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
pcicfgw8(p, PciINTL, p->intl);
|
pcicfgw8(p, PciINTL, p->intl);
|
||||||
pcicfgw8(p, PciLTR, p->ltr);
|
pcicfgw8(p, PciLTR, p->ltr);
|
||||||
pcicfgw8(p, PciCLS, p->cls);
|
pcicfgw8(p, PciCLS, p->cls);
|
||||||
|
@ -1602,7 +1621,7 @@ pcienable(Pcidev *p)
|
||||||
pcr = IOen|MEMen|MASen;
|
pcr = IOen|MEMen|MASen;
|
||||||
else {
|
else {
|
||||||
pcr = 0;
|
pcr = 0;
|
||||||
for(i = 0; i < 6; i++){
|
for(i = 0; i < nelem(p->mem); i++){
|
||||||
if(p->mem[i].size == 0)
|
if(p->mem[i].size == 0)
|
||||||
continue;
|
continue;
|
||||||
if(p->mem[i].bar & 1)
|
if(p->mem[i].bar & 1)
|
||||||
|
|
Loading…
Reference in a new issue