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

📄 bios32.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************//* *	bios32.c -- PCI access code for embedded CO-MEM Lite PCI controller. * *	(C) Copyright 1999-2000, Greg Ungerer (gerg@moreton.com.au). *	(C) Copyright 2000, Lineo (www.lineo.com) *//*****************************************************************************/#include <linux/config.h>#include <linux/kernel.h>#include <linux/types.h>// DAVIDM #include <linux/tasks.h>// DAVIDM #include <linux/bios32.h>#include <linux/pci.h>#include <linux/ptrace.h>#include <linux/spinlock.h>#include <linux/interrupt.h>#include <linux/sched.h>#include <asm/coldfire.h>#include <asm/mcfsim.h>#include <asm/irq.h>#include <asm/anchor.h>#ifdef CONFIG_eLIA#include <asm/elia.h>#endif/*****************************************************************************/#ifdef CONFIG_PCI/*****************************************************************************//* *	Debug configuration defines. DEBUGRES sets debugging output for *	the resource allocation phase. DEBUGPCI traces on pcibios_ function *	calls, and DEBUGIO traces all accesses to devices on the PCI bus. *//*#define	DEBUGRES	1*//*#define	DEBUGPCI	1*//*#define	DEBUGIO		1*//*****************************************************************************//* *	PCI markers for bus present and active slots. */int		pci_bus_is_present = 0;unsigned long	pci_slotmask = 0;/* *	We may or may not need to swap the bytes of PCI bus tranfers. *	The endianess is re-roder automatically by the CO-MEM, but it *	will get the wrong byte order for a pure data stream. */#define	pci_byteswap	0/* *	Resource tracking. The CO-MEM part creates a virtual address *	space that all the PCI devices live in - it is not in any way *	directly mapped into the ColdFire address space. So we can *	really assign any resources we like to devices, as long as *	they do not clash with other PCI devices. */unsigned int	pci_iobase = 0x100;		/* Arbitary start address */unsigned int	pci_membase = 0x00010000;	/* Arbitary start address */#define	PCI_MINIO	0x100			/* 256 byte minimum I/O */#define	PCI_MINMEM	0x00010000		/* 64k minimum chunk *//* *	The CO-MEM's shared memory segment is visible inside the PCI *	memory address space. We need to keep track of the address that *	this is mapped at, to setup the bus masters pointers. */unsigned int	pci_shmemaddr;/*****************************************************************************/void 		pci_interrupt(int irq, void *id, struct pt_regs *fp);/*****************************************************************************//* *	Some platforms have custom ways of reseting the PCI bus. */void pci_resetbus(void){#ifdef CONFIG_eLIA	int	i;#ifdef DEBUGPCI	printk("pci_resetbus()\n");#endif	*((volatile unsigned short *) (MCF_MBAR+MCFSIM_PADDR)) |= eLIA_PCIRESET;	for (i = 0; (i < 1000); i++) {		*((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = 			(ppdata | eLIA_PCIRESET);	}	*((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = ppdata;#endif}/*****************************************************************************/int pcibios_assignres(int slot){	volatile unsigned long	*rp;	volatile unsigned char	*ip;	unsigned int		idsel, addr, val, align, i;	int			bar;#ifdef DEBUGPCI	printk("pcibios_assignres(slot=%x)\n", slot);#endif	rp = (volatile unsigned long *) COMEM_BASE;	idsel = COMEM_DA_ADDR(0x1 << (slot + 16));	/* Try to assign resource to each BAR */	for (bar = 0; (bar < 6); bar++) {		addr = COMEM_PCIBUS + PCI_BASE_ADDRESS_0 + (bar * 4);		rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;		val = rp[LREG(addr)];#ifdef DEBUGRES		printk("-----------------------------------"			"-------------------------------------\n");		printk("BAR[%d]: read=%08x ", bar, val);#endif		rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;		rp[LREG(addr)] = 0xffffffff;		rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;		val = rp[LREG(addr)];#ifdef DEBUGRES		printk("write=%08x ", val);#endif		if (val == 0) {#ifdef DEBUGRES			printk("\n");#endif			continue;		}		/* Determine space required by BAR */		/* FIXME: this should go backwords from 0x80000000... */		for (i = 0; (i < 32); i++) {			if ((0x1 << i) & (val & 0xfffffffc))				break;		}#ifdef DEBUGRES		printk("size=%08x(%d)\n", (0x1 << i), i);#endif		i = 0x1 << i;		/* Assign a resource */		if (val & PCI_BASE_ADDRESS_SPACE_IO) {			if (i < PCI_MINIO)				i = PCI_MINIO;#ifdef DEBUGRES			printk("BAR[%d]: IO size=%08x iobase=%08x\n",				bar, i, pci_iobase);#endif			if (i > 0xffff) {				/* Invalid size?? */				val = 0 | PCI_BASE_ADDRESS_SPACE_IO;#ifdef DEBUGRES				printk("BAR[%d]: too big for IO??\n", bar);#endif			} else {				/* Check for un-alignment */				if ((align = pci_iobase % i))					pci_iobase += (i - align);				val = pci_iobase | PCI_BASE_ADDRESS_SPACE_IO;				pci_iobase += i;			}		} else {			if (i < PCI_MINMEM)				i = PCI_MINMEM;#ifdef DEBUGRES			printk("BAR[%d]: MEMORY size=%08x membase=%08x\n",				bar, i, pci_membase);#endif			/* Check for un-alignment */			if ((align = pci_membase % i))				pci_membase += (i - align);			val = pci_membase | PCI_BASE_ADDRESS_SPACE_MEMORY;			pci_membase += i;		}		/* Write resource back into BAR register */		rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;		rp[LREG(addr)] = val;#ifdef DEBUGRES		printk("BAR[%d]: assigned bar=%08x\n", bar, val);#endif	}#ifdef DEBUGRES	printk("-----------------------------------"			"-------------------------------------\n");#endif	/* Assign IRQ if one is wanted... */	ip = (volatile unsigned char *) (COMEM_BASE + COMEM_PCIBUS);	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;	addr = (PCI_INTERRUPT_PIN & 0xfc) + (~PCI_INTERRUPT_PIN & 0x03);	if (ip[addr]) {		rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;		addr = (PCI_INTERRUPT_LINE & 0xfc)+(~PCI_INTERRUPT_LINE & 0x03);		ip[addr] = 25;#ifdef DEBUGRES		printk("IRQ LINE=25\n");#endif	}	return(0);}/*****************************************************************************/int pcibios_enable(int slot){	volatile unsigned long	*rp;	volatile unsigned short	*wp;	unsigned int		idsel, addr;	unsigned short		cmd;#ifdef DEBUGPCI	printk("pcibios_enbale(slot=%x)\n", slot);#endif	rp = (volatile unsigned long *) COMEM_BASE;	wp = (volatile unsigned short *) COMEM_BASE;	idsel = COMEM_DA_ADDR(0x1 << (slot + 16));	/* Get current command settings */	addr = COMEM_PCIBUS + PCI_COMMAND;	addr = (addr & ~0x3) + (~addr & 0x02);	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;	cmd = wp[WREG(addr)];	/*val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);*/	/* Enable I/O and memory accesses to this device */	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;	cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;	wp[WREG(addr)] = cmd;	return(0);}/*****************************************************************************/unsigned long pcibios_init(unsigned long mem_start, unsigned long mem_end){	volatile unsigned long	*rp;	unsigned long		sel, id;	int			slot;#ifdef DEBUGPCI	printk("pcibios_init()\n");#endif	pci_resetbus();	/*	 *	Do some sort of basic check to see if the CO-MEM part	 *	is present... This works ok, but I think we really need	 *	something better...	 */	rp = (volatile unsigned long *) COMEM_BASE;	if ((rp[LREG(COMEM_LBUSCFG)] & 0xff) != 0x50) {		printk("PCI: no PCI bus present\n");		return(mem_start);	}#ifdef COMEM_BRIDGEDEV	/*	 *	Setup the PCI bridge device first. It needs resources too,	 *	so that bus masters can get to its shared memory.	 */	slot = COMEM_BRIDGEDEV;	sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));	rp[LREG(COMEM_DAHBASE)] = sel;	rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */	id = rp[LREG(COMEM_PCIBUS)];	if ((id == 0) || ((id & 0xffff0000) == (sel & 0xffff0000))) {		printk("PCI: no PCI bus bridge present\n");		return(mem_start);	}	printk("PCI: bridge device at slot=%d id=%08x\n", slot, (int) id);	pci_slotmask |= 0x1 << slot;	pci_shmemaddr = pci_membase;	pcibios_assignres(slot);	pcibios_enable(slot);#endif	pci_bus_is_present = 1;	/*	 *	Do a quick scan of the PCI bus and see what is here.	 */	for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) {		sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));		rp[LREG(COMEM_DAHBASE)] = sel;		rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */		id = rp[LREG(COMEM_PCIBUS)];		if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) {			printk("PCI: slot=%d id=%08x\n", slot, (int) id);			pci_slotmask |= 0x1 << slot;			pcibios_assignres(slot);			pcibios_enable(slot);		}	}	/* Get PCI irq for local vectoring */	if (request_irq(COMEM_IRQ, pci_interrupt, 0, "PCI bridge", NULL)) {		printk("PCI: failed to acquire interrupt %d\n", COMEM_IRQ);	} else {		mcf_autovector(COMEM_IRQ);	}	return(mem_start);}/*****************************************************************************/unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end){	return(mem_start);}/*****************************************************************************/int pcibios_present(void){	return(pci_bus_is_present);}/*****************************************************************************/int pcibios_read_config_dword(unsigned char bus, unsigned char dev,	unsigned char offset, unsigned int *val){	volatile unsigned long	*rp;	unsigned long		idsel, fnsel;#ifdef DEBUGPCI	printk("pcibios_read_config_dword(bus=%x,dev=%x,offset=%x,val=%x)\n",		 bus, dev, offset, val);#endif	if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0)) {		*val = 0xffffffff;		return(PCIBIOS_SUCCESSFUL);	}	rp = (volatile unsigned long *) COMEM_BASE;	idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16));	fnsel = (dev & 0x7) << 8;	rp[LREG(COMEM_DAHBASE)] = idsel;	*val = rp[LREG(COMEM_PCIBUS + (offset & 0xfc) + fnsel)];#if 1	/* If we get back what we wrote, then nothing there */	/* This is pretty dodgy, but, hey, what else do we do?? */	if (!offset && (*val == ((idsel & 0xfffff000) | (offset & 0x00000fff))))		*val = 0xffffffff;#endif	return(PCIBIOS_SUCCESSFUL);}/*****************************************************************************/int pcibios_read_config_word(unsigned char bus, unsigned char dev,	unsigned char offset, unsigned short *val){	volatile unsigned long	*rp;	volatile unsigned short	*bp;	unsigned long		idsel, fnsel;	unsigned char		swapoffset;#ifdef DEBUGPCI	printk("pcibios_read_config_word(bus=%x,dev=%x,offset=%x)\n",		bus, dev, offset);#endif	if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0)) {		*val = 0xffff;		return(PCIBIOS_SUCCESSFUL);	}	rp = (volatile unsigned long *) COMEM_BASE;	bp = (volatile unsigned short *) COMEM_BASE;	idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16));	fnsel = (dev & 0x7) << 8;	swapoffset = (offset & 0xfc) + (~offset & 0x02);	rp[LREG(COMEM_DAHBASE)] = idsel;	*val = bp[WREG(COMEM_PCIBUS + swapoffset + fnsel)];	return(PCIBIOS_SUCCESSFUL);}/*****************************************************************************/int pcibios_read_config_byte(unsigned char bus, unsigned char dev,	unsigned char offset, unsigned char *val){	volatile unsigned long	*rp;	volatile unsigned char	*bp;	unsigned long		idsel, fnsel;	unsigned char		swapoffset;#ifdef DEBUGPCI	printk("pcibios_read_config_byte(bus=%x,dev=%x,offset=%x)\n",		bus, dev, offset);#endif	if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0)) {		*val = 0xff;		return(PCIBIOS_SUCCESSFUL);	}	rp = (volatile unsigned long *) COMEM_BASE;	bp = (volatile unsigned char *) COMEM_BASE;	idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16));	fnsel = (dev & 0x7) << 8;	swapoffset = (offset & 0xfc) + (~offset & 0x03);	rp[LREG(COMEM_DAHBASE)] = idsel;	*val = bp[(COMEM_PCIBUS + swapoffset + fnsel)];	return(PCIBIOS_SUCCESSFUL);}/*****************************************************************************/int pcibios_write_config_dword(unsigned char bus, unsigned char dev,	unsigned char offset, unsigned int val){	volatile unsigned long	*rp;	unsigned long		idsel, fnsel;#ifdef DEBUGPCI	printk("pcibios_write_config_dword(bus=%x,dev=%x,offset=%x,val=%x)\n",		 bus, dev, offset, val);#endif	if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0))		return(PCIBIOS_SUCCESSFUL);	rp = (volatile unsigned long *) COMEM_BASE;	idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16));	fnsel = (dev & 0x7) << 8;	rp[LREG(COMEM_DAHBASE)] = idsel;	rp[LREG(COMEM_PCIBUS + (offset & 0xfc) + fnsel)] = val;	return(PCIBIOS_SUCCESSFUL);}/*****************************************************************************/int pcibios_write_config_word(unsigned char bus, unsigned char dev,	unsigned char offset, unsigned short val){	volatile unsigned long	*rp;	volatile unsigned short	*bp;	unsigned long		idsel, fnsel;	unsigned char		swapoffset;#ifdef DEBUGPCI	printk("pcibios_write_config_word(bus=%x,dev=%x,offset=%x,val=%x)\n",		 bus, dev, offset, val);#endif	if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0))		return(PCIBIOS_SUCCESSFUL);	rp = (volatile unsigned long *) COMEM_BASE;	bp = (volatile unsigned short *) COMEM_BASE;	idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16));	fnsel = (dev & 0x7) << 8;	swapoffset = (offset & 0xfc) + (~offset & 0x02);	rp[LREG(COMEM_DAHBASE)] = idsel;	bp[WREG(COMEM_PCIBUS + swapoffset + fnsel)] = val;	return(PCIBIOS_SUCCESSFUL);}/*****************************************************************************/int pcibios_write_config_byte(unsigned char bus, unsigned char dev,	unsigned char offset, unsigned char val){	volatile unsigned long	*rp;	volatile unsigned char	*bp;	unsigned long		idsel, fnsel;	unsigned char		swapoffset;#ifdef DEBUGPCI	printk("pcibios_write_config_byte(bus=%x,dev=%x,offset=%x,val=%x)\n",		 bus, dev, offset, val);#endif	if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0))		return(PCIBIOS_SUCCESSFUL);	rp = (volatile unsigned long *) COMEM_BASE;	bp = (volatile unsigned char *) COMEM_BASE;	idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16));	fnsel = (dev & 0x7) << 8;	swapoffset = (offset & 0xfc) + (~offset & 0x03);	rp[LREG(COMEM_DAHBASE)] = idsel;	bp[(COMEM_PCIBUS + swapoffset + fnsel)] = val;	return(PCIBIOS_SUCCESSFUL);}/*****************************************************************************/int pcibios_find_device(unsigned short vendor, unsigned short devid,	unsigned short index, unsigned char *bus, unsigned char *dev){	unsigned int	vendev, val;	unsigned char	devnr;#ifdef DEBUGPCI	printk("pcibios_find_device(vendor=%04x,devid=%04x,index=%d)\n",		vendor, devid, index);#endif	if (vendor == 0xffff)		return(PCIBIOS_BAD_VENDOR_ID);	vendev = (devid << 16) | vendor;	for (devnr = 0; (devnr < 32); devnr++) {		pcibios_read_config_dword(0, devnr, PCI_VENDOR_ID, &val);		if (vendev == val) {			if (index-- == 0) {				*bus = 0;				*dev = devnr;				return(PCIBIOS_SUCCESSFUL);			}		}	}	return(PCIBIOS_DEVICE_NOT_FOUND);}/*****************************************************************************/int pcibios_find_class(unsigned int class, unsigned short index,	unsigned char *bus, unsigned char *dev){	unsigned int	val;	unsigned char	devnr;#ifdef DEBUGPCI	printk("pcibios_find_class(class=%04x,index=%d)\n", class, index);#endif	/* FIXME: this ignores multi-function devices... */	for (devnr = 0; (devnr < 128); devnr += 8) {		pcibios_read_config_dword(0, devnr, PCI_CLASS_REVISION, &val);		if ((val >> 8) == class) {			if (index-- == 0) {				*bus = 0;				*dev = devnr;				return(PCIBIOS_SUCCESSFUL);			}		}	}	return(PCIBIOS_DEVICE_NOT_FOUND);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -