ref: 3bcc34f27623cf7858a7c224470ec70359cfcd48
parent: 93f6ce24f46cc596060d859ff97a276e80e1d5c5
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Jun 6 10:58:20 EDT 2020
pc, pc64: implement 64-bit pci membar support
--- a/sys/src/9/pc/io.h
+++ b/sys/src/9/pc/io.h
@@ -232,14 +232,6 @@
PciCapHSW = 0x0c, /* hot swap */
};
-typedef struct Pcisiz Pcisiz;
-struct Pcisiz
-{
- Pcidev* dev;
- int siz;
- int bar;
-};
-
typedef struct Pcidev Pcidev;
struct Pcidev
{
@@ -257,12 +249,12 @@
uchar ltr;
struct {
- ulong bar; /* base address */
+ uvlong bar; /* base address */
int size;
} mem[6];
struct {
- ulong bar;
+ uvlong bar;
int size;
} rom;
uchar intl; /* interrupt line */
@@ -273,7 +265,7 @@
Pcidev* parent; /* up a bus */
Pcidev* bridge; /* down a bus */
struct {
- ulong bar;
+ uvlong bar;
int size;
} ioa, mema;
--- a/sys/src/9/pc/pci.c
+++ b/sys/src/9/pc/pci.c
@@ -35,6 +35,15 @@
SErrEn = (1<<8),
};
+typedef struct Pcisiz Pcisiz;
+struct Pcisiz
+{
+ Pcidev* dev;
+ int siz;
+ int bar;
+ int typ;
+};
+
static Lock pcicfglock;
static Lock pcicfginitlock;
static int pcicfgmode = -1;
@@ -156,11 +165,12 @@
}
static void
-pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
+pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg)
{
Pcidev *p;
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;
if(!nobios)
@@ -169,7 +179,7 @@
ioa = *pioa;
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);
ntb = 0;
@@ -211,16 +221,18 @@
itb->dev = p;
itb->bar = -1;
itb->siz = p->ioa.size;
+ itb->typ = 0;
itb++;
mtb->dev = p;
mtb->bar = -1;
mtb->siz = p->mema.size;
+ mtb->typ = 0;
mtb++;
continue;
}
- for(i = 0; i <= 5; i++) {
+ for(i = 0; i < nelem(p->mem); i++) {
rno = PciBAR0 + i*4;
v = pcicfgrw32(p->tbdf, rno, 0, 1);
size = pcibarsize(p, rno);
@@ -232,6 +244,7 @@
itb->dev = p;
itb->bar = i;
itb->siz = size;
+ itb->typ = 1;
itb++;
}
else {
@@ -238,10 +251,10 @@
mtb->dev = p;
mtb->bar = i;
mtb->siz = size;
- mtb++;
-
- if((v & 7) == 4)
+ mtb->typ = v & 7;
+ if(mtb->typ & 4)
i++;
+ mtb++;
}
}
}
@@ -282,7 +295,7 @@
hole = tptr->siz;
if(tptr->bar == -1)
hole = 1<<20;
- mema = (mema+hole-1) & ~(hole-1);
+ mema = (mema+hole-1) & ~((uvlong)hole-1);
p = tptr->dev;
if(tptr->bar == -1)
@@ -289,9 +302,16 @@
p->mema.bar = mema;
else {
p->pcr |= MEMen;
- p->mem[tptr->bar].bar = mema;
- if(wrreg)
- pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), mema, 0);
+ p->mem[tptr->bar].bar = mema|tptr->typ;
+ if(wrreg){
+ 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;
}
@@ -425,21 +445,14 @@
if((hdt & 0x7F) != 0)
break;
rno = PciBAR0;
- for(i = 0; i <= 5; i++) {
- p->mem[i].bar = pcicfgr32(p, rno);
+ for(i = 0; i < nelem(p->mem); i++) {
+ p->mem[i].bar = (ulong)pcicfgr32(p, rno);
p->mem[i].size = pcibarsize(p, rno);
- if((p->mem[i].bar & 7) == 4 && i < 5){
- ulong hi;
-
+ if((p->mem[i].bar & 7) == 4 && i < nelem(p->mem)-1){
rno += 4;
- hi = pcicfgr32(p, rno);
- if(hi != 0){
- print("ignoring 64-bit bar %d: %llux %d from %T\n",
- 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++;
+ p->mem[i++].bar |= (uvlong)pcicfgr32(p, rno) << 32;
+ p->mem[i].bar = 0;
+ p->mem[i].size = 0;
}
rno += 4;
}
@@ -923,7 +936,7 @@
}
void
-pcibussize(Pcidev *root, ulong *msize, ulong *iosize)
+pcibussize(Pcidev *root, uvlong *msize, ulong *iosize)
{
*msize = 0;
*iosize = 0;
@@ -935,7 +948,8 @@
{
char *p;
Pcidev **list;
- ulong mema, ioa;
+ uvlong mema;
+ ulong ioa;
int bno, n, pcibios;
lock(&pcicfginitlock);
@@ -1052,10 +1066,10 @@
ioa = 0x1000;
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);
- DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
+ DBG("Sizes2: mem=%llux io=%lux\n", mema, ioa);
goto out;
}
@@ -1083,8 +1097,8 @@
*/
for(p=pciroot; p; p=p->list)
for(i=0; i<nelem(p->mem); i++)
- if((p->mem[i].bar&~4) != 0 && (p->mem[i].bar&1) == 0)
- upaalloc(p->mem[i].bar&~0x0F, p->mem[i].size, 0);
+ if(p->mem[i].size && (p->mem[i].bar&1) == 0 && (p->mem[i].bar&~0xF) != 0)
+ upaalloc(p->mem[i].bar&~0xF, p->mem[i].size, 0);
}
static int
@@ -1330,13 +1344,13 @@
for(i = 0; i < nelem(p->mem); i++) {
if(t->mem[i].size == 0)
continue;
- print("%d:%.8lux %d ", i,
+ print("%d:%.8llux %d ", i,
t->mem[i].bar, t->mem[i].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)
- print("mema:%.8lux %d ", t->mema.bar, t->mema.size);
+ print("mema:%.8llux %d ", t->mema.bar, t->mema.size);
if(t->bridge)
print("->%d", BUSBNO(t->bridge->tbdf));
print("\n");
@@ -1589,8 +1603,13 @@
delay(100); /* D3: minimum delay 50ms */
/* 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);
+ 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, PciLTR, p->ltr);
pcicfgw8(p, PciCLS, p->cls);
@@ -1602,7 +1621,7 @@
pcr = IOen|MEMen|MASen;
else {
pcr = 0;
- for(i = 0; i < 6; i++){
+ for(i = 0; i < nelem(p->mem); i++){
if(p->mem[i].size == 0)
continue;
if(p->mem[i].bar & 1)