📄 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.c (libtk/SH7751R) * * PCI device access sequence */#include <basic.h>#include <stdio.h>#include <stdlib.h>#include <tk/syslib.h>#include <util/tmonitor.h>#include "pci.h"/* PCI configuration information */LOCAL PciInfo *pciInfo = NULL;/* SH7751 definition */#define PCIPAR 0xfe2001c0#define PCIPDR 0xfe200220/* PCI configuration register input/output */LOCAL UW ioPciConf(W caddr, W reg, W mode, UW dat){ UW cfg, msk, sh, imask; UW dt = ~0; cfg = (caddr << 8) | (reg & 0xfc) | 0x80000000; DI(imask); out_w(PCIPAR, cfg); switch (mode) { default: case 0x04: dt = in_w(PCIPDR); goto fin; case 0x02: dt = in_w(PCIPDR); if (reg & 2) dt >>= 16; dt &= 0x0000ffff; goto fin; case 0x01: dt = in_w(PCIPDR); if (reg & 1) dt >>= 8; if (reg & 2) dt >>= 16; dt &= 0x000000ff; goto fin; case 0x14: out_w(PCIPDR, 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_w(PCIPDR); out_w(PCIPAR, cfg); out_w(PCIPDR, ((dat << sh) & msk) | (dt & ~msk)); fin: EI(imask); return dt;}/* Input from PCI configuration register (UB: 1byte) */EXPORT UB inPciConfB(W caddr, W reg){ return (UB)ioPciConf(caddr, reg, 0x01, 0);}/* Input from PCI configuration register (UH: 2byte) */EXPORT UH inPciConfH(W caddr, W reg){ return (UH)ioPciConf(caddr, reg, 0x02, 0);}/* Input from PCI configuration register (UW: 4byte) */EXPORT UW inPciConfW(W caddr, W reg){ return (UW)ioPciConf(caddr, reg, 0x04, 0);}/* Output to PCI configuration register (UB: 1byte) */EXPORT void outPciConfB(W caddr, W reg, UW dat){ ioPciConf(caddr, reg, 0x11, dat);}/* Output to PCI configuration register (UH: 2byte) */EXPORT void outPciConfH(W caddr, W reg, UW dat){ ioPciConf(caddr, reg, 0x12, dat);}/* Output to PCI configuration register (UW: 4byte) */EXPORT void outPciConfW(W caddr, W reg, UW dat){ ioPciConf(caddr, reg, 0x14, dat);}/* * Get base address/size for PCI configuration space * 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 number >= 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; /* Terminal */ 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 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 + -