From 005c4a8c265d4856271d391d48985c822480f6ed Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 17 May 1995 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1995-05-17 --- pc/dat.h | 1 + pc/ether509.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++---- pc/fns.h | 3 ++- pc/io.h | 37 +++++++++++++++++++++++++++++++++++ pc/pci.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 141 insertions(+), 5 deletions(-) create mode 100644 pc/pci.c diff --git a/pc/dat.h b/pc/dat.h index 2abfabf0bf920176b5b091ffed936e77b239160c..1c0db2a276b55bf9fee2688f6973bba3d9da15f0 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -7,6 +7,7 @@ typedef struct MMU MMU; typedef struct Mach Mach; typedef struct Notsave Notsave; typedef struct PCArch PCArch; +typedef struct PCIcfg PCIcfg; typedef struct PCMmap PCMmap; typedef struct Page Page; typedef struct PMMU PMMU; diff --git a/pc/ether509.c b/pc/ether509.c index d4ad7552a27ae6adebf4df92a57fe54a7f66f203..39ee2d440fd2f3ce9475bd02642e56b970a21740 100644 --- a/pc/ether509.c +++ b/pc/ether509.c @@ -369,8 +369,9 @@ interrupt(Ureg *ur, void *arg) typedef struct Adapter Adapter; struct Adapter { - Adapter *next; - ulong port; + Adapter* next; + ulong port; + PCIcfg* pcicfg; }; static Adapter *adapter; @@ -562,6 +563,37 @@ tcm579(Ether *ether) return 0; } +static PCIcfg* +tcm590(Ether *ether) +{ + PCIcfg* pcicfg; + static uchar devno = 0; + ulong port; + Adapter *ap; + + pcicfg = malloc(sizeof(PCIcfg)); + while(devno < 16){ + pcicfg->vid = 0x10B7; + pcicfg->did = 0; + if(pcimatch(0, devno++, pcicfg) == 0) + continue; + + port = pcicfg->baseaddr[0] & ~0x01; + if(ether->port == 0 || ether->port == port) + return pcicfg; + + ap = malloc(sizeof(Adapter)); + ap->pcicfg = pcicfg; + pcicfg = malloc(sizeof(PCIcfg)); + ap->port = port; + ap->next = adapter; + adapter = ap; + } + free(pcicfg); + + return 0; +} + /* * Get configuration parameters. */ @@ -573,6 +605,7 @@ ether509reset(Ether *ether) ushort x, acr; ulong port; Adapter *ap, **app; + PCIcfg *pcicfg; /* * Any adapter matches if no ether->port is supplied, @@ -583,9 +616,11 @@ ether509reset(Ether *ether) * and finally for a PCMCIA card. */ port = 0; + pcicfg = 0; for(app = &adapter, ap = *app; ap; app = &ap->next, ap = ap->next){ if(ether->port == 0 || ether->port == ap->port){ port = ap->port; + pcicfg = ap->pcicfg; *app = ap->next; free(ap); break; @@ -593,6 +628,8 @@ ether509reset(Ether *ether) } if(strcmp(ether->type, "3C589") == 0) port = ether->port; + if(port == 0 && (pcicfg = tcm590(ether))) + port = pcicfg->baseaddr[0] & ~0x01; if(port == 0) port = tcm579(ether); if(port == 0) @@ -606,7 +643,7 @@ ether509reset(Ether *ether) * The EEPROM command is 8 bits, the lower 6 bits being * the address offset. */ - if(strcmp(ether->type, "3C589") != 0) + if(strcmp(ether->type, "3C589") != 0 && pcicfg == 0) ether->irq = (ins(port+ResourceConfig)>>12) & 0x0F; for(eax = 0, i = 0; i < 3; i++, eax += 2){ while(ins(port+EEPROMcmd) & 0x8000) @@ -618,7 +655,15 @@ ether509reset(Ether *ether) ea[eax] = (x>>8) & 0xFF; ea[eax+1] = x & 0xFF; } - acr = ins(port+AddressConfig); + if(pcicfg == 0) + acr = ins(port+AddressConfig); + else{ + ether->irq = pcicfg->irq; + acr = Xcvr10BaseT; + COMMAND(port, SelectWindow, 3); + print("internal config = 0x%8.8luX\n", inl(port+0x00)); + free(pcicfg); + } /* * Finished with window 0. Now set the ethernet address diff --git a/pc/fns.h b/pc/fns.h index 0979ae82b0b18375b388ee7d70bb4e05b82909f8..03c4578abc7e651d42d2618d3dd706bbacf4575a 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -62,7 +62,8 @@ void outs(int, ushort); void outss(int, void*, int); void outl(int, ulong); void outsl(int, void*, int); -void pcicreset(void); +void pcicfgr(uchar, uchar, uchar, uchar, void*, int); +int pcimatch(uchar, uchar, PCIcfg*); PCMmap* pcmmap(int, ulong, int, int); int pcmspecial(char*, ISAConf*); void pcmspecialclose(int); diff --git a/pc/io.h b/pc/io.h index c1c554e7901770460eb5b260c66325e46432a02b..6d9a3ba10d56c4c26ba2b652e935b27f54690a18 100644 --- a/pc/io.h +++ b/pc/io.h @@ -33,3 +33,40 @@ enum { MaxEISA = 16, EISAconfig = 0xC80, }; + +/* + * PCI Local Bus support. + * Quick hack until we figure out how to + * deal with EISA, PCI, PCMCIA, PnP, etc. + */ +enum { /* configuration mechanism #1 */ + PCIaddr = 0xCF8, /* CONFIG_ADDRESS */ + PCIdata = 0xCFC, /* CONFIG_DATA */ + + /* configuration mechanism #2 */ + PCIcse = 0xCF8, /* configuration space enable */ + PCIforward = 0xCFA, /* which bus */ +}; + +typedef struct PCIcfg { + ushort vid; /* vendor ID */ + ushort did; /* device ID */ + ushort command; + ushort status; + uchar rid; /* revision ID */ + uchar loclass; /* specific register-level programming interface */ + uchar subclass; + uchar baseclass; + uchar clsize; /* cache line size */ + uchar latency; /* latency timer */ + uchar header; /* header type */ + uchar bist; /* built-in self-test */ + ulong baseaddr[6]; /* memory or I/O base address registers */ + ulong reserved28[2]; + ulong romaddr; /* expansion ROM base address */ + ulong reserved34[2]; + uchar irq; /* interrupt line */ + uchar irp; /* interrupt pin */ + uchar mingnt; /* burst period length */ + uchar maxlat; /* maximum latency between bursts */ +} PCIcfg; diff --git a/pc/pci.c b/pc/pci.c new file mode 100644 index 0000000000000000000000000000000000000000..8af745130d1441493bdbee7d34c403f822d74f5f --- /dev/null +++ b/pc/pci.c @@ -0,0 +1,52 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +static Lock pcicfglock; + +/* + * Read a chunk of PCI configuration space. + * Assumes arguments are within limits and regno and + * nbytes are DWORD aligned. + */ +void +pcicfgr(uchar busno, uchar devno, uchar funcno, uchar regno, void* data, int nbytes) +{ + ulong base, *p; + int len; + + lock(&pcicfglock); + outb(PCIcse, 0x80|((funcno & 0x07)<<1)); + outb(PCIforward, busno); + + base = (0xC000|(devno<<8)) + regno; + p = data; + for(len = nbytes/sizeof(ulong); len > 0; len--){ + *p = inl(base); + p++; + base += sizeof(ulong); + } + + outb(PCIcse, 0x00); + unlock(&pcicfglock); +} + +int +pcimatch(uchar busno, uchar devno, PCIcfg* pcicfg) +{ + ulong l; + + l = 0; + pcicfgr(busno, devno, 0, 0, &l, sizeof(ulong)); + if((l & 0xFFFF) != pcicfg->vid) + return 0; + if(pcicfg->did && ((l>>16) & 0xFFFF) != pcicfg->did) + return 0; + pcicfgr(busno, devno, 0, 0, pcicfg, sizeof(PCIcfg)); + + return 1; +}