⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci.c

📁 使用广泛的日本著名的开源嵌入式实时操作系统T-Kernel的源码
💻 C
字号:
/* *---------------------------------------------------------------------- *    T-Kernel * *    Copyright (C) 2004-2006 by Ken Sakamura. All rights reserved. *    T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * *    Version:   1.02.02 *    Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/9. * *---------------------------------------------------------------------- *//* *	@(#)pci.c (libtk/VR5500) * *	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 definitions */#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 definitions *//* *	The PCI bus number/Bus#0device number is defined as follows. * *	    Host *	    | *	    | Bus #0 (used by virtual objects, IPOCI bridge, *	    |  and external PCI bridge) *	    | *	    +---- Device #1(IOPCI(PCI1) bridge) *	    |	    | *	    |	    | Bus #1(for IOPCI device *	    |	    | *	    |	    +---- Device #x (AC97 codec) *	    |	    +---- Device #y (USB Function) *	    |	    +---- Device #z (USB Host) *	    | *	    +----Device #2(external PCI(PCI0) bridge) *		    | *		    | Bus #2 (for external PCI device *		    | *		    +---- Device #a *		    +---- Device #b *		    +---- Device #c */#define PCI_BRIDGE	0#define PCI_IOPCI	1#define PCI_EXTPCI	2/* VRC5477 definition */#define IO_START	0xaf000000#define PCI_MEMWIN	0xb0000000#define IOPCI_MEMWIN	0xb8000000/* PCI0 */#define VID0		0x0200 /* PCI0 vendor ID */#define DID0		0x0202 /* PCI0 device ID */#define PCICMD0		0x0204 /* PCI0 command */#define PCISTS0		0x0206 /* PCI0 status */#define REVID0		0x0208 /* PCI0 revision ID */#define CLASS0		0x0209 /* PCI0 class code */#define CLSIZ0		0x020c /* PCI0 cache line size */#define MLTIM0		0x020d /* PCI0 latency timer */#define HTYPE0		0x020e /* PCI0 header type */#define BARC0		0x0210 /* PCI0 base address */#define BARM010		0x0218 /* PCI0 base address SDRAM bank 01 */#define BARM230		0x0220 /* PCI0 base address SDRAM bank 23 */#define SSVID0		0x022c /* PCI0 subsystem vendor ID */#define SSID0		0x022e /* PCI0 subsystem ID */#define INTLIN0		0x023c /* PCI0 interrupt line */#define INTPIN0		0x023d /* PCI0 interrupt terminal */#define BAR00		0x0240 /* PCI0 base address LDCS0 */#define BAR10		0x0248 /* PCI0 base address LDCS1 */#define BAR20		0x0250 /* PCI0 base address LDCS2 */#define BAR30		0x0258 /* PCI0 base address LDCS3 */#define BAR40		0x0260 /* PCI0 base address LDCS4 */#define BAR50		0x0268 /* PCI0 base address LDCS5 */#define BARB0		0x0280 /* PCI0 base address BOOT */#define BARP00		0x0290 /* PCI0 base address PCI1 window0 */#define BARP10		0x0298 /* PCI0 base address PCI1 window1 */#define PCISWP0		0x02b0 /* PCI0 swap */#define PCIERR0		0x02b8 /* PCI0 error */#define PCICTL0_L	0x02e0 /* PCI0 control -L */#define PCICTL0_H	0x02e4 /* PCI0 control -H */#define PCIARB0_L	0x02e8 /* PCI0 arbitration -L */#define PCIARB0_H	0x02ec /* PCI0 arbitration -H */#define PCIINIT00	0x02f0 /* PCI0 initiator 0 */#define PCIINIT10	0x02f8 /* PCI0 initiator 1 *//* PCI1 */#define VID1		0x0600 /* PCI1 vendor ID */#define DID1		0x0602 /* PCI1 device ID */#define PCICMD1		0x0604 /* PCI1 command */#define PCISTS1		0x0606 /* PCI1 status */#define REVID1		0x0608 /* PCI1 revision ID */#define CLASS1		0x0609 /* PCI1 class code CLASS1 */#define CLSIZ1		0x060c /* PCI1 cache line size */#define MLTIM1		0x060d /* PCI1 latency timer */#define HTYPE1		0x060e /* PCI1 header type */#define BARC1		0x0610 /* PCI1 base address */#define BARM011		0x0618 /* PCI1 base address SDRAM bank 01 */#define BARM231		0x0620 /* PCI1 base address SDRAM bank 23 */#define SSVID1		0x062c /* PCI1 subsystem vendor ID */#define SSID1		0x062e /* PCI1 subsystem ID */#define INTLIN1		0x063c /* PCI1 interrupt line */#define INTPIN1		0x063d /* PCI1 interrupt terminal */#define BAR01		0x0640 /* PCI1 base address LDCS0 */#define BAR11		0x0648 /* PCI1 base address LDCS1 */#define BAR21		0x0650 /* PCI1 base address LDCS2 */#define BAR31		0x0658 /* PCI1 base address LDCS3 */#define BAR41		0x0660 /* PCI1 base address LDCS4 */#define BAR51		0x0668 /* PCI1 base address LDCS5 */#define BARB1		0x0680 /* PCI1 base address BOOT */#define BARP01		0x0690 /* PCI1 base address PCI0 window0 */#define BARP11		0x0698 /* PCI1 base address PCI0 window1 */#define PCISWP1		0x06b0 /* PCI1 swap */#define PCIERR1		0x06b8 /* PCI1 error */#define PCICTL1_L	0x06e0 /* PCI1 control -L */#define PCICTL1_H	0x06e4 /* PCI1 control -H */#define PCIARB1_L	0x06e8 /* PCI1 arbitration -L */#define PCIARB1_H	0x06ec /* PCI1 arbitration -H */#define PCIINIT01	0x06f0 /* PCI1 initiator 0 */#define PCIINIT11	0x06f8 /* PCI1 initiator 1 *//* 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, init, win, cfg, msk, svinit, imask, idsl, sh, dtmsk;	UW	dt = ~0x00000000U;	ofs = (UW)(reg & 0x000000fc);	switch (BUSNO(caddr)) {	  case PCI_BRIDGE:		/* Virtual PCI bus for host-PCI bridge */		switch (DEVNO(caddr)) {		  case PCI_EXTPCI:			ofs |= IO_START | VID0;			break;		  case PCI_IOPCI:			ofs |= IO_START | VID1;			break;		  default:			ofs  = 0;			break;		}		win = init = cfg = msk = 0;		break;	  case PCI_IOPCI:		/* IOPCI device */		win  = IOPCI_MEMWIN;		msk  = 0x00ffffffU;	/* 16Mbyte */		idsl = (0x80000000U >> DEVNO(caddr)) & 0xfffff800U;		ofs  = idsl ? (ofs | idsl | (FUNCNO(caddr) << 8)) : 0;		init = PCIINIT01;		cfg  = (0x00000000U << 9) | 0x0000001aU;		break;	  case PCI_EXTPCI:		/* PCI device */		win  = PCI_MEMWIN;		msk  = 0x03ffffffU;	/* 64Mbyte */		idsl = (0x80000000U >> DEVNO(caddr)) & 0xfffff800U;		ofs  = idsl ? (ofs | idsl | (FUNCNO(caddr) << 8)) : 0;		init = PCIINIT00;		cfg  = (0x00000000U << 9) | 0x0000001aU;		break;	  default:			/* PCI device(with PCI-PCI bridge) */		win  = PCI_MEMWIN;		msk  = 0x03ffffffU;		ofs |= caddr << 8;		init = PCIINIT00;		cfg  = (0x00000001U << 9) | 0x0000001aU;		break;	}	svinit = 0;	DI(imask);	if (win) {		/* Change memory space window to configuration space */		svinit = in_pdar_w(init);		out_pdar_w(init, (ofs & ~msk) | cfg);		(void)in_pdar_w(init);		ofs = win + (ofs & msk);	}	if (ofs) {		switch (mode) {		  default:		  case 0x04:			dt = in_w(ofs);			goto fin;		  case 0x02:			dt = in_w(ofs);			if (reg & 2) {				dt >>= 16;			}			dt &= 0x0000ffffU;			goto fin;		  case 0x01:			dt = in_w(ofs);			if (reg & 1) {				dt >>= 8;			}			if (reg & 2) {				dt >>= 16;			}			dt &= 0x000000ffU;			goto fin;		  case 0x14:			out_w(ofs, dat);			goto fin;		  case 0x12:			sh = (UW)((reg & 2) ? 16 : 0);			dtmsk = 0x0000ffffU << sh;			break;		  case 0x11:			sh = (UW)((reg & 1) ? 8 : 0) + ((reg & 2) ? 16 :0);			dtmsk = 0x000000ffU << sh;			break;		}		dt = in_w(ofs);		out_w(ofs, ((dat << sh) & dtmsk) | (dt & ~dtmsk));	} fin:	if (win) {		/* Restore window previously changed to		   configuration space */		out_pdar_w(init, svinit);		(void)in_pdar_w(init);	}	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, ~0x00000000U);	tmp = inPciConfW(caddr, reg);	outPciConfW(caddr, reg, adr);	EI(imask);	if (adr & 0x00000001U) {	/* I/O space */		kind = 1;		tmp &= ~0x00000003U;		adr &= ~0x00000003U;	} else {			/* Memory space */		kind = (W)(adr & 0x0000000fU);		tmp &= ~0x0000000fU;		adr &= ~0x0000000fU;	}	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 & 0x0000ffff;	if (!pciInfo) {		tm_extsvc(0x02, (INT)&pciInfo, 0, 0); 	}	for (i = 0; ; i++) {		caddr = pciInfo[i].caddr;		if (caddr == 0x0000ffff) {			break;	/* Terminal */		}		if (vendor >= 0x00010000) {			/* devid in order of appearance (0 - ) */			if (class == 0x0000ffff || 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 + -