From 49ea1f800be1a7b9b314fa2db96378b5cfe977ff Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 3 Oct 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-10-03 --- pc/devarch.c | 26 +++++ pc/devpccard.c | 57 +++++----- pc/devusb.c | 7 +- pc/pci.c | 276 +++++++++++++++++++++++++++++++++++++++++++++++++ port/devproc.c | 2 +- 5 files changed, 337 insertions(+), 31 deletions(-) diff --git a/pc/devarch.c b/pc/devarch.c index bf228fbc094330ca8889533b31c02be00707f3f4..785983005e9ee663de979c99e12aa9b59994ff61 100644 --- a/pc/devarch.c +++ b/pc/devarch.c @@ -98,6 +98,7 @@ addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn) void ioinit(void) { + char *excluded; int i; for(i = 0; i < nelem(iomap.maps)-1; i++) @@ -109,6 +110,31 @@ ioinit(void) ioalloc(0x10000, 1, 0, "dummy"); ioalloc(0x0fff, 1, 0, "dummy"); // i82557 is at 0x1000, the dummy // entry is needed for swappable devs. + + if ((excluded = getconf("ioexclude")) != nil) { + char *s; + + s = excluded; + while (s && *s != '\0' && *s != '\n') { + char *ends; + int io_s, io_e; + + io_s = (int)strtol(s, &ends, 0); + if (ends == nil || ends == s || *ends != '-') { + print("ioinit: cannot parse option string\n"); + break; + } + s = ++ends; + + io_e = (int)strtol(s, &ends, 0); + if (ends && *ends == ',') + *ends++ = '\0'; + s = ends; + + ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated"); + } + } + } // Reserve a range to be ioalloced later. This is in particular useful for exchangable cards, such diff --git a/pc/devpccard.c b/pc/devpccard.c index 41899949a706b34f476615fa9bc6bc3920739c2f..67df8845c755f1c7b8b45735fac9191a9b0e00b3 100644 --- a/pc/devpccard.c +++ b/pc/devpccard.c @@ -45,31 +45,22 @@ static variant_t variant[] = { /* Cardbus registers */ enum { SocketEvent = 0, + SE_CCD = 3 << 1, + SE_POWER = 1 << 3, SocketMask = 1, SocketState = 2, + SS_CCD = 3 << 1, + SS_POWER = 1 << 3, + SS_PC16 = 1 << 4, + SS_CBC = 1 << 5, + SS_NOTCARD = 1 << 7, + SS_BADVCC = 1 << 9, + SS_5V = 1 << 10, + SS_3V = 1 << 11, SocketForce = 3, SocketControl = 4, -}; - -enum { - SS_CCD = 3 << 1, - SS_POWER = 1 << 3, - SS_PC16 = 1 << 4, - SS_CBC = 1 << 5, - SS_NOTCARD = 1 << 7, - SS_BADVCC = 1 << 9, - SS_5V = 1 << 10, - SS_3V = 1 << 11, -}; - -enum { - SC_5V = 0x22, - SC_3V = 0x33, -}; - -enum { - SE_CCD = SS_CCD, - SE_POWER = SS_POWER, + SC_5V = 0x22, + SC_3V = 0x33, }; enum { @@ -523,9 +514,14 @@ devpccardlink(void) cb->cb_pci = pci; cb->cb_variant = &variant[i]; - if (intl != -1 && intl != pci->intl) - intrenable(pci->intl, interrupt, cb, pci->tbdf, "cardbus"); - intl = pci->intl; + pcicfgw32(pci, PciCBMBR0, 0xffffffff); + pcicfgw32(pci, PciCBMLR0, 0); + pcicfgw32(pci, PciCBMBR1, 0xffffffff); + pcicfgw32(pci, PciCBMLR1, 0); + pcicfgw32(pci, PciCBIBR0, 0xffffffff); + pcicfgw32(pci, PciCBILR0, 0); + pcicfgw32(pci, PciCBIBR1, 0xffffffff); + pcicfgw32(pci, PciCBILR1, 0); // Set up PCI bus numbers if needed. if (pcicfgr8(pci, PciSBN) == 0) { @@ -545,7 +541,10 @@ devpccardlink(void) if (pci->intl == 0xff || pci->intl == 0) print("#Y%d: No interrupt?\n", (int)(cb - cbslots)); } - + if (intl != -1 && intl != pci->intl) + intrenable(pci->intl, interrupt, cb, pci->tbdf, "cardbus"); + intl = pci->intl; + if ((baddr = pcicfgr32(cb->cb_pci, PciBAR0)) == 0) { int align = (pci->did == Ricoh_478_did)? 0x10000: 0x1000; @@ -696,6 +695,9 @@ configure(cb_t *cb) ulong size, bar; int memindex, ioindex; + pcicfgw16(pci, PciPCR, + pcicfgr16(pci, PciPCR) & ~(PciPCR_IO|PciPCR_MEM)); + /* Treat the found device as an ordinary PCI card. It seems that the CIS is not always present in CardBus cards. XXX, need to support multifunction cards */ @@ -711,12 +713,15 @@ configure(cb_t *cb) continue; } bar = ioreserve(-1, pci->mem[i].size, 0, "cardbus"); + pci->mem[i].bar = bar | 1; pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar); pcicfgw16(cb->cb_pci, PciCBIBR0 + ioindex * 8, bar); pcicfgw16(cb->cb_pci, PciCBILR0 + ioindex * 8, bar + pci->mem[i].size - 1); + //print("ioindex[%d] %.8uX (%d)\n", + // ioindex, bar, pci->mem[i].size); ioindex++; continue; } @@ -740,6 +745,8 @@ configure(cb_t *cb) pcicfgr16(cb->cb_pci, PciBCR) | (1 << (8 + memindex))); + //print("memindex[%d] %.8uX (%d)\n", + // memindex, bar, pci->mem[i].size); memindex++; } diff --git a/pc/devusb.c b/pc/devusb.c index 1173bffe355fdbcaa2a4d215b75b27c5ea9f8fcf..89392d18ae35ba3e33ec386b7b26b308827e98ff 100644 --- a/pc/devusb.c +++ b/pc/devusb.c @@ -692,7 +692,7 @@ isoxmit(Endpt *e, Block *b, int pid) td = e->etd; if (td == nil) panic("usb: isoxmit"); - while(td->status & Active){ + while(td->status & Active && (td->dev & 0x7ff<21) != (0x7ff<21)){ XPRINT("isoxmit: sleep %lux\n", &e->wr); sleep(&e->wr, tdisready, e->etd); XPRINT("isoxmit: awake\n"); @@ -707,10 +707,7 @@ isoxmit(Endpt *e, Block *b, int pid) n = BLEN(b); id = (e->x<<7)|(e->dev->x&0x7F); td->dev = ((n-1)<<21) | ((id&0x7FF)<<8) | pid; - if ((ioc++ & 0xff) == 0) - td->status = ErrLimit3 | Active | IsoSelect | IOC; - else - td->status = ErrLimit3 | Active | IsoSelect; + td->status = ErrLimit1 | Active | IsoSelect | IOC; e->etd = td->next; return ob; } diff --git a/pc/pci.c b/pc/pci.c index 660ff0e377a8a6f6455a9c8208cf67700b63d95a..ad4edd44fd9ed959248f744a270b79f64ae47503 100644 --- a/pc/pci.c +++ b/pc/pci.c @@ -507,6 +507,279 @@ pciscan(int bno, Pcidev **list) return ubn; } +static uchar +pIIx_link(Pcidev *router, uchar link) +{ + uchar pirq; + + /* link should be 0x60, 0x61, 0x62, 0x63 */ + pirq = pcicfgr8(router, link); + return (pirq < 16)? pirq: 0; +} + +static void +pIIx_init(Pcidev *router, uchar link, uchar irq) +{ + pcicfgw8(router, link, irq); +} + +static uchar +via_link(Pcidev *router, uchar link) +{ + uchar pirq; + + /* link should be 1, 2, 3, 5 */ + pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0; + + return (link & 1)? (pirq >> 4): (pirq & 15); +} + +static void +via_init(Pcidev *router, uchar link, uchar irq) +{ + uchar pirq; + + pirq = pcicfgr8(router, 0x55 + (link >> 1)); + pirq &= (link & 1)? 0x0f: 0xf0; + pirq |= (link & 1)? (irq << 4): (irq & 15); + pcicfgw8(router, 0x55 + (link>>1), pirq); +} + +static uchar +opti_link(Pcidev *router, uchar link) +{ + uchar pirq = 0; + + /* link should be 0x02, 0x12, 0x22, 0x32 */ + if ((link & 0xcf) == 0x02) + pirq = pcicfgr8(router, 0xb8 + (link >> 5)); + return (link & 0x10)? (pirq >> 4): (pirq & 15); +} + +static void +opti_init(Pcidev *router, uchar link, uchar irq) +{ + uchar pirq; + + pirq = pcicfgr8(router, 0xb8 + (link >> 5)); + pirq &= (link & 0x10)? 0x0f : 0xf0; + pirq |= (link & 0x10)? (irq << 4): (irq & 15); + pcicfgw8(router, 0xb8 + (link >> 5), pirq); +} + +static uchar +ali_link(Pcidev *router, uchar link) +{ + /* No, you're not dreaming */ + static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; + uchar pirq; + + /* link should be 0x01..0x08 */ + pirq = pcicfgr8(router, 0x48 + ((link-1)>>1)); + return (link & 1)? map[pirq&15]: map[pirq>>4]; +} + +static void +ali_init(Pcidev *router, uchar link, uchar irq) +{ + /* Inverse of map in ali_link */ + static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 }; + uchar pirq; + + pirq = pcicfgr8(router, 0x48 + ((link-1)>>1)); + pirq &= (link & 1)? 0x0f: 0xf0; + pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15); + pcicfgw8(router, 0x48 + ((link-1)>>1), pirq); +} + +static uchar +cyrix_link(Pcidev *router, uchar link) +{ + uchar pirq; + + /* link should be 1, 2, 3, 4 */ + pirq = pcicfgr8(router, 0x5c + ((link-1)>>1)); + return ((link & 1)? pirq >> 4: pirq & 15); +} + +static void +cyrix_init(Pcidev *router, uchar link, uchar irq) +{ + uchar pirq; + + pirq = pcicfgr8(router, 0x5c + (link>>1)); + pirq &= (link & 1)? 0x0f: 0xf0; + pirq |= (link & 1)? (irq << 4): (irq & 15); + pcicfgw8(router, 0x5c + (link>>1), pirq); +} + +enum { + Intel = 0x8086, + Intel_82371FB_0 = 0x122e, + Intel_82371SB_0 = 0x7000, + Intel_82371AB_0 = 0x7110, + Intel_82443MX_1 = 0x7198, + Intel_82801AA_0 = 0x2410, + Intel_82801AB_0 = 0x2420, + Intel_82801BA_0 = 0x2440, + Intel_82801BAM_0 = 0x244c, + Viatech = 0x1106, + Via_82C586_0 = 0x0586, + Via_82C596 = 0x0596, + Via_82C686 = 0x0686, + Opti = 0x1045, + Opti_82C700 = 0xc700, + Al = 0x10b9, + Al_M1533 = 0x1533, + SI = 0x1039, + SI_503 = 0x0008, + SI_496 = 0x0496, + Cyrix = 0x1078, + Cyrix_5530_Legacy = 0x0100, +}; + +typedef struct { + ushort sb_vid, sb_did; + uchar (*sb_translate)(Pcidev *, uchar); + void (*sb_initialize)(Pcidev *, uchar, uchar); +} bridge_t; + +static bridge_t southbridges[] = { +{ Intel, Intel_82371FB_0, pIIx_link, pIIx_init }, +{ Intel, Intel_82371SB_0, pIIx_link, pIIx_init }, +{ Intel, Intel_82371AB_0, pIIx_link, pIIx_init }, +{ Intel, Intel_82443MX_1, pIIx_link, pIIx_init }, +{ Intel, Intel_82801AA_0, pIIx_link, pIIx_init }, +{ Intel, Intel_82801AB_0, pIIx_link, pIIx_init }, +{ Intel, Intel_82801BA_0, pIIx_link, pIIx_init }, +{ Intel, Intel_82801BAM_0, pIIx_link, pIIx_init }, +{ Viatech, Via_82C586_0, via_link, via_init }, +{ Viatech, Via_82C596, via_link, via_init }, +{ Viatech, Via_82C686, via_link, via_init }, +{ Opti, Opti_82C700, opti_link, opti_init }, +{ Al, Al_M1533, ali_link, ali_init }, +{ SI, SI_503, pIIx_link, pIIx_init }, +{ SI, SI_496, pIIx_link, pIIx_init }, +{ Cyrix, Cyrix_5530_Legacy, cyrix_link, cyrix_init } +}; + +typedef struct { + uchar e_bus; // Pci bus number + uchar e_dev; // Pci device number + uchar e_maps[12]; // Avoid structs! Link and mask. + uchar e_slot; // Add-in/built-in slot + uchar e_reserved; +} slot_t; + +typedef struct { + uchar rt_signature[4]; // Routing table signature + uchar rt_version[2]; // Version number + uchar rt_size[2]; // Total table size + uchar rt_bus; // Interrupt router bus number + uchar rt_devfn; // Router's devfunc + uchar rt_pciirqs[2]; // Exclusive PCI irqs + uchar rt_compat[4]; // Compatible PCI interrupt router + uchar rt_miniport[4]; // Miniport data + uchar rt_reserved[11]; + uchar rt_checksum; +} router_t; + +static ushort pciirqs; // Exclusive PCI irqs +static bridge_t *southbridge; // Which southbridge to use. + +static void +pcirouting(void) +{ + uchar *p, pin, irq; + ulong tbdf, vdid; + ushort vid, did; + router_t *r; + slot_t *e; + int size, i, fn; + Pcidev *sbpci, *pci; + + // Peek in the BIOS + for (p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16) + if (p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R') + break; + + if (p >= (uchar *)KADDR(0xfffff)) + return; + + r = (router_t *)p; + + // print("PCI interrupt routing table version %d.%d at %.6uX\n", + // r->rt_version[0], r->rt_version[1], (ulong)r & 0xfffff); + + tbdf = (BusPCI << 24)|(r->rt_bus << 16)|(r->rt_devfn << 8); + vdid = pcicfgrw32(tbdf, PciVID, 0, 1); + vid = vdid; + did = vdid >> 16; + + for (i = 0; i != nelem(southbridges); i++) + if (vid == southbridges[i].sb_vid && did == southbridges[i].sb_did) + break; + + if (i == nelem(southbridges)) { + print("pcirouting: South bridge %.4uX, %.4uX not found\n", vid, did); + return; + } + southbridge = &southbridges[i]; + + if ((sbpci = pcimatch(nil, vid, did)) == nil) { + print("pcirouting: Cannot match south bridge %.4uX, %.4uX\n", + vid, did); + return; + } + + pciirqs = (r->rt_pciirqs[1] << 8)|r->rt_pciirqs[0]; + + size = (r->rt_size[1] << 8)|r->rt_size[0]; + for (e = (slot_t *)&r[1]; (uchar *)e < p + size; e++) { + // print("%.2uX/%.2uX %.2uX: ", e->e_bus, e->e_dev, e->e_slot); + // for (i = 0; i != 4; i++) { + // uchar *m = &e->e_maps[i * 3]; + // print("[%d] %.2uX %.4uX ", + // i, m[0], (m[2] << 8)|m[1]); + // } + // print("\n"); + + for (fn = 0; fn != 8; fn++) { + uchar *m; + + // Retrieve the did and vid through the devfn before + // obtaining the Pcidev structure. + tbdf = (BusPCI << 24)|(e->e_bus << 16)|((e->e_dev | fn) << 8); + vdid = pcicfgrw32(tbdf, PciVID, 0, 1); + if (vdid == 0xFFFFFFFF || vdid == 0) + continue; + + vid = vdid; + did = vdid >> 16; + + pci = nil; + while ((pci = pcimatch(pci, vid, did)) != nil) { + + if (pci->intl != 0 && pci->intl != 0xFF) + continue; + + pin = pcicfgr8(pci, PciINTP); + if (pin == 0 || pin == 0xff) + continue; + + m = &e->e_maps[(pin - 1) * 3]; + irq = southbridge->sb_translate(sbpci, m[0]); + if (irq) { + print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n", + vid, did, pin, irq); + pcicfgw8(pci, PciINTL, irq); + pci->intl = irq; + } + } + } + } +} + static void pcicfginit(void) { @@ -610,6 +883,9 @@ pcicfginit(void) qunlock(&pcicfginitlock); return; } + + pcirouting(); + out: qunlock(&pcicfginitlock); } diff --git a/port/devproc.c b/port/devproc.c index 602211878b43c879217118291baf2b47944e1062..f24ab2469b2cb222d6ca056c519058a75be7ee5f 100644 --- a/port/devproc.c +++ b/port/devproc.c @@ -943,7 +943,7 @@ procstopwait(Proc *p, int ctl) if(p->pdbg) error(Einuse); - if(procstopped(p)) + if(procstopped(p) || p->state == Broken) return; if(ctl != 0)