diff --git a/sys/src/9/imx8/ccm.c b/sys/src/9/imx8/ccm.c index ffec22d52..21a0321aa 100644 --- a/sys/src/9/imx8/ccm.c +++ b/sys/src/9/imx8/ccm.c @@ -1075,6 +1075,90 @@ enablepll(int input) } } +enum { + CCM_ANALOG_PLLOUT_MONITOR_CFG = 0x74/4, + PLLOUT_MONITOR_CLK_CKE = 1<<4, + CCM_ANALOG_FRAC_PLLOUT_DIV_CFG = 0x78/4, + CCM_ANALOG_SCCG_PLLOUT_DIV_CFG = 0x7C/4, +}; + +static struct { + uchar input; + uchar reg; /* divider register */ + uchar shift; /* divider shift */ +} anapllout_input[16] = { +[0] OSC_25M_REF_CLK, +[1] OSC_27M_REF_CLK, +/* [2] HDMI_PHY_27M_CLK */ +/* [3] CLK1_P_N */ +[4] OSC_32K_REF_CLK, +[5] AUDIO_PLL1_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 0, +[6] AUDIO_PLL2_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 4, +[7] GPU_PLL_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 12, +[8] VPU_PLL_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 16, +[9] VIDEO_PLL1_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 8, +[10] ARM_PLL_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 20, +[11] SYSTEM_PLL1_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 0, +[12] SYSTEM_PLL2_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 4, +[13] SYSTEM_PLL3_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 8, +[14] VIDEO_PLL2_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 16, +[15] DRAM_PLL1_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 12, +}; + +static void +setanapllout(int input, int freq) +{ + int mux, div, reg; + + for(mux = 0; mux < nelem(anapllout_input); mux++) + if(anapllout_input[mux].input == input) + goto Muxok; + panic("setanapllout: bad input clock\n"); + return; +Muxok: + anatop[CCM_ANALOG_PLLOUT_MONITOR_CFG] = mux; + if(freq <= 0) + return; + div = input_clk_freq[input] / freq; + if(div < 1 || div > 8){ + panic("setanapllout: divider out of range\n"); + return; + } + enablepll(input); + reg = anapllout_input[mux].reg; + if(reg){ + int shift = anapllout_input[mux].shift; + anatop[reg] = (anatop[reg] & ~(7<> shift) & 7)+1; + } else { + div = 1; + } + return freq / div; +} + static u32int clkgate(Clock *gate, u32int val) { @@ -1330,6 +1414,11 @@ setclkrate(char *name, char *source, int freq) { int root, input; + if(cistrcmp(name, "ccm_analog_pllout") == 0){ + setanapllout(lookinputclk(source), freq); + return; + } + if((root = lookrootclk(name)) < 0) panic("setclkrate: clock %s not defined", name); if(source == nil) @@ -1346,6 +1435,9 @@ getclkrate(char *name) { int root, input; + if(cistrcmp(name, "ccm_analog_pllout") == 0) + return getanapllout(); + if((root = lookrootclk(name)) >= 0) return rootclkgetcfg(root, &input); diff --git a/sys/src/9/imx8/fns.h b/sys/src/9/imx8/fns.h index 735225372..9958da735 100644 --- a/sys/src/9/imx8/fns.h +++ b/sys/src/9/imx8/fns.h @@ -159,3 +159,10 @@ extern uint iomuxgpr(int gpr, uint set, uint mask); #define GPIO_PIN(n, m) ((n)<<5 | (m)) extern void gpioout(uint pin, int set); extern int gpioin(uint pin); + +/* pciimx */ +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/imx8/gic.c b/sys/src/9/imx8/gic.c index bfff2eada..6c3052e1d 100644 --- a/sys/src/9/imx8/gic.c +++ b/sys/src/9/imx8/gic.c @@ -254,6 +254,11 @@ intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char *) u32int intid; int cpu, prio; + if(BUSTYPE(tbdf) == BusPCI){ + pciintrenable(tbdf, f, a); + return; + } + if(tbdf != BUSUNKNOWN) return; @@ -306,6 +311,10 @@ intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char *) } void -intrdisable(int, void (*)(Ureg*, void*), void *, int, char*) +intrdisable(int tbdf, void (*f)(Ureg*, void*), void *a, int, char*) { + if(BUSTYPE(tbdf) == BusPCI){ + pciintrdisable(tbdf, f, a); + return; + } } diff --git a/sys/src/9/imx8/io.h b/sys/src/9/imx8/io.h index 38a1ce0f3..c98fd3bdf 100644 --- a/sys/src/9/imx8/io.h +++ b/sys/src/9/imx8/io.h @@ -28,7 +28,12 @@ enum { IRQsctr0 = SPI+47, IRQsctr1 = SPI+48, + IRQpci2 = SPI+74, + IRQenet1 = SPI+118, + + IRQpci1 = SPI+122, }; #define BUSUNKNOWN (-1) +#define PCIWADDR(x) PADDR(x) diff --git a/sys/src/9/imx8/pciimx.c b/sys/src/9/imx8/pciimx.c new file mode 100644 index 000000000..a18b07c9b --- /dev/null +++ b/sys/src/9/imx8/pciimx.c @@ -0,0 +1,497 @@ +#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 Intvec Intvec; +struct Intvec +{ + Pcidev *p; + void (*f)(Ureg*, void*); + void *a; +}; + +typedef struct Ctlr Ctlr; +struct Ctlr +{ + uvlong mem_base; + uvlong mem_size; + uvlong cfg_base; + uvlong cfg_size; + uvlong io_base; + uvlong io_size; + + int bno, ubn; + int irq; + + u32int *dbi; + u32int *cfg; + Pcidev *bridge; + + Lock; + Intvec vec[32]; +}; + +static Ctlr ctlrs[2] = { + { + 0x18000000, 0x7f00000, + 0x1ff00000, 0x80000, + 0x1ff80000, 0x10000, + 0, 127, IRQpci1, + (u32int*)(VIRTIO + 0x3800000), + }, + { + 0x20000000, 0x7f00000, + 0x27f00000, 0x80000, + 0x27f80000, 0x10000, + 128, 255, IRQpci2, + (u32int*)(VIRTIO + 0x3c00000), + }, +}; + +enum { + IATU_MAX = 8, + IATU_INBOUND = 1<<0, + IATU_INDEX_SHIFT = 1, + + IATU_OFFSET = 0x300000/4, + IATU_STRIDE = 0x100/4, + + IATU_REGION_CTRL_1 = 0x00/4, + CTRL_1_FUNC_NUM_SHIFT = 20, + CTRL_1_FUNC_NUM_MASK = 7<dbi[IATU_OFFSET + IATU_STRIDE*index]; + reg[IATU_REGION_CTRL_2] &= ~CTRL_2_REGION_EN; + } +} + +static void +iatucfg(Ctlr *ctlr, int index, u32int type, uvlong target, uvlong base, uvlong size) +{ + uvlong limit = base + size - 1; + u32int *reg; + + assert(size > 0); + assert(index < IATU_MAX); + assert((index & IATU_INBOUND) == 0); + + reg = &ctlr->dbi[IATU_OFFSET + IATU_STRIDE*index]; + reg[IATU_REGION_CTRL_2] &= ~CTRL_2_REGION_EN; + + reg[IATU_LWR_BSAE_ADDR] = base; + reg[IATU_UPPER_BASE_ADDR] = base >> 32; + reg[IATU_LWR_LIMIT_ADDR] = limit; + reg[IATU_UPPER_LIMIT_ADDR] = limit >> 32; + reg[IATU_LWR_TARGET_ADDR] = target; + reg[IATU_UPPER_TARGET_ADDR] = target >> 32; + + type &= CTRL_1_TYPE_MASK; + if(((size-1)>>32) != 0) + type |= CTRL_1_INCREASE_REGION_SIZ; + + reg[IATU_REGION_CTRL_1] = type; + reg[IATU_REGION_CTRL_2] = CTRL_2_REGION_EN; + + while((reg[IATU_REGION_CTRL_2] & CTRL_2_REGION_EN) == 0) + microdelay(10); +} + +static Ctlr* +bus2ctlr(int bno) +{ + Ctlr *ctlr; + + for(ctlr = ctlrs; ctlr < &ctlrs[nelem(ctlrs)]; ctlr++) + if(bno >= ctlr->bno && bno <= ctlr->ubn) + return ctlr; + return nil; +} + +static void* +cfgaddr(int tbdf, int rno) +{ + Ctlr *ctlr; + + ctlr = bus2ctlr(BUSBNO(tbdf)); + if(ctlr == nil) + return nil; + + if(pciparentdev == nil){ + if(BUSDNO(tbdf) != 0 || BUSFNO(tbdf) != 0) + return nil; + return (uchar*)ctlr->dbi + rno; + } + + iatucfg(ctlr, 0<parent==nil? CTRL_1_TYPE_CFG0: CTRL_1_TYPE_CFG1, + BUSBNO(tbdf)<<24 | BUSDNO(tbdf)<<19 | BUSFNO(tbdf)<<16, + ctlr->cfg_base, ctlr->cfg_size); + + return (uchar*)ctlr->cfg + 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; +} + +static u16int msimsg; +#define MSI_TARGET_ADDR PADDR(&msimsg) + +enum { + MSI_CAP_ID = 0x50/4, + PCI_MSI_ENABLE = 1<<16, + + MSI_CTRL_ADDR = 0x820/4, + MSI_CTRL_UPPER_ADDR = 0x824/4, + MSI_CTRL_INT_0_EN = 0x828/4, + MSI_CTRL_INT_0_MASK = 0x82C/4, + MSI_CTRL_INT_0_STATUS = 0x830/4, + + MISC_CONTROL_1 = 0x8BC/4, + DBI_RO_WR_EN = 1<<0, +}; + +static void +pciinterrupt(Ureg *ureg, void *arg) +{ + Ctlr *ctlr = arg; + Intvec *vec; + u32int status, mask; + + status = ctlr->dbi[MSI_CTRL_INT_0_STATUS]; + if(status == 0) + return; + ctlr->dbi[MSI_CTRL_INT_0_STATUS] = status; + + ilock(ctlr); + for(vec = ctlr->vec, mask = 1; vec < &ctlr->vec[nelem(ctlr->vec)]; vec++, mask <<= 1){ + if((status & mask) != 0 && vec->f != nil) + (*vec->f)(ureg, vec->a); + } + iunlock(ctlr); +} + +static void +pciintrinit(Ctlr *ctlr) +{ + ctlr->dbi[MSI_CTRL_INT_0_EN] = 0; + ctlr->dbi[MSI_CTRL_INT_0_MASK] = 0; + ctlr->dbi[MSI_CTRL_INT_0_STATUS] = -1; + ctlr->dbi[MSI_CTRL_ADDR] = MSI_TARGET_ADDR; + ctlr->dbi[MSI_CTRL_UPPER_ADDR] = MSI_TARGET_ADDR >> 32; + + intrenable(ctlr->irq+0, pciinterrupt, ctlr, BUSUNKNOWN, "pci"); + intrenable(ctlr->irq+1, pciinterrupt, ctlr, BUSUNKNOWN, "pci"); + intrenable(ctlr->irq+2, pciinterrupt, ctlr, BUSUNKNOWN, "pci"); + intrenable(ctlr->irq+3, pciinterrupt, ctlr, BUSUNKNOWN, "pci"); + + ctlr->dbi[MSI_CAP_ID] |= PCI_MSI_ENABLE; +} + +void +pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a) +{ + Ctlr *ctlr; + Intvec *vec; + Pcidev *p; + + ctlr = bus2ctlr(BUSBNO(tbdf)); + if(ctlr == nil){ + print("pciintrenable: %T: unknown controller\n", tbdf); + return; + } + + if((p = pcimatchtbdf(tbdf)) == nil){ + print("pciintrenable: %T: unknown device\n", tbdf); + return; + } + if(pcimsidisable(p) < 0){ + print("pciintrenable: %T: device doesnt support vec\n", tbdf); + return; + } + + ilock(ctlr); + for(vec = ctlr->vec; vec < &ctlr->vec[nelem(ctlr->vec)]; vec++){ + if(vec->p == p){ + ctlr->dbi[MSI_CTRL_INT_0_EN] &= ~(1 << (vec - ctlr->vec)); + vec->p = nil; + break; + } + } + for(vec = ctlr->vec; vec < &ctlr->vec[nelem(ctlr->vec)]; vec++){ + if(vec->p == nil){ + vec->p = p; + vec->a = a; + vec->f = f; + break; + } + } + iunlock(ctlr); + + if(vec >= &ctlr->vec[nelem(ctlr->vec)]){ + print("pciintrenable: %T: out of isr slots\n", tbdf); + return; + } + ctlr->dbi[MSI_CTRL_INT_0_EN] |= (1 << (vec - ctlr->vec)); + pcimsienable(p, MSI_TARGET_ADDR, vec - ctlr->vec); +} + +void +pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a) +{ + Ctlr *ctlr; + Intvec *vec; + + ctlr = bus2ctlr(BUSBNO(tbdf)); + if(ctlr == nil){ + print("pciintrenable: %T: unknown controller\n", tbdf); + return; + } + + ilock(ctlr); + for(vec = ctlr->vec; vec < &ctlr->vec[nelem(ctlr->vec)]; vec++){ + if(vec->p == nil) + continue; + if(vec->p->tbdf == tbdf && vec->f == f && vec->a == a){ + ctlr->dbi[MSI_CTRL_INT_0_EN] &= ~(1 << (vec - ctlr->vec)); + vec->f = nil; + vec->a = nil; + vec->p = nil; + break; + } + } + iunlock(ctlr); +} + +static void +rootinit(Ctlr *ctlr) +{ + uvlong base; + ulong ioa; + + iatuinit(ctlr); + + ctlr->cfg = vmap(ctlr->cfg_base, ctlr->cfg_size); + if(ctlr->cfg == nil) + return; + + ctlr->dbi[MISC_CONTROL_1] |= DBI_RO_WR_EN; + + /* bus number */ + ctlr->dbi[PciPBN/4] &= ~0xFFFFFF; + ctlr->dbi[PciPBN/4] |= ctlr->bno | (ctlr->bno+1)<<8 | ctlr->ubn<<16; + + /* command */ + ctlr->dbi[PciPCR/4] &= ~0xFFFF; + ctlr->dbi[PciPCR/4] |= IOen | MEMen | MASen | SErrEn; + + /* device class/subclass */ + ctlr->dbi[PciRID/4] &= ~0xFFFF0000; + ctlr->dbi[PciRID/4] |= 0x06040000; + + ctlr->dbi[PciBAR0/4] = 0; + ctlr->dbi[PciBAR1/4] = 0; + + ctlr->dbi[MISC_CONTROL_1] &= ~DBI_RO_WR_EN; + + ctlr->ubn = pciscan(ctlr->bno, &ctlr->bridge, nil); + if(ctlr->bridge == nil || ctlr->bridge->bridge == nil) + return; + + pciintrinit(ctlr); + + iatucfg(ctlr, 1<io_base, ctlr->io_base, ctlr->io_size); + iatucfg(ctlr, 2<mem_base, ctlr->mem_base, ctlr->mem_size); + + ioa = ctlr->io_base; + base = ctlr->mem_base; + pcibusmap(ctlr->bridge, &base, &ioa, 1); + + pcihinv(ctlr->bridge); +} + +static void +pcicfginit(void) +{ + fmtinstall('T', tbdffmt); + rootinit(&ctlrs[0]); + rootinit(&ctlrs[1]); +} + +enum { + SRC_PCIEPHY_RCR = 0x2C/4, + SRC_PCIE2_RCR = 0x48/4, + PCIE_CTRL_APP_XFER_PENDING = 1<<16, + PCIE_CTRL_APP_UNLOCK_MSG = 1<<15, + PCIE_CTRL_SYS_INT = 1<<14, + PCIE_CTRL_CFG_L1_AUX = 1<<12, + PCIE_CTRL_APPS_TURNOFF = 1<<11, + PCIE_CTRL_APPS_PME = 1<<10, + PCIE_CTRL_APPS_EXIT = 1<<9, + PCIE_CTRL_APPS_ENTER = 1<<8, + PCIE_CTRL_APPS_READY = 1<<7, + PCIE_CTRL_APPS_EN = 1<<6, + PCIE_CTRL_APPS_RST = 1<<5, + PCIE_CTRL_APPS_CLK_REQ = 1<<4, + PCIE_PERST = 1<<3, + PCIE_BTN = 1<<2, + PCIE_G_RST = 1<<1, + PCIE_PHY_POWER_ON_RESET_N = 1<<0, +}; + +static u32int *resetc = (u32int*)(VIRTIO + 0x390000); + +void +pciimxlink(void) +{ + resetc[SRC_PCIEPHY_RCR] |= PCIE_BTN | PCIE_G_RST; + resetc[SRC_PCIE2_RCR] |= PCIE_BTN | PCIE_G_RST; + + resetc[SRC_PCIEPHY_RCR] |= PCIE_CTRL_APPS_EN; + resetc[SRC_PCIE2_RCR] |= PCIE_CTRL_APPS_EN; + + setclkgate("pcie_clk_rst.auxclk", 0); + setclkgate("pcie2_clk_rst.auxclk", 0); + + iomuxpad("pad_ecspi1_mosi", "gpio5_io07", "~LVTTL ~HYS ~PUE ~ODE FAST 45_OHM"); + iomuxpad("pad_sai5_rxd2", "gpio3_io23", "~LVTTL ~HYS ~PUE ~ODE FAST 45_OHM"); + + gpioout(GPIO_PIN(5, 7), 0); + gpioout(GPIO_PIN(3, 23), 0); + + powerup("pcie"); + powerup("pcie2"); + + /* configure monitor CLK2 output internal reference clock for PCIE1 */ + setclkrate("ccm_analog_pllout", "system_pll1_clk", 100*Mhz); + delay(10); + + /* PCIE1_REF_USE_PAD=0 */ + iomuxgpr(14, 0<<9, 1<<9); + + /* PCIE2_REF_USE_PAD=1 */ + iomuxgpr(16, 1<<9, 1<<9); + + /* PCIE1_CTRL_DEVICE_TYPE=ROOT, PCIE2_CTRL_DEVICE_TYPE=ROOT */ + iomuxgpr(12, 4<<12 | 4<<8, 0xF<<12 | 0xF<<8); + + setclkrate("ccm_pcie1_ctrl_clk_root", "system_pll2_div4", 250*Mhz); + setclkrate("ccm_pcie2_ctrl_clk_root", "system_pll2_div4", 250*Mhz); + + setclkrate("pcie_clk_rst.auxclk", "system_pll2_div10", 100*Mhz); + setclkrate("pcie2_clk_rst.auxclk", "system_pll2_div10", 100*Mhz); + + setclkrate("pcie_phy.ref_alt_clk_p", "system_pll2_div10", 100*Mhz); + setclkrate("pcie2_phy.ref_alt_clk_p", "system_pll2_div10", 100*Mhz); + + setclkgate("pcie_clk_rst.auxclk", 1); + setclkgate("pcie2_clk_rst.auxclk", 1); + + /* PCIE1_CLKREQ_B_OVERRIDE=0 PCIE1_CLKREQ_B_OVERRIDE_EN=1 */ + iomuxgpr(14, 1<<10, 3<<10); + + /* PCIE2_CLKREQ_B_OVERRIDE=0 PCIE2_CLKREQ_B_OVERRIDE_EN=1 */ + iomuxgpr(16, 1<<10, 3<<10); + + delay(100); + gpioout(GPIO_PIN(5, 7), 1); + gpioout(GPIO_PIN(3, 23), 1); + delay(1); + + resetc[SRC_PCIEPHY_RCR] &= ~(PCIE_BTN | PCIE_G_RST); + resetc[SRC_PCIE2_RCR] &= ~(PCIE_BTN | PCIE_G_RST); + + pcicfginit(); +} diff --git a/sys/src/9/imx8/reform b/sys/src/9/imx8/reform index 747451665..0fba5fc20 100644 --- a/sys/src/9/imx8/reform +++ b/sys/src/9/imx8/reform @@ -27,6 +27,7 @@ link ethermedium loopbackmedium i2cimx devi2c + pciimx pci ip tcp udp @@ -44,6 +45,7 @@ misc uartimx iomux sdmmc usdhc + sdnvme pci port int cpuserver = 0; bootdir diff --git a/sys/src/9/port/pci.c b/sys/src/9/port/pci.c index 5ca42d5ac..da1541bce 100644 --- a/sys/src/9/port/pci.c +++ b/sys/src/9/port/pci.c @@ -16,6 +16,7 @@ struct Pcisiz }; int pcimaxdno; +Pcidev *pciparentdev; static Lock pcicfglock; static Pcidev *pcilist, **pcitail; @@ -113,6 +114,8 @@ pcicfgr8(Pcidev* p, int rno) int data; ilock(&pcicfglock); + pciparentdev = p->parent; + data = pcicfgrw8(p->tbdf, rno, 0, 1); iunlock(&pcicfglock); @@ -122,6 +125,8 @@ void pcicfgw8(Pcidev* p, int rno, int data) { ilock(&pcicfglock); + pciparentdev = p->parent; + pcicfgrw8(p->tbdf, rno, data, 0); iunlock(&pcicfglock); } @@ -131,6 +136,8 @@ pcicfgr16(Pcidev* p, int rno) int data; ilock(&pcicfglock); + pciparentdev = p->parent; + data = pcicfgrw16(p->tbdf, rno, 0, 1); iunlock(&pcicfglock); @@ -140,6 +147,8 @@ void pcicfgw16(Pcidev* p, int rno, int data) { ilock(&pcicfglock); + pciparentdev = p->parent; + pcicfgrw16(p->tbdf, rno, data, 0); iunlock(&pcicfglock); } @@ -149,6 +158,8 @@ pcicfgr32(Pcidev* p, int rno) int data; ilock(&pcicfglock); + pciparentdev = p->parent; + data = pcicfgrw32(p->tbdf, rno, 0, 1); iunlock(&pcicfglock); @@ -158,6 +169,8 @@ void pcicfgw32(Pcidev* p, int rno, int data) { ilock(&pcicfglock); + pciparentdev = p->parent; + pcicfgrw32(p->tbdf, rno, data, 0); iunlock(&pcicfglock); } @@ -169,6 +182,7 @@ pcibarsize(Pcidev *p, int rno) int v; ilock(&pcicfglock); + pciparentdev = p->parent; v = pcicfgrw32(p->tbdf, rno, 0, 1); pcicfgrw32(p->tbdf, rno, -1, 0); @@ -206,6 +220,8 @@ void pcisetbar(Pcidev *p, int rno, uvlong bar) { ilock(&pcicfglock); + pciparentdev = p->parent; + 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); @@ -216,6 +232,8 @@ void pcisetwin(Pcidev *p, uvlong base, uvlong limit) { ilock(&pcicfglock); + pciparentdev = p->parent; + if(base & 1){ pcicfgrw16(p->tbdf, PciIBR, (limit & 0xF000)|((base & 0xF000)>>8), 0); pcicfgrw32(p->tbdf, PciIUBR, (limit & 0xFFFF0000)|(base>>16), 0); @@ -534,12 +552,15 @@ pciscan(int bno, Pcidev** list, Pcidev *parent) tbdf = MKBUS(BusPCI, bno, dno, fno); lock(&pcicfglock); + pciparentdev = parent; + l = pcicfgrw32(tbdf, PciVID, 0, 1); unlock(&pcicfglock); if(l == 0xFFFFFFFF || l == 0) continue; p = pcidevalloc(); + p->parent = parent; p->tbdf = tbdf; p->vid = l; p->did = l>>16; @@ -622,7 +643,6 @@ pciscan(int bno, Pcidev** list, Pcidev *parent) break; } - p->parent = parent; if(head != nil) *tail = p; else diff --git a/sys/src/9/port/pci.h b/sys/src/9/port/pci.h index 6119966b5..204f53c9a 100644 --- a/sys/src/9/port/pci.h +++ b/sys/src/9/port/pci.h @@ -223,6 +223,7 @@ enum }; extern int pcimaxdno; +extern Pcidev *pciparentdev; extern void pcidevfree(Pcidev* pcidev);