guts of 64-bit bar support for the pc kernel. Reference: /n/atom/patch/applied/pc64bitbar Date: Sat Jan 11 22:16:50 CET 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/9/pc/pci.c Sat Jan 11 22:16:20 2014 +++ /sys/src/9/pc/pci.c Sat Jan 11 22:16:20 2014 @@ -113,7 +113,7 @@ } static int -tbdffmt(Fmt* fmt) +fmtT(Fmt* fmt) { char *p; int l, r; @@ -124,18 +124,14 @@ switch(fmt->r){ case 'T': - tbdf = va_arg(fmt->args, int); - if(tbdf == BUSUNKNOWN) - snprint(p, READSTR, "unknown"); - else{ - type = BUSTYPE(tbdf); - if(type < nelem(bustypes)) - l = snprint(p, READSTR, bustypes[type]); - else - l = snprint(p, READSTR, "%d", type); - snprint(p+l, READSTR-l, ".%d.%d.%d", - BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); - } + tbdf = va_arg(fmt->args, uint); + type = BUSTYPE(tbdf); + if(type < nelem(bustypes)) + l = snprint(p, READSTR, bustypes[type]); + else + l = snprint(p, READSTR, "%d", type); + snprint(p+l, READSTR-l, ".%d.%d.%d", + BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); break; default: @@ -148,7 +144,7 @@ return r; } -ulong +u32int pcibarsize(Pcidev *p, int rno) { ulong v, size; @@ -163,6 +159,32 @@ return -(size & ~0x0F); } +static void +pcibars(Pcidev *p) +{ + int i, o; + u32int bar; + + for(i = 0; i < nelem(p->mem); i++) { + o = PciBAR0+4*i; + p->mem[i].bar = (u32int)pcicfgr32(p, o); + p->mem[i].size = pcibarsize(p, o); + if(i&1 || (p->mem[i].bar & 2<<1) == 0) + continue; + bar = pcicfgr32(p, o+4); + if(sizeof(uintmem) >= sizeof(u64int)) + p->mem[i].bar |= (u64int)bar<<32; + else if(bar != 0){ + print("%T: warning 64-bit bar %d too large\n", p->tbdf, i); + p->mem[i].bar = 0; + p->mem[i].size = 0; + } + i++; + p->mem[i].bar = 0; + p->mem[i].size = 0; + } +} + static int pcisizcmp(void *a, void *b) { @@ -433,7 +455,7 @@ pcilscan(int bno, Pcidev** list) { Pcidev *p, *head, *tail; - int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn; + int dno, fno, hdt, l, maxfno, maxubn, sbn, tbdf, ubn; maxubn = bno; head = nil; @@ -489,31 +511,16 @@ * and work out the sizes. */ switch(p->ccrb) { - case 0x01: /* mass storage controller */ - case 0x02: /* network controller */ - case 0x03: /* display controller */ - case 0x04: /* multimedia device */ - case 0x07: /* simple comm. controllers */ - case 0x08: /* base system peripherals */ - case 0x09: /* input devices */ - case 0x0A: /* docking stations */ - case 0x0B: /* processors */ - case 0x0C: /* serial bus controllers */ - if((hdt & 0x7F) != 0) - break; - rno = PciBAR0 - 4; - for(i = 0; i < nelem(p->mem); i++) { - rno += 4; - p->mem[i].bar = pcicfgr32(p, rno); - p->mem[i].size = pcibarsize(p, rno); - } + default: + if((hdt & 0x7F) == 0) + pcibars(p); break; + case 0x06: /* bridge device */ bridgecfg(p); break; case 0x00: case 0x05: /* memory controller */ - default: break; } @@ -747,14 +754,14 @@ static void pcirouting(void) { - Slot *e; - Router *r; + uchar *p, pin, irq, link, *map; int size, i, fn, tbdf; Pcidev *sbpci, *pci; - uchar *p, pin, irq, link, *map; + Router *r; + Slot *e; /* Search for PCI interrupt routing table in BIOS */ - for(p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16) + for(p = (uchar*)KADDR(0xf0000); p < (uchar*)KADDR(0xfffff); p += 16) if(p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R') break; @@ -763,8 +770,9 @@ r = (Router *)p; - // print("PCI interrupt routing table version %d.%d at %.6uX\n", - // r->version[0], r->version[1], (ulong)r & 0xfffff); + if(0) + print("PCI interrupt routing table version %d.%d at %#.6ux\n", + r->version[0], r->version[1], (uint)r & 0xfffff); tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8); sbpci = pcimatchtbdf(tbdf); @@ -779,28 +787,27 @@ break; if(i == nelem(southbridges)) { - print("pcirouting: ignoring south bridge %T %.4uX/%.4uX\n", tbdf, sbpci->vid, sbpci->did); + print("pcirouting: ignoring south bridge %T %.4ux/%.4ux\n", tbdf, sbpci->vid, sbpci->did); return; } southbridge = &southbridges[i]; if(southbridge->get == nil || southbridge->set == nil) return; - pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0]; - - size = (r->size[1] << 8)|r->size[0]; + pciirqs = r->pciirqs[1]<<8 | r->pciirqs[0]; + size = r->size[1]<<8 | r->size[0]; for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) { if (0) { - print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot); + print("%.2ux/%.2ux %.2ux: ", e->bus, e->dev, e->slot); for (i = 0; i != 4; i++) { uchar *m = &e->maps[i * 3]; - print("[%d] %.2uX %.4uX ", + print("[%d] %.2ux %.4ux ", i, m[0], (m[2] << 8)|m[1]); } print("\n"); } for(fn = 0; fn != 8; fn++) { - tbdf = (BusPCI << 24)|(e->bus << 16)|((e->dev | fn) << 8); + tbdf = MKBUS(BusPCI, e->bus, e->dev, fn); pci = pcimatchtbdf(tbdf); if(pci == nil) continue; @@ -814,7 +821,7 @@ if(irq == 0 || irq == pci->intl) continue; if(pci->intl != 0 && pci->intl != 0xFF) { - print("pcirouting: BIOS workaround: %T at pin %d link %d irq %d -> %d\n", + print("pcirouting: %T at pin %d link %d irq %d -> %d\n", tbdf, pin, link, irq, pci->intl); southbridge->set(sbpci, link, pci->intl); continue; @@ -939,6 +946,18 @@ } static void +pcireservemem(void) +{ + int i; + Pcidev *p; + + for(p = nil; p = pcimatch(p, 0, 0); ) + for(i=0; imem); i++) + if(p->mem[i].bar && (p->mem[i].bar&1) == 0) + upareserve(p->mem[i].bar&~(uintmem)0xf, p->mem[i].size); +} + +static void pcicfginit(void) { char *p; @@ -1007,7 +1026,7 @@ pcicfgmode = 3; } - fmtinstall('T', tbdffmt); + fmtinstall('T', fmtT); if(p = getconf("*pcimaxbno")) pcimaxbno = strtoul(p, 0, 0); @@ -1080,22 +1099,6 @@ pcihinv(nil); } -static void -pcireservemem(void) -{ - int i; - Pcidev *p; - - /* - * mark all the physical address space claimed by pci devices - * as in use, so that upaalloc doesn't give it out. - */ - 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); -} - static int pcicfgrw8raw(int tbdf, int rno, int data, int read) { @@ -1271,17 +1274,11 @@ { if(pcicfgmode == -1) pcicfginit(); - - if(prev == nil) - prev = pcilist; - else - prev = prev->list; - - while(prev != nil){ + prev = prev? prev->list: pcilist; + for(; prev != nil; prev = prev->list){ if((vid == 0 || prev->vid == vid) && (did == 0 || prev->did == did)) break; - prev = prev->list; } return prev; } @@ -1289,16 +1286,16 @@ Pcidev* pcimatchtbdf(int tbdf) { - Pcidev *pcidev; + Pcidev *p; if(pcicfgmode == -1) pcicfginit(); - for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) { - if(pcidev->tbdf == tbdf) + for(p = pcilist; p != nil; p = p->list) { + if(p->tbdf == tbdf) break; } - return pcidev; + return p; } uchar @@ -1321,50 +1318,32 @@ return 0; } -static void -pcilhinv(Pcidev* p) +void +pcihinv(Pcidev* p) { int i; Pcidev *t; if(p == nil) { p = pciroot; - print("bus dev type vid did intl memory\n"); + print("tbdf: type vid did intl memory\n"); } for(t = p; t != nil; t = t->link) { - print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ", - BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf), - t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl); + print("%T: %.2ux %.4ux/%.4ux %.2d", + t->tbdf, t->ccru, t->vid, t->did, t->intl); for(i = 0; i < nelem(p->mem); i++) { if(t->mem[i].size == 0) continue; - print("%d:%.8lux %d ", i, - t->mem[i].bar, t->mem[i].size); + print("%d:%#P %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); - if(t->mema.bar || t->mema.size) - print("mema:%.8lux %d ", t->mema.bar, t->mema.size); - if(t->bridge) + if(t->bridge != nil) print("->%d", BUSBNO(t->bridge->tbdf)); print("\n"); } - while(p != nil) { + for(; p != nil; p = p->link) if(p->bridge != nil) - pcilhinv(p->bridge); - p = p->link; - } -} - -void -pcihinv(Pcidev* p) -{ - if(pcicfgmode == -1) - pcicfginit(); - lock(&pcicfginitlock); - pcilhinv(p); - unlock(&pcicfginitlock); + pcihinv(p->bridge); } void @@ -1459,40 +1438,33 @@ return -1; } +enum { + Pmgcap = 2, /* capabilities; 2 bytes*/ + Pmgctl = 4, /* ctl/status; 2 bytes */ + Pmgbrg = 6, /* bridge support */ + Pmgdata = 7, +}; + int pcigetpms(Pcidev* p) { - int pmcsr, ptr; + int ptr; if((ptr = pcicap(p, PciCapPMG)) == -1) return -1; - - /* - * Power Management Register Block: - * offset 0: Capability ID - * 1: next item pointer - * 2: capabilities - * 4: control/status - * 6: bridge support extensions - * 7: data - */ - pmcsr = pcicfgr16(p, ptr+4); - - return pmcsr & 0x0003; + return pcicfgr16(p, ptr+Pmgctl) & 0x0003; } int pcisetpms(Pcidev* p, int state) { - int ostate, pmc, pmcsr, ptr; + int pmc, pmcsr, ptr; if((ptr = pcicap(p, PciCapPMG)) == -1) return -1; - pmc = pcicfgr16(p, ptr+2); - pmcsr = pcicfgr16(p, ptr+4); - ostate = pmcsr & 0x0003; - pmcsr &= ~0x0003; + pmc = pcicfgr16(p, ptr+Pmgcap); + pmcsr = pcicfgr16(p, ptr+Pmgctl); switch(state){ default: @@ -1510,8 +1482,6 @@ case 3: break; } - pmcsr |= state; - pcicfgw16(p, ptr+4, pmcsr); - - return ostate; + pcicfgw16(p, ptr+4, (pmcsr & ~3) | state); + return pmcsr & 3; } --- /sys/src/9/pc/memory.c Sat Jan 11 22:16:20 2014 +++ /sys/src/9/pc/memory.c Sat Jan 11 22:16:20 2014 @@ -49,7 +49,7 @@ /* * Memory allocation tracking. */ -static Map mapupa[16]; +static Map mapupa[64]; static RMap rmapupa = { "unallocated unbacked physical memory", mapupa, @@ -836,37 +836,37 @@ /* * Allocate memory from the upper memory blocks. */ -ulong -umbmalloc(ulong addr, int size, int align) +uintptr +umbmalloc(uintmem addr, int size, int align) { - ulong a; - - if(a = mapalloc(&rmapumb, addr, size, align)) - return (ulong)KADDR(a); + uintmem a; + a = mapalloc(&rmapumb, addr, size, align); + if(a != 0) + return (uintptr)KADDR(a); return 0; } void -umbfree(ulong addr, int size) +umbfree(uintptr va, int size) { - mapfree(&rmapumb, PADDR(addr), size); + mapfree(&rmapumb, PADDR(va), size); } -ulong -umbrwmalloc(ulong addr, int size, int align) +uintptr +umbrwmalloc(uintmem pa, int size, int align) { - ulong a; + uintmem a; uchar o[2], *p; - if(a = mapalloc(&rmapumbrw, addr, size, align)) - return (ulong)KADDR(a); + if(a = mapalloc(&rmapumbrw, pa, size, align)) + return (uintptr)KADDR(a); /* * Perhaps the memory wasn't visible before * the interface is initialised, so try again. */ - if((a = umbmalloc(addr, size, align)) == 0) + if((a = umbmalloc(pa, size, align)) == 0) return 0; p = (uchar*)a; o[0] = p[0]; @@ -891,14 +891,14 @@ /* * Give out otherwise-unused physical address space - * for use in configuring devices. Note that unlike upamalloc + * for use in configuring devices. Note that unlike umbmalloc * before it, upaalloc does not map the physical address * into virtual memory. Call vmap to do that. */ -ulong +uintmem upaalloc(int size, int align) { - ulong a; + uintmem a; a = mapalloc(&rmapupa, 0, size, align); if(a == 0){ @@ -909,24 +909,23 @@ } void -upafree(ulong pa, int size) +upafree(uintmem pa, int size) { mapfree(&rmapupa, pa, size); } void -upareserve(ulong pa, int size) +upareserve(uintmem pa, int size) { - ulong a; - + uintmem a; + a = mapalloc(&rmapupa, pa, size, 0); if(a != pa){ /* - * This can happen when we're using the E820 - * map, which might have already reserved some + * The E820 map may have already reserved some * of the regions claimed by the pci devices. */ - // print("upareserve: cannot reserve pa=%#.8lux size=%d\n", pa, size); + // print("upareserve: cannot reserve pa=%#P size=%d\n", pa, size); if(a != 0) mapfree(&rmapupa, a, size); } --- /sys/src/9/pc/io.h Sat Jan 11 22:16:20 2014 +++ /sys/src/9/pc/io.h Sat Jan 11 22:16:20 2014 @@ -258,24 +258,24 @@ uchar ccrb; uchar cls; uchar ltr; + uchar intl; /* interrupt line */ struct { - ulong bar; /* base address */ + uintmem bar; /* base address */ int size; } mem[6]; struct { - ulong bar; + uintmem bar; int size; } rom; - uchar intl; /* interrupt line */ Pcidev* list; Pcidev* link; /* next device on this bno */ Pcidev* bridge; /* down a bus */ struct { - ulong bar; + uintmem bar; int size; } ioa, mema; }; --- /sys/src/9/pc/etherdp83820.c Sat Jan 11 22:16:20 2014 +++ /sys/src/9/pc/etherdp83820.c Sat Jan 11 22:16:20 2014 @@ -1159,7 +1159,7 @@ break; } - mem = vmap(p->mem[1].bar & ~(uintmem)0xf p->mem[1].size); + mem = vmap(p->mem[1].bar & ~(uintmem)0xf, p->mem[1].size); if(mem == nil){ print("DP83820: can't map %#P\n", p->mem[1].bar); continue; --- /sys/src/9/pc/vgamga4xx.c Sat Jan 11 22:16:21 2014 +++ /sys/src/9/pc/vgamga4xx.c Sat Jan 11 22:16:21 2014 @@ -133,11 +133,11 @@ if(pci == nil) return; - scr->mmio = vmap(pci->mem[1].bar&~0x0F, 16*1024); + scr->mmio = vmap(pci->mem[1].bar&~(uintmem)0xf, 16*1024); if(scr->mmio == nil) return; - addvgaseg("mga4xxmmio", pci->mem[1].bar&~0x0F, pci->mem[1].size); + addvgaseg("mga4xxmmio", pci->mem[1].bar&~(uintmem)0xf, pci->mem[1].size); /* need to map frame buffer here too, so vga can find memory size */ if(pci->did == MGA4xx || pci->did == MGA550)