From 4f85115526a87063489dc7cf347343bd520159b1 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 13 Sep 2020 20:33:17 +0200 Subject: [PATCH] kernel: massive pci code rewrite The new pci code is moved to port/pci.[hc] and shared by all ports. Each port has its own PCI controller implementation, providing the pcicfgrw*() functions for low level pci config space access. The locking for pcicfgrw*() is now done by the caller (only port/pci.c). Device drivers now need to include "../port/pci.h" in addition to "io.h". The new code now checks bridge windows and membars, while enumerating the bus, giving the pc driver a chance to re-assign them. This is needed because some UEFI implementations fail to assign the bars for some devices, so we need to do it outselfs. (See pcireservemem()). While working on this, it was discovered that the pci code assimed the smallest I/O bar size is 16 (pcibarsize()), which is wrong. I/O bars can be as small as 4 bytes. Bit 1 in an I/O bar is also reserved and should be masked off, making the port mask: port = bar & ~3; --- sys/src/9/bcm64/archbcm4.c | 1 + sys/src/9/bcm64/fns.h | 27 +- sys/src/9/bcm64/gic.c | 1 + sys/src/9/bcm64/io.h | 228 ----- sys/src/9/bcm64/mkfile | 1 + sys/src/9/bcm64/pcibcm.c | 310 ++++++ sys/src/9/bcm64/pi4 | 4 +- sys/src/9/kw/fns.h | 25 - sys/src/9/kw/io.h | 162 --- sys/src/9/mtx/ether2114x.c | 1 + sys/src/9/mtx/fns.h | 18 +- sys/src/9/mtx/io.h | 142 +-- sys/src/9/mtx/mkfile | 2 +- sys/src/9/mtx/mtx | 2 + sys/src/9/mtx/mtxcpu | 44 - sys/src/9/mtx/pci.c | 908 ----------------- sys/src/9/mtx/pcimtx.c | 224 +++++ sys/src/9/pc/archacpi.c | 1 + sys/src/9/pc/archmp.c | 1 + sys/src/9/pc/audioac97.c | 1 + sys/src/9/pc/audiohda.c | 1 + sys/src/9/pc/cputemp.c | 1 + sys/src/9/pc/devarch.c | 1 - sys/src/9/pc/devlm78.c | 1 + sys/src/9/pc/devlml.c | 1 + sys/src/9/pc/devpccard.c | 3 +- sys/src/9/pc/devtv.c | 5 +- sys/src/9/pc/devvga.c | 1 + sys/src/9/pc/ether2000.c | 3 +- sys/src/9/pc/ether2114x.c | 3 +- sys/src/9/pc/ether79c970.c | 5 +- sys/src/9/pc/ether8139.c | 3 +- sys/src/9/pc/ether8169.c | 3 +- sys/src/9/pc/ether82543gc.c | 4 +- sys/src/9/pc/ether82557.c | 3 +- sys/src/9/pc/ether82563.c | 1 + sys/src/9/pc/ether82598.c | 1 + sys/src/9/pc/ether83815.c | 3 +- sys/src/9/pc/etherbcm.c | 1 + sys/src/9/pc/etherdp83820.c | 1 + sys/src/9/pc/etherelnk3.c | 3 +- sys/src/9/pc/etherga620.c | 10 +- sys/src/9/pc/etherigbe.c | 7 +- sys/src/9/pc/etheriwl.c | 1 + sys/src/9/pc/etherm10g.c | 1 + sys/src/9/pc/etherrt2860.c | 1 + sys/src/9/pc/ethervgbe.c | 3 +- sys/src/9/pc/ethervirtio.c | 7 +- sys/src/9/pc/ethervt6102.c | 9 +- sys/src/9/pc/ethervt6105m.c | 9 +- sys/src/9/pc/etherwavelan.c | 1 + sys/src/9/pc/etherwpi.c | 1 + sys/src/9/pc/etherx550.c | 1 + sys/src/9/pc/etheryuk.c | 1 + sys/src/9/pc/fns.h | 31 +- sys/src/9/pc/io.h | 219 +--- sys/src/9/pc/main.c | 2 +- sys/src/9/pc/memory.c | 18 + sys/src/9/pc/mp.c | 1 + sys/src/9/pc/pc | 22 +- sys/src/9/pc/pci.c | 1647 ------------------------------- sys/src/9/pc/pcipc.c | 739 ++++++++++++++ sys/src/9/pc/piix4smbus.c | 1 + sys/src/9/pc/pmmc.c | 1 + sys/src/9/pc/screen.c | 1 + sys/src/9/pc/sd53c8xx.c | 1 + sys/src/9/pc/sdiahci.c | 1 + sys/src/9/pc/sdide.c | 9 +- sys/src/9/pc/sdmv50xx.c | 1 + sys/src/9/pc/sdmylex.c | 3 +- sys/src/9/pc/sdnvme.c | 1 + sys/src/9/pc/sdodin.c | 1 + sys/src/9/pc/sdvirtio.c | 5 +- sys/src/9/pc/uartaxp.c | 1 + sys/src/9/pc/uartpci.c | 17 +- sys/src/9/pc/usbehcipc.c | 1 + sys/src/9/pc/usbohci.c | 1 + sys/src/9/pc/usbuhci.c | 3 +- sys/src/9/pc/vga3dfx.c | 1 + sys/src/9/pc/vgaclgd546x.c | 1 + sys/src/9/pc/vgacyber938x.c | 1 + sys/src/9/pc/vgageode.c | 1 + sys/src/9/pc/vgahiqvideo.c | 1 + sys/src/9/pc/vgai81x.c | 1 + sys/src/9/pc/vgaigfx.c | 1 + sys/src/9/pc/vgamach64xx.c | 1 + sys/src/9/pc/vgamga2164w.c | 1 + sys/src/9/pc/vgamga4xx.c | 1 + sys/src/9/pc/vganeomagic.c | 1 + sys/src/9/pc/vganvidia.c | 1 + sys/src/9/pc/vgaradeon.c | 1 + sys/src/9/pc/vgas3.c | 1 + sys/src/9/pc/vgat2r4.c | 1 + sys/src/9/pc/vgavesa.c | 1 + sys/src/9/pc/vgavmware.c | 1 + sys/src/9/pc64/fns.h | 31 +- sys/src/9/pc64/main.c | 2 +- sys/src/9/pc64/pc64 | 17 +- sys/src/9/port/devpnp.c | 1 + sys/src/9/{bcm64 => port}/pci.c | 847 +++++++--------- sys/src/9/port/pci.h | 292 ++++++ sys/src/9/port/portmkfile | 3 +- sys/src/9/port/usbxhci.c | 1 + sys/src/9/ppc/fns.h | 6 - sys/src/9/teg2/ether8169.c | 12 +- sys/src/9/teg2/fns.h | 24 +- sys/src/9/teg2/io.h | 215 ---- sys/src/9/teg2/main.c | 1 + sys/src/9/teg2/pci.c | 853 ---------------- sys/src/9/teg2/pciteg.c | 268 +++++ sys/src/9/teg2/ts | 5 +- 111 files changed, 2400 insertions(+), 5125 deletions(-) create mode 100644 sys/src/9/bcm64/pcibcm.c delete mode 100644 sys/src/9/mtx/mtxcpu delete mode 100644 sys/src/9/mtx/pci.c create mode 100644 sys/src/9/mtx/pcimtx.c delete mode 100644 sys/src/9/pc/pci.c create mode 100644 sys/src/9/pc/pcipc.c rename sys/src/9/{bcm64 => port}/pci.c (55%) create mode 100644 sys/src/9/port/pci.h delete mode 100644 sys/src/9/teg2/pci.c create mode 100644 sys/src/9/teg2/pciteg.c diff --git a/sys/src/9/bcm64/archbcm4.c b/sys/src/9/bcm64/archbcm4.c index d47ba96e1..3fefe9b9d 100644 --- a/sys/src/9/bcm64/archbcm4.c +++ b/sys/src/9/bcm64/archbcm4.c @@ -9,6 +9,7 @@ #include "fns.h" #include "../port/error.h" #include "io.h" +#include "../port/pci.h" #include "sysreg.h" typedef struct Mbox Mbox; diff --git a/sys/src/9/bcm64/fns.h b/sys/src/9/bcm64/fns.h index f42c2736c..7ace1ce9a 100644 --- a/sys/src/9/bcm64/fns.h +++ b/sys/src/9/bcm64/fns.h @@ -183,28 +183,9 @@ extern void screeninit(void); extern int isaconfig(char*, int, ISAConf*); -/* pci */ -typedef struct Pcidev Pcidev; -extern int pcicfgr32(Pcidev* pcidev, int rno); -extern void pcicfgw32(Pcidev* pcidev, int rno, int data); -extern int pcicfgr16(Pcidev* pcidev, int rno); -extern void pcicfgw16(Pcidev* pcidev, int rno, int data); -extern int pcicfgr8(Pcidev* pcidev, int rno); -extern void pcicfgw8(Pcidev* pcidev, int rno, int data); -extern Pcidev* pcimatch(Pcidev* prev, int vid, int did); -extern Pcidev* pcimatchtbdf(int tbdf); -extern void pcisetioe(Pcidev* p); -extern void pciclrioe(Pcidev* p); -extern void pcisetbme(Pcidev* p); -extern void pciclrbme(Pcidev* p); -extern void pcisetmwi(Pcidev* p); -extern void pciclrmwi(Pcidev* p); -extern int pcicap(Pcidev *p, int cap); -extern int pcinextcap(Pcidev *pci, int offset); -extern int pcihtcap(Pcidev *p, int cap); -extern int pcigetpms(Pcidev* p); -extern int pcisetpms(Pcidev* p, int state); -extern void pcienable(Pcidev *p); -extern void pcidisable(Pcidev *p); +/* pcibcm */ +extern int pcicfgrw8(int tbdf, int rno, int data, int read); +extern int pcicfgrw16(int tbdf, int rno, int data, int read); +extern int pcicfgrw32(int tbdf, int rno, int data, int read); extern void pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a); extern void pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a); diff --git a/sys/src/9/bcm64/gic.c b/sys/src/9/bcm64/gic.c index e6352ab5f..469a1b0e5 100644 --- a/sys/src/9/bcm64/gic.c +++ b/sys/src/9/bcm64/gic.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "ureg.h" #include "sysreg.h" #include "../port/error.h" diff --git a/sys/src/9/bcm64/io.h b/sys/src/9/bcm64/io.h index ffcbee67c..ef6fab282 100644 --- a/sys/src/9/bcm64/io.h +++ b/sys/src/9/bcm64/io.h @@ -6,233 +6,5 @@ enum { IRQether = IRQgic + 29, }; -/* - * PCI - */ -enum { - BusCBUS = 0, /* Corollary CBUS */ - BusCBUSII, /* Corollary CBUS II */ - BusEISA, /* Extended ISA */ - BusFUTURE, /* IEEE Futurebus */ - BusINTERN, /* Internal bus */ - BusISA, /* Industry Standard Architecture */ - BusMBI, /* Multibus I */ - BusMBII, /* Multibus II */ - BusMCA, /* Micro Channel Architecture */ - BusMPI, /* MPI */ - BusMPSA, /* MPSA */ - BusNUBUS, /* Apple Macintosh NuBus */ - BusPCI, /* Peripheral Component Interconnect */ - BusPCMCIA, /* PC Memory Card International Association */ - BusTC, /* DEC TurboChannel */ - BusVL, /* VESA Local bus */ - BusVME, /* VMEbus */ - BusXPRESS, /* Express System Bus */ -}; - -#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8)) -#define BUSFNO(tbdf) (((tbdf)>>8)&0x07) -#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F) -#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF) -#define BUSTYPE(tbdf) ((tbdf)>>24) -#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00) - -enum { /* type 0 & type 1 pre-defined header */ - PciVID = 0x00, /* vendor ID */ - PciDID = 0x02, /* device ID */ - PciPCR = 0x04, /* command */ - PciPSR = 0x06, /* status */ - PciRID = 0x08, /* revision ID */ - PciCCRp = 0x09, /* programming interface class code */ - PciCCRu = 0x0A, /* sub-class code */ - PciCCRb = 0x0B, /* base class code */ - PciCLS = 0x0C, /* cache line size */ - PciLTR = 0x0D, /* latency timer */ - PciHDT = 0x0E, /* header type */ - PciBST = 0x0F, /* BIST */ - - PciBAR0 = 0x10, /* base address */ - PciBAR1 = 0x14, - - PciCAP = 0x34, /* capabilities pointer */ - PciINTL = 0x3C, /* interrupt line */ - PciINTP = 0x3D, /* interrupt pin */ -}; - -/* ccrb (base class code) values; controller types */ -enum { - Pcibcpci1 = 0, /* pci 1.0; no class codes defined */ - Pcibcstore = 1, /* mass storage */ - Pcibcnet = 2, /* network */ - Pcibcdisp = 3, /* display */ - Pcibcmmedia = 4, /* multimedia */ - Pcibcmem = 5, /* memory */ - Pcibcbridge = 6, /* bridge */ - Pcibccomm = 7, /* simple comms (e.g., serial) */ - Pcibcbasesys = 8, /* base system */ - Pcibcinput = 9, /* input */ - Pcibcdock = 0xa, /* docking stations */ - Pcibcproc = 0xb, /* processors */ - Pcibcserial = 0xc, /* serial bus (e.g., USB) */ - Pcibcwireless = 0xd, /* wireless */ - Pcibcintell = 0xe, /* intelligent i/o */ - Pcibcsatcom = 0xf, /* satellite comms */ - Pcibccrypto = 0x10, /* encryption/decryption */ - Pcibcdacq = 0x11, /* data acquisition & signal proc. */ -}; - -/* ccru (sub-class code) values; common cases only */ -enum { - /* mass storage */ - Pciscscsi = 0, /* SCSI */ - Pciscide = 1, /* IDE (ATA) */ - Pciscsata = 6, /* SATA */ - - /* network */ - Pciscether = 0, /* Ethernet */ - - /* display */ - Pciscvga = 0, /* VGA */ - Pciscxga = 1, /* XGA */ - Pcisc3d = 2, /* 3D */ - - /* bridges */ - Pcischostpci = 0, /* host/pci */ - Pciscpcicpci = 1, /* pci/pci */ - - /* simple comms */ - Pciscserial = 0, /* 16450, etc. */ - Pciscmultiser = 1, /* multiport serial */ - - /* serial bus */ - Pciscusb = 3, /* USB */ -}; - -enum { /* type 0 pre-defined header */ - PciCIS = 0x28, /* cardbus CIS pointer */ - PciSVID = 0x2C, /* subsystem vendor ID */ - PciSID = 0x2E, /* subsystem ID */ - PciEBAR0 = 0x30, /* expansion ROM base address */ - PciMGNT = 0x3E, /* burst period length */ - PciMLT = 0x3F, /* maximum latency between bursts */ -}; - -enum { /* type 1 pre-defined header */ - PciPBN = 0x18, /* primary bus number */ - PciSBN = 0x19, /* secondary bus number */ - PciUBN = 0x1A, /* subordinate bus number */ - PciSLTR = 0x1B, /* secondary latency timer */ - PciIBR = 0x1C, /* I/O base */ - PciILR = 0x1D, /* I/O limit */ - PciSPSR = 0x1E, /* secondary status */ - PciMBR = 0x20, /* memory base */ - PciMLR = 0x22, /* memory limit */ - PciPMBR = 0x24, /* prefetchable memory base */ - PciPMLR = 0x26, /* prefetchable memory limit */ - PciPUBR = 0x28, /* prefetchable base upper 32 bits */ - PciPULR = 0x2C, /* prefetchable limit upper 32 bits */ - PciIUBR = 0x30, /* I/O base upper 16 bits */ - PciIULR = 0x32, /* I/O limit upper 16 bits */ - PciEBAR1 = 0x28, /* expansion ROM base address */ - PciBCR = 0x3E, /* bridge control register */ -}; - -enum { /* type 2 pre-defined header */ - PciCBExCA = 0x10, - PciCBSPSR = 0x16, - PciCBPBN = 0x18, /* primary bus number */ - PciCBSBN = 0x19, /* secondary bus number */ - PciCBUBN = 0x1A, /* subordinate bus number */ - PciCBSLTR = 0x1B, /* secondary latency timer */ - PciCBMBR0 = 0x1C, - PciCBMLR0 = 0x20, - PciCBMBR1 = 0x24, - PciCBMLR1 = 0x28, - PciCBIBR0 = 0x2C, /* I/O base */ - PciCBILR0 = 0x30, /* I/O limit */ - PciCBIBR1 = 0x34, /* I/O base */ - PciCBILR1 = 0x38, /* I/O limit */ - PciCBSVID = 0x40, /* subsystem vendor ID */ - PciCBSID = 0x42, /* subsystem ID */ - PciCBLMBAR = 0x44, /* legacy mode base address */ -}; - -enum { - /* bar bits */ - Barioaddr = 1<<0, /* vs. memory addr */ - Barwidthshift = 1, - Barwidthmask = 3, - Barwidth32 = 0, - Barwidth64 = 2, - Barprefetch = 1<<3, -}; - -enum -{ /* command register */ - IOen = (1<<0), - MEMen = (1<<1), - MASen = (1<<2), - MemWrInv = (1<<4), - PErrEn = (1<<6), - SErrEn = (1<<8), -}; - -/* capabilities */ -enum { - PciCapPMG = 0x01, /* power management */ - PciCapAGP = 0x02, - PciCapVPD = 0x03, /* vital product data */ - PciCapSID = 0x04, /* slot id */ - PciCapMSI = 0x05, - PciCapCHS = 0x06, /* compact pci hot swap */ - PciCapPCIX = 0x07, - PciCapHTC = 0x08, /* hypertransport irq conf */ - PciCapVND = 0x09, /* vendor specific information */ - PciCapPCIe = 0x10, - PciCapMSIX = 0x11, - PciCapSATA = 0x12, - PciCapHSW = 0x0c, /* hot swap */ -}; - -typedef struct Pcidev Pcidev; -struct Pcidev -{ - int tbdf; /* type+bus+device+function */ - ushort vid; /* vendor ID */ - ushort did; /* device ID */ - - ushort pcr; - - uchar rid; - uchar ccrp; - uchar ccru; - uchar ccrb; - uchar cls; - uchar ltr; - - struct { - uvlong bar; /* base address */ - int size; - } mem[6]; - - uchar intl; /* interrupt line */ - - Pcidev* list; - Pcidev* link; /* next device on this bno */ - - Pcidev* parent; /* up a bus */ - Pcidev* bridge; /* down a bus */ - - int pmrb; /* power management register block */ - - struct { - uvlong bar; - int size; - } ioa, mema; -}; - #define PCIWINDOW 0 #define PCIWADDR(va) (PADDR(va)+PCIWINDOW) - -#pragma varargck type "T" int -#pragma varargck type "T" uint diff --git a/sys/src/9/bcm64/mkfile b/sys/src/9/bcm64/mkfile index 4ba978899..2a030b59f 100644 --- a/sys/src/9/bcm64/mkfile +++ b/sys/src/9/bcm64/mkfile @@ -103,6 +103,7 @@ trap.$O main.$O: /sys/include/tos.h l.$O cache.v8.$O mmu.$O rebootcode.$O: mem.h l.$O cache.v8.$O archbcm3.$O clock.$O fpu.$O trap.$O mmu.$O rebootcode.$O: sysreg.h main.$O: rebootcode.i +pcibcm.$O: ../port/pci.h devmouse.$O mouse.$O screen.$O: screen.h usbdwc.$O: dwcotg.h ../port/usb.h diff --git a/sys/src/9/bcm64/pcibcm.c b/sys/src/9/bcm64/pcibcm.c new file mode 100644 index 000000000..c1270f51c --- /dev/null +++ b/sys/src/9/bcm64/pcibcm.c @@ -0,0 +1,310 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/pci.h" + +/* bcmstb PCIe controller registers */ +enum{ + RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 = 0x0188/4, + RC_CFG_PRIV1_ID_VAL3 = 0x043c/4, + RC_DL_MDIO_ADDR = 0x1100/4, + RC_DL_MDIO_WR_DATA = 0x1104/4, + RC_DL_MDIO_RD_DATA = 0x1108/4, + MISC_MISC_CTRL = 0x4008/4, + MISC_CPU_2_PCIE_MEM_WIN0_LO = 0x400c/4, + MISC_CPU_2_PCIE_MEM_WIN0_HI = 0x4010/4, + MISC_RC_BAR1_CONFIG_LO = 0x402c/4, + MISC_RC_BAR2_CONFIG_LO = 0x4034/4, + MISC_RC_BAR2_CONFIG_HI = 0x4038/4, + MISC_RC_BAR3_CONFIG_LO = 0x403c/4, + MISC_MSI_BAR_CONFIG_LO = 0x4044/4, + MISC_MSI_BAR_CONFIG_HI = 0x4048/4, + MISC_MSI_DATA_CONFIG = 0x404c/4, + MISC_EOI_CTRL = 0x4060/4, + MISC_PCIE_CTRL = 0x4064/4, + MISC_PCIE_STATUS = 0x4068/4, + MISC_REVISION = 0x406c/4, + MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT = 0x4070/4, + MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI = 0x4080/4, + MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI = 0x4084/4, + MISC_HARD_PCIE_HARD_DEBUG = 0x4204/4, + + INTR2_CPU_BASE = 0x4300/4, + MSI_INTR2_BASE = 0x4500/4, + INTR_STATUS = 0, + INTR_SET, + INTR_CLR, + INTR_MASK_STATUS, + INTR_MASK_SET, + INTR_MASK_CLR, + + EXT_CFG_INDEX = 0x9000/4, + RGR1_SW_INIT_1 = 0x9210/4, + EXT_CFG_DATA = 0x8000/4, + +}; + +#define MSI_TARGET_ADDR 0xFFFFFFFFCULL + +static u32int *regs = (u32int*)(VIRTIO1 + 0x500000); +static Pcidev* pciroot; + +static void* +cfgaddr(int tbdf, int rno) +{ + if(BUSBNO(tbdf) == 0 && BUSDNO(tbdf) == 0) + return (uchar*)regs + rno; + regs[EXT_CFG_INDEX] = BUSBNO(tbdf) << 20 | BUSDNO(tbdf) << 15 | BUSFNO(tbdf) << 12; + coherence(); + return ((uchar*)®s[EXT_CFG_DATA]) + rno; +} + +int +pcicfgrw32(int tbdf, int rno, int data, int read) +{ + u32int *p; + + if((p = cfgaddr(tbdf, rno & ~3)) != nil){ + if(read) + data = *p; + else + *p = data; + } else { + data = -1; + } + return data; +} + +int +pcicfgrw16(int tbdf, int rno, int data, int read) +{ + u16int *p; + + if((p = cfgaddr(tbdf, rno & ~1)) != nil){ + if(read) + data = *p; + else + *p = data; + } else { + data = -1; + } + return data; +} + +int +pcicfgrw8(int tbdf, int rno, int data, int read) +{ + u8int *p; + + if((p = cfgaddr(tbdf, rno)) != nil){ + if(read) + data = *p; + else + *p = data; + } else { + data = -1; + } + return data; +} + +enum { + MSICtrl = 0x02, /* message control register (16 bit) */ + MSIAddr = 0x04, /* message address register (64 bit) */ + MSIData32 = 0x08, /* message data register for 32 bit MSI (16 bit) */ + MSIData64 = 0x0C, /* message data register for 64 bit MSI (16 bit) */ +}; + +typedef struct Pciisr Pciisr; +struct Pciisr { + void (*f)(Ureg*, void*); + void *a; + Pcidev *p; +}; + +static Pciisr pciisr[32]; +static Lock pciisrlk; + +void +pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a) +{ + int cap, ok64; + u32int dat; + u64int adr; + Pcidev *p; + Pciisr *isr; + + if((p = pcimatchtbdf(tbdf)) == nil){ + print("pciintrenable: %T: unknown device\n", tbdf); + return; + } + if((cap = pcicap(p, PciCapMSI)) < 0){ + print("pciintrenable: %T: no MSI cap\n", tbdf); + return; + } + + lock(&pciisrlk); + for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){ + if(isr->p == p){ + isr->p = nil; + regs[MSI_INTR2_BASE + INTR_MASK_SET] = 1 << (isr-pciisr); + break; + } + } + for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){ + if(isr->p == nil){ + isr->p = p; + isr->a = a; + isr->f = f; + regs[MSI_INTR2_BASE + INTR_CLR] = 1 << (isr-pciisr); + regs[MSI_INTR2_BASE + INTR_MASK_CLR] = 1 << (isr-pciisr); + break; + } + } + unlock(&pciisrlk); + + if(isr >= &pciisr[nelem(pciisr)]){ + print("pciintrenable: %T: out of isr slots\n", tbdf); + return; + } + + adr = MSI_TARGET_ADDR; + ok64 = (pcicfgr16(p, cap + MSICtrl) & (1<<7)) != 0; + pcicfgw32(p, cap + MSIAddr, adr); + if(ok64) pcicfgw32(p, cap + MSIAddr + 4, adr>>32); + dat = regs[MISC_MSI_DATA_CONFIG]; + dat = ((dat >> 16) & (dat & 0xFFFF)) | (isr-pciisr); + pcicfgw16(p, cap + (ok64 ? MSIData64 : MSIData32), dat); + pcicfgw16(p, cap + MSICtrl, 1); +} + +void +pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a) +{ + Pciisr *isr; + + lock(&pciisrlk); + for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){ + if(isr->p != nil && isr->p->tbdf == tbdf && isr->f == f && isr->a == a){ + regs[MSI_INTR2_BASE + INTR_MASK_SET] = 1 << (isr-pciisr); + isr->p = nil; + isr->f = nil; + isr->a = nil; + break; + } + } + unlock(&pciisrlk); +} + +static void +pciinterrupt(Ureg *ureg, void*) +{ + Pciisr *isr; + u32int sts; + + sts = regs[MSI_INTR2_BASE + INTR_STATUS]; + if(sts == 0) + return; + regs[MSI_INTR2_BASE + INTR_CLR] = sts; + for(isr = pciisr; sts != 0 && isr < &pciisr[nelem(pciisr)]; isr++, sts>>=1){ + if((sts & 1) != 0 && isr->f != nil) + (*isr->f)(ureg, isr->a); + } + regs[MISC_EOI_CTRL] = 1; +} + +static void +pcicfginit(void) +{ + uvlong base, limit; + ulong ioa; + + fmtinstall('T', tbdffmt); + + pciscan(0, &pciroot); + if(pciroot == nil) + return; + + /* + * Work out how big the top bus is + */ + ioa = 0; + base = soc.pciwin; + pcibusmap(pciroot, &base, &ioa, 0); + limit = base-1; + + /* + * Align the windows and map it + */ + base = soc.pciwin; + regs[MISC_CPU_2_PCIE_MEM_WIN0_LO] = base; + regs[MISC_CPU_2_PCIE_MEM_WIN0_HI] = base >> 32; + base >>= 20, limit >>= 20; + regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT] = (base & 0xFFF) << 4 | (limit & 0xFFF) << 20; + regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI] = base >> 12; + regs[MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI] = limit >> 12; + + ioa = 0; + base = soc.pciwin; + pcibusmap(pciroot, &base, &ioa, 1); + + pcihinv(pciroot); +} + +void +pcibcmlink(void) +{ + int log2dmasize = 30; // 1GB + + regs[RGR1_SW_INIT_1] |= 3; + delay(200); + regs[RGR1_SW_INIT_1] &= ~2; + regs[MISC_PCIE_CTRL] &= ~5; + delay(200); + + regs[MISC_HARD_PCIE_HARD_DEBUG] &= ~0x08000000; + delay(200); + + regs[MSI_INTR2_BASE + INTR_CLR] = -1; + regs[MSI_INTR2_BASE + INTR_MASK_SET] = -1; + + regs[MISC_CPU_2_PCIE_MEM_WIN0_LO] = 0; + regs[MISC_CPU_2_PCIE_MEM_WIN0_HI] = 0; + regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT] = 0; + regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI] = 0; + regs[MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI] = 0; + + // SCB_ACCESS_EN, CFG_READ_UR_MODE, MAX_BURST_SIZE_128, SCB0SIZE + regs[MISC_MISC_CTRL] = 1<<12 | 1<<13 | 0<<20 | (log2dmasize-15)<<27; + + regs[MISC_RC_BAR2_CONFIG_LO] = (log2dmasize-15); + regs[MISC_RC_BAR2_CONFIG_HI] = 0; + + regs[MISC_RC_BAR1_CONFIG_LO] = 0; + regs[MISC_RC_BAR3_CONFIG_LO] = 0; + + regs[MISC_MSI_BAR_CONFIG_LO] = MSI_TARGET_ADDR | 1; + regs[MISC_MSI_BAR_CONFIG_HI] = MSI_TARGET_ADDR>>32; + regs[MISC_MSI_DATA_CONFIG] = 0xFFF86540; + intrenable(IRQpci, pciinterrupt, nil, BUSUNKNOWN, "pci"); + + // force to GEN2 + regs[(0xAC + 12)/4] = (regs[(0xAC + 12)/4] & ~15) | 2; // linkcap + regs[(0xAC + 48)/4] = (regs[(0xAC + 48)/4] & ~15) | 2; // linkctl2 + + regs[RGR1_SW_INIT_1] &= ~1; + delay(500); + + if((regs[MISC_PCIE_STATUS] & 0x30) != 0x30){ + print("pcireset: phy link is down\n"); + return; + } + + regs[RC_CFG_PRIV1_ID_VAL3] = 0x060400; + regs[RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1] &= ~0xC; + regs[MISC_HARD_PCIE_HARD_DEBUG] |= 2; + + pcicfginit(); +} diff --git a/sys/src/9/bcm64/pi4 b/sys/src/9/bcm64/pi4 index 1a3b815ff..2bd10a1ea 100644 --- a/sys/src/9/bcm64/pi4 +++ b/sys/src/9/bcm64/pi4 @@ -26,7 +26,7 @@ dev link gisb - pci + pcibcm archbcm4 pci usbxhci pci archbcm4 ethergenet ethermii @@ -49,7 +49,7 @@ misc dma gic vcore - + pci pcibcm dtracysys dtracytimer diff --git a/sys/src/9/kw/fns.h b/sys/src/9/kw/fns.h index 703e8c503..50c6ea014 100644 --- a/sys/src/9/kw/fns.h +++ b/sys/src/9/kw/fns.h @@ -130,31 +130,6 @@ extern int splflo(void); extern void sysprocsetup(Proc*); extern int isaconfig(char*, int, ISAConf*); /* only devusb.c */ -/* - * PCI - */ -ulong pcibarsize(Pcidev*, int); -void pcibussize(Pcidev*, ulong*, ulong*); -int pcicfgr8(Pcidev*, int); -int pcicfgr16(Pcidev*, int); -int pcicfgr32(Pcidev*, int); -void pcicfgw8(Pcidev*, int, int); -void pcicfgw16(Pcidev*, int, int); -void pcicfgw32(Pcidev*, int, int); -void pciclrbme(Pcidev*); -void pciclrioe(Pcidev*); -void pciclrmwi(Pcidev*); -int pcigetpms(Pcidev*); -void pcihinv(Pcidev*); -uchar pciipin(Pcidev*, uchar); -Pcidev* pcimatch(Pcidev*, int, int); -Pcidev* pcimatchtbdf(int); -void pcireset(void); -int pciscan(int, Pcidev**); -void pcisetbme(Pcidev*); -void pcisetioe(Pcidev*); -void pcisetmwi(Pcidev*); -int pcisetpms(Pcidev*, int); int cas32(void*, u32int, u32int); int tas32(void*); diff --git a/sys/src/9/kw/io.h b/sys/src/9/kw/io.h index b05603254..e76f6faef 100644 --- a/sys/src/9/kw/io.h +++ b/sys/src/9/kw/io.h @@ -27,168 +27,6 @@ enum { #define BUSTYPE(tbdf) ((tbdf)>>24) #define BUSBDF(tbdf) ((tbdf)&0x00FFFF00) -/* - * PCI support code. - */ -enum { /* type 0 & type 1 pre-defined header */ - PciVID = 0x00, /* vendor ID */ - PciDID = 0x02, /* device ID */ - PciPCR = 0x04, /* command */ - PciPSR = 0x06, /* status */ - PciRID = 0x08, /* revision ID */ - PciCCRp = 0x09, /* programming interface class code */ - PciCCRu = 0x0A, /* sub-class code */ - PciCCRb = 0x0B, /* base class code */ - PciCLS = 0x0C, /* cache line size */ - PciLTR = 0x0D, /* latency timer */ - PciHDT = 0x0E, /* header type */ - PciBST = 0x0F, /* BIST */ -}; - -/* ccrb (base class code) values; controller types */ -enum { - Pcibcpci1 = 0, /* pci 1.0; no class codes defined */ - Pcibcstore = 1, /* mass storage */ - Pcibcnet = 2, /* network */ - Pcibcdisp = 3, /* display */ - Pcibcmmedia = 4, /* multimedia */ - Pcibcmem = 5, /* memory */ - Pcibcbridge = 6, /* bridge */ - Pcibccomm = 7, /* simple comms (e.g., serial) */ - Pcibcbasesys = 8, /* base system */ - Pcibcinput = 9, /* input */ - Pcibcdock = 0xa, /* docking stations */ - Pcibcproc = 0xb, /* processors */ - Pcibcserial = 0xc, /* serial bus (e.g., USB) */ - Pcibcwireless = 0xd, /* wireless */ - Pcibcintell = 0xe, /* intelligent i/o */ - Pcibcsatcom = 0xf, /* satellite comms */ - Pcibccrypto = 0x10, /* encryption/decryption */ - Pcibcdacq = 0x11, /* data acquisition & signal proc. */ -}; - -/* ccru (sub-class code) values; common cases only */ -enum { - /* mass storage */ - Pciscscsi = 0, /* SCSI */ - Pciscide = 1, /* IDE (ATA) */ - - /* network */ - Pciscether = 0, /* Ethernet */ - - /* display */ - Pciscvga = 0, /* VGA */ - Pciscxga = 1, /* XGA */ - Pcisc3d = 2, /* 3D */ - - /* bridges */ - Pcischostpci = 0, /* host/pci */ - Pciscpcicpci = 1, /* pci/pci */ - - /* simple comms */ - Pciscserial = 0, /* 16450, etc. */ - Pciscmultiser = 1, /* multiport serial */ - - /* serial bus */ - Pciscusb = 3, /* USB */ -}; - -enum { /* type 0 pre-defined header */ - PciCIS = 0x28, /* cardbus CIS pointer */ - PciSVID = 0x2C, /* subsystem vendor ID */ - PciSID = 0x2E, /* subsystem ID */ - PciEBAR0 = 0x30, /* expansion ROM base address */ - PciMGNT = 0x3E, /* burst period length */ - PciMLT = 0x3F, /* maximum latency between bursts */ -}; - -enum { /* type 1 pre-defined header */ - PciPBN = 0x18, /* primary bus number */ - PciSBN = 0x19, /* secondary bus number */ - PciUBN = 0x1A, /* subordinate bus number */ - PciSLTR = 0x1B, /* secondary latency timer */ - PciIBR = 0x1C, /* I/O base */ - PciILR = 0x1D, /* I/O limit */ - PciSPSR = 0x1E, /* secondary status */ - PciMBR = 0x20, /* memory base */ - PciMLR = 0x22, /* memory limit */ - PciPMBR = 0x24, /* prefetchable memory base */ - PciPMLR = 0x26, /* prefetchable memory limit */ - PciPUBR = 0x28, /* prefetchable base upper 32 bits */ - PciPULR = 0x2C, /* prefetchable limit upper 32 bits */ - PciIUBR = 0x30, /* I/O base upper 16 bits */ - PciIULR = 0x32, /* I/O limit upper 16 bits */ - PciEBAR1 = 0x28, /* expansion ROM base address */ - PciBCR = 0x3E, /* bridge control register */ -}; - -enum { /* type 2 pre-defined header */ - PciCBExCA = 0x10, - PciCBSPSR = 0x16, - PciCBPBN = 0x18, /* primary bus number */ - PciCBSBN = 0x19, /* secondary bus number */ - PciCBUBN = 0x1A, /* subordinate bus number */ - PciCBSLTR = 0x1B, /* secondary latency timer */ - PciCBMBR0 = 0x1C, - PciCBMLR0 = 0x20, - PciCBMBR1 = 0x24, - PciCBMLR1 = 0x28, - PciCBIBR0 = 0x2C, /* I/O base */ - PciCBILR0 = 0x30, /* I/O limit */ - PciCBIBR1 = 0x34, /* I/O base */ - PciCBILR1 = 0x38, /* I/O limit */ - PciCBSVID = 0x40, /* subsystem vendor ID */ - PciCBSID = 0x42, /* subsystem ID */ - PciCBLMBAR = 0x44, /* legacy mode base address */ -}; - -typedef struct Pcisiz Pcisiz; -struct Pcisiz -{ - Pcidev* dev; - int siz; - int bar; -}; - -typedef struct Pcidev Pcidev; -struct Pcidev -{ - int tbdf; /* type+bus+device+function */ - ushort vid; /* vendor ID */ - ushort did; /* device ID */ - - ushort pcr; - - uchar rid; - uchar ccrp; - uchar ccru; - uchar ccrb; - uchar cls; - uchar ltr; - - struct { - ulong bar; /* base address */ - int size; - } mem[6]; - - struct { - ulong 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; - int size; - } ioa, mema; - - int pmrb; /* power management register block */ -}; - #define PCIWINDOW 0 #define PCIWADDR(va) (PADDR(va)+PCIWINDOW) diff --git a/sys/src/9/mtx/ether2114x.c b/sys/src/9/mtx/ether2114x.c index 8906b3499..25260d4ea 100644 --- a/sys/src/9/mtx/ether2114x.c +++ b/sys/src/9/mtx/ether2114x.c @@ -14,6 +14,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/mtx/fns.h b/sys/src/9/mtx/fns.h index 98d2b28cc..d63cc6ddb 100644 --- a/sys/src/9/mtx/fns.h +++ b/sys/src/9/mtx/fns.h @@ -65,21 +65,9 @@ void outs(int, ushort); void outss(int, void*, int); void outl(int, ulong); void outsl(int, void*, int); -int pciscan(int, Pcidev **); -ulong pcibarsize(Pcidev *, int); -int pcicfgr8(Pcidev*, int); -int pcicfgr16(Pcidev*, int); -int pcicfgr32(Pcidev*, int); -void pcicfgw8(Pcidev*, int, int); -void pcicfgw16(Pcidev*, int, int); -void pcicfgw32(Pcidev*, int, int); -void pciclrbme(Pcidev*); -void pcihinv(Pcidev*); -uchar pciipin(Pcidev *, uchar); -Pcidev* pcimatch(Pcidev*, int, int); -Pcidev* pcimatchtbdf(int); -void pcireset(void); -void pcisetbme(Pcidev*); +int pcicfgrw8(int, int, int, int); +int pcicfgrw16(int, int, int, int); +int pcicfgrw32(int, int, int, int); #define procrestore(p) void procsave(Proc*); void procsetup(Proc*); diff --git a/sys/src/9/mtx/io.h b/sys/src/9/mtx/io.h index 255debf97..3ebe26a7b 100644 --- a/sys/src/9/mtx/io.h +++ b/sys/src/9/mtx/io.h @@ -31,150 +31,12 @@ typedef struct Vctl { void* a; /* argument to call it with */ } Vctl; -enum { - BusCBUS = 0, /* Corollary CBUS */ - BusCBUSII, /* Corollary CBUS II */ - BusEISA, /* Extended ISA */ - BusFUTURE, /* IEEE Futurebus */ - BusINTERN, /* Internal bus */ - BusISA, /* Industry Standard Architecture */ - BusMBI, /* Multibus I */ - BusMBII, /* Multibus II */ - BusMCA, /* Micro Channel Architecture */ - BusMPI, /* MPI */ - BusMPSA, /* MPSA */ - BusNUBUS, /* Apple Macintosh NuBus */ - BusPCI, /* Peripheral Component Interconnect */ - BusPCMCIA, /* PC Memory Card International Association */ - BusTC, /* DEC TurboChannel */ - BusVL, /* VESA Local bus */ - BusVME, /* VMEbus */ - BusXPRESS, /* Express System Bus */ -}; - -#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8)) -#define BUSFNO(tbdf) (((tbdf)>>8)&0x07) -#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F) -#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF) -#define BUSTYPE(tbdf) ((tbdf)>>24) -#define BUSDF(tbdf) ((tbdf)&0x000FF00) -#define BUSBDF(tbdf) ((tbdf)&0x0FFFF00) -#define BUSUNKNOWN (-1) - enum { MaxEISA = 16, EISAconfig = 0xC80, }; -/* - * PCI support code. - */ -enum { /* type 0 and type 1 pre-defined header */ - PciVID = 0x00, /* vendor ID */ - PciDID = 0x02, /* device ID */ - PciPCR = 0x04, /* command */ - PciPSR = 0x06, /* status */ - PciRID = 0x08, /* revision ID */ - PciCCRp = 0x09, /* programming interface class code */ - PciCCRu = 0x0A, /* sub-class code */ - PciCCRb = 0x0B, /* base class code */ - PciCLS = 0x0C, /* cache line size */ - PciLTR = 0x0D, /* latency timer */ - PciHDT = 0x0E, /* header type */ - PciBST = 0x0F, /* BIST */ - - PciBAR0 = 0x10, /* base address */ - PciBAR1 = 0x14, - - PciINTL = 0x3C, /* interrupt line */ - PciINTP = 0x3D, /* interrupt pin */ -}; - -enum { /* type 0 pre-defined header */ - PciCIS = 0x28, /* cardbus CIS pointer */ - PciSVID = 0x2C, /* subsystem vendor ID */ - PciSID = 0x2E, /* subsystem ID */ - PciEBAR0 = 0x30, /* expansion ROM base address */ - PciMGNT = 0x3E, /* burst period length */ - PciMLT = 0x3F, /* maximum latency between bursts */ -}; - -enum { /* type 1 pre-defined header */ - PciPBN = 0x18, /* primary bus number */ - PciSBN = 0x19, /* secondary bus number */ - PciUBN = 0x1A, /* subordinate bus number */ - PciSLTR = 0x1B, /* secondary latency timer */ - PciIBR = 0x1C, /* I/O base */ - PciILR = 0x1D, /* I/O limit */ - PciSPSR = 0x1E, /* secondary status */ - PciMBR = 0x20, /* memory base */ - PciMLR = 0x22, /* memory limit */ - PciPMBR = 0x24, /* prefetchable memory base */ - PciPMLR = 0x26, /* prefetchable memory limit */ - PciPUBR = 0x28, /* prefetchable base upper 32 bits */ - PciPULR = 0x2C, /* prefetchable limit upper 32 bits */ - PciIUBR = 0x30, /* I/O base upper 16 bits */ - PciIULR = 0x32, /* I/O limit upper 16 bits */ - PciEBAR1 = 0x28, /* expansion ROM base address */ - PciBCR = 0x3E, /* bridge control register */ -}; - -enum { /* type 2 pre-defined header */ - PciCBExCA = 0x10, - PciCBSPSR = 0x16, - PciCBPBN = 0x18, /* primary bus number */ - PciCBSBN = 0x19, /* secondary bus number */ - PciCBUBN = 0x1A, /* subordinate bus number */ - PciCBSLTR = 0x1B, /* secondary latency timer */ - PciCBMBR0 = 0x1C, - PciCBMLR0 = 0x20, - PciCBMBR1 = 0x24, - PciCBMLR1 = 0x28, - PciCBIBR0 = 0x2C, /* I/O base */ - PciCBILR0 = 0x30, /* I/O limit */ - PciCBIBR1 = 0x34, /* I/O base */ - PciCBILR1 = 0x38, /* I/O limit */ - PciCBSVID = 0x40, /* subsystem vendor ID */ - PciCBSID = 0x42, /* subsystem ID */ - PciCBLMBAR = 0x44, /* legacy mode base address */ -}; - -typedef struct Pcisiz Pcisiz; -struct Pcisiz -{ - Pcidev* dev; - int siz; - int bar; -}; - -typedef struct Pcidev Pcidev; -typedef struct Pcidev { - int tbdf; /* type+bus+device+function */ - ushort vid; /* vendor ID */ - ushort did; /* device ID */ - - uchar rid; - uchar ccrp; - uchar ccru; - uchar ccrb; - - struct { - ulong bar; /* base address */ - int size; - } mem[6]; - - uchar intl; /* interrupt line */ - - Pcidev* list; - Pcidev* link; /* next device on this bno */ - - Pcidev* bridge; /* down a bus */ - struct { - ulong bar; - int size; - } ioa, mema; - ulong pcr; -}; - #define PCIWINDOW 0x80000000 #define PCIWADDR(va) (PADDR(va)+PCIWINDOW) + +#define BUSUNKNOWN (-1) diff --git a/sys/src/9/mtx/mkfile b/sys/src/9/mtx/mkfile index 6dd9ba614..df5ba47e8 100644 --- a/sys/src/9/mtx/mkfile +++ b/sys/src/9/mtx/mkfile @@ -1,5 +1,5 @@ CONF=mtx -CONFLIST=mtx mtxcpu +CONFLIST=mtx objtype=power r){ - case 'T': - tbdf = va_arg(fmt->args, int); - 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: - snprint(p, READSTR, "(tbdfconv)"); - break; - } - r = fmtstrcpy(fmt, p); - free(p); - - return r; -} - -ulong -pcibarsize(Pcidev *p, int rno) -{ - ulong v, size; - - v = pcicfgrw32(p->tbdf, rno, 0, 1); - pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0); - size = pcicfgrw32(p->tbdf, rno, 0, 1); - if(v & 1) - size |= 0xFFFF0000; - pcicfgrw32(p->tbdf, rno, v, 0); - - return -(size & ~0x0F); -} - -static int -pcisizcmp(void *a, void *b) -{ - Pcisiz *aa, *bb; - - aa = a; - bb = b; - return aa->siz - bb->siz; -} - -static ulong -pcimask(ulong v) -{ - ulong m; - - m = BI2BY*sizeof(v); - for(m = 1<<(m-1); m != 0; m >>= 1) { - if(m & v) - break; - } - - m--; - if((v & m) == 0) - return v; - - v |= m; - return v+1; -} - -static void -pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg) -{ - Pcidev *p; - int ntb, i, size, rno, hole; - ulong v, mema, ioa, sioa, smema, base, limit; - Pcisiz *table, *tptr, *mtb, *itb; - extern void qsort(void*, long, long, int (*)(void*, void*)); - - ioa = *pioa; - mema = *pmema; - - DBG("pcibusmap wr=%d %T mem=%luX io=%luX\n", - wrreg, root->tbdf, mema, ioa); - - ntb = 0; - for(p = root; p != nil; p = p->link) - ntb++; - - ntb *= (PciCIS-PciBAR0)/4; - table = malloc(2*ntb*sizeof(Pcisiz)); - itb = table; - mtb = table+ntb; - - /* - * Build a table of sizes - */ - for(p = root; p != nil; p = p->link) { - if(p->ccrb == 0x06) { - if(p->ccru == 0x04 && p->bridge != nil) { - sioa = ioa; - smema = mema; - pcibusmap(p->bridge, &smema, &sioa, 0); - - hole = pcimask(smema-mema); - if(hole < (1<<20)) - hole = 1<<20; - p->mema.size = hole; - - hole = pcimask(sioa-ioa); - if(hole < (1<<12)) - hole = 1<<12; - - p->ioa.size = hole; - - itb->dev = p; - itb->bar = -1; - itb->siz = p->ioa.size; - itb++; - - mtb->dev = p; - mtb->bar = -1; - mtb->siz = p->mema.size; - mtb++; - } - if((pcicfgr8(p, PciHDT)&0x7f) != 0) - continue; - } - - for(i = 0; i <= 5; i++) { - rno = PciBAR0 + i*4; - v = pcicfgrw32(p->tbdf, rno, 0, 1); - size = pcibarsize(p, rno); - if(size == 0) - continue; - - if(v & 1) { - itb->dev = p; - itb->bar = i; - itb->siz = size; - itb++; - } - else { - mtb->dev = p; - mtb->bar = i; - mtb->siz = size; - mtb++; - } - - p->mem[i].size = size; - } - } - - /* - * Sort both tables IO smallest first, Memory largest - */ - qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp); - tptr = table+ntb; - qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp); - - /* - * Allocate IO address space on this bus - */ - for(tptr = table; tptr < itb; tptr++) { - hole = tptr->siz; - if(tptr->bar == -1) - hole = 1<<12; - ioa = (ioa+hole-1) & ~(hole-1); - - p = tptr->dev; - if(tptr->bar == -1) - p->ioa.bar = ioa; - else { - p->pcr |= IOen; - p->mem[tptr->bar].bar = ioa|1; - if(wrreg) - pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0); - } - - ioa += tptr->siz; - } - - /* - * Allocate Memory address space on this bus - */ - for(tptr = table+ntb; tptr < mtb; tptr++) { - hole = tptr->siz; - if(tptr->bar == -1) - hole = 1<<20; - mema = (mema+hole-1) & ~(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); - } - mema += tptr->siz; - } - - *pmema = mema; - *pioa = ioa; - free(table); - - if(wrreg == 0) - return; - - /* - * Finally set all the bridge addresses & registers - */ - for(p = root; p != nil; p = p->link) { - if(p->bridge == nil) { - pcicfgrw8(p->tbdf, PciLTR, 64, 0); - - p->pcr |= MASen; - pcicfgrw32(p->tbdf, PciPCR, p->pcr, 0); - continue; - } - - base = p->ioa.bar; - limit = base+p->ioa.size-1; - v = pcicfgrw32(p->tbdf, PciIBR, 0, 1); - v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8); - pcicfgrw32(p->tbdf, PciIBR, v, 0); - v = (limit & 0xFFFF0000)|(base>>16); - pcicfgrw32(p->tbdf, PciIUBR, v, 0); - - base = p->mema.bar; - limit = base+p->mema.size-1; - v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16); - pcicfgrw32(p->tbdf, PciMBR, v, 0); - - /* - * Disable memory prefetch - */ - pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0); - pcicfgrw8(p->tbdf, PciLTR, 64, 0); - - /* - * Enable the bridge - */ - v = 0xFFFF0000 | IOen | MEMen | MASen; - pcicfgrw32(p->tbdf, PciPCR, v, 0); - - sioa = p->ioa.bar; - smema = p->mema.bar; - pcibusmap(p->bridge, &smema, &sioa, 1); - } -} - -static int -pcilscan(int bno, Pcidev** list) -{ - Pcidev *p, *head, *tail; - int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn; - - maxubn = bno; - head = nil; - tail = nil; - for(dno = 0; dno <= pcimaxdno; dno++){ - maxfno = 0; - for(fno = 0; fno <= maxfno; fno++){ - /* - * For this possible device, form the - * bus+device+function triplet needed to address it - * and try to read the vendor and device ID. - * If successful, allocate a device struct and - * start to fill it in with some useful information - * from the device's configuration space. - */ - tbdf = MKBUS(BusPCI, bno, dno, fno); - l = pcicfgrw32(tbdf, PciVID, 0, 1); - if(l == 0xFFFFFFFF || l == 0) - continue; - p = malloc(sizeof(*p)); - p->tbdf = tbdf; - p->vid = l; - p->did = l>>16; - - if(pcilist != nil) - pcitail->list = p; - else - pcilist = p; - pcitail = p; - - p->rid = pcicfgr8(p, PciRID); - p->ccrp = pcicfgr8(p, PciCCRp); - p->ccru = pcicfgr8(p, PciCCRu); - p->ccrb = pcicfgr8(p, PciCCRb); - p->pcr = pcicfgr32(p, PciPCR); - - p->intl = pcicfgr8(p, PciINTL); - - /* - * If the device is a multi-function device adjust the - * loop count so all possible functions are checked. - */ - hdt = pcicfgr8(p, PciHDT); - if(hdt & 0x80) - maxfno = MaxFNO; - - /* - * If appropriate, read the base address registers - * 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 0x06: /* bridge 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); - } - break; - - case 0x00: - case 0x05: /* memory controller */ - default: - break; - } - - if(head != nil) - tail->link = p; - else - head = p; - tail = p; - } - } - - *list = head; - for(p = head; p != nil; p = p->link){ - /* - * Find PCI-PCI bridges and recursively descend the tree. - */ - if(p->ccrb != 0x06 || p->ccru != 0x04) - continue; - - /* - * If the secondary or subordinate bus number is not - * initialised try to do what the PCI BIOS should have - * done and fill in the numbers as the tree is descended. - * On the way down the subordinate bus number is set to - * the maximum as it's not known how many buses are behind - * this one; the final value is set on the way back up. - */ - sbn = pcicfgr8(p, PciSBN); - ubn = pcicfgr8(p, PciUBN); - - if(sbn == 0 || ubn == 0) { - sbn = maxubn+1; - /* - * Make sure memory, I/O and master enables are - * off, set the primary, secondary and subordinate - * bus numbers and clear the secondary status before - * attempting to scan the secondary bus. - * - * Initialisation of the bridge should be done here. - */ - pcicfgw32(p, PciPCR, 0xFFFF0000); - l = (MaxUBN<<16)|(sbn<<8)|bno; - pcicfgw32(p, PciPBN, l); - pcicfgw16(p, PciSPSR, 0xFFFF); - maxubn = pcilscan(sbn, &p->bridge); - l = (maxubn<<16)|(sbn<<8)|bno; - - pcicfgw32(p, PciPBN, l); - } - else { - maxubn = ubn; - pcilscan(sbn, &p->bridge); - } - } - - return maxubn; -} - -int -pciscan(int bno, Pcidev **list) -{ - int ubn; - - qlock(&pcicfginitlock); - ubn = pcilscan(bno, list); - qunlock(&pcicfginitlock); - return ubn; -} - -static void -pcicfginit(void) -{ - char *p; - int bno; - Pcidev **list; - ulong mema, ioa; - - qlock(&pcicfginitlock); - if(pcicfgmode != -1) - goto out; - - /* - * Try to determine which PCI configuration mode is implemented. - * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses - * a DWORD at 0xCF8 and another at 0xCFC and will pass through - * any non-DWORD accesses as normal I/O cycles. There shouldn't be - * a device behind these addresses so if Mode2 accesses fail try - * for Mode1 (which is preferred, Mode2 is deprecated). - */ - outb(PciCSE, 0); - if(inb(PciCSE) == 0){ - pcicfgmode = 2; - pcimaxdno = 15; - } - else { - outl(PciADDR, 0); - if(inl(PciADDR) == 0){ - pcicfgmode = 1; - pcimaxdno = 31; - } - } - - if(pcicfgmode < 0) - goto out; - - fmtinstall('T', tbdffmt); - - if(p = getconf("*pcimaxbno")) - pcimaxbno = strtoul(p, 0, 0); - if(p = getconf("*pcimaxdno")) - pcimaxdno = strtoul(p, 0, 0); - - list = &pciroot; - for(bno = 0; bno <= pcimaxbno; bno++) { - int sbno = bno; - bno = pcilscan(bno, list); - - while(*list) - list = &(*list)->link; - - if (sbno == 0) { - Pcidev *pci; - - /* - * If we have found a PCI-to-Cardbus bridge, make sure - * it has no valid mappings anymore. - */ - pci = pciroot; - while (pci) { - if (pci->ccrb == 6 && pci->ccru == 7) { - ushort bcr; - - /* reset the cardbus */ - bcr = pcicfgr16(pci, PciBCR); - pcicfgw16(pci, PciBCR, 0x40 | bcr); - delay(50); - } - pci = pci->link; - } - } - } - - if(pciroot == nil) - goto out; - - /* - * Work out how big the top bus is - */ - mema = 0; - ioa = 0; - pcibusmap(pciroot, &mema, &ioa, 0); - - DBG("Sizes: mem=%8.8lux size=%8.8lux io=%8.8lux\n", - mema, pcimask(mema), ioa); - - /* - * Align the windows and map it - */ - ioa = 0x1000; - mema = 0; - - pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa); - - pcibusmap(pciroot, &mema, &ioa, 1); - DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa); - -out: - qunlock(&pcicfginitlock); -} - -static int -pcicfgrw8(int tbdf, int rno, int data, int read) -{ - int o, type, x; - - if(pcicfgmode == -1) - pcicfginit(); - - if(BUSBNO(tbdf)) - type = 0x01; - else - type = 0x00; - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - lock(&pcicfglock); - switch(pcicfgmode){ - - case 1: - o = rno & 0x03; - rno &= ~0x03; - outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); - if(read) - x = inb(PciDATA+o); - else - outb(PciDATA+o, data); - outl(PciADDR, 0); - break; - - case 2: - outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); - outb(PciFORWARD, BUSBNO(tbdf)); - if(read) - x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno); - else - outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); - outb(PciCSE, 0); - break; - } - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr8(Pcidev* pcidev, int rno) -{ - return pcicfgrw8(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw8(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw8(pcidev->tbdf, rno, data, 0); -} - -static int -pcicfgrw16(int tbdf, int rno, int data, int read) -{ - int o, type, x; - - if(pcicfgmode == -1) - pcicfginit(); - - if(BUSBNO(tbdf)) - type = 0x01; - else - type = 0x00; - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - lock(&pcicfglock); - switch(pcicfgmode){ - - case 1: - o = rno & 0x02; - rno &= ~0x03; - outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); - if(read) - x = ins(PciDATA+o); - else - outs(PciDATA+o, data); - outl(PciADDR, 0); - break; - - case 2: - outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); - outb(PciFORWARD, BUSBNO(tbdf)); - if(read) - x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno); - else - outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); - outb(PciCSE, 0); - break; - } - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr16(Pcidev* pcidev, int rno) -{ - return pcicfgrw16(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw16(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw16(pcidev->tbdf, rno, data, 0); -} - -static int -pcicfgrw32(int tbdf, int rno, int data, int read) -{ - int type, x; - - if(pcicfgmode == -1) - pcicfginit(); - - if(BUSBNO(tbdf)) - type = 0x01; - else - type = 0x00; - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - lock(&pcicfglock); - switch(pcicfgmode){ - - case 1: - rno &= ~0x03; - outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); - if(read) - x = inl(PciDATA); - else - outl(PciDATA, data); - outl(PciADDR, 0); - break; - - case 2: - outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); - outb(PciFORWARD, BUSBNO(tbdf)); - if(read) - x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno); - else - outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); - outb(PciCSE, 0); - break; - } - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr32(Pcidev* pcidev, int rno) -{ - return pcicfgrw32(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw32(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw32(pcidev->tbdf, rno, data, 0); -} - -Pcidev* -pcimatch(Pcidev* prev, int vid, int did) -{ - if(pcicfgmode == -1) - pcicfginit(); - - if(prev == nil) - prev = pcilist; - else - prev = prev->list; - - while(prev != nil){ - if((vid == 0 || prev->vid == vid) - && (did == 0 || prev->did == did)) - break; - prev = prev->list; - } - return prev; -} - -Pcidev* -pcimatchtbdf(int tbdf) -{ - Pcidev *pcidev; - - if(pcicfgmode == -1) - pcicfginit(); - - for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) { - if(pcidev->tbdf == tbdf) - break; - } - return pcidev; -} - -uchar -pciipin(Pcidev *pci, uchar pin) -{ - if (pci == nil) - pci = pcilist; - - while (pci) { - uchar intl; - - if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff) - return pci->intl; - - if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0) - return intl; - - pci = pci->list; - } - return 0; -} - -static void -pcilhinv(Pcidev* p) -{ - int i; - Pcidev *t; - - if(p == nil) { - putstrn(PCICONS.output, PCICONS.ptr); - p = pciroot; - print("bus dev 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); - - 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); - } - 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) - print("->%d", BUSBNO(t->bridge->tbdf)); - print("\n"); - } - while(p != nil) { - if(p->bridge != nil) - pcilhinv(p->bridge); - p = p->link; - } -} - -void -pcihinv(Pcidev* p) -{ - if(pcicfgmode == -1) - pcicfginit(); - qlock(&pcicfginitlock); - pcilhinv(p); - qunlock(&pcicfginitlock); -} - -void -pcireset(void) -{ - Pcidev *p; - int pcr; - - if(pcicfgmode == -1) - pcicfginit(); - - for(p = pcilist; p != nil; p = p->list){ - pcr = pcicfgr16(p, PciPCR); - pcr &= ~0x0004; - pcicfgw16(p, PciPCR, pcr); - } -} - -void -pcisetbme(Pcidev* p) -{ - int pcr; - - pcr = pcicfgr16(p, PciPCR); - pcr |= MASen; - pcicfgw16(p, PciPCR, pcr); -} - -void -pciclrbme(Pcidev* p) -{ - int pcr; - - pcr = pcicfgr16(p, PciPCR); - pcr &= ~MASen; - pcicfgw16(p, PciPCR, pcr); -} diff --git a/sys/src/9/mtx/pcimtx.c b/sys/src/9/mtx/pcimtx.c new file mode 100644 index 000000000..02f1f4e9a --- /dev/null +++ b/sys/src/9/mtx/pcimtx.c @@ -0,0 +1,224 @@ +/* + * PCI support code. + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/pci.h" +#include "../port/error.h" + +enum { + /* configuration mechanism #1 */ + PciADDR = 0xCF8, /* CONFIG_ADDRESS */ + PciDATA = 0xCFC, /* CONFIG_DATA */ + + /* configuration mechanism #2 */ + PciCSE = 0xCF8, /* configuration space enable */ + PciFORWARD = 0xCFA, /* which bus */ +}; + +static int pcicfgmode = -1; +static int pcimaxbno = 7; +static Pcidev* pciroot; + +static void +pcicfginit(void) +{ + char *p; + int bno; + Pcidev **list; + uvlong mema; + ulong ioa; + + fmtinstall('T', tbdffmt); + + /* + * Try to determine which PCI configuration mode is implemented. + * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses + * a DWORD at 0xCF8 and another at 0xCFC and will pass through + * any non-DWORD accesses as normal I/O cycles. There shouldn't be + * a device behind these addresses so if Mode2 accesses fail try + * for Mode1 (which is preferred, Mode2 is deprecated). + */ + outb(PciCSE, 0); + if(inb(PciCSE) == 0){ + pcicfgmode = 2; + pcimaxdno = 15; + } + else { + outl(PciADDR, 0); + if(inl(PciADDR) == 0){ + pcicfgmode = 1; + pcimaxdno = 31; + } + } + + if(pcicfgmode < 0) + return; + + if(p = getconf("*pcimaxbno")) + pcimaxbno = strtoul(p, 0, 0); + if(p = getconf("*pcimaxdno")) + pcimaxdno = strtoul(p, 0, 0); + + list = &pciroot; + for(bno = 0; bno <= pcimaxbno; bno++) { + int sbno = bno; + bno = pciscan(bno, list); + + while(*list) + list = &(*list)->link; + + if (sbno == 0) { + Pcidev *pci; + + /* + * If we have found a PCI-to-Cardbus bridge, make sure + * it has no valid mappings anymore. + */ + pci = pciroot; + while (pci) { + if (pci->ccrb == 6 && pci->ccru == 7) { + ushort bcr; + + /* reset the cardbus */ + bcr = pcicfgr16(pci, PciBCR); + pcicfgw16(pci, PciBCR, 0x40 | bcr); + delay(50); + } + pci = pci->link; + } + } + } + + if(pciroot == nil) + return; + + /* + * Work out how big the top bus is + */ + mema = 0; + ioa = 0; + pcibusmap(pciroot, &mema, &ioa, 0); + + /* + * Align the windows and map it + */ + ioa = 0x1000; + mema = 0; + pcibusmap(pciroot, &mema, &ioa, 1); +} + +int +pcicfgrw8(int tbdf, int rno, int data, int read) +{ + int o, type, x; + + if(BUSBNO(tbdf)) + type = 0x01; + else + type = 0x00; + switch(pcicfgmode){ + case 1: + o = rno & 0x03; + rno &= ~0x03; + outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); + if(read) + data = inb(PciDATA+o); + else + outb(PciDATA+o, data); + outl(PciADDR, 0); + break; + + case 2: + outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); + outb(PciFORWARD, BUSBNO(tbdf)); + if(read) + data = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno); + else + outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); + outb(PciCSE, 0); + break; + default: + data = -1; + } + return data; +} + +int +pcicfgrw16(int tbdf, int rno, int data, int read) +{ + int o, type; + + if(BUSBNO(tbdf)) + type = 0x01; + else + type = 0x00; + switch(pcicfgmode){ + case 1: + o = rno & 0x02; + rno &= ~0x03; + outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); + if(read) + data = ins(PciDATA+o); + else + outs(PciDATA+o, data); + outl(PciADDR, 0); + break; + case 2: + outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); + outb(PciFORWARD, BUSBNO(tbdf)); + if(read) + data = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno); + else + outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); + outb(PciCSE, 0); + break; + default: + data = -1; + } + return data; +} + +int +pcicfgrw32(int tbdf, int rno, int data, int read) +{ + int type; + + if(BUSBNO(tbdf)) + type = 0x01; + else + type = 0x00; + switch(pcicfgmode){ + case 1: + rno &= ~0x03; + outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); + if(read) + data = inl(PciDATA); + else + outl(PciDATA, data); + outl(PciADDR, 0); + break; + case 2: + outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); + outb(PciFORWARD, BUSBNO(tbdf)); + if(read) + data = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno); + else + outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); + outb(PciCSE, 0); + break; + default: + data = -1; + } + return data; +} + +void +pcimtxlink(void) +{ + pcicfginit(); +} diff --git a/sys/src/9/pc/archacpi.c b/sys/src/9/pc/archacpi.c index d74054c7d..e19c70166 100644 --- a/sys/src/9/pc/archacpi.c +++ b/sys/src/9/pc/archacpi.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "mp.h" diff --git a/sys/src/9/pc/archmp.c b/sys/src/9/pc/archmp.c index edf256256..5d613dd0d 100644 --- a/sys/src/9/pc/archmp.c +++ b/sys/src/9/pc/archmp.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "mp.h" diff --git a/sys/src/9/pc/audioac97.c b/sys/src/9/pc/audioac97.c index e4f175882..0a336cae4 100644 --- a/sys/src/9/pc/audioac97.c +++ b/sys/src/9/pc/audioac97.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/audioif.h" diff --git a/sys/src/9/pc/audiohda.c b/sys/src/9/pc/audiohda.c index bb32e09e3..f04ad11ee 100644 --- a/sys/src/9/pc/audiohda.c +++ b/sys/src/9/pc/audiohda.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/audioif.h" diff --git a/sys/src/9/pc/cputemp.c b/sys/src/9/pc/cputemp.c index 944c4a774..1ffbeb08b 100644 --- a/sys/src/9/pc/cputemp.c +++ b/sys/src/9/pc/cputemp.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" static int intelcputempok(void) diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index 5ba04b59c..9a845b3ab 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -153,7 +153,6 @@ ioinit(void) ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated"); } } - } /* diff --git a/sys/src/9/pc/devlm78.c b/sys/src/9/pc/devlm78.c index 617d5cb92..3aa4cf333 100644 --- a/sys/src/9/pc/devlm78.c +++ b/sys/src/9/pc/devlm78.c @@ -5,6 +5,7 @@ #include "fns.h" #include "io.h" #include "ureg.h" +#include "../port/pci.h" #include "../port/error.h" /* this driver doesn't implement the management interrupts. we diff --git a/sys/src/9/pc/devlml.c b/sys/src/9/pc/devlml.c index 83c57b855..377b95e3e 100644 --- a/sys/src/9/pc/devlml.c +++ b/sys/src/9/pc/devlml.c @@ -8,6 +8,7 @@ #include "fns.h" #include "../port/error.h" #include "io.h" +#include "../port/pci.h" #include "devlml.h" diff --git a/sys/src/9/pc/devpccard.c b/sys/src/9/pc/devpccard.c index 68be9047a..b6c9bb682 100644 --- a/sys/src/9/pc/devpccard.c +++ b/sys/src/9/pc/devpccard.c @@ -8,6 +8,7 @@ #include "fns.h" #include "../port/error.h" #include "io.h" +#include "../port/pci.h" #define DEBUG 0 @@ -922,7 +923,7 @@ unconfigure(Cardbus *cb) if (pci->mem[i].size == 0) continue; if (pci->mem[i].bar & 1) { - iofree(pci->mem[i].bar & ~1); + iofree(pci->mem[i].bar & ~3); pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, (ushort)-1); pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0); diff --git a/sys/src/9/pc/devtv.c b/sys/src/9/pc/devtv.c index 4e0c32792..e5690a88d 100644 --- a/sys/src/9/pc/devtv.c +++ b/sys/src/9/pc/devtv.c @@ -8,8 +8,9 @@ #include "dat.h" #include "fns.h" #include "../port/error.h" -#include "io.h" -#include "hcwAMC.h" +#include "io.h" +#include "../port/pci.h" +#include "hcwAMC.h" #define max(a, b) (((a) > (b))? (a): (b)) diff --git a/sys/src/9/pc/devvga.c b/sys/src/9/pc/devvga.c index 5d95c98eb..cb97a4901 100644 --- a/sys/src/9/pc/devvga.c +++ b/sys/src/9/pc/devvga.c @@ -7,6 +7,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/ether2000.c b/sys/src/9/pc/ether2000.c index 6cebf4f9f..3077e190c 100644 --- a/sys/src/9/pc/ether2000.c +++ b/sys/src/9/pc/ether2000.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -62,7 +63,7 @@ ne2000match(Ether* edev, int id) p = ctlr->pcidev; if(((p->did<<16)|p->vid) != id) continue; - port = p->mem[0].bar & ~0x01; + port = p->mem[0].bar & ~3; if(edev->port != 0 && edev->port != port) continue; diff --git a/sys/src/9/pc/ether2114x.c b/sys/src/9/pc/ether2114x.c index 57d426952..d451a1a1d 100644 --- a/sys/src/9/pc/ether2114x.c +++ b/sys/src/9/pc/ether2114x.c @@ -14,6 +14,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -1671,7 +1672,7 @@ dec2114xpci(void) print("dec2114x: can't allocate memory\n"); continue; } - ctlr->port = p->mem[0].bar & ~0x01; + ctlr->port = p->mem[0].bar & ~3; ctlr->pcidev = p; ctlr->id = (p->did<<16)|p->vid; diff --git a/sys/src/9/pc/ether79c970.c b/sys/src/9/pc/ether79c970.c index d9e17e0b4..c2b629bbd 100644 --- a/sys/src/9/pc/ether79c970.c +++ b/sys/src/9/pc/ether79c970.c @@ -10,6 +10,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -490,7 +491,7 @@ amd79c970pci(void) p = nil; while(p = pcimatch(p, 0x1022, 0x2000)){ - port = p->mem[0].bar & ~0x01; + port = p->mem[0].bar & ~3; if(ioalloc(port, p->mem[0].size, 0, "amd79c970") < 0){ print("amd79c970: port 0x%uX in use\n", port); continue; @@ -501,7 +502,7 @@ amd79c970pci(void) iofree(port); continue; } - ctlr->port = p->mem[0].bar & ~0x01; + ctlr->port = port; ctlr->pcidev = p; if(ctlrhead != nil) diff --git a/sys/src/9/pc/ether8139.c b/sys/src/9/pc/ether8139.c index 21a1cad39..a5eccd230 100644 --- a/sys/src/9/pc/ether8139.c +++ b/sys/src/9/pc/ether8139.c @@ -9,6 +9,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -693,7 +694,7 @@ rtl8139match(Ether* edev, int id) p = ctlr->pcidev; if(((p->did<<16)|p->vid) != id) continue; - port = p->mem[0].bar & ~0x01; + port = p->mem[0].bar & ~3; if(edev->port != 0 && edev->port != port) continue; diff --git a/sys/src/9/pc/ether8169.c b/sys/src/9/pc/ether8169.c index bf6cf8ef4..a871a55d2 100644 --- a/sys/src/9/pc/ether8169.c +++ b/sys/src/9/pc/ether8169.c @@ -13,6 +13,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -1102,7 +1103,7 @@ rtl8169pci(void) break; } - port = p->mem[0].bar & ~0x01; + port = p->mem[0].bar & ~3; if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){ print("rtl8169: port %#ux in use\n", port); continue; diff --git a/sys/src/9/pc/ether82543gc.c b/sys/src/9/pc/ether82543gc.c index 3b326b4af..b43beb161 100644 --- a/sys/src/9/pc/ether82543gc.c +++ b/sys/src/9/pc/ether82543gc.c @@ -16,6 +16,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -1282,8 +1283,7 @@ gc82543pci(void) free(ctlr); continue; } - cls = pcicfgr8(p, PciCLS); - switch(cls){ + switch(p->cls){ case 0x08: case 0x10: break; diff --git a/sys/src/9/pc/ether82557.c b/sys/src/9/pc/ether82557.c index b764f1c0b..33d7b6957 100644 --- a/sys/src/9/pc/ether82557.c +++ b/sys/src/9/pc/ether82557.c @@ -14,6 +14,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -963,7 +964,7 @@ i82557pci(void) * bar[1] is the I/O port register address (32 bytes) and * bar[2] is for the flash ROM (1MB). */ - port = p->mem[1].bar & ~0x01; + port = p->mem[1].bar & ~3; if(ioalloc(port, p->mem[1].size, 0, "i82557") < 0){ print("i82557: port %#ux in use\n", port); continue; diff --git a/sys/src/9/pc/ether82563.c b/sys/src/9/pc/ether82563.c index 4559fda5c..75af7825c 100644 --- a/sys/src/9/pc/ether82563.c +++ b/sys/src/9/pc/ether82563.c @@ -9,6 +9,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/ether82598.c b/sys/src/9/pc/ether82598.c index 6792e779a..89ee64011 100644 --- a/sys/src/9/pc/ether82598.c +++ b/sys/src/9/pc/ether82598.c @@ -8,6 +8,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/ether83815.c b/sys/src/9/pc/ether83815.c index a65fe719e..ebbec582f 100644 --- a/sys/src/9/pc/ether83815.c +++ b/sys/src/9/pc/ether83815.c @@ -22,6 +22,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -1089,7 +1090,7 @@ scanpci83815(void) print("ns83815: can't allocate memory\n"); continue; } - ctlr->port = p->mem[0].bar & ~0x01; + ctlr->port = p->mem[0].bar & ~3; ctlr->pcidev = p; ctlr->id = id; diff --git a/sys/src/9/pc/etherbcm.c b/sys/src/9/pc/etherbcm.c index 6ad24640c..cc96c8976 100644 --- a/sys/src/9/pc/etherbcm.c +++ b/sys/src/9/pc/etherbcm.c @@ -13,6 +13,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/etherdp83820.c b/sys/src/9/pc/etherdp83820.c index 1b466d42a..deb427fb4 100644 --- a/sys/src/9/pc/etherdp83820.c +++ b/sys/src/9/pc/etherdp83820.c @@ -10,6 +10,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/etherelnk3.c b/sys/src/9/pc/etherelnk3.c index 21ce10c65..ff5f173c2 100644 --- a/sys/src/9/pc/etherelnk3.c +++ b/sys/src/9/pc/etherelnk3.c @@ -14,6 +14,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -1475,7 +1476,7 @@ tcm59Xpci(void) */ if(!(p->mem[0].bar & 0x01)) continue; - port = p->mem[0].bar & ~0x01; + port = p->mem[0].bar & ~3; if((port = ioalloc((port == 0)? -1: port, p->mem[0].size, 0, "tcm59Xpci")) < 0){ print("tcm59Xpci: port 0x%uX in use\n", port); diff --git a/sys/src/9/pc/etherga620.c b/sys/src/9/pc/etherga620.c index c57159b7c..7a093d295 100644 --- a/sys/src/9/pc/etherga620.c +++ b/sys/src/9/pc/etherga620.c @@ -16,6 +16,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -1085,7 +1086,7 @@ print("ga620shutdown\n"); static int ga620reset(Ctlr* ctlr) { - int cls, csr, i, r; + int csr, i, r; if(ga620detach(ctlr) < 0) return -1; @@ -1108,9 +1109,10 @@ ga620reset(Ctlr* ctlr) csr = csr32r(ctlr, Ps) & (PCI32|PCI66); csr |= PCIwcmd|PCIrcmd|PCImrm; if(ctlr->pcidev->pcr & 0x0010){ - cls = pcicfgr8(ctlr->pcidev, PciCLS) * 4; - if(cls != 32) - pcicfgw8(ctlr->pcidev, PciCLS, 32/4); + if(ctlr->pcidev->cls != 32/4){ + ctlr->pcidev->cls = 32/4; + pcicfgw8(ctlr->pcidev, PciCLS, ctlr->pcidev->cls); + } csr |= PCIwm32; } csr32w(ctlr, Ps, csr); diff --git a/sys/src/9/pc/etherigbe.c b/sys/src/9/pc/etherigbe.c index ab28a824c..b75dc50dc 100644 --- a/sys/src/9/pc/etherigbe.c +++ b/sys/src/9/pc/etherigbe.c @@ -22,6 +22,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -1910,7 +1911,6 @@ igbereset(Ctlr* ctlr) static void igbepci(void) { - int cls; Pcidev *p; Ctlr *ctlr; void *mem; @@ -1949,8 +1949,7 @@ igbepci(void) print("igbe: can't map %llux\n", p->mem[0].bar & ~0xF); continue; } - cls = pcicfgr8(p, PciCLS); - switch(cls){ + switch(p->cls){ default: print("igbe: p->cls %#ux, setting to 0x10\n", p->cls); p->cls = 0x10; @@ -1969,7 +1968,7 @@ igbepci(void) ctlr->pcidev = p; pcienable(p); ctlr->id = (p->did<<16)|p->vid; - ctlr->cls = cls*4; + ctlr->cls = p->cls*4; ctlr->nic = mem; if(igbereset(ctlr)){ diff --git a/sys/src/9/pc/etheriwl.c b/sys/src/9/pc/etheriwl.c index d91e7ce40..297be586c 100644 --- a/sys/src/9/pc/etheriwl.c +++ b/sys/src/9/pc/etheriwl.c @@ -12,6 +12,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/etherm10g.c b/sys/src/9/pc/etherm10g.c index f74dab554..80a084d65 100644 --- a/sys/src/9/pc/etherm10g.c +++ b/sys/src/9/pc/etherm10g.c @@ -12,6 +12,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/etherrt2860.c b/sys/src/9/pc/etherrt2860.c index bbebc2bab..a545dc5a3 100644 --- a/sys/src/9/pc/etherrt2860.c +++ b/sys/src/9/pc/etherrt2860.c @@ -12,6 +12,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/ethervgbe.c b/sys/src/9/pc/ethervgbe.c index 3249549d0..eaf0a33b5 100644 --- a/sys/src/9/pc/ethervgbe.c +++ b/sys/src/9/pc/ethervgbe.c @@ -27,6 +27,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -942,7 +943,7 @@ vgbepci(void) continue; } - port &= 0xfffe; + port &= 0xfffc; if(size != 256){ print("vgbe: invalid io size: %d\n", size); diff --git a/sys/src/9/pc/ethervirtio.c b/sys/src/9/pc/ethervirtio.c index 92ec308b9..871f6d884 100644 --- a/sys/src/9/pc/ethervirtio.c +++ b/sys/src/9/pc/ethervirtio.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -563,6 +564,9 @@ pciprobe(int typ) /* non-transitional devices will have a revision > 0 */ if(p->rid != 0) continue; + /* first membar needs to be I/O */ + if((p->mem[0].bar & 1) == 0) + continue; /* non-transitional device will have typ+0x40 */ if(pcicfgr16(p, 0x2E) != typ) continue; @@ -570,8 +574,7 @@ pciprobe(int typ) print("ethervirtio: no memory for Ctlr\n"); break; } - - c->port = p->mem[0].bar & ~0x1; + c->port = p->mem[0].bar & ~3; if(ioalloc(c->port, p->mem[0].size, 0, "ethervirtio") < 0){ print("ethervirtio: port %ux in use\n", c->port); free(c); diff --git a/sys/src/9/pc/ethervt6102.c b/sys/src/9/pc/ethervt6102.c index b76d3be8b..9ea47f1ae 100644 --- a/sys/src/9/pc/ethervt6102.c +++ b/sys/src/9/pc/ethervt6102.c @@ -15,6 +15,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -947,7 +948,7 @@ vt6102pci(void) { Pcidev *p; Ctlr *ctlr; - int cls, port; + int port; p = nil; while(p = pcimatch(p, 0, 0)){ @@ -962,7 +963,7 @@ vt6102pci(void) break; } - port = p->mem[0].bar & ~0x01; + port = p->mem[0].bar & ~3; if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){ print("vt6102: port 0x%uX in use\n", port); continue; @@ -977,9 +978,7 @@ vt6102pci(void) ctlr->pcidev = p; pcienable(p); ctlr->id = (p->did<<16)|p->vid; - if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF) - cls = 0x10; - ctlr->cls = cls*4; + ctlr->cls = p->cls*4; ctlr->tft = Ctft64; if(vt6102reset(ctlr)){ diff --git a/sys/src/9/pc/ethervt6105m.c b/sys/src/9/pc/ethervt6105m.c index bd1e4543c..c0f513b52 100644 --- a/sys/src/9/pc/ethervt6105m.c +++ b/sys/src/9/pc/ethervt6105m.c @@ -18,6 +18,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -1112,7 +1113,7 @@ vt6105Mpci(void) { Pcidev *p; Ctlr *ctlr; - int cls, port; + int port; p = nil; while(p = pcimatch(p, 0, 0)){ @@ -1126,7 +1127,7 @@ vt6105Mpci(void) break; } - port = p->mem[0].bar & ~0x01; + port = p->mem[0].bar & ~3; if(ioalloc(port, p->mem[0].size, 0, "vt6105M") < 0){ print("vt6105M: port 0x%uX in use\n", port); continue; @@ -1141,9 +1142,7 @@ vt6105Mpci(void) ctlr->pcidev = p; pcienable(p); ctlr->id = (p->did<<16)|p->vid; - if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF) - cls = 0x10; - ctlr->cls = cls*4; + ctlr->cls = p->cls*4; ctlr->tft = CtftSAF; if(vt6105Mreset(ctlr)){ diff --git a/sys/src/9/pc/etherwavelan.c b/sys/src/9/pc/etherwavelan.c index bc7fc8e8c..4bbc94770 100644 --- a/sys/src/9/pc/etherwavelan.c +++ b/sys/src/9/pc/etherwavelan.c @@ -6,6 +6,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/etherwpi.c b/sys/src/9/pc/etherwpi.c index f43ff64a1..5173c2869 100644 --- a/sys/src/9/pc/etherwpi.c +++ b/sys/src/9/pc/etherwpi.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/etherx550.c b/sys/src/9/pc/etherx550.c index cdea48f04..c35325d14 100644 --- a/sys/src/9/pc/etherx550.c +++ b/sys/src/9/pc/etherx550.c @@ -9,6 +9,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/etheryuk.c b/sys/src/9/pc/etheryuk.c index b856a3465..fca293329 100644 --- a/sys/src/9/pc/etheryuk.c +++ b/sys/src/9/pc/etheryuk.c @@ -8,6 +8,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index 7b15b2e74..1bda49c67 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -125,32 +125,10 @@ void outl(int, ulong); void outsl(int, void*, int); ulong paddr(void*); void patwc(void*, int); -ulong pcibarsize(Pcidev*, int); -void pcibussize(Pcidev*, uvlong*, ulong*); -int pcicfgr8(Pcidev*, int); -int pcicfgr16(Pcidev*, int); -int pcicfgr32(Pcidev*, int); -void pcicfgw8(Pcidev*, int, int); -void pcicfgw16(Pcidev*, int, int); -void pcicfgw32(Pcidev*, int, int); -void pciclrbme(Pcidev*); -void pciclrioe(Pcidev*); -void pciclrmwi(Pcidev*); -int pcigetpms(Pcidev*); -void pcihinv(Pcidev*); -uchar pciipin(Pcidev*, uchar); -Pcidev* pcimatch(Pcidev*, int, int); -Pcidev* pcimatchtbdf(int); -int pcicap(Pcidev*, int); -int pcihtcap(Pcidev*, int); -void pcireset(void); -int pciscan(int, Pcidev**); -void pcisetbme(Pcidev*); -void pcisetioe(Pcidev*); -void pcisetmwi(Pcidev*); -int pcisetpms(Pcidev*, int); -void pcienable(Pcidev*); -void pcidisable(Pcidev*); +void pcicfginit(void); +int (*pcicfgrw8)(int, int, int, int); +int (*pcicfgrw16)(int, int, int, int); +int (*pcicfgrw32)(int, int, int, int); void pcmcisread(PCMslot*); int pcmcistuple(int, int, int, void*, int); PCMmap* pcmmap(int, ulong, int, int); @@ -193,6 +171,7 @@ uvlong tscticks(uvlong*); ulong umballoc(ulong, ulong, ulong); void umbfree(ulong, ulong); uvlong upaalloc(uvlong, ulong, ulong); +uvlong upaallocwin(uvlong, ulong, ulong, ulong); void upafree(uvlong, ulong); void vectortable(void); void* vmap(uvlong, int); diff --git a/sys/src/9/pc/io.h b/sys/src/9/pc/io.h index 6179a47f6..01204ffa3 100644 --- a/sys/src/9/pc/io.h +++ b/sys/src/9/pc/io.h @@ -59,230 +59,18 @@ typedef struct Vctl { void* a; /* argument to call it with */ } Vctl; -enum { - BusCBUS = 0, /* Corollary CBUS */ - BusCBUSII, /* Corollary CBUS II */ - BusEISA, /* Extended ISA */ - BusFUTURE, /* IEEE Futurebus */ - BusINTERN, /* Internal bus */ - BusISA, /* Industry Standard Architecture */ - BusMBI, /* Multibus I */ - BusMBII, /* Multibus II */ - BusMCA, /* Micro Channel Architecture */ - BusMPI, /* MPI */ - BusMPSA, /* MPSA */ - BusNUBUS, /* Apple Macintosh NuBus */ - BusPCI, /* Peripheral Component Interconnect */ - BusPCMCIA, /* PC Memory Card International Association */ - BusTC, /* DEC TurboChannel */ - BusVL, /* VESA Local bus */ - BusVME, /* VMEbus */ - BusXPRESS, /* Express System Bus */ -}; - -#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8)) -#define BUSFNO(tbdf) (((tbdf)>>8)&0x07) -#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F) -#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF) -#define BUSTYPE(tbdf) ((tbdf)>>24) -#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00) -#define BUSUNKNOWN (-1) - enum { MaxEISA = 16, CfgEISA = 0xC80, }; -/* - * PCI support code. - */ -enum { /* type 0 & type 1 pre-defined header */ - PciVID = 0x00, /* vendor ID */ - PciDID = 0x02, /* device ID */ - PciPCR = 0x04, /* command */ - PciPSR = 0x06, /* status */ - PciRID = 0x08, /* revision ID */ - PciCCRp = 0x09, /* programming interface class code */ - PciCCRu = 0x0A, /* sub-class code */ - PciCCRb = 0x0B, /* base class code */ - PciCLS = 0x0C, /* cache line size */ - PciLTR = 0x0D, /* latency timer */ - PciHDT = 0x0E, /* header type */ - PciBST = 0x0F, /* BIST */ - - PciBAR0 = 0x10, /* base address */ - PciBAR1 = 0x14, - - PciCAP = 0x34, /* capabilities pointer */ - PciINTL = 0x3C, /* interrupt line */ - PciINTP = 0x3D, /* interrupt pin */ -}; - -/* ccrb (base class code) values; controller types */ -enum { - Pcibcpci1 = 0, /* pci 1.0; no class codes defined */ - Pcibcstore = 1, /* mass storage */ - Pcibcnet = 2, /* network */ - Pcibcdisp = 3, /* display */ - Pcibcmmedia = 4, /* multimedia */ - Pcibcmem = 5, /* memory */ - Pcibcbridge = 6, /* bridge */ - Pcibccomm = 7, /* simple comms (e.g., serial) */ - Pcibcbasesys = 8, /* base system */ - Pcibcinput = 9, /* input */ - Pcibcdock = 0xa, /* docking stations */ - Pcibcproc = 0xb, /* processors */ - Pcibcserial = 0xc, /* serial bus (e.g., USB) */ - Pcibcwireless = 0xd, /* wireless */ - Pcibcintell = 0xe, /* intelligent i/o */ - Pcibcsatcom = 0xf, /* satellite comms */ - Pcibccrypto = 0x10, /* encryption/decryption */ - Pcibcdacq = 0x11, /* data acquisition & signal proc. */ -}; - -/* ccru (sub-class code) values; common cases only */ -enum { - /* mass storage */ - Pciscscsi = 0, /* SCSI */ - Pciscide = 1, /* IDE (ATA) */ - - /* network */ - Pciscether = 0, /* Ethernet */ - - /* display */ - Pciscvga = 0, /* VGA */ - Pciscxga = 1, /* XGA */ - Pcisc3d = 2, /* 3D */ - - /* bridges */ - Pcischostpci = 0, /* host/pci */ - Pciscpcicpci = 1, /* pci/pci */ - - /* simple comms */ - Pciscserial = 0, /* 16450, etc. */ - Pciscmultiser = 1, /* multiport serial */ - - /* serial bus */ - Pciscusb = 3, /* USB */ -}; - -enum { /* type 0 pre-defined header */ - PciCIS = 0x28, /* cardbus CIS pointer */ - PciSVID = 0x2C, /* subsystem vendor ID */ - PciSID = 0x2E, /* subsystem ID */ - PciEBAR0 = 0x30, /* expansion ROM base address */ - PciMGNT = 0x3E, /* burst period length */ - PciMLT = 0x3F, /* maximum latency between bursts */ -}; - -enum { /* type 1 pre-defined header */ - PciPBN = 0x18, /* primary bus number */ - PciSBN = 0x19, /* secondary bus number */ - PciUBN = 0x1A, /* subordinate bus number */ - PciSLTR = 0x1B, /* secondary latency timer */ - PciIBR = 0x1C, /* I/O base */ - PciILR = 0x1D, /* I/O limit */ - PciSPSR = 0x1E, /* secondary status */ - PciMBR = 0x20, /* memory base */ - PciMLR = 0x22, /* memory limit */ - PciPMBR = 0x24, /* prefetchable memory base */ - PciPMLR = 0x26, /* prefetchable memory limit */ - PciPUBR = 0x28, /* prefetchable base upper 32 bits */ - PciPULR = 0x2C, /* prefetchable limit upper 32 bits */ - PciIUBR = 0x30, /* I/O base upper 16 bits */ - PciIULR = 0x32, /* I/O limit upper 16 bits */ - PciEBAR1 = 0x28, /* expansion ROM base address */ - PciBCR = 0x3E, /* bridge control register */ -}; - -enum { /* type 2 pre-defined header */ - PciCBExCA = 0x10, - PciCBSPSR = 0x16, - PciCBPBN = 0x18, /* primary bus number */ - PciCBSBN = 0x19, /* secondary bus number */ - PciCBUBN = 0x1A, /* subordinate bus number */ - PciCBSLTR = 0x1B, /* secondary latency timer */ - PciCBMBR0 = 0x1C, - PciCBMLR0 = 0x20, - PciCBMBR1 = 0x24, - PciCBMLR1 = 0x28, - PciCBIBR0 = 0x2C, /* I/O base */ - PciCBILR0 = 0x30, /* I/O limit */ - PciCBIBR1 = 0x34, /* I/O base */ - PciCBILR1 = 0x38, /* I/O limit */ - PciCBSVID = 0x40, /* subsystem vendor ID */ - PciCBSID = 0x42, /* subsystem ID */ - PciCBLMBAR = 0x44, /* legacy mode base address */ -}; - -/* capabilities */ -enum { - PciCapPMG = 0x01, /* power management */ - PciCapAGP = 0x02, - PciCapVPD = 0x03, /* vital product data */ - PciCapSID = 0x04, /* slot id */ - PciCapMSI = 0x05, - PciCapCHS = 0x06, /* compact pci hot swap */ - PciCapPCIX = 0x07, - PciCapHTC = 0x08, /* hypertransport irq conf */ - PciCapVND = 0x09, /* vendor specific information */ - PciCapPCIe = 0x10, - PciCapMSIX = 0x11, - PciCapSATA = 0x12, - PciCapHSW = 0x0c, /* hot swap */ -}; - -typedef struct Pcidev Pcidev; -struct Pcidev -{ - int tbdf; /* type+bus+device+function */ - ushort vid; /* vendor ID */ - ushort did; /* device ID */ - - ushort pcr; - - uchar rid; - uchar ccrp; - uchar ccru; - uchar ccrb; - uchar cls; - uchar ltr; - - struct { - uvlong bar; /* base address */ - int size; - } mem[6]; - - struct { - uvlong bar; - int size; - } rom; - uchar intl; /* interrupt line */ - - Pcidev* list; - Pcidev* link; /* next device on this bno */ - - Pcidev* parent; /* up a bus */ - Pcidev* bridge; /* down a bus */ - struct { - uvlong bar; - int size; - } ioa, mema; - - int pmrb; /* power management register block */ -}; - -enum { - /* vendor ids */ - Vintel = 0x8086, - Vmyricom= 0x14c1, -}; - #define PCIWINDOW 0 #define PCIWADDR(va) (PADDR(va)+PCIWINDOW) #define ISAWINDOW 0 #define ISAWADDR(va) (PADDR(va)+ISAWINDOW) +#define BUSUNKNOWN (-1) + /* SMBus transactions */ enum { @@ -387,6 +175,3 @@ struct PCMslot int time; PCMmap mmap[4]; /* maps, last is always for the kernel */ }; - -#pragma varargck type "T" int -#pragma varargck type "T" uint diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index 01fa783ad..231a62ad3 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -40,6 +40,7 @@ main(void) ramdiskinit(); confinit(); xinit(); + pcicfginit(); bootscreeninit(); if(i8237alloc != nil) i8237alloc(); @@ -57,7 +58,6 @@ main(void) initseg(); if(delaylink){ bootlinks(); - pcimatch(0, 0, 0); }else links(); chandevreset(); diff --git a/sys/src/9/pc/memory.c b/sys/src/9/pc/memory.c index 04cf3b9fe..e5eefd17b 100644 --- a/sys/src/9/pc/memory.c +++ b/sys/src/9/pc/memory.c @@ -250,6 +250,24 @@ upaalloc(uvlong pa, ulong size, ulong align) return memmapalloc(pa, size, align, MemUPA); } +uvlong +upaallocwin(uvlong pa, ulong win, ulong size, ulong align) +{ + uvlong a, base, top = pa + win; + + for(base = memmapnext(-1, MemUPA); base != -1 && base < top; base = memmapnext(base, MemUPA)){ + if(base < pa){ + if(pa >= base + memmapsize(base, 0)) + continue; + base = pa; + } + a = upaalloc(base, size, align); + if(a != -1) + return a; + } + return -1ULL; +} + void upafree(uvlong pa, ulong size) { diff --git a/sys/src/9/pc/mp.c b/sys/src/9/pc/mp.c index 382e247f7..60b720c81 100644 --- a/sys/src/9/pc/mp.c +++ b/sys/src/9/pc/mp.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "ureg.h" #include "mp.h" diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index e4171f127..3f7816d6e 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -27,7 +27,7 @@ dev draw screen vga vgax vgasoft mouse mouse kbd - vga + vga pci sd floppy dma @@ -35,7 +35,7 @@ dev lpt audio dma - pccard + pccard pci i82365 cis uart usb @@ -45,11 +45,11 @@ dev link segdesc - devpccard + devpccard pci devi82365 - cputemp + cputemp pci apm apmjump - ether2000 ether8390 + ether2000 pci ether8390 ether2114x pci ether589 etherelnk3 ether79c970 pci @@ -73,7 +73,7 @@ link ethervt6102 pci ethermii ethervt6105m pci ethermii ethersink - ethersmc devi82365 cis + ethersmc pci devi82365 cis etheryuk pci etherwavelan wavelan devi82365 cis pci etheriwl pci wifi @@ -84,16 +84,18 @@ link pcmciamodem netdevmedium loopbackmedium - usbuhci - usbohci + usbuhci pci + usbohci pci usbehci usbehcipc usbxhci pci audiosb16 dma - audioac97 audioac97mix - audiohda + audioac97 pci audioac97mix + audiohda pci misc + pci pcipc + archacpi mp apic squidboy ec archmp mp apic squidboy mtrr diff --git a/sys/src/9/pc/pci.c b/sys/src/9/pc/pci.c deleted file mode 100644 index 3d3239e18..000000000 --- a/sys/src/9/pc/pci.c +++ /dev/null @@ -1,1647 +0,0 @@ -/* - * PCI support code. - * Needs a massive rewrite. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define DBG if(0) print - -enum -{ /* configuration mechanism #1 */ - PciADDR = 0xCF8, /* CONFIG_ADDRESS */ - PciDATA = 0xCFC, /* CONFIG_DATA */ - - /* configuration mechanism #2 */ - PciCSE = 0xCF8, /* configuration space enable */ - PciFORWARD = 0xCFA, /* which bus */ - - MaxFNO = 7, - MaxUBN = 255, -}; - -enum -{ /* command register */ - IOen = (1<<0), - MEMen = (1<<1), - MASen = (1<<2), - MemWrInv = (1<<4), - PErrEn = (1<<6), - 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; -static int pcimaxbno = 255; -static int pcimaxdno; -static Pcidev* pciroot; -static Pcidev* pcilist; -static Pcidev* pcitail; -static int nobios, nopcirouting; -static BIOS32si* pcibiossi; - -static int pcicfgrw8raw(int, int, int, int); -static int pcicfgrw16raw(int, int, int, int); -static int pcicfgrw32raw(int, int, int, int); - -static int (*pcicfgrw8)(int, int, int, int) = pcicfgrw8raw; -static int (*pcicfgrw16)(int, int, int, int) = pcicfgrw16raw; -static int (*pcicfgrw32)(int, int, int, int) = pcicfgrw32raw; - -static char* bustypes[] = { - "CBUSI", - "CBUSII", - "EISA", - "FUTURE", - "INTERN", - "ISA", - "MBI", - "MBII", - "MCA", - "MPI", - "MPSA", - "NUBUS", - "PCI", - "PCMCIA", - "TC", - "VL", - "VME", - "XPRESS", -}; - -static int -tbdffmt(Fmt* fmt) -{ - char *p; - int l, r; - uint type, tbdf; - - if((p = malloc(READSTR)) == nil) - return fmtstrcpy(fmt, "(tbdfconv)"); - - 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)); - } - break; - - default: - snprint(p, READSTR, "(tbdfconv)"); - break; - } - r = fmtstrcpy(fmt, p); - free(p); - - return r; -} - -ulong -pcibarsize(Pcidev *p, int rno) -{ - ulong v, size; - - v = pcicfgrw32(p->tbdf, rno, 0, 1); - pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0); - size = pcicfgrw32(p->tbdf, rno, 0, 1); - if(v & 1) - size |= 0xFFFF0000; - pcicfgrw32(p->tbdf, rno, v, 0); - - return -(size & ~0x0F); -} - -static int -pcisizcmp(void *a, void *b) -{ - Pcisiz *aa, *bb; - - aa = a; - bb = b; - return aa->siz - bb->siz; -} - -static ulong -pcimask(ulong v) -{ - ulong m; - - m = BI2BY*sizeof(v); - for(m = 1<<(m-1); m != 0; m >>= 1) { - if(m & v) - break; - } - - m--; - if((v & m) == 0) - return v; - - v |= m; - return v+1; -} - -static void -pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg) -{ - Pcidev *p; - int ntb, i, size, rno, hole; - uvlong mema, smema, base, limit; - ulong ioa, sioa, v; - Pcisiz *table, *tptr, *mtb, *itb; - - if(!nobios) - return; - - ioa = *pioa; - mema = *pmema; - - DBG("pcibusmap wr=%d %T mem=%lluX io=%luX\n", - wrreg, root->tbdf, mema, ioa); - - ntb = 0; - for(p = root; p != nil; p = p->link) - ntb++; - - ntb *= (PciCIS-PciBAR0)/4; - table = malloc(2*ntb*sizeof(Pcisiz)); - if(table == nil) - panic("pcibusmap: can't allocate memory"); - itb = table; - mtb = table+ntb; - - /* - * Build a table of sizes - */ - for(p = root; p != nil; p = p->link) { - if(p->ccrb == 0x06) { - if(p->ccru != 0x04 || p->bridge == nil) { - DBG("pci: ignored bridge %T\n", p->tbdf); - continue; - } - - sioa = ioa; - smema = mema; - pcibusmap(p->bridge, &smema, &sioa, 0); - - hole = pcimask(smema-mema); - if(hole < (1<<20)) - hole = 1<<20; - p->mema.size = hole; - - hole = pcimask(sioa-ioa); - if(hole < (1<<12)) - hole = 1<<12; - - p->ioa.size = hole; - - 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 < nelem(p->mem); i++) { - rno = PciBAR0 + i*4; - v = pcicfgrw32(p->tbdf, rno, 0, 1); - size = pcibarsize(p, rno); - if(size == 0) - continue; - - p->mem[i].size = size; - if(v & 1) { - itb->dev = p; - itb->bar = i; - itb->siz = size; - itb->typ = 1; - itb++; - } - else { - mtb->dev = p; - mtb->bar = i; - mtb->siz = size; - mtb->typ = v & 7; - if(mtb->typ & 4) - i++; - mtb++; - } - } - } - - /* - * Sort both tables IO smallest first, Memory largest - */ - qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp); - tptr = table+ntb; - qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp); - - /* - * Allocate IO address space on this bus - */ - for(tptr = table; tptr < itb; tptr++) { - hole = tptr->siz; - if(tptr->bar == -1) - hole = 1<<12; - ioa = (ioa+hole-1) & ~(hole-1); - - p = tptr->dev; - if(tptr->bar == -1) - p->ioa.bar = ioa; - else { - p->pcr |= IOen; - p->mem[tptr->bar].bar = ioa|1; - if(wrreg) - pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0); - } - - ioa += tptr->siz; - } - - /* - * Allocate Memory address space on this bus - */ - for(tptr = table+ntb; tptr < mtb; tptr++) { - hole = tptr->siz; - if(tptr->bar == -1) - hole = 1<<20; - 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|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; - } - - *pmema = mema; - *pioa = ioa; - free(table); - - if(wrreg == 0) - return; - - /* - * Finally set all the bridge addresses & registers - */ - for(p = root; p != nil; p = p->link) { - if(p->bridge == nil) { - pcicfgrw8(p->tbdf, PciLTR, 64, 0); - - p->pcr |= MASen; - pcicfgrw16(p->tbdf, PciPCR, p->pcr, 0); - continue; - } - - base = p->ioa.bar; - limit = base+p->ioa.size-1; - v = pcicfgrw32(p->tbdf, PciIBR, 0, 1); - v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8); - pcicfgrw32(p->tbdf, PciIBR, v, 0); - v = (limit & 0xFFFF0000)|(base>>16); - pcicfgrw32(p->tbdf, PciIUBR, v, 0); - - base = p->mema.bar; - limit = base+p->mema.size-1; - v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16); - pcicfgrw32(p->tbdf, PciMBR, v, 0); - - /* - * Disable memory prefetch - */ - pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0); - pcicfgrw8(p->tbdf, PciLTR, 64, 0); - - /* - * Enable the bridge - */ - p->pcr |= IOen|MEMen|MASen; - pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr , 0); - - sioa = p->ioa.bar; - smema = p->mema.bar; - pcibusmap(p->bridge, &smema, &sioa, 1); - } -} - -static int -pcilscan(int bno, Pcidev** list, Pcidev *parent) -{ - Pcidev *p, *head, *tail; - int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn; - - maxubn = bno; - head = nil; - tail = nil; - for(dno = 0; dno <= pcimaxdno; dno++){ - maxfno = 0; - for(fno = 0; fno <= maxfno; fno++){ - /* - * For this possible device, form the - * bus+device+function triplet needed to address it - * and try to read the vendor and device ID. - * If successful, allocate a device struct and - * start to fill it in with some useful information - * from the device's configuration space. - */ - tbdf = MKBUS(BusPCI, bno, dno, fno); - l = pcicfgrw32(tbdf, PciVID, 0, 1); - if(l == 0xFFFFFFFF || l == 0) - continue; - p = malloc(sizeof(*p)); - if(p == nil) - panic("pcilscan: can't allocate memory"); - p->tbdf = tbdf; - p->vid = l; - p->did = l>>16; - - if(pcilist != nil) - pcitail->list = p; - else - pcilist = p; - pcitail = p; - - p->pcr = pcicfgr16(p, PciPCR); - p->rid = pcicfgr8(p, PciRID); - p->ccrp = pcicfgr8(p, PciCCRp); - p->ccru = pcicfgr8(p, PciCCRu); - p->ccrb = pcicfgr8(p, PciCCRb); - p->cls = pcicfgr8(p, PciCLS); - p->ltr = pcicfgr8(p, PciLTR); - - p->intl = pcicfgr8(p, PciINTL); - - /* - * If the device is a multi-function device adjust the - * loop count so all possible functions are checked. - */ - hdt = pcicfgr8(p, PciHDT); - if(hdt & 0x80) - maxfno = MaxFNO; - - /* - * If appropriate, read the base address registers - * and work out the sizes. - */ - switch(p->ccrb) { - case 0x00: /* prehistoric */ - 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 */ - case 0x0D: /* wireless controllers */ - case 0x0E: /* intelligent I/O controllers */ - case 0x0F: /* sattelite communication controllers */ - case 0x10: /* encryption/decryption controllers */ - case 0x11: /* signal processing controllers */ - if((hdt & 0x7F) != 0) - break; - rno = PciBAR0; - 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 < nelem(p->mem)-1){ - rno += 4; - p->mem[i++].bar |= (uvlong)pcicfgr32(p, rno) << 32; - p->mem[i].bar = 0; - p->mem[i].size = 0; - } - rno += 4; - } - break; - - case 0x05: /* memory controller */ - case 0x06: /* bridge device */ - default: - break; - } - - p->parent = parent; - if(head != nil) - tail->link = p; - else - head = p; - tail = p; - } - } - - *list = head; - for(p = head; p != nil; p = p->link){ - /* - * Find PCI-PCI bridges and recursively descend the tree. - */ - if(p->ccrb != 0x06 || p->ccru != 0x04) - continue; - - /* - * If the secondary or subordinate bus number is not - * initialised try to do what the PCI BIOS should have - * done and fill in the numbers as the tree is descended. - * On the way down the subordinate bus number is set to - * the maximum as it's not known how many buses are behind - * this one; the final value is set on the way back up. - */ - sbn = pcicfgr8(p, PciSBN); - ubn = pcicfgr8(p, PciUBN); - - if(sbn == 0 || ubn == 0 || nobios) { - sbn = maxubn+1; - /* - * Make sure memory, I/O and master enables are - * off, set the primary, secondary and subordinate - * bus numbers and clear the secondary status before - * attempting to scan the secondary bus. - * - * Initialisation of the bridge should be done here. - */ - pcicfgw32(p, PciPCR, 0xFFFF0000); - l = (MaxUBN<<16)|(sbn<<8)|bno; - pcicfgw32(p, PciPBN, l); - pcicfgw16(p, PciSPSR, 0xFFFF); - maxubn = pcilscan(sbn, &p->bridge, p); - l = (maxubn<<16)|(sbn<<8)|bno; - - pcicfgw32(p, PciPBN, l); - } - else { - if(ubn > maxubn) - maxubn = ubn; - pcilscan(sbn, &p->bridge, p); - } - } - - return maxubn; -} - -int -pciscan(int bno, Pcidev **list) -{ - int ubn; - - lock(&pcicfginitlock); - ubn = pcilscan(bno, list, nil); - unlock(&pcicfginitlock); - return ubn; -} - -static uchar -pIIxget(Pcidev *router, uchar link) -{ - uchar pirq; - - /* link should be 0x60, 0x61, 0x62, 0x63 */ - pirq = pcicfgr8(router, link); - return (pirq < 16)? pirq: 0; -} - -static void -pIIxset(Pcidev *router, uchar link, uchar irq) -{ - pcicfgw8(router, link, irq); -} - -static uchar -viaget(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 -viaset(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 -optiget(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 -optiset(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 -aliget(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 -aliset(Pcidev *router, uchar link, uchar irq) -{ - /* Inverse of map in aliget */ - 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 -cyrixget(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 -cyrixset(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); -} - -typedef struct Bridge Bridge; -struct Bridge -{ - ushort vid; - ushort did; - uchar (*get)(Pcidev *, uchar); - void (*set)(Pcidev *, uchar, uchar); -}; - -static Bridge southbridges[] = { - { 0x8086, 0x122e, pIIxget, pIIxset }, /* Intel 82371FB */ - { 0x8086, 0x1234, pIIxget, pIIxset }, /* Intel 82371MX */ - { 0x8086, 0x7000, pIIxget, pIIxset }, /* Intel 82371SB */ - { 0x8086, 0x7110, pIIxget, pIIxset }, /* Intel 82371AB */ - { 0x8086, 0x7198, pIIxget, pIIxset }, /* Intel 82443MX (fn 1) */ - { 0x8086, 0x2410, pIIxget, pIIxset }, /* Intel 82801AA */ - { 0x8086, 0x2420, pIIxget, pIIxset }, /* Intel 82801AB */ - { 0x8086, 0x2440, pIIxget, pIIxset }, /* Intel 82801BA */ - { 0x8086, 0x2448, pIIxget, pIIxset }, /* Intel 82801BAM/CAM/DBM */ - { 0x8086, 0x244c, pIIxget, pIIxset }, /* Intel 82801BAM */ - { 0x8086, 0x244e, pIIxget, pIIxset }, /* Intel 82801 */ - { 0x8086, 0x2480, pIIxget, pIIxset }, /* Intel 82801CA */ - { 0x8086, 0x248c, pIIxget, pIIxset }, /* Intel 82801CAM */ - { 0x8086, 0x24c0, pIIxget, pIIxset }, /* Intel 82801DBL */ - { 0x8086, 0x24cc, pIIxget, pIIxset }, /* Intel 82801DBM */ - { 0x8086, 0x24d0, pIIxget, pIIxset }, /* Intel 82801EB */ - { 0x8086, 0x25a1, pIIxget, pIIxset }, /* Intel 6300ESB */ - { 0x8086, 0x2640, pIIxget, pIIxset }, /* Intel 82801FB */ - { 0x8086, 0x2641, pIIxget, pIIxset }, /* Intel 82801FBM */ - { 0x8086, 0x2670, pIIxget, pIIxset }, /* Intel 632xesb */ - { 0x8086, 0x27b8, pIIxget, pIIxset }, /* Intel 82801GB */ - { 0x8086, 0x27b9, pIIxget, pIIxset }, /* Intel 82801GBM */ - { 0x8086, 0x27bd, pIIxget, pIIxset }, /* Intel 82801GB/GR */ - { 0x8086, 0x3a16, pIIxget, pIIxset }, /* Intel 82801JIR */ - { 0x8086, 0x3a40, pIIxget, pIIxset }, /* Intel 82801JI */ - { 0x8086, 0x3a42, pIIxget, pIIxset }, /* Intel 82801JI */ - { 0x8086, 0x3a48, pIIxget, pIIxset }, /* Intel 82801JI */ - { 0x8086, 0x2916, pIIxget, pIIxset }, /* Intel 82801? */ - { 0x8086, 0x1c02, pIIxget, pIIxset }, /* Intel 6 Series/C200 */ - { 0x8086, 0x1e53, pIIxget, pIIxset }, /* Intel 7 Series/C216 */ - { 0x8086, 0x8c56, pIIxget, pIIxset }, /* Intel 8 Series/C226 */ - { 0x8086, 0x2810, pIIxget, pIIxset }, /* Intel 82801HB/HR (ich8/r) */ - { 0x8086, 0x2812, pIIxget, pIIxset }, /* Intel 82801HH (ich8dh) */ - { 0x8086, 0x2912, pIIxget, pIIxset }, /* Intel 82801ih ich9dh */ - { 0x8086, 0x2914, pIIxget, pIIxset }, /* Intel 82801io ich9do */ - { 0x8086, 0x2916, pIIxget, pIIxset }, /* Intel 82801ibr ich9r */ - { 0x8086, 0x2917, pIIxget, pIIxset }, /* Intel 82801iem ich9m-e */ - { 0x8086, 0x2918, pIIxget, pIIxset }, /* Intel 82801ib ich9 */ - { 0x8086, 0x2919, pIIxget, pIIxset }, /* Intel 82801? ich9m */ - { 0x8086, 0x3a16, pIIxget, pIIxset }, /* Intel 82801jir ich10r */ - { 0x8086, 0x3a18, pIIxget, pIIxset }, /* Intel 82801jib ich10 */ - { 0x8086, 0x3a40, pIIxget, pIIxset }, /* Intel 82801ji */ - { 0x8086, 0x3a42, pIIxget, pIIxset }, /* Intel 82801ji */ - { 0x8086, 0x3a48, pIIxget, pIIxset }, /* Intel 82801ji */ - { 0x8086, 0x3b06, pIIxget, pIIxset }, /* Intel 82801? ibex peak */ - { 0x8086, 0x3b14, pIIxget, pIIxset }, /* Intel 82801? 3420 */ - { 0x8086, 0x1c49, pIIxget, pIIxset }, /* Intel 82hm65 cougar point pch */ - { 0x8086, 0x1c4b, pIIxget, pIIxset }, /* Intel 82hm67 */ - { 0x8086, 0x1c4f, pIIxget, pIIxset }, /* Intel 82qm67 cougar point pch */ - { 0x8086, 0x1c52, pIIxget, pIIxset }, /* Intel 82q65 cougar point pch */ - { 0x8086, 0x1c54, pIIxget, pIIxset }, /* Intel 82q67 cougar point pch */ - { 0x8086, 0x1e55, pIIxget, pIIxset }, /* Intel QM77 panter point lpc */ - - { 0x1106, 0x0586, viaget, viaset }, /* Viatech 82C586 */ - { 0x1106, 0x0596, viaget, viaset }, /* Viatech 82C596 */ - { 0x1106, 0x0686, viaget, viaset }, /* Viatech 82C686 */ - { 0x1106, 0x3177, viaget, viaset }, /* Viatech VT8235 */ - { 0x1106, 0x3227, viaget, viaset }, /* Viatech VT8237 */ - { 0x1106, 0x3287, viaget, viaset }, /* Viatech VT8251 */ - { 0x1106, 0x8410, viaget, viaset }, /* Viatech PV530 bridge */ - { 0x1045, 0xc700, optiget, optiset }, /* Opti 82C700 */ - { 0x10b9, 0x1533, aliget, aliset }, /* Al M1533 */ - { 0x1039, 0x0008, pIIxget, pIIxset }, /* SI 503 */ - { 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 */ - { 0x10de, 0x00e1, nil, nil }, /* NVIDIA nForce 3 250 Series */ - { 0x1166, 0x0200, nil, nil }, /* ServerWorks ServerSet III LE */ - { 0x1002, 0x4377, nil, nil }, /* ATI Radeon Xpress 200M */ - { 0x1002, 0x4372, nil, nil }, /* ATI SB400 */ - { 0x1002, 0x9601, nil, nil }, /* AMD SB710 */ - { 0x1002, 0x438d, nil, nil }, /* AMD SB600 */ - { 0x1002, 0x439d, nil, nil }, /* AMD SB810 */ -}; - -typedef struct Slot Slot; -struct Slot { - uchar bus; /* Pci bus number */ - uchar dev; /* Pci device number */ - uchar maps[12]; /* Avoid structs! Link and mask. */ - uchar slot; /* Add-in/built-in slot */ - uchar reserved; -}; - -typedef struct Router Router; -struct Router { - uchar signature[4]; /* Routing table signature */ - uchar version[2]; /* Version number */ - uchar size[2]; /* Total table size */ - uchar bus; /* Interrupt router bus number */ - uchar devfn; /* Router's devfunc */ - uchar pciirqs[2]; /* Exclusive PCI irqs */ - uchar compat[4]; /* Compatible PCI interrupt router */ - uchar miniport[4]; /* Miniport data */ - uchar reserved[11]; - uchar checksum; -}; - -static ushort pciirqs; /* Exclusive PCI irqs */ -static Bridge *southbridge; /* Which southbridge to use. */ - -static void -pcirouting(void) -{ - Slot *e; - Router *r; - int i, size, tbdf; - Pcidev *sbpci, *pci; - uchar *p, pin, irq, link, *map; - - if((p = sigsearch("$PIR", 0)) == nil) - return; - - r = (Router*)p; - size = (r->size[1] << 8)|r->size[0]; - if(size < sizeof(Router) || checksum(r, size)) - return; - - if(0) print("PCI interrupt routing table version %d.%d at %p\n", - r->version[0], r->version[1], r); - - tbdf = MKBUS(BusPCI, r->bus, (r->devfn>>3)&0x1f, r->devfn&7); - sbpci = pcimatchtbdf(tbdf); - if(sbpci == nil) { - print("pcirouting: Cannot find south bridge %T\n", tbdf); - return; - } - - for(i = 0; i < nelem(southbridges); i++) - if(sbpci->vid == southbridges[i].vid && sbpci->did == southbridges[i].did) - break; - - if(i == nelem(southbridges)) { - print("pcirouting: ignoring south bridge %T %.4uX/%.4uX\n", tbdf, sbpci->vid, sbpci->did); - return; - } - southbridge = &southbridges[i]; - if(southbridge->get == nil) - return; - - pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0]; - for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) { - if(0) { - print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot); - for (i = 0; i < 4; i++) { - map = &e->maps[i * 3]; - print("[%d] %.2uX %.4uX ", i, map[0], (map[2] << 8)|map[1]); - } - print("\n"); - } - for(i = 0; i < 8; i++) { - tbdf = MKBUS(BusPCI, e->bus, (e->dev>>3)&0x1f, i); - pci = pcimatchtbdf(tbdf); - if(pci == nil) - continue; - pin = pcicfgr8(pci, PciINTP); - if(pin == 0 || pin == 0xff) - continue; - - map = &e->maps[((pin - 1) % 4) * 3]; - link = map[0]; - irq = southbridge->get(sbpci, link); - if(irq == pci->intl) - continue; - if(irq == 0 || (irq & 0x80) != 0){ - irq = pci->intl; - if(irq == 0 || irq == 0xff) - continue; - if(southbridge->set == nil) - continue; - southbridge->set(sbpci, link, irq); - } - print("pcirouting: %T at pin %d link %.2uX irq %d -> %d\n", tbdf, pin, link, pci->intl, irq); - pcicfgw8(pci, PciINTL, irq); - pci->intl = irq; - } - } -} - -static void pcireservemem(void); - -static int -pcicfgrw8bios(int tbdf, int rno, int data, int read) -{ - BIOS32ci ci; - - if(pcibiossi == nil) - return -1; - - memset(&ci, 0, sizeof(BIOS32ci)); - ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf); - ci.edi = rno; - if(read){ - ci.eax = 0xB108; - if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) - return ci.ecx & 0xFF; - } - else{ - ci.eax = 0xB10B; - ci.ecx = data & 0xFF; - if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) - return 0; - } - - return -1; -} - -static int -pcicfgrw16bios(int tbdf, int rno, int data, int read) -{ - BIOS32ci ci; - - if(pcibiossi == nil) - return -1; - - memset(&ci, 0, sizeof(BIOS32ci)); - ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf); - ci.edi = rno; - if(read){ - ci.eax = 0xB109; - if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) - return ci.ecx & 0xFFFF; - } - else{ - ci.eax = 0xB10C; - ci.ecx = data & 0xFFFF; - if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) - return 0; - } - - return -1; -} - -static int -pcicfgrw32bios(int tbdf, int rno, int data, int read) -{ - BIOS32ci ci; - - if(pcibiossi == nil) - return -1; - - memset(&ci, 0, sizeof(BIOS32ci)); - ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf); - ci.edi = rno; - if(read){ - ci.eax = 0xB10A; - if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) - return ci.ecx; - } - else{ - ci.eax = 0xB10D; - ci.ecx = data; - if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) - return 0; - } - - return -1; -} - -static BIOS32si* -pcibiosinit(void) -{ - BIOS32ci ci; - BIOS32si *si; - - if((si = bios32open("$PCI")) == nil) - return nil; - - memset(&ci, 0, sizeof(BIOS32ci)); - ci.eax = 0xB101; - if(bios32ci(si, &ci) || ci.edx != ((' '<<24)|('I'<<16)|('C'<<8)|'P')){ - free(si); - return nil; - } - if(ci.eax & 0x01) - pcimaxdno = 31; - else - pcimaxdno = 15; - pcimaxbno = ci.ecx & 0xff; - - return si; -} - -void -pcibussize(Pcidev *root, uvlong *msize, ulong *iosize) -{ - *msize = 0; - *iosize = 0; - pcibusmap(root, msize, iosize, 0); -} - -static void -pcicfginit(void) -{ - char *p; - Pcidev **list; - uvlong mema; - ulong ioa; - int bno, n, pcibios; - - lock(&pcicfginitlock); - if(pcicfgmode != -1) - goto out; - - pcibios = 0; - if(getconf("*nobios")) - nobios = 1; - else if(getconf("*pcibios")) - pcibios = 1; - if(getconf("*nopcirouting")) - nopcirouting = 1; - - /* - * Try to determine which PCI configuration mode is implemented. - * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses - * a DWORD at 0xCF8 and another at 0xCFC and will pass through - * any non-DWORD accesses as normal I/O cycles. There shouldn't be - * a device behind these addresses so if Mode1 accesses fail try - * for Mode2 (Mode2 is deprecated). - */ - if(!pcibios){ - /* - * Bits [30:24] of PciADDR must be 0, - * according to the spec. - */ - n = inl(PciADDR); - if(!(n & 0x7F000000)){ - outl(PciADDR, 0x80000000); - outb(PciADDR+3, 0); - if(inl(PciADDR) & 0x80000000){ - pcicfgmode = 1; - pcimaxdno = 31; - } - } - outl(PciADDR, n); - - if(pcicfgmode < 0){ - /* - * The 'key' part of PciCSE should be 0. - */ - n = inb(PciCSE); - if(!(n & 0xF0)){ - outb(PciCSE, 0x0E); - if(inb(PciCSE) == 0x0E){ - pcicfgmode = 2; - pcimaxdno = 15; - } - } - outb(PciCSE, n); - } - } - - if(pcicfgmode < 0 || pcibios) { - if((pcibiossi = pcibiosinit()) == nil) - goto out; - pcicfgrw8 = pcicfgrw8bios; - pcicfgrw16 = pcicfgrw16bios; - pcicfgrw32 = pcicfgrw32bios; - pcicfgmode = 3; - } - - fmtinstall('T', tbdffmt); - - if(p = getconf("*pcimaxbno")) - pcimaxbno = strtoul(p, 0, 0); - if(p = getconf("*pcimaxdno")){ - n = strtoul(p, 0, 0); - if(n < pcimaxdno) - pcimaxdno = n; - } - - list = &pciroot; - for(bno = 0; bno <= pcimaxbno; bno++) { - int sbno = bno; - bno = pcilscan(bno, list, nil); - - while(*list) - list = &(*list)->link; - - if (sbno == 0) { - Pcidev *pci; - - /* - * If we have found a PCI-to-Cardbus bridge, make sure - * it has no valid mappings anymore. - */ - for(pci = pciroot; pci != nil; pci = pci->link){ - if (pci->ccrb == 6 && pci->ccru == 7) { - ushort bcr; - - /* reset the cardbus */ - bcr = pcicfgr16(pci, PciBCR); - pcicfgw16(pci, PciBCR, 0x40 | bcr); - delay(50); - } - } - } - } - - if(pciroot == nil) - goto out; - - if(nobios) { - /* - * Work out how big the top bus is - */ - pcibussize(pciroot, &mema, &ioa); - - /* - * Align the windows and map it - */ - ioa = 0x1000; - mema = 0x90000000; - - DBG("Mask sizes: mem=%llux io=%lux\n", mema, ioa); - - pcibusmap(pciroot, &mema, &ioa, 1); - DBG("Sizes2: mem=%llux io=%lux\n", mema, ioa); - - goto out; - } - - if(!nopcirouting) - pcirouting(); - -out: - pcireservemem(); - unlock(&pcicfginitlock); - - if(getconf("*pcihinv")) - 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].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 -pcicfgrw8raw(int tbdf, int rno, int data, int read) -{ - int o, type, x; - - if(pcicfgmode == -1) - pcicfginit(); - - if(BUSBNO(tbdf)) - type = 0x01; - else - type = 0x00; - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - lock(&pcicfglock); - switch(pcicfgmode){ - - case 1: - o = rno & 0x03; - rno &= ~0x03; - outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); - if(read) - x = inb(PciDATA+o); - else - outb(PciDATA+o, data); - outl(PciADDR, 0); - break; - - case 2: - outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); - outb(PciFORWARD, BUSBNO(tbdf)); - if(read) - x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno); - else - outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); - outb(PciCSE, 0); - break; - } - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr8(Pcidev* pcidev, int rno) -{ - return pcicfgrw8(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw8(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw8(pcidev->tbdf, rno, data, 0); -} - -static int -pcicfgrw16raw(int tbdf, int rno, int data, int read) -{ - int o, type, x; - - if(pcicfgmode == -1) - pcicfginit(); - - if(BUSBNO(tbdf)) - type = 0x01; - else - type = 0x00; - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - lock(&pcicfglock); - switch(pcicfgmode){ - - case 1: - o = rno & 0x02; - rno &= ~0x03; - outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); - if(read) - x = ins(PciDATA+o); - else - outs(PciDATA+o, data); - outl(PciADDR, 0); - break; - - case 2: - outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); - outb(PciFORWARD, BUSBNO(tbdf)); - if(read) - x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno); - else - outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); - outb(PciCSE, 0); - break; - } - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr16(Pcidev* pcidev, int rno) -{ - return pcicfgrw16(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw16(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw16(pcidev->tbdf, rno, data, 0); -} - -static int -pcicfgrw32raw(int tbdf, int rno, int data, int read) -{ - int type, x; - - if(pcicfgmode == -1) - pcicfginit(); - - if(BUSBNO(tbdf)) - type = 0x01; - else - type = 0x00; - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - lock(&pcicfglock); - switch(pcicfgmode){ - - case 1: - rno &= ~0x03; - outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); - if(read) - x = inl(PciDATA); - else - outl(PciDATA, data); - outl(PciADDR, 0); - break; - - case 2: - outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); - outb(PciFORWARD, BUSBNO(tbdf)); - if(read) - x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno); - else - outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); - outb(PciCSE, 0); - break; - } - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr32(Pcidev* pcidev, int rno) -{ - return pcicfgrw32(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw32(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw32(pcidev->tbdf, rno, data, 0); -} - -Pcidev* -pcimatch(Pcidev* prev, int vid, int did) -{ - if(pcicfgmode == -1) - pcicfginit(); - - if(prev == nil) - prev = pcilist; - else - prev = prev->list; - - while(prev != nil){ - if((vid == 0 || prev->vid == vid) - && (did == 0 || prev->did == did)) - break; - prev = prev->list; - } - return prev; -} - -Pcidev* -pcimatchtbdf(int tbdf) -{ - Pcidev *pcidev; - - if(pcicfgmode == -1) - pcicfginit(); - - for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) { - if(pcidev->tbdf == tbdf) - break; - } - return pcidev; -} - -uchar -pciipin(Pcidev *pci, uchar pin) -{ - if (pci == nil) - pci = pcilist; - - while (pci) { - uchar intl; - - if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff) - return pci->intl; - - if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0) - return intl; - - pci = pci->list; - } - return 0; -} - -static void -pcilhinv(Pcidev* p) -{ - int i; - Pcidev *t; - - if(p == nil) { - p = pciroot; - print("bus dev 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); - - for(i = 0; i < nelem(p->mem); i++) { - if(t->mem[i].size == 0) - continue; - print("%d:%.8llux %d ", i, - t->mem[i].bar, t->mem[i].size); - } - if(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:%.8llux %d ", t->mema.bar, t->mema.size); - if(t->bridge) - print("->%d", BUSBNO(t->bridge->tbdf)); - print("\n"); - } - while(p != nil) { - if(p->bridge != nil) - pcilhinv(p->bridge); - p = p->link; - } -} - -void -pcihinv(Pcidev* p) -{ - if(pcicfgmode == -1) - pcicfginit(); - lock(&pcicfginitlock); - pcilhinv(p); - unlock(&pcicfginitlock); -} - -void -pcireset(void) -{ - Pcidev *p; - - if(pcicfgmode == -1) - pcicfginit(); - - for(p = pcilist; p != nil; p = p->list) { - /* don't mess with the bridges */ - if(p->ccrb == 0x06) - continue; - pciclrbme(p); - } -} - -void -pcisetioe(Pcidev* p) -{ - p->pcr |= IOen; - pcicfgw16(p, PciPCR, p->pcr); -} - -void -pciclrioe(Pcidev* p) -{ - p->pcr &= ~IOen; - pcicfgw16(p, PciPCR, p->pcr); -} - -void -pcisetbme(Pcidev* p) -{ - p->pcr |= MASen; - pcicfgw16(p, PciPCR, p->pcr); -} - -void -pciclrbme(Pcidev* p) -{ - p->pcr &= ~MASen; - pcicfgw16(p, PciPCR, p->pcr); -} - -void -pcisetmwi(Pcidev* p) -{ - p->pcr |= MemWrInv; - pcicfgw16(p, PciPCR, p->pcr); -} - -void -pciclrmwi(Pcidev* p) -{ - p->pcr &= ~MemWrInv; - pcicfgw16(p, PciPCR, p->pcr); -} - -static int -enumcaps(Pcidev *p, int (*fmatch)(Pcidev*, int, int, int), int arg) -{ - int i, r, cap, off; - - /* status register bit 4 has capabilities */ - if((pcicfgr16(p, PciPSR) & 1<<4) == 0) - return -1; - switch(pcicfgr8(p, PciHDT) & 0x7F){ - default: - return -1; - case 0: /* etc */ - case 1: /* pci to pci bridge */ - off = 0x34; - break; - case 2: /* cardbus bridge */ - off = 0x14; - break; - } - for(i = 48; i--;){ - off = pcicfgr8(p, off); - if(off < 0x40 || (off & 3)) - break; - off &= ~3; - cap = pcicfgr8(p, off); - if(cap == 0xff) - break; - r = (*fmatch)(p, cap, off, arg); - if(r < 0) - break; - if(r == 0) - return off; - off++; - } - return -1; -} - -static int -matchcap(Pcidev *, int cap, int, int arg) -{ - return cap != arg; -} - -static int -matchhtcap(Pcidev *p, int cap, int off, int arg) -{ - int mask; - - if(cap != PciCapHTC) - return 1; - if(arg == 0x00 || arg == 0x20) - mask = 0xE0; - else - mask = 0xF8; - cap = pcicfgr8(p, off+3); - return (cap & mask) != arg; -} - -int -pcicap(Pcidev *p, int cap) -{ - return enumcaps(p, matchcap, cap); -} - -int -pcihtcap(Pcidev *p, int cap) -{ - return enumcaps(p, matchhtcap, cap); -} - -static int -pcigetpmrb(Pcidev* p) -{ - if(p->pmrb != 0) - return p->pmrb; - return p->pmrb = pcicap(p, PciCapPMG); -} - -int -pcigetpms(Pcidev* p) -{ - int pmcsr, ptr; - - if((ptr = pcigetpmrb(p)) == -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; -} - -int -pcisetpms(Pcidev* p, int state) -{ - int ostate, pmc, pmcsr, ptr; - - if((ptr = pcigetpmrb(p)) == -1) - return -1; - - pmc = pcicfgr16(p, ptr+2); - pmcsr = pcicfgr16(p, ptr+4); - ostate = pmcsr & 0x0003; - pmcsr &= ~0x0003; - - switch(state){ - default: - return -1; - case 0: - break; - case 1: - if(!(pmc & 0x0200)) - return -1; - break; - case 2: - if(!(pmc & 0x0400)) - return -1; - break; - case 3: - break; - } - pmcsr |= state; - pcicfgw16(p, ptr+4, pmcsr); - - return ostate; -} - -int -pcinextcap(Pcidev *pci, int offset) -{ - if(offset == 0) { - if((pcicfgr16(pci, PciPSR) & (1<<4)) == 0) - return 0; /* no capabilities */ - offset = PciCAP-1; - } - 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); -} diff --git a/sys/src/9/pc/pcipc.c b/sys/src/9/pc/pcipc.c new file mode 100644 index 000000000..f618d24ba --- /dev/null +++ b/sys/src/9/pc/pcipc.c @@ -0,0 +1,739 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/pci.h" +#include "../port/error.h" + +#define DBG if(1) print + +enum +{ /* configuration mechanism #1 */ + PciADDR = 0xCF8, /* CONFIG_ADDRESS */ + PciDATA = 0xCFC, /* CONFIG_DATA */ + + /* configuration mechanism #2 */ + PciCSE = 0xCF8, /* configuration space enable */ + PciFORWARD = 0xCFA, /* which bus */ +}; + +static int pcimaxbno = 255; +static int pcicfgmode = -1; +static Pcidev* pciroot; +static int nobios, nopcirouting; +static BIOS32si* pcibiossi; + +static int pcicfgrw8raw(int, int, int, int); +static int pcicfgrw16raw(int, int, int, int); +static int pcicfgrw32raw(int, int, int, int); + +int (*pcicfgrw8)(int, int, int, int) = pcicfgrw8raw; +int (*pcicfgrw16)(int, int, int, int) = pcicfgrw16raw; +int (*pcicfgrw32)(int, int, int, int) = pcicfgrw32raw; + +static int +pcicfgrw8raw(int tbdf, int rno, int data, int read) +{ + int o, type; + + if(BUSBNO(tbdf)) + type = 0x01; + else + type = 0x00; + switch(pcicfgmode){ + case 1: + o = rno & 0x03; + rno &= ~0x03; + outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); + if(read) + data = inb(PciDATA+o); + else + outb(PciDATA+o, data); + outl(PciADDR, 0); + break; + + case 2: + outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); + outb(PciFORWARD, BUSBNO(tbdf)); + if(read) + data = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno); + else + outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); + outb(PciCSE, 0); + break; + default: + data = -1; + } + return data; +} + +static int +pcicfgrw16raw(int tbdf, int rno, int data, int read) +{ + int o, type; + + if(BUSBNO(tbdf)) + type = 0x01; + else + type = 0x00; + switch(pcicfgmode){ + case 1: + o = rno & 0x02; + rno &= ~0x03; + outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); + if(read) + data = ins(PciDATA+o); + else + outs(PciDATA+o, data); + outl(PciADDR, 0); + break; + + case 2: + outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); + outb(PciFORWARD, BUSBNO(tbdf)); + if(read) + data = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno); + else + outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); + outb(PciCSE, 0); + break; + default: + data = -1; + } + return data; +} + +static int +pcicfgrw32raw(int tbdf, int rno, int data, int read) +{ + int type; + + if(BUSBNO(tbdf)) + type = 0x01; + else + type = 0x00; + switch(pcicfgmode){ + case 1: + rno &= ~0x03; + outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); + if(read) + data = inl(PciDATA); + else + outl(PciDATA, data); + outl(PciADDR, 0); + break; + + case 2: + outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); + outb(PciFORWARD, BUSBNO(tbdf)); + if(read) + data = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno); + else + outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); + outb(PciCSE, 0); + break; + default: + data = -1; + } + return data; +} + +static int +pcicfgrw8bios(int tbdf, int rno, int data, int read) +{ + BIOS32ci ci; + + if(pcibiossi == nil) + return -1; + + memset(&ci, 0, sizeof(BIOS32ci)); + ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf); + ci.edi = rno; + if(read){ + ci.eax = 0xB108; + if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) + return ci.ecx & 0xFF; + } + else{ + ci.eax = 0xB10B; + ci.ecx = data & 0xFF; + if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) + return 0; + } + + return -1; +} + +static int +pcicfgrw16bios(int tbdf, int rno, int data, int read) +{ + BIOS32ci ci; + + if(pcibiossi == nil) + return -1; + + memset(&ci, 0, sizeof(BIOS32ci)); + ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf); + ci.edi = rno; + if(read){ + ci.eax = 0xB109; + if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) + return ci.ecx & 0xFFFF; + } + else{ + ci.eax = 0xB10C; + ci.ecx = data & 0xFFFF; + if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) + return 0; + } + + return -1; +} + +static int +pcicfgrw32bios(int tbdf, int rno, int data, int read) +{ + BIOS32ci ci; + + if(pcibiossi == nil) + return -1; + + memset(&ci, 0, sizeof(BIOS32ci)); + ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf); + ci.edi = rno; + if(read){ + ci.eax = 0xB10A; + if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) + return ci.ecx; + } + else{ + ci.eax = 0xB10D; + ci.ecx = data; + if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/) + return 0; + } + + return -1; +} + +static BIOS32si* +pcibiosinit(void) +{ + BIOS32ci ci; + BIOS32si *si; + + if((si = bios32open("$PCI")) == nil) + return nil; + + memset(&ci, 0, sizeof(BIOS32ci)); + ci.eax = 0xB101; + if(bios32ci(si, &ci) || ci.edx != ((' '<<24)|('I'<<16)|('C'<<8)|'P')){ + free(si); + return nil; + } + if(ci.eax & 0x01) + pcimaxdno = 31; + else + pcimaxdno = 15; + pcimaxbno = ci.ecx & 0xff; + + return si; +} + +static uchar +pIIxget(Pcidev *router, uchar link) +{ + uchar pirq; + + /* link should be 0x60, 0x61, 0x62, 0x63 */ + pirq = pcicfgr8(router, link); + return (pirq < 16)? pirq: 0; +} + +static void +pIIxset(Pcidev *router, uchar link, uchar irq) +{ + pcicfgw8(router, link, irq); +} + +static uchar +viaget(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 +viaset(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 +optiget(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 +optiset(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 +aliget(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 +aliset(Pcidev *router, uchar link, uchar irq) +{ + /* Inverse of map in aliget */ + 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 +cyrixget(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 +cyrixset(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); +} + +typedef struct Bridge Bridge; +struct Bridge +{ + ushort vid; + ushort did; + uchar (*get)(Pcidev *, uchar); + void (*set)(Pcidev *, uchar, uchar); +}; + +static Bridge southbridges[] = { + { 0x8086, 0x122e, pIIxget, pIIxset }, /* Intel 82371FB */ + { 0x8086, 0x1234, pIIxget, pIIxset }, /* Intel 82371MX */ + { 0x8086, 0x7000, pIIxget, pIIxset }, /* Intel 82371SB */ + { 0x8086, 0x7110, pIIxget, pIIxset }, /* Intel 82371AB */ + { 0x8086, 0x7198, pIIxget, pIIxset }, /* Intel 82443MX (fn 1) */ + { 0x8086, 0x2410, pIIxget, pIIxset }, /* Intel 82801AA */ + { 0x8086, 0x2420, pIIxget, pIIxset }, /* Intel 82801AB */ + { 0x8086, 0x2440, pIIxget, pIIxset }, /* Intel 82801BA */ + { 0x8086, 0x2448, pIIxget, pIIxset }, /* Intel 82801BAM/CAM/DBM */ + { 0x8086, 0x244c, pIIxget, pIIxset }, /* Intel 82801BAM */ + { 0x8086, 0x244e, pIIxget, pIIxset }, /* Intel 82801 */ + { 0x8086, 0x2480, pIIxget, pIIxset }, /* Intel 82801CA */ + { 0x8086, 0x248c, pIIxget, pIIxset }, /* Intel 82801CAM */ + { 0x8086, 0x24c0, pIIxget, pIIxset }, /* Intel 82801DBL */ + { 0x8086, 0x24cc, pIIxget, pIIxset }, /* Intel 82801DBM */ + { 0x8086, 0x24d0, pIIxget, pIIxset }, /* Intel 82801EB */ + { 0x8086, 0x25a1, pIIxget, pIIxset }, /* Intel 6300ESB */ + { 0x8086, 0x2640, pIIxget, pIIxset }, /* Intel 82801FB */ + { 0x8086, 0x2641, pIIxget, pIIxset }, /* Intel 82801FBM */ + { 0x8086, 0x2670, pIIxget, pIIxset }, /* Intel 632xesb */ + { 0x8086, 0x27b8, pIIxget, pIIxset }, /* Intel 82801GB */ + { 0x8086, 0x27b9, pIIxget, pIIxset }, /* Intel 82801GBM */ + { 0x8086, 0x27bd, pIIxget, pIIxset }, /* Intel 82801GB/GR */ + { 0x8086, 0x3a16, pIIxget, pIIxset }, /* Intel 82801JIR */ + { 0x8086, 0x3a40, pIIxget, pIIxset }, /* Intel 82801JI */ + { 0x8086, 0x3a42, pIIxget, pIIxset }, /* Intel 82801JI */ + { 0x8086, 0x3a48, pIIxget, pIIxset }, /* Intel 82801JI */ + { 0x8086, 0x2916, pIIxget, pIIxset }, /* Intel 82801? */ + { 0x8086, 0x1c02, pIIxget, pIIxset }, /* Intel 6 Series/C200 */ + { 0x8086, 0x1e53, pIIxget, pIIxset }, /* Intel 7 Series/C216 */ + { 0x8086, 0x8c56, pIIxget, pIIxset }, /* Intel 8 Series/C226 */ + { 0x8086, 0x2810, pIIxget, pIIxset }, /* Intel 82801HB/HR (ich8/r) */ + { 0x8086, 0x2812, pIIxget, pIIxset }, /* Intel 82801HH (ich8dh) */ + { 0x8086, 0x2912, pIIxget, pIIxset }, /* Intel 82801ih ich9dh */ + { 0x8086, 0x2914, pIIxget, pIIxset }, /* Intel 82801io ich9do */ + { 0x8086, 0x2916, pIIxget, pIIxset }, /* Intel 82801ibr ich9r */ + { 0x8086, 0x2917, pIIxget, pIIxset }, /* Intel 82801iem ich9m-e */ + { 0x8086, 0x2918, pIIxget, pIIxset }, /* Intel 82801ib ich9 */ + { 0x8086, 0x2919, pIIxget, pIIxset }, /* Intel 82801? ich9m */ + { 0x8086, 0x3a16, pIIxget, pIIxset }, /* Intel 82801jir ich10r */ + { 0x8086, 0x3a18, pIIxget, pIIxset }, /* Intel 82801jib ich10 */ + { 0x8086, 0x3a40, pIIxget, pIIxset }, /* Intel 82801ji */ + { 0x8086, 0x3a42, pIIxget, pIIxset }, /* Intel 82801ji */ + { 0x8086, 0x3a48, pIIxget, pIIxset }, /* Intel 82801ji */ + { 0x8086, 0x3b06, pIIxget, pIIxset }, /* Intel 82801? ibex peak */ + { 0x8086, 0x3b14, pIIxget, pIIxset }, /* Intel 82801? 3420 */ + { 0x8086, 0x1c49, pIIxget, pIIxset }, /* Intel 82hm65 cougar point pch */ + { 0x8086, 0x1c4b, pIIxget, pIIxset }, /* Intel 82hm67 */ + { 0x8086, 0x1c4f, pIIxget, pIIxset }, /* Intel 82qm67 cougar point pch */ + { 0x8086, 0x1c52, pIIxget, pIIxset }, /* Intel 82q65 cougar point pch */ + { 0x8086, 0x1c54, pIIxget, pIIxset }, /* Intel 82q67 cougar point pch */ + { 0x8086, 0x1e55, pIIxget, pIIxset }, /* Intel QM77 panter point lpc */ + + { 0x1106, 0x0586, viaget, viaset }, /* Viatech 82C586 */ + { 0x1106, 0x0596, viaget, viaset }, /* Viatech 82C596 */ + { 0x1106, 0x0686, viaget, viaset }, /* Viatech 82C686 */ + { 0x1106, 0x3177, viaget, viaset }, /* Viatech VT8235 */ + { 0x1106, 0x3227, viaget, viaset }, /* Viatech VT8237 */ + { 0x1106, 0x3287, viaget, viaset }, /* Viatech VT8251 */ + { 0x1106, 0x8410, viaget, viaset }, /* Viatech PV530 bridge */ + { 0x1045, 0xc700, optiget, optiset }, /* Opti 82C700 */ + { 0x10b9, 0x1533, aliget, aliset }, /* Al M1533 */ + { 0x1039, 0x0008, pIIxget, pIIxset }, /* SI 503 */ + { 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 */ + { 0x10de, 0x00e1, nil, nil }, /* NVIDIA nForce 3 250 Series */ + { 0x1166, 0x0200, nil, nil }, /* ServerWorks ServerSet III LE */ + { 0x1002, 0x4377, nil, nil }, /* ATI Radeon Xpress 200M */ + { 0x1002, 0x4372, nil, nil }, /* ATI SB400 */ + { 0x1002, 0x9601, nil, nil }, /* AMD SB710 */ + { 0x1002, 0x438d, nil, nil }, /* AMD SB600 */ + { 0x1002, 0x439d, nil, nil }, /* AMD SB810 */ +}; + +typedef struct Slot Slot; +struct Slot { + uchar bus; /* Pci bus number */ + uchar dev; /* Pci device number */ + uchar maps[12]; /* Avoid structs! Link and mask. */ + uchar slot; /* Add-in/built-in slot */ + uchar reserved; +}; + +typedef struct Router Router; +struct Router { + uchar signature[4]; /* Routing table signature */ + uchar version[2]; /* Version number */ + uchar size[2]; /* Total table size */ + uchar bus; /* Interrupt router bus number */ + uchar devfn; /* Router's devfunc */ + uchar pciirqs[2]; /* Exclusive PCI irqs */ + uchar compat[4]; /* Compatible PCI interrupt router */ + uchar miniport[4]; /* Miniport data */ + uchar reserved[11]; + uchar checksum; +}; + +static ushort pciirqs; /* Exclusive PCI irqs */ +static Bridge *southbridge; /* Which southbridge to use. */ + +static void +pcirouting(void) +{ + Slot *e; + Router *r; + int i, size, tbdf; + Pcidev *sbpci, *pci; + uchar *p, pin, irq, link, *map; + + if((p = sigsearch("$PIR", 0)) == nil) + return; + + r = (Router*)p; + size = (r->size[1] << 8)|r->size[0]; + if(size < sizeof(Router) || checksum(r, size)) + return; + + if(0) print("PCI interrupt routing table version %d.%d at %p\n", + r->version[0], r->version[1], r); + + tbdf = MKBUS(BusPCI, r->bus, (r->devfn>>3)&0x1f, r->devfn&7); + sbpci = pcimatchtbdf(tbdf); + if(sbpci == nil) { + print("pcirouting: Cannot find south bridge %T\n", tbdf); + return; + } + + for(i = 0; i < nelem(southbridges); i++) + if(sbpci->vid == southbridges[i].vid && sbpci->did == southbridges[i].did) + break; + + if(i == nelem(southbridges)) { + print("pcirouting: ignoring south bridge %T %.4uX/%.4uX\n", tbdf, sbpci->vid, sbpci->did); + return; + } + southbridge = &southbridges[i]; + if(southbridge->get == nil) + return; + + pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0]; + for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) { + if(0) { + print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot); + for (i = 0; i < 4; i++) { + map = &e->maps[i * 3]; + print("[%d] %.2uX %.4uX ", i, map[0], (map[2] << 8)|map[1]); + } + print("\n"); + } + for(i = 0; i < 8; i++) { + tbdf = MKBUS(BusPCI, e->bus, (e->dev>>3)&0x1f, i); + pci = pcimatchtbdf(tbdf); + if(pci == nil) + continue; + pin = pcicfgr8(pci, PciINTP); + if(pin == 0 || pin == 0xff) + continue; + + map = &e->maps[((pin - 1) % 4) * 3]; + link = map[0]; + irq = southbridge->get(sbpci, link); + if(irq == pci->intl) + continue; + if(irq == 0 || (irq & 0x80) != 0){ + irq = pci->intl; + if(irq == 0 || irq == 0xff) + continue; + if(southbridge->set == nil) + continue; + southbridge->set(sbpci, link, irq); + } + print("pcirouting: %T at pin %d link %.2uX irq %d -> %d\n", tbdf, pin, link, pci->intl, irq); + pcicfgw8(pci, PciINTL, irq); + pci->intl = irq; + } + } +} + +static void +pcireservemem(void) +{ + Pcidev *p; + uvlong pa; + int i; + + /* + * mark all valid physical address space claimed by pci devices + * as in use, so that upaalloc doesn't give it out. + */ + for(p=pciroot; p != nil; p=p->list){ + for(i=0; imem); i++){ + if(p->mem[i].size == 0) + continue; + if(p->mem[i].bar & 1) + continue; + if((p->mem[i].bar & ~0xFULL) == 0) + continue; + upaalloc(p->mem[i].bar&~0xFULL, p->mem[i].size, 0); + } + } + + /* + * allocate physical address space for unassigned membars. + */ + for(p=pciroot; p != nil; p=p->list){ + for(i=0; imem); i++){ + if(p->mem[i].size == 0) + continue; + if(p->mem[i].bar & ~0xEULL) + continue; + + if(p->parent == nil){ + pa = upaalloc(-1ULL, + p->mem[i].size, p->mem[i].size); + } else if(p->mem[i].bar & 8){ + pa = upaallocwin(p->parent->prefa.bar, p->parent->prefa.size, + p->mem[i].size, p->mem[i].size); + if(pa == -1ULL) + goto Mem; + } else { + Mem: + pa = upaallocwin(p->parent->mema.bar, p->parent->mema.size, + p->mem[i].size, p->mem[i].size); + } + if(pa == -1ULL) + continue; + + p->mem[i].bar |= pa; + pcisetbar(p, PciBAR0 + i*4, p->mem[i].bar); + + DBG("%T: bar%d: fixed %.8lluX %d\n", + p->tbdf, i, p->mem[i].bar, p->mem[i].size); + } + } +} + +void +pcicfginit(void) +{ + char *p; + Pcidev **list; + int bno, n, pcibios; + + fmtinstall('T', tbdffmt); + + pcibios = 0; + if(getconf("*nobios")) + nobios = 1; + else if(getconf("*pcibios")) + pcibios = 1; + if(getconf("*nopcirouting")) + nopcirouting = 1; + + /* + * Try to determine which PCI configuration mode is implemented. + * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses + * a DWORD at 0xCF8 and another at 0xCFC and will pass through + * any non-DWORD accesses as normal I/O cycles. There shouldn't be + * a device behind these addresses so if Mode1 accesses fail try + * for Mode2 (Mode2 is deprecated). + */ + if(!pcibios){ + /* + * Bits [30:24] of PciADDR must be 0, + * according to the spec. + */ + n = inl(PciADDR); + if(!(n & 0x7F000000)){ + outl(PciADDR, 0x80000000); + outb(PciADDR+3, 0); + if(inl(PciADDR) & 0x80000000){ + pcicfgmode = 1; + pcimaxdno = 31; + } + } + outl(PciADDR, n); + + if(pcicfgmode < 0){ + /* + * The 'key' part of PciCSE should be 0. + */ + n = inb(PciCSE); + if(!(n & 0xF0)){ + outb(PciCSE, 0x0E); + if(inb(PciCSE) == 0x0E){ + pcicfgmode = 2; + pcimaxdno = 15; + } + } + outb(PciCSE, n); + } + } + + if(pcicfgmode < 0 || pcibios) { + if((pcibiossi = pcibiosinit()) == nil) + goto out; + pcicfgrw8 = pcicfgrw8bios; + pcicfgrw16 = pcicfgrw16bios; + pcicfgrw32 = pcicfgrw32bios; + pcicfgmode = 3; + } + + if(p = getconf("*pcimaxbno")) + pcimaxbno = strtoul(p, 0, 0); + if(p = getconf("*pcimaxdno")){ + n = strtoul(p, 0, 0); + if(n < pcimaxdno) + pcimaxdno = n; + } + + list = &pciroot; + for(bno = 0; bno <= pcimaxbno; bno++) { + int sbno = bno; + bno = pciscan(bno, list); + + while(*list) + list = &(*list)->link; + + if (sbno == 0) { + Pcidev *pci; + + /* + * If we have found a PCI-to-Cardbus bridge, make sure + * it has no valid mappings anymore. + */ + for(pci = pciroot; pci != nil; pci = pci->link){ + if (pci->ccrb == 6 && pci->ccru == 7) { + ushort bcr; + + /* reset the cardbus */ + bcr = pcicfgr16(pci, PciBCR); + pcicfgw16(pci, PciBCR, 0x40 | bcr); + delay(50); + } + } + } + } + + if(pciroot == nil) + goto out; + + if(nobios) { + uvlong mema; + ulong ioa; + + /* + * Work out how big the top bus is + */ + pcibussize(pciroot, &mema, &ioa); + DBG("Size: mem=%.8llux io=%lux\n", mema, ioa); + + /* + * Align the windows and map it + */ + mema = upaalloc(-1ULL, mema, mema); + if(mema == -1ULL) + panic("pcicfginit: can't allocate pci window"); + + ioa = 0x1000; + DBG("Base: mem=%.8llux io=%lux\n", mema, ioa); + pcibusmap(pciroot, &mema, &ioa, 1); + DBG("Limit: mem=%.8llux io=%lux\n", mema, ioa); + goto out; + } + + pcireservemem(); + + if(!nopcirouting) + pcirouting(); + +out: + if(getconf("*pcihinv")) + pcihinv(pciroot); +} diff --git a/sys/src/9/pc/piix4smbus.c b/sys/src/9/pc/piix4smbus.c index 7ea4b8706..82d09a232 100644 --- a/sys/src/9/pc/piix4smbus.c +++ b/sys/src/9/pc/piix4smbus.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" /* * SMBus support for the PIIX4 diff --git a/sys/src/9/pc/pmmc.c b/sys/src/9/pc/pmmc.c index 2578f7a8f..710ce52bc 100644 --- a/sys/src/9/pc/pmmc.c +++ b/sys/src/9/pc/pmmc.c @@ -13,6 +13,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/sd.h" /* registers */ diff --git a/sys/src/9/pc/screen.c b/sys/src/9/pc/screen.c index af5799934..947c9aee0 100644 --- a/sys/src/9/pc/screen.c +++ b/sys/src/9/pc/screen.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "ureg.h" #include "../port/error.h" diff --git a/sys/src/9/pc/sd53c8xx.c b/sys/src/9/pc/sd53c8xx.c index f16644fff..234be0758 100644 --- a/sys/src/9/pc/sd53c8xx.c +++ b/sys/src/9/pc/sd53c8xx.c @@ -23,6 +23,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/sd.h" extern SDifc sd53c8xxifc; diff --git a/sys/src/9/pc/sdiahci.c b/sys/src/9/pc/sdiahci.c index 644850dd8..0247e7802 100644 --- a/sys/src/9/pc/sdiahci.c +++ b/sys/src/9/pc/sdiahci.c @@ -9,6 +9,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/sd.h" #include diff --git a/sys/src/9/pc/sdide.c b/sys/src/9/pc/sdide.c index 7da95b2e8..a7626726a 100644 --- a/sys/src/9/pc/sdide.c +++ b/sys/src/9/pc/sdide.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "ureg.h" #include "../port/error.h" @@ -352,7 +353,7 @@ pc87415ienable(Ctlr* ctlr) return; x = pcicfgr32(p, 0x40); - if(ctlr->cmdport == p->mem[0].bar) + if(ctlr->cmdport == (p->mem[0].bar & ~3)) x &= ~0x00000100; else x &= ~0x00000200; @@ -2142,8 +2143,8 @@ atapnp(void) if((map & 1<mem[0+2*channel].bar & ~0x01, - p->mem[1+2*channel].bar & ~0x01, + sdev = ataprobe(p->mem[0+2*channel].bar & ~3, + p->mem[1+2*channel].bar & ~3, p->intl, 3); tbdf = p->tbdf; } @@ -2169,7 +2170,7 @@ atapnp(void) ctlr->span = span; ctlr->irqack = irqack; if((pi & 0x80) && (p->mem[4].bar & 0x01)) - ctlr->bmiba = (p->mem[4].bar & ~0x01) + channel*8; + ctlr->bmiba = (p->mem[4].bar & ~3) + channel*8; if(head != nil) tail->next = sdev; else diff --git a/sys/src/9/pc/sdmv50xx.c b/sys/src/9/pc/sdmv50xx.c index a48264d89..a1103cbc5 100644 --- a/sys/src/9/pc/sdmv50xx.c +++ b/sys/src/9/pc/sdmv50xx.c @@ -15,6 +15,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/sd.h" #include diff --git a/sys/src/9/pc/sdmylex.c b/sys/src/9/pc/sdmylex.c index 75cf5ac5b..a0785a7c1 100644 --- a/sys/src/9/pc/sdmylex.c +++ b/sys/src/9/pc/sdmylex.c @@ -15,6 +15,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "ureg.h" #include "../port/error.h" @@ -1054,7 +1055,7 @@ mylexpnp(void) p = nil; head = tail = nil; while(p = pcimatch(p, 0x104B, 0)){ - if((sdev = mylexprobe(p->mem[0].bar & ~0x01, p->intl)) == nil) + if((sdev = mylexprobe(p->mem[0].bar & ~3, p->intl)) == nil) continue; ctlr = sdev->ctlr; diff --git a/sys/src/9/pc/sdnvme.c b/sys/src/9/pc/sdnvme.c index 1db5fb677..152dba187 100644 --- a/sys/src/9/pc/sdnvme.c +++ b/sys/src/9/pc/sdnvme.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "ureg.h" #include "../port/error.h" diff --git a/sys/src/9/pc/sdodin.c b/sys/src/9/pc/sdodin.c index 6c4277676..3ad371f82 100644 --- a/sys/src/9/pc/sdodin.c +++ b/sys/src/9/pc/sdodin.c @@ -10,6 +10,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/sd.h" #include diff --git a/sys/src/9/pc/sdvirtio.c b/sys/src/9/pc/sdvirtio.c index 57ed15811..e5a60767f 100644 --- a/sys/src/9/pc/sdvirtio.c +++ b/sys/src/9/pc/sdvirtio.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "ureg.h" #include "../port/error.h" @@ -203,13 +204,15 @@ viopnpdevs(int typ) continue; if(p->rid != 0) continue; + if((p->mem[0].bar & 1) == 0) + continue; if(pcicfgr16(p, 0x2E) != typ) continue; if((vd = malloc(sizeof(*vd))) == nil){ print("virtio: no memory for Vdev\n"); break; } - vd->port = p->mem[0].bar & ~0x1; + vd->port = p->mem[0].bar & ~3; if(ioalloc(vd->port, p->mem[0].size, 0, "virtio") < 0){ print("virtio: port %lux in use\n", vd->port); free(vd); diff --git a/sys/src/9/pc/uartaxp.c b/sys/src/9/pc/uartaxp.c index 2b84f6a30..48a26b3f6 100644 --- a/sys/src/9/pc/uartaxp.c +++ b/sys/src/9/pc/uartaxp.c @@ -7,6 +7,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "uartaxp.i" diff --git a/sys/src/9/pc/uartpci.c b/sys/src/9/pc/uartpci.c index aed64a1b1..5819a4896 100644 --- a/sys/src/9/pc/uartpci.c +++ b/sys/src/9/pc/uartpci.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" extern PhysUart i8250physuart; @@ -21,21 +22,21 @@ uartpci(int ctlrno, Pcidev* p, int barno, int n, int freq, char* name, char buf[64]; Uart *head, *uart; - head = malloc(sizeof(Uart)*n); - if(head == nil){ - print("uartpci: no memory for Uarts\n"); + if((p->mem[barno].bar & 1) == 0) return nil; - } - - io = p->mem[barno].bar & ~0x01; + io = p->mem[barno].bar & ~3; snprint(buf, sizeof(buf), "%s%d", pciphysuart.name, ctlrno); if(ioalloc(io, p->mem[barno].size, 0, buf) < 0){ print("uartpci: I/O 0x%uX in use\n", io); - free(head); return nil; } - pcienable(p); + head = malloc(sizeof(Uart)*n); + if(head == nil){ + print("uartpci: no memory for Uarts\n"); + iofree(io); + return nil; + } uart = head; for(i = 0; i < n; i++){ ctlr = i8250alloc(io + i*iosize, p->intl, p->tbdf); diff --git a/sys/src/9/pc/usbehcipc.c b/sys/src/9/pc/usbehcipc.c index 7f6e47923..276bba117 100644 --- a/sys/src/9/pc/usbehcipc.c +++ b/sys/src/9/pc/usbehcipc.c @@ -10,6 +10,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/usb.h" #include "usbehci.h" diff --git a/sys/src/9/pc/usbohci.c b/sys/src/9/pc/usbohci.c index d24f2388e..1725c0351 100644 --- a/sys/src/9/pc/usbohci.c +++ b/sys/src/9/pc/usbohci.c @@ -16,6 +16,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/usb.h" diff --git a/sys/src/9/pc/usbuhci.c b/sys/src/9/pc/usbuhci.c index 1666be00d..a5783d546 100644 --- a/sys/src/9/pc/usbuhci.c +++ b/sys/src/9/pc/usbuhci.c @@ -14,6 +14,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/usb.h" @@ -2131,7 +2132,7 @@ scanpci(void) case 0: if((p->mem[4].bar & 1) == 0) continue; - io = (int)p->mem[4].bar & ~0xF; + io = p->mem[4].bar & ~3; break; default: continue; diff --git a/sys/src/9/pc/vga3dfx.c b/sys/src/9/pc/vga3dfx.c index 214adfbca..07afd740c 100644 --- a/sys/src/9/pc/vga3dfx.c +++ b/sys/src/9/pc/vga3dfx.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgaclgd546x.c b/sys/src/9/pc/vgaclgd546x.c index e31ed432c..06762a876 100644 --- a/sys/src/9/pc/vgaclgd546x.c +++ b/sys/src/9/pc/vgaclgd546x.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgacyber938x.c b/sys/src/9/pc/vgacyber938x.c index 4678680dc..4259f06de 100644 --- a/sys/src/9/pc/vgacyber938x.c +++ b/sys/src/9/pc/vgacyber938x.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgageode.c b/sys/src/9/pc/vgageode.c index 0fe7890b5..7b6106fbe 100644 --- a/sys/src/9/pc/vgageode.c +++ b/sys/src/9/pc/vgageode.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgahiqvideo.c b/sys/src/9/pc/vgahiqvideo.c index 824d5db0c..4a54b676c 100644 --- a/sys/src/9/pc/vgahiqvideo.c +++ b/sys/src/9/pc/vgahiqvideo.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgai81x.c b/sys/src/9/pc/vgai81x.c index 1827aceac..f80a11bf5 100644 --- a/sys/src/9/pc/vgai81x.c +++ b/sys/src/9/pc/vgai81x.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgaigfx.c b/sys/src/9/pc/vgaigfx.c index 6ad761b9b..ea70310ab 100644 --- a/sys/src/9/pc/vgaigfx.c +++ b/sys/src/9/pc/vgaigfx.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgamach64xx.c b/sys/src/9/pc/vgamach64xx.c index 0f6ea6c10..0f1606c24 100644 --- a/sys/src/9/pc/vgamach64xx.c +++ b/sys/src/9/pc/vgamach64xx.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgamga2164w.c b/sys/src/9/pc/vgamga2164w.c index 3269cd7a5..df9fa5ddf 100644 --- a/sys/src/9/pc/vgamga2164w.c +++ b/sys/src/9/pc/vgamga2164w.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgamga4xx.c b/sys/src/9/pc/vgamga4xx.c index d29d3cfdc..30bcf7822 100644 --- a/sys/src/9/pc/vgamga4xx.c +++ b/sys/src/9/pc/vgamga4xx.c @@ -14,6 +14,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vganeomagic.c b/sys/src/9/pc/vganeomagic.c index b1bd3f84c..1cc2a02d9 100644 --- a/sys/src/9/pc/vganeomagic.c +++ b/sys/src/9/pc/vganeomagic.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vganvidia.c b/sys/src/9/pc/vganvidia.c index 54de9dc6e..0d20f43a8 100644 --- a/sys/src/9/pc/vganvidia.c +++ b/sys/src/9/pc/vganvidia.c @@ -46,6 +46,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgaradeon.c b/sys/src/9/pc/vgaradeon.c index 9430a1a6c..e23d90753 100644 --- a/sys/src/9/pc/vgaradeon.c +++ b/sys/src/9/pc/vgaradeon.c @@ -8,6 +8,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgas3.c b/sys/src/9/pc/vgas3.c index f055d8919..710756d7c 100644 --- a/sys/src/9/pc/vgas3.c +++ b/sys/src/9/pc/vgas3.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgat2r4.c b/sys/src/9/pc/vgat2r4.c index 5cf282325..32ffeb833 100644 --- a/sys/src/9/pc/vgat2r4.c +++ b/sys/src/9/pc/vgat2r4.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc/vgavesa.c b/sys/src/9/pc/vgavesa.c index 3f7300326..08021c7bf 100644 --- a/sys/src/9/pc/vgavesa.c +++ b/sys/src/9/pc/vgavesa.c @@ -7,6 +7,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Ureg Ureg386 diff --git a/sys/src/9/pc/vgavmware.c b/sys/src/9/pc/vgavmware.c index aa4b12e30..8c84158a7 100644 --- a/sys/src/9/pc/vgavmware.c +++ b/sys/src/9/pc/vgavmware.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #define Image IMAGE diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h index 2bbd3ffd8..39afc4864 100644 --- a/sys/src/9/pc64/fns.h +++ b/sys/src/9/pc64/fns.h @@ -124,32 +124,10 @@ void outl(int, ulong); void outsl(int, void*, int); uintptr paddr(void*); void patwc(void*, int); -ulong pcibarsize(Pcidev*, int); -void pcibussize(Pcidev*, uvlong*, ulong*); -int pcicfgr8(Pcidev*, int); -int pcicfgr16(Pcidev*, int); -int pcicfgr32(Pcidev*, int); -void pcicfgw8(Pcidev*, int, int); -void pcicfgw16(Pcidev*, int, int); -void pcicfgw32(Pcidev*, int, int); -void pciclrbme(Pcidev*); -void pciclrioe(Pcidev*); -void pciclrmwi(Pcidev*); -int pcigetpms(Pcidev*); -void pcihinv(Pcidev*); -uchar pciipin(Pcidev*, uchar); -Pcidev* pcimatch(Pcidev*, int, int); -Pcidev* pcimatchtbdf(int); -int pcicap(Pcidev*, int); -int pcihtcap(Pcidev*, int); -void pcireset(void); -int pciscan(int, Pcidev**); -void pcisetbme(Pcidev*); -void pcisetioe(Pcidev*); -void pcisetmwi(Pcidev*); -int pcisetpms(Pcidev*, int); -void pcienable(Pcidev*); -void pcidisable(Pcidev*); +void pcicfginit(void); +int (*pcicfgrw8)(int, int, int, int); +int (*pcicfgrw16)(int, int, int, int); +int (*pcicfgrw32)(int, int, int, int); void pcmcisread(PCMslot*); int pcmcistuple(int, int, int, void*, int); PCMmap* pcmmap(int, ulong, int, int); @@ -192,6 +170,7 @@ uvlong tscticks(uvlong*); ulong umballoc(ulong, ulong, ulong); void umbfree(ulong, ulong); uvlong upaalloc(uvlong, ulong, ulong); +uvlong upaallocwin(uvlong, ulong, ulong, ulong); void upafree(uvlong, ulong); void vectortable(void); void vmxprocrestore(Proc *); diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 83f770587..50649d724 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -190,6 +190,7 @@ main(void) ramdiskinit(); confinit(); xinit(); + pcicfginit(); bootscreeninit(); if(i8237alloc != nil) i8237alloc(); @@ -207,7 +208,6 @@ main(void) initseg(); if(delaylink){ bootlinks(); - pcimatch(0, 0, 0); }else links(); chandevreset(); diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index 6e03dc00e..c5ef1fbbe 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -26,7 +26,7 @@ dev draw screen vga vgax vgasoft mouse mouse kbd - vga + vga pci sd # floppy dma @@ -44,9 +44,9 @@ dev dtracy link -# devpccard +# devpccard pci # devi82365 - cputemp + cputemp pci # ether2000 ether8390 # ether2114x pci # ether589 etherelnk3 @@ -82,16 +82,17 @@ link # pcmciamodem netdevmedium loopbackmedium - usbuhci - usbohci - usbehci usbehcipc + usbuhci pci + usbohci pci + usbehci pci usbehcipc usbxhci pci # audiosb16 dma -# audioac97 audioac97mix - audiohda +# audioac97 pci audioac97mix + audiohda pci misc + pci pcipc archacpi mp apic squidboy ec archmp mp apic squidboy mtrr diff --git a/sys/src/9/port/devpnp.c b/sys/src/9/port/devpnp.c index ebaaa5cb7..7402a71d6 100644 --- a/sys/src/9/port/devpnp.c +++ b/sys/src/9/port/devpnp.c @@ -14,6 +14,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" typedef struct Pnp Pnp; diff --git a/sys/src/9/bcm64/pci.c b/sys/src/9/port/pci.c similarity index 55% rename from sys/src/9/bcm64/pci.c rename to sys/src/9/port/pci.c index 62e8d6624..63d051ac9 100644 --- a/sys/src/9/bcm64/pci.c +++ b/sys/src/9/port/pci.c @@ -4,73 +4,22 @@ #include "dat.h" #include "fns.h" #include "io.h" - -/* bcmstb PCIe controller registers */ -enum{ - RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 = 0x0188/4, - RC_CFG_PRIV1_ID_VAL3 = 0x043c/4, - RC_DL_MDIO_ADDR = 0x1100/4, - RC_DL_MDIO_WR_DATA = 0x1104/4, - RC_DL_MDIO_RD_DATA = 0x1108/4, - MISC_MISC_CTRL = 0x4008/4, - MISC_CPU_2_PCIE_MEM_WIN0_LO = 0x400c/4, - MISC_CPU_2_PCIE_MEM_WIN0_HI = 0x4010/4, - MISC_RC_BAR1_CONFIG_LO = 0x402c/4, - MISC_RC_BAR2_CONFIG_LO = 0x4034/4, - MISC_RC_BAR2_CONFIG_HI = 0x4038/4, - MISC_RC_BAR3_CONFIG_LO = 0x403c/4, - MISC_MSI_BAR_CONFIG_LO = 0x4044/4, - MISC_MSI_BAR_CONFIG_HI = 0x4048/4, - MISC_MSI_DATA_CONFIG = 0x404c/4, - MISC_EOI_CTRL = 0x4060/4, - MISC_PCIE_CTRL = 0x4064/4, - MISC_PCIE_STATUS = 0x4068/4, - MISC_REVISION = 0x406c/4, - MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT = 0x4070/4, - MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI = 0x4080/4, - MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI = 0x4084/4, - MISC_HARD_PCIE_HARD_DEBUG = 0x4204/4, - - INTR2_CPU_BASE = 0x4300/4, - MSI_INTR2_BASE = 0x4500/4, - INTR_STATUS = 0, - INTR_SET, - INTR_CLR, - INTR_MASK_STATUS, - INTR_MASK_SET, - INTR_MASK_CLR, - - EXT_CFG_INDEX = 0x9000/4, - RGR1_SW_INIT_1 = 0x9210/4, - EXT_CFG_DATA = 0x8000/4, - -}; - -#define MSI_TARGET_ADDR 0xFFFFFFFFCULL - -static u32int *regs = (u32int*)(VIRTIO1 + 0x500000); - -static Lock pcicfglock; -static int pcimaxbno = 0; -static int pcimaxdno = 0; -static Pcidev* pciroot; -static Pcidev* pcilist; -static Pcidev* pcitail; +#include "../port/pci.h" typedef struct Pcisiz Pcisiz; struct Pcisiz { Pcidev* dev; - int bar; int siz; + int bar; int typ; }; -enum -{ - MaxFNO = 7, - MaxUBN = 255, -}; +int pcimaxdno; + +static Lock pcicfglock; +static Pcidev* pcilist; +static Pcidev* pcitail; static char* bustypes[] = { "CBUSI", @@ -93,176 +42,133 @@ static char* bustypes[] = { "XPRESS", }; -static int +int tbdffmt(Fmt* fmt) { - char *p; - int l, r; - uint type, tbdf; - - if((p = malloc(READSTR)) == nil) - return fmtstrcpy(fmt, "(tbdfconv)"); + int type, tbdf; switch(fmt->r){ + default: + return fmtstrcpy(fmt, "(tbdffmt)"); + case 'T': tbdf = va_arg(fmt->args, int); - if(tbdf == BUSUNKNOWN) - snprint(p, READSTR, "unknown"); - else{ + if(tbdf == BUSUNKNOWN) { + return fmtstrcpy(fmt, "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)); + if(type < nelem(bustypes)) { + return fmtprint(fmt, "%s.%d.%d.%d", + bustypes[type], BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); + } else { + return fmtprint(fmt, "%d.%d.%d.%d", + type, BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); + } } - break; - - default: - snprint(p, READSTR, "(tbdfconv)"); - break; } - r = fmtstrcpy(fmt, p); - free(p); - - return r; -} - -static void pcicfginit(void); - -static void* -cfgaddr(int tbdf, int rno) -{ - if(BUSBNO(tbdf) == 0 && BUSDNO(tbdf) == 0) - return (uchar*)regs + rno; - regs[EXT_CFG_INDEX] = BUSBNO(tbdf) << 20 | BUSDNO(tbdf) << 15 | BUSFNO(tbdf) << 12; - coherence(); - return ((uchar*)®s[EXT_CFG_DATA]) + rno; -} - -static int -pcicfgrw32(int tbdf, int rno, int data, int read) -{ - int x = -1; - u32int *p; - - ilock(&pcicfglock); - if((p = cfgaddr(tbdf, rno & ~3)) != nil){ - if(read) - x = *p; - else - *p = data; - } - iunlock(&pcicfglock); - return x; -} -static int -pcicfgrw16(int tbdf, int rno, int data, int read) -{ - int x = -1; - u16int *p; - - ilock(&pcicfglock); - if((p = cfgaddr(tbdf, rno & ~1)) != nil){ - if(read) - x = *p; - else - *p = data; - } - iunlock(&pcicfglock); - return x; -} -static int -pcicfgrw8(int tbdf, int rno, int data, int read) -{ - int x = -1; - u8int *p; - - ilock(&pcicfglock); - if((p = cfgaddr(tbdf, rno)) != nil){ - if(read) - x = *p; - else - *p = data; - } - iunlock(&pcicfglock); - return x; } int -pcicfgr32(Pcidev* pcidev, int rno) +pcicfgr8(Pcidev* p, int rno) { - return pcicfgrw32(pcidev->tbdf, rno, 0, 1); + int data; + + ilock(&pcicfglock); + data = pcicfgrw8(p->tbdf, rno, 0, 1); + iunlock(&pcicfglock); + + return data; } void -pcicfgw32(Pcidev* pcidev, int rno, int data) +pcicfgw8(Pcidev* p, int rno, int data) { - pcicfgrw32(pcidev->tbdf, rno, data, 0); + ilock(&pcicfglock); + pcicfgrw8(p->tbdf, rno, data, 0); + iunlock(&pcicfglock); } int -pcicfgr16(Pcidev* pcidev, int rno) +pcicfgr16(Pcidev* p, int rno) { - return pcicfgrw16(pcidev->tbdf, rno, 0, 1); + int data; + + ilock(&pcicfglock); + data = pcicfgrw16(p->tbdf, rno, 0, 1); + iunlock(&pcicfglock); + + return data; } void -pcicfgw16(Pcidev* pcidev, int rno, int data) +pcicfgw16(Pcidev* p, int rno, int data) { - pcicfgrw16(pcidev->tbdf, rno, data, 0); + ilock(&pcicfglock); + pcicfgrw16(p->tbdf, rno, data, 0); + iunlock(&pcicfglock); } int -pcicfgr8(Pcidev* pcidev, int rno) +pcicfgr32(Pcidev* p, int rno) { - return pcicfgrw8(pcidev->tbdf, rno, 0, 1); + int data; + + ilock(&pcicfglock); + data = pcicfgrw32(p->tbdf, rno, 0, 1); + iunlock(&pcicfglock); + + return data; } void -pcicfgw8(Pcidev* pcidev, int rno, int data) +pcicfgw32(Pcidev* p, int rno, int data) { - pcicfgrw8(pcidev->tbdf, rno, data, 0); + ilock(&pcicfglock); + pcicfgrw32(p->tbdf, rno, data, 0); + iunlock(&pcicfglock); } -Pcidev* -pcimatch(Pcidev* prev, int vid, int did) -{ - if(prev == nil) - prev = pcilist; - else - prev = prev->list; - - while(prev != nil){ - if((vid == 0 || prev->vid == vid) - && (did == 0 || prev->did == did)) - break; - prev = prev->list; - } - return prev; -} - -Pcidev* -pcimatchtbdf(int tbdf) -{ - Pcidev *pcidev; - - for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) { - if(pcidev->tbdf == tbdf) - break; - } - return pcidev; -} - -static u32int +int pcibarsize(Pcidev *p, int rno) { - u32int v, size; + int v, size; + ilock(&pcicfglock); v = pcicfgrw32(p->tbdf, rno, 0, 1); - pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0); + pcicfgrw32(p->tbdf, rno, -1, 0); size = pcicfgrw32(p->tbdf, rno, 0, 1); - if(v & 1) - size |= 0xFFFF0000; pcicfgrw32(p->tbdf, rno, v, 0); + iunlock(&pcicfglock); - return -(size & ~0x0F); + if(v & 1){ + size = (short)size; + size &= ~3; + } else { + size &= ~0xF; + } + return -size; +} + +void +pcisetbar(Pcidev *p, int rno, uvlong bar) +{ + ilock(&pcicfglock); + pcicfgrw32(p->tbdf, rno, bar, 0); + if((bar&7) == 4 && rno >= PciBAR0 && rno < PciBAR0+4*(nelem(p->mem)-1)) + pcicfgrw32(p->tbdf, rno+4, bar>>32, 0); + iunlock(&pcicfglock); +} + +void +pcisetwin(Pcidev *p, uvlong base, uvlong limit) +{ + ilock(&pcicfglock); + if(base & 1){ + pcicfgrw16(p->tbdf, PciIBR, (limit & 0xF000)|((base & 0xF000)>>8), 0); + pcicfgrw32(p->tbdf, PciIUBR, (limit & 0xFFFF0000)|(base>>16), 0); + } else if(base & 8){ + pcicfgrw32(p->tbdf, PciPMBR, (limit & 0xFFF00000)|((base & 0xFFF00000)>>16), 0); + pcicfgrw32(p->tbdf, PciPUBR, base >> 32, 0); + pcicfgrw32(p->tbdf, PciPULR, limit >> 32, 0); + } else { + pcicfgrw32(p->tbdf, PciMBR, (limit & 0xFFF00000)|((base & 0xFFF00000)>>16), 0); + } + iunlock(&pcicfglock); } static int @@ -294,13 +200,13 @@ pcimask(ulong v) return v+1; } -static void +void pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg) { Pcidev *p; int ntb, i, size, rno, hole; - uvlong v, mema, smema, base, limit; - ulong ioa, sioa; + uvlong mema, smema; + ulong ioa, sioa, v; Pcisiz *table, *tptr, *mtb, *itb; ioa = *pioa; @@ -329,26 +235,21 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg) smema = mema; pcibusmap(p->bridge, &smema, &sioa, 0); - hole = pcimask(smema-mema); - if(hole < (1<<20)) - hole = 1<<20; - p->mema.size = hole; - hole = pcimask(sioa-ioa); if(hole < (1<<12)) hole = 1<<12; - - p->ioa.size = hole; - itb->dev = p; itb->bar = -1; - itb->siz = p->ioa.size; + itb->siz = hole; itb->typ = 0; itb++; + hole = pcimask(smema-mema); + if(hole < (1<<20)) + hole = 1<<20; mtb->dev = p; mtb->bar = -1; - mtb->siz = p->mema.size; + mtb->siz = hole; mtb->typ = 0; mtb++; continue; @@ -356,20 +257,17 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg) for(i = 0; i < nelem(p->mem); i++) { rno = PciBAR0 + i*4; - v = pcicfgrw32(p->tbdf, rno, 0, 1); + v = pcicfgr32(p, rno); size = pcibarsize(p, rno); if(size == 0) continue; - - p->mem[i].size = size; if(v & 1) { itb->dev = p; itb->bar = i; itb->siz = size; itb->typ = 1; itb++; - } - else { + } else { mtb->dev = p; mtb->bar = i; mtb->siz = size; @@ -396,17 +294,17 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg) if(tptr->bar == -1) hole = 1<<12; ioa = (ioa+hole-1) & ~(hole-1); - - p = tptr->dev; - if(tptr->bar == -1) - p->ioa.bar = ioa; - else { - p->pcr |= IOen; - p->mem[tptr->bar].bar = ioa|1; - if(wrreg) - pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0); + if(wrreg){ + p = tptr->dev; + if(tptr->bar == -1) { + p->ioa.bar = ioa; + p->ioa.size = tptr->siz; + } else { + p->mem[tptr->bar].size = tptr->siz; + p->mem[tptr->bar].bar = ioa|1; + pcisetbar(p, PciBAR0+tptr->bar*4, p->mem[tptr->bar].bar); + } } - ioa += tptr->siz; } @@ -418,21 +316,15 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg) if(tptr->bar == -1) hole = 1<<20; 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|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); - } + if(wrreg){ + p = tptr->dev; + if(tptr->bar == -1) { + p->mema.bar = mema; + p->mema.size = tptr->siz; + } else { + p->mem[tptr->bar].size = tptr->siz; + p->mem[tptr->bar].bar = mema|tptr->typ; + pcisetbar(p, PciBAR0+tptr->bar*4, p->mem[tptr->bar].bar); } } mema += tptr->siz; @@ -450,51 +342,19 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg) */ for(p = root; p != nil; p = p->link) { if(p->bridge == nil) { - if(p->cls == 0){ - p->cls = 64; - pcicfgw8(p, PciCLS, p->cls); - } - pcicfgrw8(p->tbdf, PciLTR, 64, 0); - p->pcr |= MASen; - pcicfgrw16(p->tbdf, PciPCR, p->pcr, 0); + pcienable(p); continue; } - if(p == pciroot){ - base = p->mema.bar; - limit = base+p->mema.size-1; - regs[MISC_CPU_2_PCIE_MEM_WIN0_LO] = base; - regs[MISC_CPU_2_PCIE_MEM_WIN0_HI] = base >> 32; - base >>= 20, limit >>= 20; - regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT] = (base & 0xFFF) << 4 | (limit & 0xFFF) << 20; - regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI] = base >> 12; - regs[MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI] = limit >> 12; - } + /* Set I/O and Mem windows */ + pcisetwin(p, p->ioa.bar|1, p->ioa.bar+p->ioa.size-1); + pcisetwin(p, p->mema.bar|0, p->mema.bar+p->mema.size-1); - base = p->ioa.bar; - limit = base+p->ioa.size-1; - v = pcicfgrw32(p->tbdf, PciIBR, 0, 1); - v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8); - pcicfgrw32(p->tbdf, PciIBR, v, 0); - v = (limit & 0xFFFF0000)|(base>>16); - pcicfgrw32(p->tbdf, PciIUBR, v, 0); + /* Disable prefetch */ + pcisetwin(p, 0xFFF00000|8, 0); - base = p->mema.bar; - limit = base+p->mema.size-1; - v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16); - pcicfgrw32(p->tbdf, PciMBR, v, 0); - - /* - * Disable memory prefetch - */ - pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0); - pcicfgrw8(p->tbdf, PciLTR, 64, 0); - - /* - * Enable the bridge - */ - p->pcr |= IOen|MEMen|MASen; - pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr, 0); + /* Enable the bridge */ + pcienable(p); sioa = p->ioa.bar; smema = p->mema.bar; @@ -502,6 +362,53 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg) } } +static int +pcivalidwin(Pcidev *p, uvlong base, uvlong limit) +{ + Pcidev *bridge = p->parent; + char *typ; + + if(base & 1){ + typ = "io"; + base &= ~3; + if(base > limit) + return 0; + if(bridge == nil) + return 1; + if(base >= bridge->ioa.bar && limit < (bridge->ioa.bar + bridge->ioa.size)) + return 1; + } else { + typ = "mem"; + base &= ~0xFULL; + if(base > limit) + return 0; + if(bridge == nil) + return 1; + if(base >= bridge->mema.bar && limit < (bridge->mema.bar + bridge->mema.size)) + return 1; + if(base >= bridge->prefa.bar && limit < (bridge->prefa.bar + bridge->prefa.size)) + return 1; + } + print("%T: %.2uX invalid %s-window: %.8llux-%.8llux\n", p->tbdf, p->ccrb, typ, base, limit); + return 0; +} + +static int +pcivalidbar(Pcidev *p, uvlong bar, int size) +{ + if(bar & 1){ + bar &= ~3; + if(bar == 0 || size < 4 || (bar & (size-1)) != 0) + return 0; + return pcivalidwin(p, bar|1, bar+size-1); + } else { + bar &= ~0xFULL; + if(bar == 0 || size < 16 || (bar & (size-1)) != 0) + return 0; + return pcivalidwin(p, bar|0, bar+size-1); + } +} + static int pcilscan(int bno, Pcidev** list, Pcidev *parent) { @@ -523,12 +430,16 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent) * from the device's configuration space. */ tbdf = MKBUS(BusPCI, bno, dno, fno); + + lock(&pcicfglock); l = pcicfgrw32(tbdf, PciVID, 0, 1); + unlock(&pcicfglock); + if(l == 0xFFFFFFFF || l == 0) continue; p = malloc(sizeof(*p)); if(p == nil) - panic("pcilscan: no memory"); + panic("pcilscan: can't allocate memory"); p->tbdf = tbdf; p->vid = l; p->did = l>>16; @@ -546,7 +457,6 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent) p->ccrb = pcicfgr8(p, PciCCRb); p->cls = pcicfgr8(p, PciCLS); p->ltr = pcicfgr8(p, PciLTR); - p->intl = pcicfgr8(p, PciINTL); /* @@ -614,8 +524,24 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent) /* * Find PCI-PCI bridges and recursively descend the tree. */ - if(p->ccrb != 0x06 || p->ccru != 0x04) + switch(p->ccrb) { + case 0x06: + if(p->ccru == 0x04) + break; + default: + for(i = 0; i < nelem(p->mem); i++) { + if(p->mem[i].size == 0) + continue; + if(!pcivalidbar(p, p->mem[i].bar, p->mem[i].size)){ + if(p->mem[i].bar & 1) + p->mem[i].bar &= 3; + else + p->mem[i].bar &= 0xF; + pcisetbar(p, PciBAR0 + i*4, p->mem[i].bar); + } + } continue; + } /* * If the secondary or subordinate bus number is not @@ -638,16 +564,75 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent) * * Initialisation of the bridge should be done here. */ + p->pcr = 0; pcicfgw32(p, PciPCR, 0xFFFF0000); l = (MaxUBN<<16)|(sbn<<8)|bno; pcicfgw32(p, PciPBN, l); pcicfgw16(p, PciSPSR, 0xFFFF); + + p->ioa.bar = 0; + p->ioa.size = 0; + p->mema.bar = 0; + p->mema.size = 0; + p->prefa.bar = 0; + p->prefa.size = 0; + + pcisetwin(p, 0xFFFFF000|1, 0); + pcisetwin(p, 0xFFF00000|0, 0); + pcisetwin(p, 0xFFF00000|8, 0); + maxubn = pcilscan(sbn, &p->bridge, p); l = (maxubn<<16)|(sbn<<8)|bno; pcicfgw32(p, PciPBN, l); } else { + uvlong base, limit; + ulong v; + + v = pcicfgr16(p, PciIBR); + limit = (v & 0xF000) | 0x0FFF; + base = (v & 0x00F0) << 8; + if((v & 0x0F) == 0x01){ + v = pcicfgr32(p, PciIUBR); + limit |= (v & 0xFFFF0000); + base |= (v & 0x0000FFFF) << 16; + } + if(pcivalidwin(p, base|1, limit)){ + p->ioa.bar = base; + p->ioa.size = (limit - base)+1; + } else { + pcisetwin(p, 0xFFFFF000|1, 0); + p->ioa.bar = 0; + p->ioa.size = 0; + } + + v = pcicfgr32(p, PciMBR); + limit = (v & 0xFFF00000) | 0x000FFFFF; + base = (v & 0x0000FFF0) << 16; + if(pcivalidwin(p, base|0, limit)){ + p->mema.bar = base; + p->mema.size = (limit - base)+1; + } else { + pcisetwin(p, 0xFFF00000|0, 0); + p->mema.bar = 0; + p->mema.size = 0; + } + + v = pcicfgr32(p, PciPMBR); + limit = (v & 0xFFF00000) | 0x000FFFFF; + limit |= (uvlong)pcicfgr32(p, PciPULR) << 32; + base = (v & 0x0000FFF0) << 16; + base |= (uvlong)pcicfgr32(p, PciPUBR) << 32; + if(pcivalidwin(p, base|8, limit)){ + p->prefa.bar = base; + p->prefa.size = (limit - base)+1; + } else { + pcisetwin(p, 0xFFF00000|8, 0); + p->prefa.bar = 0; + p->prefa.size = 0; + } + if(ubn > maxubn) maxubn = ubn; pcilscan(sbn, &p->bridge, p); @@ -657,29 +642,67 @@ pcilscan(int bno, Pcidev** list, Pcidev *parent) return maxubn; } -static void -pcicfginit(void) +int +pciscan(int bno, Pcidev **list) { - uvlong mema; - ulong ioa; + return pcilscan(bno, list, nil); +} - fmtinstall('T', tbdffmt); +void +pcibussize(Pcidev *root, uvlong *msize, ulong *iosize) +{ + *msize = 0; + *iosize = 0; + pcibusmap(root, msize, iosize, 0); +} - pcilscan(0, &pciroot, nil); +Pcidev* +pcimatch(Pcidev* prev, int vid, int did) +{ + if(prev == nil) + prev = pcilist; + else + prev = prev->list; - /* - * Work out how big the top bus is - */ - ioa = 0; - mema = 0; - pcibusmap(pciroot, &mema, &ioa, 0); + while(prev != nil){ + if((vid == 0 || prev->vid == vid) + && (did == 0 || prev->did == did)) + break; + prev = prev->list; + } + return prev; +} - /* - * Align the windows and map it - */ - ioa = 0; - mema = soc.pciwin; - pcibusmap(pciroot, &mema, &ioa, 1); +Pcidev* +pcimatchtbdf(int tbdf) +{ + Pcidev *pcidev; + + for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) { + if(pcidev->tbdf == tbdf) + break; + } + return pcidev; +} + +uchar +pciipin(Pcidev *pci, uchar pin) +{ + if (pci == nil) + pci = pcilist; + + while (pci != nil) { + uchar intl; + + if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff) + return pci->intl; + + if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0) + return intl; + + pci = pci->list; + } + return 0; } static void @@ -688,21 +711,21 @@ pcilhinv(Pcidev* p) int i; Pcidev *t; - if(p == nil) { - p = pciroot; - print("bus dev 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); - for(i = 0; i < nelem(p->mem); i++) { if(t->mem[i].size == 0) continue; - print("%d:%llux %d ", i, - (uvlong)t->mem[i].bar, t->mem[i].size); + print("%d:%.8llux %d ", i, t->mem[i].bar, t->mem[i].size); } + if(t->ioa.bar || t->ioa.size) + print("ioa:%.8llux-%.8llux %d ", t->ioa.bar, t->ioa.bar+t->ioa.size, t->ioa.size); + if(t->mema.bar || t->mema.size) + print("mema:%.8llux-%.8llux %d ", t->mema.bar, t->mema.bar+t->mema.size, t->mema.size); + if(t->prefa.bar || t->prefa.size) + print("prefa:%.8llux-%.8llux %llud ", t->prefa.bar, t->prefa.bar+t->prefa.size, t->prefa.size); if(t->bridge) print("->%d", BUSBNO(t->bridge->tbdf)); print("\n"); @@ -714,12 +737,26 @@ pcilhinv(Pcidev* p) } } -static void +void pcihinv(Pcidev* p) { + print("bus dev type vid did intl memory\n"); pcilhinv(p); } +void +pcireset(void) +{ + Pcidev *p; + + for(p = pcilist; p != nil; p = p->list) { + /* don't mess with the bridges */ + if(p->ccrb == 0x06) + continue; + pciclrbme(p); + } +} + void pcisetioe(Pcidev* p) { @@ -826,17 +863,6 @@ pcicap(Pcidev *p, int cap) return enumcaps(p, matchcap, cap); } -int -pcinextcap(Pcidev *pci, int offset) -{ - if(offset == 0) { - if((pcicfgr16(pci, PciPSR) & (1<<4)) == 0) - return 0; /* no capabilities */ - offset = PciCAP-1; - } - return pcicfgr8(pci, offset+1) & ~3; -} - int pcihtcap(Pcidev *p, int cap) { @@ -908,6 +934,17 @@ pcisetpms(Pcidev* p, int state) return ostate; } +int +pcinextcap(Pcidev *pci, int offset) +{ + if(offset == 0) { + if((pcicfgr16(pci, PciPSR) & (1<<4)) == 0) + return 0; /* no capabilities */ + offset = PciCAP-1; + } + return pcicfgr8(pci, offset+1) & ~3; +} + void pcienable(Pcidev *p) { @@ -936,12 +973,11 @@ pcienable(Pcidev *p) /* 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++; - } + if(p->mem[i].size == 0) + continue; + pcisetbar(p, PciBAR0+i*4, p->mem[i].bar); } + pcicfgw8(p, PciINTL, p->intl); pcicfgw8(p, PciLTR, p->ltr); pcicfgw8(p, PciCLS, p->cls); @@ -949,6 +985,15 @@ pcienable(Pcidev *p) break; } + if(p->ltr == 0 || p->ltr == 0xFF){ + p->ltr = 64; + pcicfgw8(p,PciLTR, p->ltr); + } + if(p->cls == 0 || p->cls == 0xFF){ + p->cls = 64/4; + pcicfgw8(p, PciCLS, p->cls); + } + if(p->bridge != nil) pcr = IOen|MEMen|MASen; else { @@ -966,7 +1011,7 @@ pcienable(Pcidev *p) 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); + pcicfgw32(p, PciPCR, 0xFFFF0000|p->pcr); } } @@ -977,165 +1022,3 @@ pcidisable(Pcidev *p) return; pciclrbme(p); } - -enum { - MSICtrl = 0x02, /* message control register (16 bit) */ - MSIAddr = 0x04, /* message address register (64 bit) */ - MSIData32 = 0x08, /* message data register for 32 bit MSI (16 bit) */ - MSIData64 = 0x0C, /* message data register for 64 bit MSI (16 bit) */ -}; - -typedef struct Pciisr Pciisr; -struct Pciisr { - void (*f)(Ureg*, void*); - void *a; - Pcidev *p; -}; - -static Pciisr pciisr[32]; -static Lock pciisrlk; - -void -pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a) -{ - int cap, ok64; - u32int dat; - u64int adr; - Pcidev *p; - Pciisr *isr; - - if((p = pcimatchtbdf(tbdf)) == nil){ - print("pciintrenable: %T: unknown device\n", tbdf); - return; - } - if((cap = pcicap(p, PciCapMSI)) < 0){ - print("pciintrenable: %T: no MSI cap\n", tbdf); - return; - } - - lock(&pciisrlk); - for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){ - if(isr->p == p){ - isr->p = nil; - regs[MSI_INTR2_BASE + INTR_MASK_SET] = 1 << (isr-pciisr); - break; - } - } - for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){ - if(isr->p == nil){ - isr->p = p; - isr->a = a; - isr->f = f; - regs[MSI_INTR2_BASE + INTR_CLR] = 1 << (isr-pciisr); - regs[MSI_INTR2_BASE + INTR_MASK_CLR] = 1 << (isr-pciisr); - break; - } - } - unlock(&pciisrlk); - - if(isr >= &pciisr[nelem(pciisr)]){ - print("pciintrenable: %T: out of isr slots\n", tbdf); - return; - } - - adr = MSI_TARGET_ADDR; - ok64 = (pcicfgr16(p, cap + MSICtrl) & (1<<7)) != 0; - pcicfgw32(p, cap + MSIAddr, adr); - if(ok64) pcicfgw32(p, cap + MSIAddr + 4, adr>>32); - dat = regs[MISC_MSI_DATA_CONFIG]; - dat = ((dat >> 16) & (dat & 0xFFFF)) | (isr-pciisr); - pcicfgw16(p, cap + (ok64 ? MSIData64 : MSIData32), dat); - pcicfgw16(p, cap + MSICtrl, 1); -} - -void -pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a) -{ - Pciisr *isr; - - lock(&pciisrlk); - for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){ - if(isr->p != nil && isr->p->tbdf == tbdf && isr->f == f && isr->a == a){ - regs[MSI_INTR2_BASE + INTR_MASK_SET] = 1 << (isr-pciisr); - isr->p = nil; - isr->f = nil; - isr->a = nil; - break; - } - } - unlock(&pciisrlk); -} - -static void -pciinterrupt(Ureg *ureg, void*) -{ - Pciisr *isr; - u32int sts; - - sts = regs[MSI_INTR2_BASE + INTR_STATUS]; - if(sts == 0) - return; - regs[MSI_INTR2_BASE + INTR_CLR] = sts; - for(isr = pciisr; sts != 0 && isr < &pciisr[nelem(pciisr)]; isr++, sts>>=1){ - if((sts & 1) != 0 && isr->f != nil) - (*isr->f)(ureg, isr->a); - } - regs[MISC_EOI_CTRL] = 1; -} - -void -pcilink(void) -{ - int log2dmasize = 30; // 1GB - - regs[RGR1_SW_INIT_1] |= 3; - delay(200); - regs[RGR1_SW_INIT_1] &= ~2; - regs[MISC_PCIE_CTRL] &= ~5; - delay(200); - - regs[MISC_HARD_PCIE_HARD_DEBUG] &= ~0x08000000; - delay(200); - - regs[MSI_INTR2_BASE + INTR_CLR] = -1; - regs[MSI_INTR2_BASE + INTR_MASK_SET] = -1; - - regs[MISC_CPU_2_PCIE_MEM_WIN0_LO] = 0; - regs[MISC_CPU_2_PCIE_MEM_WIN0_HI] = 0; - regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT] = 0; - regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI] = 0; - regs[MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI] = 0; - - // SCB_ACCESS_EN, CFG_READ_UR_MODE, MAX_BURST_SIZE_128, SCB0SIZE - regs[MISC_MISC_CTRL] = 1<<12 | 1<<13 | 0<<20 | (log2dmasize-15)<<27; - - regs[MISC_RC_BAR2_CONFIG_LO] = (log2dmasize-15); - regs[MISC_RC_BAR2_CONFIG_HI] = 0; - - regs[MISC_RC_BAR1_CONFIG_LO] = 0; - regs[MISC_RC_BAR3_CONFIG_LO] = 0; - - regs[MISC_MSI_BAR_CONFIG_LO] = MSI_TARGET_ADDR | 1; - regs[MISC_MSI_BAR_CONFIG_HI] = MSI_TARGET_ADDR>>32; - regs[MISC_MSI_DATA_CONFIG] = 0xFFF86540; - intrenable(IRQpci, pciinterrupt, nil, BUSUNKNOWN, "pci"); - - // force to GEN2 - regs[(0xAC + 12)/4] = (regs[(0xAC + 12)/4] & ~15) | 2; // linkcap - regs[(0xAC + 48)/4] = (regs[(0xAC + 48)/4] & ~15) | 2; // linkctl2 - - regs[RGR1_SW_INIT_1] &= ~1; - delay(500); - - if((regs[MISC_PCIE_STATUS] & 0x30) != 0x30){ - print("pcireset: phy link is down\n"); - return; - } - - regs[RC_CFG_PRIV1_ID_VAL3] = 0x060400; - regs[RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1] &= ~0xC; - regs[MISC_HARD_PCIE_HARD_DEBUG] |= 2; - - pcicfginit(); - pcihinv(nil); -} diff --git a/sys/src/9/port/pci.h b/sys/src/9/port/pci.h new file mode 100644 index 000000000..25a6bb803 --- /dev/null +++ b/sys/src/9/port/pci.h @@ -0,0 +1,292 @@ +/* + * PCI support code. + */ +enum { /* type 0 & type 1 pre-defined header */ + PciVID = 0x00, /* vendor ID */ + PciDID = 0x02, /* device ID */ + PciPCR = 0x04, /* command */ + PciPSR = 0x06, /* status */ + PciRID = 0x08, /* revision ID */ + PciCCRp = 0x09, /* programming interface class code */ + PciCCRu = 0x0A, /* sub-class code */ + PciCCRb = 0x0B, /* base class code */ + PciCLS = 0x0C, /* cache line size */ + PciLTR = 0x0D, /* latency timer */ + PciHDT = 0x0E, /* header type */ + PciBST = 0x0F, /* BIST */ + + PciBAR0 = 0x10, /* base address */ + PciBAR1 = 0x14, + + PciCAP = 0x34, /* capabilities pointer */ + PciINTL = 0x3C, /* interrupt line */ + PciINTP = 0x3D, /* interrupt pin */ +}; + +/* ccrb (base class code) values; controller types */ +enum { + Pcibcpci1 = 0, /* pci 1.0; no class codes defined */ + Pcibcstore = 1, /* mass storage */ + Pcibcnet = 2, /* network */ + Pcibcdisp = 3, /* display */ + Pcibcmmedia = 4, /* multimedia */ + Pcibcmem = 5, /* memory */ + Pcibcbridge = 6, /* bridge */ + Pcibccomm = 7, /* simple comms (e.g., serial) */ + Pcibcbasesys = 8, /* base system */ + Pcibcinput = 9, /* input */ + Pcibcdock = 0xa, /* docking stations */ + Pcibcproc = 0xb, /* processors */ + Pcibcserial = 0xc, /* serial bus (e.g., USB) */ + Pcibcwireless = 0xd, /* wireless */ + Pcibcintell = 0xe, /* intelligent i/o */ + Pcibcsatcom = 0xf, /* satellite comms */ + Pcibccrypto = 0x10, /* encryption/decryption */ + Pcibcdacq = 0x11, /* data acquisition & signal proc. */ +}; + +/* ccru (sub-class code) values; common cases only */ +enum { + /* mass storage */ + Pciscscsi = 0, /* SCSI */ + Pciscide = 1, /* IDE (ATA) */ + + /* network */ + Pciscether = 0, /* Ethernet */ + + /* display */ + Pciscvga = 0, /* VGA */ + Pciscxga = 1, /* XGA */ + Pcisc3d = 2, /* 3D */ + + /* bridges */ + Pcischostpci = 0, /* host/pci */ + Pciscpcicpci = 1, /* pci/pci */ + + /* simple comms */ + Pciscserial = 0, /* 16450, etc. */ + Pciscmultiser = 1, /* multiport serial */ + + /* serial bus */ + Pciscusb = 3, /* USB */ +}; + +enum { /* type 0 pre-defined header */ + PciCIS = 0x28, /* cardbus CIS pointer */ + PciSVID = 0x2C, /* subsystem vendor ID */ + PciSID = 0x2E, /* subsystem ID */ + PciEBAR0 = 0x30, /* expansion ROM base address */ + PciMGNT = 0x3E, /* burst period length */ + PciMLT = 0x3F, /* maximum latency between bursts */ +}; + +enum { /* type 1 pre-defined header */ + PciPBN = 0x18, /* primary bus number */ + PciSBN = 0x19, /* secondary bus number */ + PciUBN = 0x1A, /* subordinate bus number */ + PciSLTR = 0x1B, /* secondary latency timer */ + PciIBR = 0x1C, /* I/O base */ + PciILR = 0x1D, /* I/O limit */ + PciSPSR = 0x1E, /* secondary status */ + PciMBR = 0x20, /* memory base */ + PciMLR = 0x22, /* memory limit */ + PciPMBR = 0x24, /* prefetchable memory base */ + PciPMLR = 0x26, /* prefetchable memory limit */ + PciPUBR = 0x28, /* prefetchable base upper 32 bits */ + PciPULR = 0x2C, /* prefetchable limit upper 32 bits */ + PciIUBR = 0x30, /* I/O base upper 16 bits */ + PciIULR = 0x32, /* I/O limit upper 16 bits */ + PciEBAR1 = 0x28, /* expansion ROM base address */ + PciBCR = 0x3E, /* bridge control register */ +}; + +enum { /* type 2 pre-defined header */ + PciCBExCA = 0x10, + PciCBSPSR = 0x16, + PciCBPBN = 0x18, /* primary bus number */ + PciCBSBN = 0x19, /* secondary bus number */ + PciCBUBN = 0x1A, /* subordinate bus number */ + PciCBSLTR = 0x1B, /* secondary latency timer */ + PciCBMBR0 = 0x1C, + PciCBMLR0 = 0x20, + PciCBMBR1 = 0x24, + PciCBMLR1 = 0x28, + PciCBIBR0 = 0x2C, /* I/O base */ + PciCBILR0 = 0x30, /* I/O limit */ + PciCBIBR1 = 0x34, /* I/O base */ + PciCBILR1 = 0x38, /* I/O limit */ + PciCBSVID = 0x40, /* subsystem vendor ID */ + PciCBSID = 0x42, /* subsystem ID */ + PciCBLMBAR = 0x44, /* legacy mode base address */ +}; + +/* capabilities */ +enum { + PciCapPMG = 0x01, /* power management */ + PciCapAGP = 0x02, + PciCapVPD = 0x03, /* vital product data */ + PciCapSID = 0x04, /* slot id */ + PciCapMSI = 0x05, + PciCapCHS = 0x06, /* compact pci hot swap */ + PciCapPCIX = 0x07, + PciCapHTC = 0x08, /* hypertransport irq conf */ + PciCapVND = 0x09, /* vendor specific information */ + PciCapPCIe = 0x10, + PciCapMSIX = 0x11, + PciCapSATA = 0x12, + PciCapHSW = 0x0c, /* hot swap */ +}; + +enum { + /* bar bits */ + Barioaddr = 1<<0, /* vs. memory addr */ + Barwidthshift = 1, + Barwidthmask = 3, + Barwidth32 = 0, + Barwidth64 = 2, + Barprefetch = 1<<3, +}; + +enum +{ /* command register */ + IOen = (1<<0), + MEMen = (1<<1), + MASen = (1<<2), + MemWrInv = (1<<4), + PErrEn = (1<<6), + SErrEn = (1<<8), +}; + +typedef struct Pcidev Pcidev; +struct Pcidev +{ + int tbdf; /* type+bus+device+function */ + ushort vid; /* vendor ID */ + ushort did; /* device ID */ + + ushort pcr; + + uchar rid; + uchar ccrp; + uchar ccru; + uchar ccrb; + uchar cls; + uchar ltr; + + struct { + uvlong bar; /* base address */ + int size; + } mem[6]; + + struct { + uvlong bar; + int size; + } rom; + uchar intl; /* interrupt line */ + + Pcidev* list; + Pcidev* link; /* next device on this bno */ + + Pcidev* parent; /* up a bus */ + Pcidev* bridge; /* down a bus */ + struct { + uvlong bar; + int size; + } ioa, mema; + struct { + uvlong bar; + uvlong size; + } prefa; + + int pmrb; /* power management register block */ +}; + +enum { + /* vendor ids */ + Vintel = 0x8086, + Vmyricom= 0x14c1, + Vatiamd = 0x1002, + Vjmicron= 0x197b, + Vmarvell= 0x1b4b, + Vnvidia = 0x10de, + Vrealtek= 0x10ec, +}; + +enum +{ + MaxFNO = 7, + MaxUBN = 255, +}; + +extern int pcimaxdno; + +extern int pcicfgr32(Pcidev* pcidev, int rno); +extern void pcicfgw32(Pcidev* pcidev, int rno, int data); +extern int pcicfgr16(Pcidev* pcidev, int rno); +extern void pcicfgw16(Pcidev* pcidev, int rno, int data); +extern int pcicfgr8(Pcidev* pcidev, int rno); +extern void pcicfgw8(Pcidev* pcidev, int rno, int data); + +extern int pciscan(int bno, Pcidev **list); +extern void pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg); +extern void pcibussize(Pcidev *root, uvlong *msize, ulong *iosize); + +extern Pcidev* pcimatch(Pcidev* prev, int vid, int did); +extern Pcidev* pcimatchtbdf(int tbdf); + +extern int pcibarsize(Pcidev *, int rno); +extern void pcisetbar(Pcidev *, int, uvlong); + +extern uchar pciipin(Pcidev *pci, uchar pin); + +extern void pcisetioe(Pcidev* p); +extern void pciclrioe(Pcidev* p); +extern void pcisetbme(Pcidev* p); +extern void pciclrbme(Pcidev* p); +extern void pcisetmwi(Pcidev* p); +extern void pciclrmwi(Pcidev* p); + +extern int pcicap(Pcidev *p, int cap); +extern int pcinextcap(Pcidev *pci, int offset); +extern int pcihtcap(Pcidev *p, int cap); +extern int pcigetpms(Pcidev* p); +extern int pcisetpms(Pcidev* p, int state); + +extern void pcienable(Pcidev *p); +extern void pcidisable(Pcidev *p); + +extern void pcihinv(Pcidev* p); +extern void pcireset(void); + +enum { + BusCBUS = 0, /* Corollary CBUS */ + BusCBUSII, /* Corollary CBUS II */ + BusEISA, /* Extended ISA */ + BusFUTURE, /* IEEE Futurebus */ + BusINTERN, /* Internal bus */ + BusISA, /* Industry Standard Architecture */ + BusMBI, /* Multibus I */ + BusMBII, /* Multibus II */ + BusMCA, /* Micro Channel Architecture */ + BusMPI, /* MPI */ + BusMPSA, /* MPSA */ + BusNUBUS, /* Apple Macintosh NuBus */ + BusPCI, /* Peripheral Component Interconnect */ + BusPCMCIA, /* PC Memory Card International Association */ + BusTC, /* DEC TurboChannel */ + BusVL, /* VESA Local bus */ + BusVME, /* VMEbus */ + BusXPRESS, /* Express System Bus */ +}; + +#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8)) +#define BUSFNO(tbdf) (((tbdf)>>8)&0x07) +#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F) +#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF) +#define BUSTYPE(tbdf) ((tbdf)>>24) +#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00) + +extern int tbdffmt(Fmt*); + +#pragma varargck type "T" int +#pragma varargck type "T" uint diff --git a/sys/src/9/port/portmkfile b/sys/src/9/port/portmkfile index 5e88150c7..07f1b2518 100644 --- a/sys/src/9/port/portmkfile +++ b/sys/src/9/port/portmkfile @@ -40,7 +40,7 @@ clean:V: nuke:V: clean rm -f ../boot/libboot.a$O *.elf *.rr *.acid -%.$O: /$objtype/include/u.h ../port/lib.h mem.h dat.h fns.h io.h ../port/error.h ../port/portdat.h ../port/portfns.h +%.$O: /$objtype/include/u.h ../port/lib.h mem.h dat.h fns.h io.h ../port/pci.h ../port/error.h ../port/portdat.h ../port/portfns.h ../port/systab.h:D: /sys/src/libc/9syscall/sys.h ../port/mksystab rc ../port/mksystab > ../port/systab.h @@ -112,3 +112,4 @@ devether.$O ethersink.$O: ../port/etherif.h ../port/netif.h wifi.$O: ../port/etherif.h ../port/netif.h ../port/wifi.h /sys/include/libsec.h wifi.$O: ../ip/ip.h ../ip/ipv6.h ethermii.$O: ../port/ethermii.h +pci.$O devpnp.$O usbxhci.$O: ../port/pci.h diff --git a/sys/src/9/port/usbxhci.c b/sys/src/9/port/usbxhci.c index 1f87fddbe..5af746dfa 100644 --- a/sys/src/9/port/usbxhci.c +++ b/sys/src/9/port/usbxhci.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/usb.h" diff --git a/sys/src/9/ppc/fns.h b/sys/src/9/ppc/fns.h index 5ae2f8097..0606e3b69 100644 --- a/sys/src/9/ppc/fns.h +++ b/sys/src/9/ppc/fns.h @@ -67,12 +67,6 @@ void mmuinit(void); void mmusweep(void*); int newmmupid(void); void outb(int, int); -int pcicfgr16(Pcidev*, int); -int pcicfgr32(Pcidev*, int); -int pcicfgr8(Pcidev*, int); -void pcicfgw16(Pcidev*, int, int); -void pcicfgw32(Pcidev*, int, int); -void pcicfgw8(Pcidev*, int, int); void procsave(Proc*); void procsetup(Proc*); void procfork(Proc*); diff --git a/sys/src/9/teg2/ether8169.c b/sys/src/9/teg2/ether8169.c index d51816fcb..39bd5ae9f 100644 --- a/sys/src/9/teg2/ether8169.c +++ b/sys/src/9/teg2/ether8169.c @@ -13,6 +13,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include "../port/error.h" #include "../port/netif.h" #include "../port/etherif.h" @@ -1566,16 +1567,7 @@ rtl8169pci(void) continue; } - if(pcigetpms(p) > 0){ - pcisetpms(p, 0); - - for(i = 0; i < 6; i++) - pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar); - pcicfgw8(p, PciINTL, p->intl); - pcicfgw8(p, PciLTR, p->ltr); - pcicfgw8(p, PciCLS, p->cls); - pcicfgw16(p, PciPCR, p->pcr); - } + pcienable(p); if(rtl8169reset(ctlr)){ free(ctlr); diff --git a/sys/src/9/teg2/fns.h b/sys/src/9/teg2/fns.h index 62e253c27..801656c0e 100644 --- a/sys/src/9/teg2/fns.h +++ b/sys/src/9/teg2/fns.h @@ -88,28 +88,10 @@ extern void mmuidmap(uintptr phys, int mbs); extern void mmuinvalidate(void); /* 'mmu' or 'tlb'? */ extern void mmuinvalidateaddr(u32int); /* 'mmu' or 'tlb'? */ extern void mousectl(Cmdbuf *cb); -extern ulong pcibarsize(Pcidev*, int); -extern void pcibussize(Pcidev*, ulong*, ulong*); -extern int pcicfgr8(Pcidev*, int); -extern int pcicfgr16(Pcidev*, int); -extern int pcicfgr32(Pcidev*, int); -extern void pcicfgw8(Pcidev*, int, int); -extern void pcicfgw16(Pcidev*, int, int); -extern void pcicfgw32(Pcidev*, int, int); -extern void pciclrbme(Pcidev*); -extern void pciclrioe(Pcidev*); -extern void pciclrmwi(Pcidev*); +extern int pcicfgrw8(int, int, int, int); +extern int pcicfgrw16(int, int, int, int); +extern int pcicfgrw32(int, int, int, int); extern void pcieintrdone(void); -extern int pcigetpms(Pcidev*); -extern void pcihinv(Pcidev*); -extern uchar pciipin(Pcidev*, uchar); -extern Pcidev* pcimatch(Pcidev*, int, int); -extern Pcidev* pcimatchtbdf(int); -extern void pcireset(void); -extern void pcisetbme(Pcidev*); -extern void pcisetioe(Pcidev*); -extern void pcisetmwi(Pcidev*); -extern int pcisetpms(Pcidev*, int); extern u32int pidget(void); extern void pidput(u32int); extern void prcachecfg(void); diff --git a/sys/src/9/teg2/io.h b/sys/src/9/teg2/io.h index e56d6c354..54818843b 100644 --- a/sys/src/9/teg2/io.h +++ b/sys/src/9/teg2/io.h @@ -1,219 +1,4 @@ -#pragma varargck type "T" int -#pragma varargck type "T" uint - -/* - * PCI - */ - -enum { - BusCBUS = 0, /* Corollary CBUS */ - BusCBUSII, /* Corollary CBUS II */ - BusEISA, /* Extended ISA */ - BusFUTURE, /* IEEE Futurebus */ - BusINTERN, /* Internal bus */ - BusISA, /* Industry Standard Architecture */ - BusMBI, /* Multibus I */ - BusMBII, /* Multibus II */ - BusMCA, /* Micro Channel Architecture */ - BusMPI, /* MPI */ - BusMPSA, /* MPSA */ - BusNUBUS, /* Apple Macintosh NuBus */ - BusPCI, /* Peripheral Component Interconnect */ - BusPCMCIA, /* PC Memory Card International Association */ - BusTC, /* DEC TurboChannel */ - BusVL, /* VESA Local bus */ - BusVME, /* VMEbus */ - BusXPRESS, /* Express System Bus */ -}; - -#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8)) -#define BUSFNO(tbdf) (((tbdf)>>8)&0x07) -#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F) -#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF) -#define BUSTYPE(tbdf) ((tbdf)>>24) -#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00) #define BUSUNKNOWN (-1) -enum { /* type 0 & type 1 pre-defined header */ - PciVID = 0x00, /* vendor ID */ - PciDID = 0x02, /* device ID */ - PciPCR = 0x04, /* command */ - PciPSR = 0x06, /* status */ - PciRID = 0x08, /* revision ID */ - PciCCRp = 0x09, /* programming interface class code */ - PciCCRu = 0x0A, /* sub-class code */ - PciCCRb = 0x0B, /* base class code */ - PciCLS = 0x0C, /* cache line size */ - PciLTR = 0x0D, /* latency timer */ - PciHDT = 0x0E, /* header type */ - PciBST = 0x0F, /* BIST */ - - PciBAR0 = 0x10, /* base address */ - PciBAR1 = 0x14, - - PciINTL = 0x3C, /* interrupt line */ - PciINTP = 0x3D, /* interrupt pin */ -}; - -/* ccrb (base class code) values; controller types */ -enum { - Pcibcpci1 = 0, /* pci 1.0; no class codes defined */ - Pcibcstore = 1, /* mass storage */ - Pcibcnet = 2, /* network */ - Pcibcdisp = 3, /* display */ - Pcibcmmedia = 4, /* multimedia */ - Pcibcmem = 5, /* memory */ - Pcibcbridge = 6, /* bridge */ - Pcibccomm = 7, /* simple comms (e.g., serial) */ - Pcibcbasesys = 8, /* base system */ - Pcibcinput = 9, /* input */ - Pcibcdock = 0xa, /* docking stations */ - Pcibcproc = 0xb, /* processors */ - Pcibcserial = 0xc, /* serial bus (e.g., USB) */ - Pcibcwireless = 0xd, /* wireless */ - Pcibcintell = 0xe, /* intelligent i/o */ - Pcibcsatcom = 0xf, /* satellite comms */ - Pcibccrypto = 0x10, /* encryption/decryption */ - Pcibcdacq = 0x11, /* data acquisition & signal proc. */ -}; - -/* ccru (sub-class code) values; common cases only */ -enum { - /* mass storage */ - Pciscscsi = 0, /* SCSI */ - Pciscide = 1, /* IDE (ATA) */ - Pciscsata = 6, /* SATA */ - - /* network */ - Pciscether = 0, /* Ethernet */ - - /* display */ - Pciscvga = 0, /* VGA */ - Pciscxga = 1, /* XGA */ - Pcisc3d = 2, /* 3D */ - - /* bridges */ - Pcischostpci = 0, /* host/pci */ - Pciscpcicpci = 1, /* pci/pci */ - - /* simple comms */ - Pciscserial = 0, /* 16450, etc. */ - Pciscmultiser = 1, /* multiport serial */ - - /* serial bus */ - Pciscusb = 3, /* USB */ -}; - -enum { /* type 0 pre-defined header */ - PciCIS = 0x28, /* cardbus CIS pointer */ - PciSVID = 0x2C, /* subsystem vendor ID */ - PciSID = 0x2E, /* subsystem ID */ - PciEBAR0 = 0x30, /* expansion ROM base address */ - PciMGNT = 0x3E, /* burst period length */ - PciMLT = 0x3F, /* maximum latency between bursts */ -}; - -enum { /* type 1 pre-defined header */ - PciPBN = 0x18, /* primary bus number */ - PciSBN = 0x19, /* secondary bus number */ - PciUBN = 0x1A, /* subordinate bus number */ - PciSLTR = 0x1B, /* secondary latency timer */ - PciIBR = 0x1C, /* I/O base */ - PciILR = 0x1D, /* I/O limit */ - PciSPSR = 0x1E, /* secondary status */ - PciMBR = 0x20, /* memory base */ - PciMLR = 0x22, /* memory limit */ - PciPMBR = 0x24, /* prefetchable memory base */ - PciPMLR = 0x26, /* prefetchable memory limit */ - PciPUBR = 0x28, /* prefetchable base upper 32 bits */ - PciPULR = 0x2C, /* prefetchable limit upper 32 bits */ - PciIUBR = 0x30, /* I/O base upper 16 bits */ - PciIULR = 0x32, /* I/O limit upper 16 bits */ - PciEBAR1 = 0x28, /* expansion ROM base address */ - PciBCR = 0x3E, /* bridge control register */ -}; - -enum { /* type 2 pre-defined header */ - PciCBExCA = 0x10, - PciCBSPSR = 0x16, - PciCBPBN = 0x18, /* primary bus number */ - PciCBSBN = 0x19, /* secondary bus number */ - PciCBUBN = 0x1A, /* subordinate bus number */ - PciCBSLTR = 0x1B, /* secondary latency timer */ - PciCBMBR0 = 0x1C, - PciCBMLR0 = 0x20, - PciCBMBR1 = 0x24, - PciCBMLR1 = 0x28, - PciCBIBR0 = 0x2C, /* I/O base */ - PciCBILR0 = 0x30, /* I/O limit */ - PciCBIBR1 = 0x34, /* I/O base */ - PciCBILR1 = 0x38, /* I/O limit */ - PciCBSVID = 0x40, /* subsystem vendor ID */ - PciCBSID = 0x42, /* subsystem ID */ - PciCBLMBAR = 0x44, /* legacy mode base address */ -}; - -enum { - /* bar bits */ - Barioaddr = 1<<0, /* vs. memory addr */ - Barwidthshift = 1, - Barwidthmask = MASK(2), - Barwidth32 = 0, - Barwidth64 = 2, - Barprefetch = 1<<3, -}; - -struct Pcisiz -{ - Pcidev* dev; - int siz; - int bar; -}; - -struct Pcidev -{ - int tbdf; /* type+bus+device+function */ - ushort vid; /* vendor ID */ - ushort did; /* device ID */ - - ushort pcr; - - uchar rid; - uchar ccrp; - uchar ccru; - uchar ccrb; - uchar cls; - uchar ltr; - - struct { - ulong bar; /* base address */ - int size; - } mem[6]; - - struct { - ulong bar; - int size; - } rom; - uchar intl; /* interrupt line */ - - Pcidev* list; - Pcidev* link; /* next device on this bno */ - - Pcidev* bridge; /* down a bus */ - - int pmrb; /* power management register block */ -}; - -enum { - /* vendor ids */ - Vatiamd = 0x1002, - Vintel = 0x8086, - Vjmicron= 0x197b, - Vmarvell= 0x1b4b, - Vmyricom= 0x14c1, - Vnvidia = 0x10de, - Vrealtek= 0x10ec, -}; - #define PCIWINDOW 0 #define PCIWADDR(va) (PADDR(va)+PCIWINDOW) diff --git a/sys/src/9/teg2/main.c b/sys/src/9/teg2/main.c index b08a00178..276a2fa68 100644 --- a/sys/src/9/teg2/main.c +++ b/sys/src/9/teg2/main.c @@ -5,6 +5,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "../port/pci.h" #include diff --git a/sys/src/9/teg2/pci.c b/sys/src/9/teg2/pci.c deleted file mode 100644 index cd13902e8..000000000 --- a/sys/src/9/teg2/pci.c +++ /dev/null @@ -1,853 +0,0 @@ -/* - * PCI support code. - * Needs a massive rewrite. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#define DBG if(0) pcilog - -typedef struct Pci Pci; - -struct -{ - char output[16*1024]; - int ptr; -}PCICONS; - -int -pcilog(char *fmt, ...) -{ - int n; - va_list arg; - char buf[PRINTSIZE]; - - va_start(arg, fmt); - n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; - va_end(arg); - - memmove(PCICONS.output+PCICONS.ptr, buf, n); - PCICONS.ptr += n; - return n; -} - -enum -{ - MaxFNO = 7, - MaxUBN = 255, -}; - -enum -{ /* command register */ - IOen = (1<<0), - MEMen = (1<<1), - MASen = (1<<2), - MemWrInv = (1<<4), - PErrEn = (1<<6), - SErrEn = (1<<8), -}; - -typedef struct { - ulong cap; - ulong ctl; -} Capctl; -typedef struct { - Capctl dev; - Capctl link; - Capctl slot; -} Devlinkslot; - -/* capability list id 0x10 is pci-e */ -struct Pci { - /* pci-compatible config */ - /* what io.h calls type 0 & type 1 pre-defined header */ - ulong id; - ulong cs; - ulong revclass; - ulong misc; /* cache line size, latency timer, header type, bist */ - ulong bar[2]; /* always 0 on tegra 2 */ - - /* types 1 & 2 pre-defined header */ - ulong bus; - ulong ioaddrs; - ulong memaddrs; - ulong prefmem; - ulong prefbasehi; - ulong preflimhi; - /* type 2 pre-defined header only */ - ulong ioaddrhi; - ulong cfgcapoff; /* offset in cfg. space to cap. list (0x40) */ - ulong rom; - ulong intr; /* PciINT[LP] */ - /* subsystem capability regs */ - ulong subsysid; - ulong subsyscap; - /* */ - - Capctl pwrmgmt; - - /* msi */ - ulong msictlcap; - ulong msimsgaddr[2]; /* little-endian */ - ulong msimsgdata; - - /* pci-e cap. */ - uchar _pad0[0x80-0x60]; - ulong pciecap; - Devlinkslot port0; - ulong rootctl; - ulong rootsts; - Devlinkslot port1; - - /* 0xbc */ - -}; - -enum { - /* offsets from soc.pci */ - Port0 = 0, - Port1 = 0x1000, - Pads = 0x3000, - Afi = 0x3800, - Aficfg = Afi + 0xac, - Cfgspace = 0x4000, - Ecfgspace = 0x104000, - - /* cs bits */ - Iospace = 1<<0, - Memspace = 1<<1, - Busmaster = 1<<2, - - /* Aficfg bits */ - Fpcion = 1<<0, -}; - -struct Pcictlr { - union { - uchar _padpci[0x1000]; - Pci; - } ports[2]; - uchar _padpads[0x1000]; - uchar pads[0x800]; - uchar afi[0x800]; - ulong cfg[0x1000]; - ulong extcfg[0x1000]; -}; - -static Lock pcicfglock; -static Lock pcicfginitlock; -static int pcicfgmode = -1; -static int pcimaxbno = 1; /* was 7; only 2 pci buses; touching 3rd hangs */ -static int pcimaxdno; -static Pcidev* pciroot; -static Pcidev* pcilist; -static Pcidev* pcitail; - -static int pcicfgrw8(int, int, int, int); -static int pcicfgrw16(int, int, int, int); -static int pcicfgrw32(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", -}; - -static int -tbdffmt(Fmt* fmt) -{ - char *p; - int l, r; - uint type, tbdf; - - if((p = malloc(READSTR)) == nil) - return fmtstrcpy(fmt, "(tbdfconv)"); - - 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)); - } - break; - - default: - snprint(p, READSTR, "(tbdfconv)"); - break; - } - r = fmtstrcpy(fmt, p); - free(p); - - return r; -} - -ulong -pcibarsize(Pcidev *p, int rno) -{ - ulong v, size; - - v = pcicfgrw32(p->tbdf, rno, 0, 1); - pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0); - size = pcicfgrw32(p->tbdf, rno, 0, 1); - if(v & 1) - size |= 0xFFFF0000; - pcicfgrw32(p->tbdf, rno, v, 0); - - return -(size & ~0x0F); -} - -static int -pcilscan(int bno, Pcidev** list) -{ - Pcidev *p, *head, *tail; - int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn; - - maxubn = bno; - head = nil; - tail = nil; - for(dno = 0; dno <= pcimaxdno; dno++){ - maxfno = 0; - for(fno = 0; fno <= maxfno; fno++){ - /* - * For this possible device, form the - * bus+device+function triplet needed to address it - * and try to read the vendor and device ID. - * If successful, allocate a device struct and - * start to fill it in with some useful information - * from the device's configuration space. - */ - tbdf = MKBUS(BusPCI, bno, dno, fno); - l = pcicfgrw32(tbdf, PciVID, 0, 1); - if(l == 0xFFFFFFFF || l == 0) - continue; - p = malloc(sizeof(*p)); - if(p == nil) - panic("pcilscan: no memory"); - p->tbdf = tbdf; - p->vid = l; - p->did = l>>16; - - if(pcilist != nil) - pcitail->list = p; - else - pcilist = p; - pcitail = p; - - p->pcr = pcicfgr16(p, PciPCR); - p->rid = pcicfgr8(p, PciRID); - p->ccrp = pcicfgr8(p, PciCCRp); - p->ccru = pcicfgr8(p, PciCCRu); - p->ccrb = pcicfgr8(p, PciCCRb); - p->cls = pcicfgr8(p, PciCLS); - p->ltr = pcicfgr8(p, PciLTR); - - p->intl = pcicfgr8(p, PciINTL); - - /* - * If the device is a multi-function device adjust the - * loop count so all possible functions are checked. - */ - hdt = pcicfgr8(p, PciHDT); - if(hdt & 0x80) - maxfno = MaxFNO; - - /* - * If appropriate, read the base address registers - * and work out the sizes. - */ - switch(p->ccrb) { - case 0x03: /* display controller */ - /* fall through */ - case 0x01: /* mass storage controller */ - case 0x02: /* network 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); - } - break; - - case 0x00: - case 0x05: /* memory controller */ - case 0x06: /* bridge device */ - default: - break; - } - - if(head != nil) - tail->link = p; - else - head = p; - tail = p; - } - } - - *list = head; - for(p = head; p != nil; p = p->link){ - /* - * Find PCI-PCI bridges and recursively descend the tree. - */ - if(p->ccrb != 0x06 || p->ccru != 0x04) - continue; - - /* - * If the secondary or subordinate bus number is not - * initialised try to do what the PCI BIOS should have - * done and fill in the numbers as the tree is descended. - * On the way down the subordinate bus number is set to - * the maximum as it's not known how many buses are behind - * this one; the final value is set on the way back up. - */ - sbn = pcicfgr8(p, PciSBN); - ubn = pcicfgr8(p, PciUBN); - - if(sbn == 0 || ubn == 0) { - sbn = maxubn+1; - /* - * Make sure memory, I/O and master enables are - * off, set the primary, secondary and subordinate - * bus numbers and clear the secondary status before - * attempting to scan the secondary bus. - * - * Initialisation of the bridge should be done here. - */ - pcicfgw32(p, PciPCR, 0xFFFF0000); - l = (MaxUBN<<16)|(sbn<<8)|bno; - pcicfgw32(p, PciPBN, l); - pcicfgw16(p, PciSPSR, 0xFFFF); - maxubn = pcilscan(sbn, &p->bridge); - l = (maxubn<<16)|(sbn<<8)|bno; - - pcicfgw32(p, PciPBN, l); - } - else { - if(ubn > maxubn) - maxubn = ubn; - pcilscan(sbn, &p->bridge); - } - } - - return maxubn; -} - -extern void rtl8169interrupt(Ureg*, void* arg); - -/* not used yet */ -static void -pciintr(Ureg *ureg, void *p) -{ - rtl8169interrupt(ureg, p); /* HACK */ -} - -static void -pcicfginit(void) -{ - char *p; - Pci *pci = (Pci *)soc.pci; - Pcidev **list; - int bno, n; - - lock(&pcicfginitlock); - if(pcicfgmode != -1) { - unlock(&pcicfginitlock); - return; - } - - /* - * TrimSlice # pci 0 1 - * Scanning PCI devices on bus 0 1 - * BusDevFun VendorId DeviceId Device Class Sub-Class - * _____________________________________________________________ - * 00.00.00 0x10de 0x0bf0 Bridge device 0x04 - * 01.00.00 0x10ec 0x8168 Network controller 0x00 - * - * thus pci bus 0 has a bridge with, perhaps, an ide/sata ctlr behind, - * and pci bus 1 has the realtek 8169 on it: - * - * TrimSlice # pci 1 long - * Scanning PCI devices on bus 1 - * - * Found PCI device 01.00.00: - * vendor ID = 0x10ec - * device ID = 0x8168 - * command register = 0x0007 - * status register = 0x0010 - * revision ID = 0x03 - * class code = 0x02 (Network controller) - * sub class code = 0x00 - * programming interface = 0x00 - * cache line = 0x08 - * base address 0 = 0x80400001 config - * base address 1 = 0x00000000 (ext. config) - * base address 2 = 0xa000000c "downstream" - * base address 3 = 0x00000000 (prefetchable) - * base address 4 = 0xa000400c not " - * base address 5 = 0x00000000 (unused) - */ - n = pci->id >> 16; - if (((pci->id & MASK(16)) != Vnvidia || (n != 0xbf0 && n != 0xbf1)) && - (pci->id & MASK(16)) != Vrealtek) { - print("no pci controller at %#p\n", pci); - unlock(&pcicfginitlock); - return; - } - if (0) - iprint("pci: %#p: nvidia, rev %#ux class %#6.6lux misc %#8.8lux\n", - pci, (uchar)pci->revclass, pci->revclass >> 8, - pci->misc); - - pci->cs &= Iospace; - pci->cs |= Memspace | Busmaster; - coherence(); - - pcicfgmode = 1; -// pcimaxdno = 31; - pcimaxdno = 15; /* for trimslice */ - - fmtinstall('T', tbdffmt); - - if(p = getconf("*pcimaxbno")){ - n = strtoul(p, 0, 0); - if(n < pcimaxbno) - pcimaxbno = n; - } - if(p = getconf("*pcimaxdno")){ - n = strtoul(p, 0, 0); - if(n < pcimaxdno) - pcimaxdno = n; - } - - list = &pciroot; - /* was bno = 0; trimslice needs to start at 1 */ - for(bno = 1; bno <= pcimaxbno; bno++) { - bno = pcilscan(bno, list); - while(*list) - list = &(*list)->link; - } - unlock(&pcicfginitlock); - - if(getconf("*pcihinv")) - pcihinv(nil); -} - -enum { - Afiintrcode = 0xb8, -}; - -void -pcieintrdone(void) /* dismiss pci-e intr */ -{ - ulong *afi; - - afi = (ulong *)(soc.pci + Afi); - afi[Afiintrcode/sizeof *afi] = 0; /* magic */ - coherence(); -} - -/* - * whole config space for tbdf should be at (return address - rno). - */ -static void * -tegracfgaddr(int tbdf, int rno) -{ - uintptr addr; - - addr = soc.pci + (rno < 256? Cfgspace: Ecfgspace) + BUSBDF(tbdf) + rno; -// if (BUSBNO(tbdf) == 1) -// addr += Port1; - return (void *)addr; -} - -static int -pcicfgrw8(int tbdf, int rno, int data, int read) -{ - int x; - void *addr; - - if(pcicfgmode == -1) - pcicfginit(); - - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - addr = tegracfgaddr(tbdf, rno); - - lock(&pcicfglock); - if(read) - x = *(uchar *)addr; - else - *(uchar *)addr = data; - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr8(Pcidev* pcidev, int rno) -{ - return pcicfgrw8(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw8(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw8(pcidev->tbdf, rno, data, 0); -} - -static int -pcicfgrw16(int tbdf, int rno, int data, int read) -{ - int x; - void *addr; - - if(pcicfgmode == -1) - pcicfginit(); - - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - addr = tegracfgaddr(tbdf, rno); - - lock(&pcicfglock); - if(read) - x = *(ushort *)addr; - else - *(ushort *)addr = data; - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr16(Pcidev* pcidev, int rno) -{ - return pcicfgrw16(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw16(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw16(pcidev->tbdf, rno, data, 0); -} - -static int -pcicfgrw32(int tbdf, int rno, int data, int read) -{ - int x; - vlong v; - void *addr; - - if(pcicfgmode == -1) - pcicfginit(); - - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - addr = tegracfgaddr(tbdf, rno); - v = probeaddr((uintptr)addr); - if (v < 0) - return -1; - - lock(&pcicfglock); - if(read) - x = *(ulong *)addr; - else - *(ulong *)addr = data; - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr32(Pcidev* pcidev, int rno) -{ - return pcicfgrw32(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw32(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw32(pcidev->tbdf, rno, data, 0); -} - -Pcidev* -pcimatch(Pcidev* prev, int vid, int did) -{ - if(pcicfgmode == -1) - pcicfginit(); - - if(prev == nil) - prev = pcilist; - else - prev = prev->list; - - while(prev != nil){ - if((vid == 0 || prev->vid == vid) - && (did == 0 || prev->did == did)) - break; - prev = prev->list; - } - return prev; -} - -Pcidev* -pcimatchtbdf(int tbdf) -{ - Pcidev *pcidev; - - if(pcicfgmode == -1) - pcicfginit(); - - for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) { - if(pcidev->tbdf == tbdf) - break; - } - return pcidev; -} - -static void -pcilhinv(Pcidev* p) -{ - int i; - Pcidev *t; - - if(p == nil) { - putstrn(PCICONS.output, PCICONS.ptr); - p = pciroot; - print("bus dev 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); - - 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); - } - if(t->bridge) - print("->%d", BUSBNO(t->bridge->tbdf)); - print("\n"); - } - while(p != nil) { - if(p->bridge != nil) - pcilhinv(p->bridge); - p = p->link; - } -} - -void -pcihinv(Pcidev* p) -{ - if(pcicfgmode == -1) - pcicfginit(); - lock(&pcicfginitlock); - pcilhinv(p); - unlock(&pcicfginitlock); -} - -void -pcireset(void) -{ - Pcidev *p; - - if(pcicfgmode == -1) - pcicfginit(); - - for(p = pcilist; p != nil; p = p->list) { - /* don't mess with the bridges */ - if(p->ccrb == 0x06) - continue; - pciclrbme(p); - } -} - -void -pcisetioe(Pcidev* p) -{ - p->pcr |= IOen; - pcicfgw16(p, PciPCR, p->pcr); -} - -void -pciclrioe(Pcidev* p) -{ - p->pcr &= ~IOen; - pcicfgw16(p, PciPCR, p->pcr); -} - -void -pcisetbme(Pcidev* p) -{ - p->pcr |= MASen; - pcicfgw16(p, PciPCR, p->pcr); -} - -void -pciclrbme(Pcidev* p) -{ - p->pcr &= ~MASen; - pcicfgw16(p, PciPCR, p->pcr); -} - -void -pcisetmwi(Pcidev* p) -{ - p->pcr |= MemWrInv; - pcicfgw16(p, PciPCR, p->pcr); -} - -void -pciclrmwi(Pcidev* p) -{ - p->pcr &= ~MemWrInv; - pcicfgw16(p, PciPCR, p->pcr); -} - -static int -pcigetpmrb(Pcidev* p) -{ - int ptr; - - if(p->pmrb != 0) - return p->pmrb; - p->pmrb = -1; - - /* - * If there are no extended capabilities implemented, - * (bit 4 in the status register) assume there's no standard - * power management method. - * Find the capabilities pointer based on PCI header type. - */ - if(!(pcicfgr16(p, PciPSR) & 0x0010)) - return -1; - switch(pcicfgr8(p, PciHDT)){ - default: - return -1; - case 0: /* all other */ - case 1: /* PCI to PCI bridge */ - ptr = 0x34; - break; - case 2: /* CardBus bridge */ - ptr = 0x14; - break; - } - ptr = pcicfgr32(p, ptr); - - while(ptr != 0){ - /* - * Check for validity. - * Can't be in standard header and must be double - * word aligned. - */ - if(ptr < 0x40 || (ptr & ~0xFC)) - return -1; - if(pcicfgr8(p, ptr) == 0x01){ - p->pmrb = ptr; - return ptr; - } - - ptr = pcicfgr8(p, ptr+1); - } - - return -1; -} - -int -pcigetpms(Pcidev* p) -{ - int pmcsr, ptr; - - if((ptr = pcigetpmrb(p)) == -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; -} - -int -pcisetpms(Pcidev* p, int state) -{ - int ostate, pmc, pmcsr, ptr; - - if((ptr = pcigetpmrb(p)) == -1) - return -1; - - pmc = pcicfgr16(p, ptr+2); - pmcsr = pcicfgr16(p, ptr+4); - ostate = pmcsr & 0x0003; - pmcsr &= ~0x0003; - - switch(state){ - default: - return -1; - case 0: - break; - case 1: - if(!(pmc & 0x0200)) - return -1; - break; - case 2: - if(!(pmc & 0x0400)) - return -1; - break; - case 3: - break; - } - pmcsr |= state; - pcicfgw16(p, ptr+4, pmcsr); - - return ostate; -} diff --git a/sys/src/9/teg2/pciteg.c b/sys/src/9/teg2/pciteg.c new file mode 100644 index 000000000..d6cc8a291 --- /dev/null +++ b/sys/src/9/teg2/pciteg.c @@ -0,0 +1,268 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/pci.h" + +typedef struct { + ulong cap; + ulong ctl; +} Capctl; + +typedef struct { + Capctl dev; + Capctl link; + Capctl slot; +} Devlinkslot; + +/* capability list id 0x10 is pci-e */ +typedef struct Pci Pci; +struct Pci { + /* pci-compatible config */ + /* what io.h calls type 0 & type 1 pre-defined header */ + ulong id; + ulong cs; + ulong revclass; + ulong misc; /* cache line size, latency timer, header type, bist */ + ulong bar[2]; /* always 0 on tegra 2 */ + + /* types 1 & 2 pre-defined header */ + ulong bus; + ulong ioaddrs; + ulong memaddrs; + ulong prefmem; + ulong prefbasehi; + ulong preflimhi; + /* type 2 pre-defined header only */ + ulong ioaddrhi; + ulong cfgcapoff; /* offset in cfg. space to cap. list (0x40) */ + ulong rom; + ulong intr; /* PciINT[LP] */ + /* subsystem capability regs */ + ulong subsysid; + ulong subsyscap; + /* */ + + Capctl pwrmgmt; + + /* msi */ + ulong msictlcap; + ulong msimsgaddr[2]; /* little-endian */ + ulong msimsgdata; + + /* pci-e cap. */ + uchar _pad0[0x80-0x60]; + ulong pciecap; + Devlinkslot port0; + ulong rootctl; + ulong rootsts; + Devlinkslot port1; + + /* 0xbc */ + +}; + +enum { + /* offsets from soc.pci */ + Port0 = 0, + Port1 = 0x1000, + Pads = 0x3000, + Afi = 0x3800, + Aficfg = Afi + 0xac, + Cfgspace = 0x4000, + Ecfgspace = 0x104000, + + /* cs bits */ + Iospace = 1<<0, + Memspace = 1<<1, + Busmaster = 1<<2, + + /* Aficfg bits */ + Fpcion = 1<<0, +}; + +struct Pcictlr { + union { + uchar _padpci[0x1000]; + Pci; + } ports[2]; + uchar _padpads[0x1000]; + uchar pads[0x800]; + uchar afi[0x800]; + ulong cfg[0x1000]; + ulong extcfg[0x1000]; +}; + +static int pcicfgmode = -1; +static int pcimaxbno = 1; /* was 7; only 2 pci buses; touching 3rd hangs */ +static Pcidev* pciroot; + +extern void rtl8169interrupt(Ureg*, void* arg); + +/* not used yet */ +static void +pciintr(Ureg *ureg, void *p) +{ + rtl8169interrupt(ureg, p); /* HACK */ +} + +static void +pcicfginit(void) +{ + char *p; + Pci *pci = (Pci *)soc.pci; + Pcidev **list; + int bno, n; + + /* + * TrimSlice # pci 0 1 + * Scanning PCI devices on bus 0 1 + * BusDevFun VendorId DeviceId Device Class Sub-Class + * _____________________________________________________________ + * 00.00.00 0x10de 0x0bf0 Bridge device 0x04 + * 01.00.00 0x10ec 0x8168 Network controller 0x00 + * + * thus pci bus 0 has a bridge with, perhaps, an ide/sata ctlr behind, + * and pci bus 1 has the realtek 8169 on it: + * + * TrimSlice # pci 1 long + * Scanning PCI devices on bus 1 + * + * Found PCI device 01.00.00: + * vendor ID = 0x10ec + * device ID = 0x8168 + * command register = 0x0007 + * status register = 0x0010 + * revision ID = 0x03 + * class code = 0x02 (Network controller) + * sub class code = 0x00 + * programming interface = 0x00 + * cache line = 0x08 + * base address 0 = 0x80400001 config + * base address 1 = 0x00000000 (ext. config) + * base address 2 = 0xa000000c "downstream" + * base address 3 = 0x00000000 (prefetchable) + * base address 4 = 0xa000400c not " + * base address 5 = 0x00000000 (unused) + */ + n = pci->id >> 16; + if (((pci->id & MASK(16)) != Vnvidia || (n != 0xbf0 && n != 0xbf1)) && + (pci->id & MASK(16)) != Vrealtek) { + print("no pci controller at %#p\n", pci); + return; + } + if (0) + iprint("pci: %#p: nvidia, rev %#ux class %#6.6lux misc %#8.8lux\n", + pci, (uchar)pci->revclass, pci->revclass >> 8, + pci->misc); + + pci->cs &= Iospace; + pci->cs |= Memspace | Busmaster; + coherence(); + + pcicfgmode = 1; + pcimaxdno = 15; /* for trimslice */ + + fmtinstall('T', tbdffmt); + + if(p = getconf("*pcimaxbno")){ + n = strtoul(p, 0, 0); + if(n < pcimaxbno) + pcimaxbno = n; + } + if(p = getconf("*pcimaxdno")){ + n = strtoul(p, 0, 0); + if(n < pcimaxdno) + pcimaxdno = n; + } + + list = &pciroot; + /* was bno = 0; trimslice needs to start at 1 */ + for(bno = 1; bno <= pcimaxbno; bno++) { + bno = pciscan(bno, list); + while(*list) + list = &(*list)->link; + } + + if(getconf("*pcihinv")) + pcihinv(pciroot); +} + +enum { + Afiintrcode = 0xb8, +}; + +void +pcieintrdone(void) /* dismiss pci-e intr */ +{ + ulong *afi; + + afi = (ulong *)(soc.pci + Afi); + afi[Afiintrcode/sizeof *afi] = 0; /* magic */ + coherence(); +} + +/* + * whole config space for tbdf should be at (return address - rno). + */ +static void * +tegracfgaddr(int tbdf, int rno) +{ + uintptr addr; + + addr = soc.pci + (rno < 256? Cfgspace: Ecfgspace) + BUSBDF(tbdf) + rno; +// if (BUSBNO(tbdf) == 1) +// addr += Port1; + return (void *)addr; +} + +int +pcicfgrw8(int tbdf, int rno, int data, int read) +{ + void *addr; + + addr = tegracfgaddr(tbdf, rno); + if(read) + data = *(uchar *)addr; + else + *(uchar *)addr = data; + return data; +} + +int +pcicfgrw16(int tbdf, int rno, int data, int read) +{ + void *addr; + + addr = tegracfgaddr(tbdf, rno); + if(read) + data = *(ushort *)addr; + else + *(ushort *)addr = data; + return data; +} + +int +pcicfgrw32(int tbdf, int rno, int data, int read) +{ + vlong v; + void *addr; + + addr = tegracfgaddr(tbdf, rno); + v = probeaddr((uintptr)addr); + if (v < 0) + return -1; + if(read) + data = *(ulong *)addr; + else + *(ulong *)addr = data; + return data; +} + +void +pciteglink(void) +{ + pcicfginit(); +} diff --git a/sys/src/9/teg2/ts b/sys/src/9/teg2/ts index 0af12b757..3573a7dba 100644 --- a/sys/src/9/teg2/ts +++ b/sys/src/9/teg2/ts @@ -33,13 +33,14 @@ dev # usb link + pciteg archtegra ethermedium # flashtegra ecc loopbackmedium netdevmedium - ether8169 ethermii + ether8169 pci ethermii # usbohci # usbehci usbehcitegra @@ -54,7 +55,7 @@ ip esp misc - pci + pci pciteg rdb coproc v7-arch