📄 pci.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel * * Copyright (C) 2004 by Ken Sakamura. All rights reserved. * T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * * Version: 1.01.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2004/6/28. * *---------------------------------------------------------------------- *//* * @(#)pci_vr4131.c (libtk/VR4131) * * PCI device access sequence */#include <basic.h>#include <libstr.h>#include <tk/syslib.h>#include <tm/tmonitor.h>#include "pci.h"/* PCI configuration information */LOCAL PciInfo *pciInfo = NULL;/* PCI configuration address definition */#define CADDR(bus, dev, func) (((bus) << 8) | ((dev) << 3) | (func))#define BUSNO(caddr) (((caddr) >> 8) & 0xff)#define DEVNO(caddr) (((caddr) >> 3) & 0x1f)#define FUNCNO(caddr) ((caddr) & 0x07)/* PCI bus number definition *//* * The PCI bus number/Bus#0 device number is defined as follows. * * Host * | * | Bus #0(used by virtual objects and PCI bridge) * | * +----Device #2(PCI bridge) * | * | Bus #2 (for PCI devices) * | * +---- Device #a * +---- Device #b * +---- Device #c */#define PCI_BRIDGE 0#define PCI_IOPCI 1#define PCI_EXTPCI 2/* VR4131 definitions */#define IO_START 0xaf000000#define PCIMMAW1REG 0x0C00 /* Master PCI memory space address conversion 1 */#define PCIMMAW2REG 0x0C04 /* Master PCI memory space address conversion 2 */#define PCITAW1REG 0x0C08 /* Target internal memory space conversion 1 */#define PCITAW2REG 0x0C0C /* Target internal memory space conversion 2 */#define PCIMIOAWREG 0x0C10 /* Master PCI I/O space address conversion */#define PCICONFDREG 0x0C14 /* Configuration address */#define PCICONFAREG 0x0C18 /* Configuration data */#define PCIMAILREG 0x0C1C /* For mailbox use */#define BUSERRADREG 0x0C24 /* Store bus/error generation address */#define INTCNTSTAREG 0x0C28 /* Display interrupt status and control */#define PCIEXACCREG 0x0C2C /* Display exclusive access and control */#define PCIRECONTREG 0x0C30 /* Retry/count */#define PCIENREG 0x0C34 /* Finish configuration setting */#define PCICLKSELREG 0x0C38 /* Select PCI bus action clock */#define PCITRDYVREG 0x0C3C /* Set TRDY signal */#define PCICLKRUNREG 0x0C60 /* Set CLKRUN signal */#define VENDORIDREG 0x0D00 /* Vendor ID */#define DEVICEIDREG 0x0D00 /* Device ID */#define COMMANDREG 0x0D04 /* PCI interface set command */#define STATUSREG 0x0D04 /* PCI interface status */#define REVIDREG 0x0D08 /* Device revision */#define CLASSREG 0x0D08 /* Device class */#define CACHELSREG 0x0D0C /* System cache line size */#define LATTIMEREG 0x0D0C /* Set timer count value */#define MAILBAREG 0x0D10 /* PCIMAILREG base address */#define PCIMBA1REG 0x0D14 /* PCI memory space base address 1 */#define PCIMBA2REG 0x0D18 /* PCI memory space base address 2 */#define INTLINEREG 0x0D3C /* PCI interrupt line */#define INTPINREG 0x0D3C /* PCI interrupt terminal */#define RETVALREG 0x0D40 /* Set retry/limit value */#define PCIAPCNTREG 0x0D40 /* Select PCI arbitration protocol *//* PDAR input/output */#define in_pdar_b(idx) in_b(IO_START + (idx))#define in_pdar_h(idx) in_h(IO_START + (idx))#define in_pdar_w(idx) in_w(IO_START + (idx))#define out_pdar_b(idx, dat) out_b(IO_START + (idx), (dat))#define out_pdar_h(idx, dat) out_h(IO_START + (idx), (dat))#define out_pdar_w(idx, dat) out_w(IO_START + (idx), (dat))/* PCI configuration register input/output */LOCAL UW ioPciConf(W caddr, W reg, W mode, UW dat){ UW ofs, cfg, msk, sh, idsl, imask; UW dt = ~0; ofs = reg & 0xff; switch (BUSNO(caddr)) { case PCI_BRIDGE: /* Host-PCI bridge */ DI(imask); switch (DEVNO(caddr)) { case PCI_EXTPCI: ofs |= VENDORIDREG; switch (mode) { case 0x01: dt = in_pdar_b(ofs); break; case 0x02: dt = in_pdar_h(ofs & ~1); break; case 0x03: dt = in_pdar_w(ofs & ~3); break; case 0x11: out_pdar_b(ofs, dat); break; case 0x12: out_pdar_h(ofs & ~1, dat); break; case 0x14: out_pdar_w(ofs & ~3, dat); break; } } EI(imask); return dt; case PCI_IOPCI: /* Internal PCI device (does not exist) */ cfg = 0; break; case PCI_EXTPCI: /* External PCI device */ idsl = (((UW)0x00000800) << DEVNO(caddr)) & 0xfffff800; cfg = idsl ? (idsl | ((FUNCNO(caddr)) << 8) | (ofs & ~3)) : 0; break; default: /* External PCI device */ cfg = (caddr << 8) | (ofs & ~3) | 1; break; } if (!cfg) return dt; DI(imask); out_pdar_w(PCICONFAREG, cfg); switch (mode) { default: case 0x04: dt = in_pdar_w(PCICONFDREG); goto fin; case 0x02: dt = in_pdar_w(PCICONFDREG); if (reg & 2) dt >>= 16; dt &= 0x0000ffff; goto fin; case 0x01: dt = in_pdar_w(PCICONFDREG); if (reg & 1) dt >>= 8; if (reg & 2) dt >>= 16; dt &= 0x000000ff; goto fin; case 0x14: out_pdar_w(PCICONFDREG, dat); goto fin; case 0x12: sh = (reg & 2) ? 16 : 0; msk = 0x0000ffff << sh; break; case 0x11: sh = ((reg & 1) ? 8 : 0) + ((reg & 2) ? 16 : 0); msk = 0x000000ff << sh; break; } dt = in_pdar_w(PCICONFDREG); out_pdar_w(PCICONFDREG, ((dat << sh) & msk) | (dt & ~msk)); fin: EI(imask); return dt;}/* Input from PCI configuration register (UB: 1 byte) */EXPORT UB inPciConfB(W caddr, W reg){ return (UB)ioPciConf(caddr, reg, 0x01, 0);}/* Input from PCI configuration register (UH: 2 byte) */EXPORT UH inPciConfH(W caddr, W reg){ return (UH)ioPciConf(caddr, reg, 0x02, 0);}/* Input from PCI configuration register (UW: 4 byte) */EXPORT UW inPciConfW(W caddr, W reg){ return (UW)ioPciConf(caddr, reg, 0x04, 0);}/* Output to PCI configuration register (UB: 1 byte) */EXPORT void outPciConfB(W caddr, W reg, UW dat){ ioPciConf(caddr, reg, 0x11, dat);}/* Output to PCI configuration register (UH: 2 byte) */EXPORT void outPciConfH(W caddr, W reg, UW dat){ ioPciConf(caddr, reg, 0x12, dat);}/* Output to PCI configuration register (UW: 4 byte) */EXPORT void outPciConfW(W caddr, W reg, UW dat){ ioPciConf(caddr, reg, 0x14, dat);}/* * Get PCI configuration space base address/size * Return value PTTI I = 1:I/O address, 0:memory address * T = 0:32bit, 1:20bit, 2:64bit * P = 1:prefetch enable */EXPORT W getPciBaseAddr(W caddr, W reg, VP *addr, W *size){ UW imask; UW adr, tmp; W sz, kind; /* Write 0xffffffff, then determine size from how far it was possible to write from the top order */ DI(imask); adr = inPciConfW(caddr, reg); outPciConfW(caddr, reg, ~0); tmp = inPciConfW(caddr, reg); outPciConfW(caddr, reg, adr); EI(imask); if (adr & 1) { /* I/O space */ kind = 1; tmp &= ~0x03; adr &= ~0x03; } else { /* Memory space */ kind = adr & 0x0f; tmp &= ~0x0f; adr &= ~0x0f; } if (!tmp) sz = 0; else for (sz = 1; !(tmp & 1); tmp >>= 1) sz <<= 1; *addr = (VP)adr; *size = sz; return kind;}/* * PCI device search * * vendor < 0x10000 : vendor, devid device * == 0x1ffff : devid number device * == 0x1#### : devid number class == #### device * Function value >= 0 : PCI address * < 0 : Not found */EXPORT INT searchPciDev(W vendor, W devid){ W i, caddr, class; class = vendor & 0xffff; if (!pciInfo) tm_extsvc(0x02, (INT)&pciInfo, 0, 0); for (i = 0; ; i++) { caddr = pciInfo[i].caddr; if (caddr == 0xffff) break; /* Termination */ if (vendor >= 0x10000) { /* devid in order of appearance (0 - ) */ if (class == 0xffff || pciInfo[i].devclass == class) { if (devid-- == 0) return caddr; } } else { if (pciInfo[i].vendor == vendor && pciInfo[i].devid == devid) return caddr; } } return -1; /* Not found */}/* * PCI - CPU memory / I/O space address conversion * * pciMemToCpuAddr: Gets CPU memory address * corresponding to PCI memory address * pciIoToCpuAddr: Gets CPU I/O address corresponding to PCI I/O space * (for memory mapped I/O, the CPU memory address * corresponding to the PCI I/O space) * cpuAddrToPciMem: Gets PCI memory address corresponding * to CPU memory address */EXPORT UW pciMemToCpuAddr(UW pcimem){ UW cnvaddr; tm_extsvc(0x03, 0x00, pcimem, (INT)&cnvaddr); return cnvaddr;}EXPORT UW pciIoToCpuAddr(UW pciio){ UW cnvaddr; tm_extsvc(0x03, 0x01, pciio, (INT)&cnvaddr); return cnvaddr;}EXPORT UW cpuAddrToPciMem(UW cpuaddr){ UW cnvaddr; tm_extsvc(0x03, 0x02, cpuaddr, (INT)&cnvaddr); return cnvaddr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -