must not turn of bme for pci bridges during pci reset. this will render devices behind the bridges inaccessable. also, sync with nix kernel. further syncing should be possible. Reference: /n/atom/patch/applied2013/fs64pcibrg Date: Sat Sep 14 19:37:49 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/fs/amd64/pci.c Sat Sep 14 19:32:59 2013 +++ /sys/src/fs/amd64/pci.c Sat Sep 14 19:33:01 2013 @@ -29,36 +29,64 @@ static Pcidev* pcilist; static Pcidev* pcitail; -static int pcicfgrw(int, int, int, int, int); +static char* bustypes[] = { + "CBUSI", + "CBUSII", + "EISA", + "FUTURE", + "INTERN", + "ISA", + "MBI", + "MBII", + "MCA", + "MPI", + "MPSA", + "NUBUS", + "PCI", + "PCMCIA", + "TC", + "VL", + "VME", + "XPRESS", +}; -u32int -pcibarsize(Pcidev *p, int rno) -{ - u32int v, size; +static int pcicfgrw(int, int, int, int, int); - v = pcicfgr32(p, rno); - pcicfgw32(p, rno, 0xFFFFFFF0); - size = pcicfgr32(p, rno); - if(v & 1) - size |= 0xFFFF0000; - pcicfgw32(p, rno, v); +static int +strtobus(char *s) +{ + int i; - return -(size & ~0x0F); + for(i = 0; i < nelem(bustypes); i++) + if(cistrcmp(s, bustypes[i]) == 0) + return i; + return BUSUNKNOWN; } -static void -cmd_pcihinv(int argc, char *argv[]) +int +strtotbdf(char *p, char **r, int base) { - int i, flags = 0; + char buf[12], *f0[4], **f; + int i, n, bus, t[4]; - for (i = 1; i < argc; i++) - if (strcmp(argv[i], "-v") == 0) - flags |= 1; - else { - print("unknown pcihinv option %s; options are: -v\n", argv[i]); - return; - } - pcihinv(nil, flags); /* print the whole device tree */ + if(strchr(p, '.') == nil) + return strtoul(p, r, base); + + snprint(buf, sizeof buf, "%s", p); + f = f0; + n = getfields(buf, f, nelem(f0), 1, "."); + memset(t, 0, sizeof t); + t[0] = BusPCI; + if((bus = strtobus(f[0])) != BUSUNKNOWN){ + t[0] = bus; + f++; + n--; + } + for(i = 0; i < n; i++) + t[i+1] = strtoul(f[i], r, base); + if(r != nil) + *r = *r-buf + p; + return MKBUS(t[0], t[1], t[2], t[3]); } static u32int @@ -80,6 +108,21 @@ return v+1; } +u32int +pcibarsize(Pcidev *p, int rno) +{ + u32int v, size; + + v = pcicfgr32(p, rno); + pcicfgw32(p, rno, 0xFFFFFFF0); + size = pcicfgr32(p, rno); + if(v & 1) + size |= 0xFFFF0000; + pcicfgw32(p, rno, v); + + return -(size & ~0x0F); +} + static int pcilscan(int bno, Pcidev** list) { @@ -300,13 +343,15 @@ e = buf+sizeof buf; tbdf = va_arg(fmt->args, int); if(tbdf == -1) - return fmtstrcpy(fmt, "unk"); - type = BUSTYPE(tbdf); - if(type == 12) - p = seprint(p, e, "pci"); - else - p = seprint(p, e, "%d", type); - seprint(p, e, ".%d.%d.%d", + return fmtstrcpy(fmt, "isa"); + if(fmt->flags & FmtLong){ + type = BUSTYPE(tbdf); + if(type == 12) + p = seprint(p, e, "pci."); + else + p = seprint(p, e, "%d.", type); + } + seprint(p, e, "%d.%d.%d", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); return fmtstrcpy(fmt, buf); } @@ -318,8 +363,8 @@ int size, i, fn, tbdf; Bridge *southbridge; Pcidev *sbpci, *pci; - Slot *e; Router *r; + Slot *e; /* Search for PCI interrupt routing table in BIOS */ for(p = (uchar*)KADDR(0xf0000); p < (uchar*)KADDR(0xfffff); p += 16) @@ -356,7 +401,7 @@ if(southbridge->get == nil || southbridge->set == nil) return; - size = (r->size[1] << 8)|r->size[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); @@ -396,6 +441,21 @@ } static void +cmd_pcihinv(int argc, char *argv[]) +{ + int i, flags = 0; + + for (i = 1; i < argc; i++) + if (strcmp(argv[i], "-v") == 0) + flags |= 1; + else { + print("unknown pcihinv option %s; options are: -v\n", argv[i]); + return; + } + pcihinv(nil, flags); /* print the whole device tree */ +} + +static void pcicfginit(void) { int bno, n; @@ -451,8 +511,7 @@ { int o, x, er; - if(pcicfgmode == -1) - pcicfginit(); + pcicfginit(); if(pcicfgmode != 1) return -1; if(BUSDNO(tbdf) > Maxdev) @@ -542,9 +601,7 @@ Pcidev* pcimatch(Pcidev* prev, int vid, int did) { - if(pcicfgmode == -1) - pcicfginit(); - + pcicfginit(); prev = prev? prev->list: pcilist; for(; prev != nil; prev = prev->list){ if((vid == 0 || prev->vid == vid) @@ -559,9 +616,6 @@ { Pcidev *p; - if(pcicfgmode == -1) - pcicfginit(); - for(p = nil; p = pcimatch(p, 0, 0); ) if(p->tbdf == tbdf) break; @@ -571,7 +625,7 @@ static char * ccru2name(int ccru) { - switch (ccru>>8) { + switch (ccru) { case 0x01: /* mass storage controller */ return "disks"; case 0x02: /* network controller */ @@ -716,10 +770,10 @@ { Pcidev *p; - if(pcicfgmode == -1) - pcicfginit(); - for(p = pcilist; p != nil; p = p->list) - pciclrbme(p); + for(p = nil; p = pcimatch(p, 0, 0); ) + /* don't mess with the bridges */ + if(p->ccrb != 0x06) + pciclrbme(p); } void