X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=sys%2Fsrc%2F9%2Fpc%2Fpci.c;h=3d3239e18598e590d05dc4908a34d3420f1af546;hb=8243b6600f4c8d60e520aa1b20368ae9575aabf9;hp=85d05295400060a3acba36757158f7f1c9b66300;hpb=0431ea242d8856c5a780ab3a01252f3909349a49;p=plan9front.git diff --git a/sys/src/9/pc/pci.c b/sys/src/9/pc/pci.c index 85d052954..3d3239e18 100644 --- a/sys/src/9/pc/pci.c +++ b/sys/src/9/pc/pci.c @@ -35,6 +35,15 @@ enum 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 @@ pcimask(ulong v) } 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 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg) 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 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg) 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,16 +244,17 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg) itb->dev = p; itb->bar = i; itb->siz = size; + itb->typ = 1; itb++; } else { 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,16 +295,23 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg) 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) 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 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent) 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; } @@ -701,6 +714,7 @@ static Bridge southbridges[] = { { 0x1039, 0x0496, pIIxget, pIIxset }, /* SI 496 */ { 0x1078, 0x0100, cyrixget, cyrixset }, /* Cyrix 5530 Legacy */ + { 0x1022, 0x790e, nil, nil }, /* AMD FCH LPC bridge */ { 0x1022, 0x746b, nil, nil }, /* AMD 8111 */ { 0x10de, 0x00d1, nil, nil }, /* NVIDIA nForce 3 */ { 0x10de, 0x00e0, nil, nil }, /* NVIDIA nForce 3 250 Series */ @@ -922,7 +936,7 @@ pcibiosinit(void) } void -pcibussize(Pcidev *root, ulong *msize, ulong *iosize) +pcibussize(Pcidev *root, uvlong *msize, ulong *iosize) { *msize = 0; *iosize = 0; @@ -934,7 +948,8 @@ pcicfginit(void) { char *p; Pcidev **list; - ulong mema, ioa; + uvlong mema; + ulong ioa; int bno, n, pcibios; lock(&pcicfginitlock); @@ -1051,10 +1066,10 @@ pcicfginit(void) 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; } @@ -1082,8 +1097,8 @@ pcireservemem(void) */ for(p=pciroot; p; p=p->list) for(i=0; imem); i++) - if(p->mem[i].bar && (p->mem[i].bar&1) == 0) - upareserve(p->mem[i].bar&~0x0F, p->mem[i].size); + 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 @@ -1329,13 +1344,13 @@ pcilhinv(Pcidev* p) 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"); @@ -1560,3 +1575,73 @@ pcinextcap(Pcidev *pci, int offset) } return pcicfgr8(pci, offset+1) & ~3; } + +void +pcienable(Pcidev *p) +{ + uint pcr; + int i; + + if(p == nil) + return; + + pcienable(p->parent); + + switch(pcisetpms(p, 0)){ + case 1: + print("pcienable %T: wakeup from D1\n", p->tbdf); + break; + case 2: + print("pcienable %T: wakeup from D2\n", p->tbdf); + if(p->bridge != nil) + delay(100); /* B2: minimum delay 50ms */ + else + delay(1); /* D2: minimum delay 200µs */ + break; + case 3: + print("pcienable %T: wakeup from D3\n", p->tbdf); + delay(100); /* D3: minimum delay 50ms */ + + /* restore registers */ + 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); + pcicfgw16(p, PciPCR, p->pcr); + break; + } + + if(p->bridge != nil) + pcr = IOen|MEMen|MASen; + else { + pcr = 0; + for(i = 0; i < nelem(p->mem); i++){ + if(p->mem[i].size == 0) + continue; + if(p->mem[i].bar & 1) + pcr |= IOen; + else + pcr |= MEMen; + } + } + + if((p->pcr & pcr) != pcr){ + print("pcienable %T: pcr %ux->%ux\n", p->tbdf, p->pcr, p->pcr|pcr); + p->pcr |= pcr; + pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr, 0); + } +} + +void +pcidisable(Pcidev *p) +{ + if(p == nil) + return; + pciclrbme(p); +}