OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [m68knommu/] [platform/] [5307/] [bios32.c] - Rev 1781

Go to most recent revision | Compare with Previous | Blame | View Log

/*****************************************************************************/
 
/*
 *	bios32.c -- PCI access code for embedded CO-MEM Lite PCI controller.
 *
 *	(C) Copyright 1999-2000, Greg Ungerer (gerg@moreton.com.au).
 */
 
/*****************************************************************************/
 
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/tasks.h>
#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/elia.h>
#include <asm/irq.h>
#include <asm/anchor.h>
 
/*****************************************************************************/
#ifdef CONFIG_PCI
/*****************************************************************************/
 
/*
 *	PCI markers for bus present and active slots.
 */
int		pci_bus_is_present = 0;
unsigned long	pci_slotmask = 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 */
 
/*****************************************************************************/
 
void 		pci_interrupt(int irq, void *id, struct pt_regs *fp);
extern int	mcf_autovector(int irq);
 
/*****************************************************************************/
 
void pci_resetbus(void)
{
	int	i;
 
#if 1
	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;
}
 
/*****************************************************************************/
 
int pcibios_assignres(int slot)
{
	volatile unsigned long	*rp;
	volatile unsigned char	*ip;
	unsigned int		idsel, addr, val, align, i;
	int			bar;
 
#if 0
	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_CFGWR | idsel;
		rp[LREG(addr)] = 0xffffffff;
 
		rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
		val = rp[LREG(addr)];
#if 1
printk("--------------------------------------------------------------\n");
printk("%s(%d): BAR[%d] initial read=%08x\n", __FILE__, __LINE__, bar, val);
#endif
		if (val == 0)
			continue;
 
#if 1
printk("%s(%d): BAR[%d] after all 1 write=%08x\n", __FILE__, __LINE__, bar, val);
#endif
 
		/* Determine space required by BAR */
		/* FIXME: this should go backwords from 0x80000000... */
		for (i = 0; (i < 32); i++) {
			if ((0x1 << i) & (val & 0xfffffffc))
				break;
		}
 
#if 1
printk("%s(%d): BAR[%d] size=%08x(%d)\n", __FILE__, __LINE__, bar, (0x1 << i), i);
#endif
		i = 0x1 << i;
 
		/* Assign a resource */
		if (val & PCI_BASE_ADDRESS_SPACE_IO) {
#if 1
printk("%s(%d): BAR[%d] IO assignment size=%08x iobase=%08x\n", __FILE__, __LINE__, bar, i, pci_iobase);
#endif
			if (i < PCI_MINIO) {
				i = PCI_MINIO;
#if 1
printk("%s(%d): BAR[%d] adjusted minimum size=%08x\n", __FILE__, __LINE__, bar, i);
#endif
			}
			if (i > 0xffff) {
				/* Invalid size?? */
				val = 0 | PCI_BASE_ADDRESS_SPACE_IO;
#if 1
printk("%s(%d): BAR[%d] too big for IO??\n", __FILE__, __LINE__, 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;
#if 1
printk("%s(%d): BAR[%d]=%08x alignment=%08x iobase=%08x\n", __FILE__, __LINE__, bar, val, i, pci_iobase);
#endif
			}
		} else {
 
#if 1
printk("%s(%d): BAR[%d] MEM assignment size=%08x membase=%08x\n", __FILE__, __LINE__, bar, i, pci_membase);
#endif
			if (i < PCI_MINMEM) {
				i = PCI_MINMEM;
#if 1
printk("%s(%d): BAR[%d] adjusted minimum size=%08x\n", __FILE__, __LINE__, bar, i);
#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;
#if 1
printk("%s(%d): BAR[%d]=%08x alignment=%08x membase=%08x\n", __FILE__, __LINE__, bar, val, i, pci_membase);
#endif
		}
 
		/* Write resource back into BAR register */
		rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
		rp[LREG(addr)] = val;
	}
 
 
	/* Assign IRQ if one is wanted... */
	ip = (volatile unsigned char *) (COMEM_BASE + COMEM_PCIBUS);
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
 
#if 0
	addr = (PCI_INTERRUPT_PIN & 0xfc) + (~PCI_INTERRUPT_PIN & 0x03);
	val = ip[addr];
	addr = (PCI_INTERRUPT_LINE & 0xfc) + (~PCI_INTERRUPT_LINE & 0x03);
	i = ip[addr];
printk("%s(%d): BEFORE interrupt[%x] line=%d pin=%d\n", __FILE__, __LINE__, (int) &ip[addr], i, val);
#endif
	addr = (PCI_INTERRUPT_PIN & 0xfc) + (~PCI_INTERRUPT_PIN & 0x03);
	if (ip[addr]) {
#if 0
printk("%s(%d): setting interrupt line...\n", __FILE__, __LINE__);
#endif
		rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
		addr = (PCI_INTERRUPT_LINE & 0xfc) + (~PCI_INTERRUPT_LINE & 0x03);
		ip[addr] = 25;
	}
#if 0
rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
addr = (PCI_INTERRUPT_LINE & 0xfc) + (~PCI_INTERRUPT_LINE & 0x03);
val = ip[addr];
addr = (PCI_INTERRUPT_PIN & 0xfc) + (~PCI_INTERRUPT_PIN & 0x03);
i = ip[addr];
printk("%s(%d): AFTER interrupt[%x] line=%d pin=%d\n", __FILE__, __LINE__, (int) &ip[PCI_INTERRUPT_LINE], val, i);
#endif
 
	return(0);
}
 
/*****************************************************************************/
 
int pcibios_enable(int slot)
{
	volatile unsigned long	*rp;
	unsigned int		idsel, addr;
 
#if 0
	printk("pcibios_enbale(slot=%x)\n", slot);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	idsel = COMEM_DA_ADDR(0x1 << (slot + 16));
 
	/* Enable I/O and memory accesses to this device */
	addr = COMEM_PCIBUS + PCI_COMMAND;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
	rp[LREG(addr)] = (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
 
#if 0
rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
printk("%s(%d): command[%x]=%x\n", __FILE__, __LINE__, (int) &rp[LREG(addr)], (int) rp[LREG(addr)]);
#endif
 
	return(0);
}
 
/*****************************************************************************/
 
unsigned long pcibios_init(unsigned long mem_start, unsigned long mem_end)
{
	volatile unsigned long	*rp;
	unsigned long		sel, id;
	int			slot;
 
#if 0
	printk("pcibios_init()\n");
#endif
 
	pci_resetbus();
 
	/*
	 *	Do some sort of basic check to see if the CO-MEM part
	 *	is present...
	 */
	rp = (volatile unsigned long *) COMEM_BASE;
	if ((rp[LREG(COMEM_LBUSCFG)] & 0xffff) != 0x0b50) {
		printk("PCI: no PCI bus present\n");
		return(mem_start);
	}
 
	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 {
#if 1
		printk("%s(%d): setting auto-vector...\n", __FILE__, __LINE__);
#endif
		mcf_autovector(COMEM_IRQ);
	}
 
#if 0
{
	int i;
	for (i = 0; (i < 0x100); i++) {
		if ((i % 0x10) == 0)
			printk("\n%08x: ", i);
		printk("%02x ", pci_inb(i + 0x200));
	}
	printk("\n");
}
#endif
	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;
 
#if 0
	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;
 
#if 0
	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;
 
#if 0
	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;
 
#if 0
	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;
 
#if 0
	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;
 
#if 0
	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;
 
#if 1
	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;
 
#if 0
	printk("pcibios_find_class(class=%04x,index=%d)\n", class, index);
#endif
 
	for (devnr = 0; (devnr < 32); devnr++) {
		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);
}
 
/*****************************************************************************/
 
/*
 *	Local routines to interrcept the standard I/O and vector handling
 *	code. Don't include this 'till now - initialization code above needs
 *	access to the real code too.
 */
#include <asm/mcfpci.h>
 
/*****************************************************************************/
 
void pci_outb(unsigned char val, unsigned int addr)
{
	volatile unsigned long	*rp;
	volatile unsigned char	*bp;
 
#if 1
	printk("pci_outb(val=%02x,addr=%x)\n", val, addr);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	bp = (volatile unsigned char *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
	addr = (addr & ~0x3) + (~addr & 0x03);
	bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
}
 
/*****************************************************************************/
 
void pci_outw(unsigned short val, unsigned int addr)
{
	volatile unsigned long	*rp;
	volatile unsigned short	*sp;
 
#if 1
	printk("pci_outw(val=%04x,addr=%x)\n", val, addr);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	sp = (volatile unsigned short *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
	addr = (addr & ~0x3) + (~addr & 0x02);
	sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
}
 
/*****************************************************************************/
 
void pci_outl(unsigned int val, unsigned int addr)
{
	volatile unsigned long	*rp;
	volatile unsigned int	*lp;
 
#if 1
	printk("pci_outl(val=%08x,addr=%x)\n", val, addr);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	lp = (volatile unsigned int *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
	lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
}
 
/*****************************************************************************/
 
unsigned char pci_inb(unsigned int addr)
{
	volatile unsigned long	*rp;
	volatile unsigned char	*bp;
	unsigned char		val;
 
#if 1
	printk("pci_inb(addr=%x)\n", addr);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	bp = (volatile unsigned char *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(addr);
	addr = (addr & ~0x3) + (~addr & 0x03);
	val = bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
#if 0
printk("%s(%d): (BASE=%08x)(addr=%x,OFFSET=%x) %08x=%02x\n",
	__FILE__, __LINE__, rp[LREG(COMEM_DAHBASE)], 
	addr, COMEM_DA_OFFSET(addr),
	(int) &bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))], val);
#endif
#if 1
	printk("pci_inb(addr=%x)=%02x\n", addr, val);
#endif
	return(val);
}
 
/*****************************************************************************/
 
unsigned short pci_inw(unsigned int addr)
{
	volatile unsigned long	*rp;
	volatile unsigned short	*sp;
	unsigned short		val;
 
#if 0
	printk("pci_inw(addr=%x)\n", addr);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	sp = (volatile unsigned short *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(addr);
	addr = (addr & ~0x3) + (~addr & 0x02);
	val = sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
#if 1
	printk("pci_inw(addr=%x)=%04x\n", addr, val);
#endif
	return(val);
}
 
/*****************************************************************************/
 
unsigned int pci_inl(unsigned int addr)
{
	volatile unsigned long	*rp;
	volatile unsigned int	*lp;
	unsigned int		val;
 
#if 0
	printk("pci_inl(addr=%x)\n", addr);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	lp = (volatile unsigned int *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(addr);
	val = lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
#if 1
	printk("pci_inl(addr=%x)=%08x\n", addr, val);
#endif
	return(val);
}
 
/*****************************************************************************/
 
void pci_outsb(void *addr, void *buf, int len)
{
	volatile unsigned long	*rp;
	volatile unsigned char	*bp;
	unsigned char		*dp = (unsigned char *) buf;
	unsigned int		a = (unsigned int) addr;
 
#if 1
	printk("pci_outsb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
 
	a = (a & ~0x3) + (~a & 0x03);
	bp = (volatile unsigned char *)
		(COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 
	while (len--)
		*bp = *dp++;
}
 
/*****************************************************************************/
 
void pci_outsw(void *addr, void *buf, int len)
{
	volatile unsigned long	*rp;
	volatile unsigned short	*wp;
	unsigned short		*dp = (unsigned short *) buf;
	unsigned int		a = (unsigned int) addr;
 
#if 1
	printk("pci_outsw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
 
	a = (a & ~0x3) + (~a & 0x2);
	wp = (volatile unsigned short *)
		(COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 
	while (len--)
		*wp = *dp++;
}
 
/*****************************************************************************/
 
void pci_outsl(void *addr, void *buf, int len)
{
	volatile unsigned long	*rp;
	volatile unsigned long	*lp;
	unsigned long		*dp = (unsigned long *) buf;
	unsigned int		a = (unsigned int) addr;
 
#if 1
	printk("pci_outsl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
 
	lp = (volatile unsigned long *)
		(COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 
	while (len--)
		*lp = *dp++;
}
 
/*****************************************************************************/
 
void pci_insb(void *addr, void *buf, int len)
{
	volatile unsigned long	*rp;
	volatile unsigned char	*bp;
	unsigned char		*dp = (unsigned char *) buf;
	unsigned int		a = (unsigned int) addr;
 
#if 1
	printk("pci_insb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
 
	a = (a & ~0x3) + (~a & 0x03);
	bp = (volatile unsigned char *)
		(COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 
	while (len--)
		*dp++ = *bp;
}
 
/*****************************************************************************/
 
void pci_insw(void *addr, void *buf, int len)
{
	volatile unsigned long	*rp;
	volatile unsigned short	*wp;
	unsigned short		*dp = (unsigned short *) buf;
	unsigned int		a = (unsigned int) addr;
 
#if 1
	printk("pci_insw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
 
	a = (a & ~0x3) + (~a & 0x2);
	wp = (volatile unsigned short *)
		(COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 
	while (len--)
		*dp++ = *wp;
}
 
/*****************************************************************************/
 
void pci_insl(void *addr, void *buf, int len)
{
	volatile unsigned long	*rp;
	volatile unsigned long	*lp;
	unsigned long		*dp = (unsigned long *) buf;
	unsigned int		a = (unsigned int) addr;
 
#if 1
	printk("pci_insl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
#endif
 
	rp = (volatile unsigned long *) COMEM_BASE;
	rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
 
	lp = (volatile unsigned long *)
		(COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 
	while (len--)
		*dp++ = *lp;
}
 
/*****************************************************************************/
 
typedef struct pci_localirqlist {
	void		(*handler)(int, void *, struct pt_regs *);
	const char	*device;
	void		*dev_id;
};
 
struct pci_localirqlist	pci_irqlist[COMEM_MAXPCI];
 
/*****************************************************************************/
 
int pci_request_irq(unsigned int irq,
	void (*handler)(int, void *, struct pt_regs *),
	unsigned long flags, const char *device, void *dev_id)
{
	int	i;
 
#if 1
	printk("pci_request_irq(irq=%d,handler=%x,flags=%x,device=%s,"
		"dev_id=%x)\n", irq, (int) handler, (int) flags, device,
		(int) dev_id);
#endif
 
	/* Check if this interrupt handler is already lodged */
	for (i = 0; (i < COMEM_MAXPCI); i++) {
		if (pci_irqlist[i].handler == handler)
			return(0);
	}
 
	/* Find a free spot to put this handler */
	for (i = 0; (i < COMEM_MAXPCI); i++) {
		if (pci_irqlist[i].handler == 0) {
			pci_irqlist[i].handler = handler;
			pci_irqlist[i].device = device;
			pci_irqlist[i].dev_id = dev_id;
			return(0);
		}
	}
 
	/* Couldn't fit?? */
	return(1);
}
 
/*****************************************************************************/
 
void pci_free_irq(unsigned int irq, void *dev_id)
{
#if 1
	printk("pci_free_irq(irq=%d,dev_id=%x)\n", irq, (int) dev_id);
#endif
 
	/* FIXME: need to free up irq... how to id it?? */
}
 
/*****************************************************************************/
 
void pci_interrupt(int irq, void *id, struct pt_regs *fp)
{
	int	i;
 
#if 1
	printk("pci_interrupt(irq=%d,id=%x,fp=%x)\n", irq, (int) id, (int) fp);
#endif
 
	for (i = 0; (i < COMEM_MAXPCI); i++) {
		if (pci_irqlist[i].handler) {
#if 1
			printk("%s(%d): calling handler=%x\n",
				__FILE__, __LINE__,
				(int) pci_irqlist[i].handler);
#endif
			(*pci_irqlist[i].handler)(irq, id, fp);
		}
	}
}
 
/*****************************************************************************/
#endif	/* CONFIG_PCI */
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.