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

📄 rte_mb_a_pci.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * arch/v850/kernel/mb_a_pci.c -- PCI support for Midas lab RTE-MOTHER-A board * *  Copyright (C) 2001,2002  NEC Corporation *  Copyright (C) 2001,2002  Miles Bader <miles@gnu.org> * * This file is subject to the terms and conditions of the GNU General * Public License.  See the file COPYING in the main directory of this * archive for more details. * * Written by Miles Bader <miles@gnu.org> */#include <linux/config.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/spinlock.h>#include <linux/pci.h>#include <asm/machdep.h>/* __nomods_init is like __devinit, but is a no-op when modules are enabled.   This is used by some routines that can be called either during boot   or by a module.  */#ifdef CONFIG_MODULES#define __nomods_init /*nothing*/#else#define __nomods_init __devinit#endif/* PCI devices on the Mother-A board can only do DMA to/from the MB SRAM   (the RTE-V850E/MA1-CB cpu board doesn't support PCI access to   CPU-board memory), and since linux DMA buffers are allocated in   normal kernel memory, we basically have to copy DMA blocks around   (this is like a `bounce buffer').  When a DMA block is `mapped', we   allocate an identically sized block in MB SRAM, and if we're doing   output to the device, copy the CPU-memory block to the MB-SRAM block.   When an active block is `unmapped', we will copy the block back to   CPU memory if necessary, and then deallocate the MB SRAM block.   Ack.  *//* Where the motherboard SRAM is in the PCI-bus address space (the   first 512K of it is also mapped at PCI address 0).  */#define PCI_MB_SRAM_ADDR 0x800000/* Convert CPU-view MB SRAM address to/from PCI-view addresses of the   same memory.  */#define MB_SRAM_TO_PCI(mb_sram_addr) \   ((dma_addr_t)mb_sram_addr - MB_A_SRAM_ADDR + PCI_MB_SRAM_ADDR)#define PCI_TO_MB_SRAM(pci_addr)     \   (void *)(pci_addr - PCI_MB_SRAM_ADDR + MB_A_SRAM_ADDR)static void pcibios_assign_resources (void);struct mb_pci_dev_irq {	unsigned dev;		/* PCI device number */	unsigned irq_base;	/* First IRQ  */	unsigned query_pin;	/* True if we should read the device's				   Interrupt Pin info, and allocate				   interrupt IRQ_BASE + PIN.  */};/* PCI interrupts are mapped statically to GBUS interrupts.  */static struct mb_pci_dev_irq mb_pci_dev_irqs[] = {	/* Motherboard SB82558 ethernet controller */	{ 10,	IRQ_MB_A_LAN,		0 },	/* PCI slot 1 */	{ 8, 	IRQ_MB_A_PCI1(0),	1 },	/* PCI slot 2 */	{ 9, 	IRQ_MB_A_PCI2(0),	1 }};#define NUM_MB_PCI_DEV_IRQS \  (sizeof mb_pci_dev_irqs / sizeof mb_pci_dev_irqs[0])/* PCI configuration primitives.  */#define CONFIG_DMCFGA(dev, offs)					      \   (0x80000000								      \    | ((offs) & ~0x3)							      \    | ((dev)->devfn << 8)						      \    | ((dev)->bus->number << 16))#define DEF_MB_PCI_READ_CONFIG_OP(pci_type, c_type)			      \static int								      \mb_pci_read_config_ ## pci_type (struct pci_dev *dev, int offs, c_type *rval) \{									      \	int flags;							      \	save_flags_cli (flags);						      \									      \	MB_A_PCI_PCICR = 0x7;						      \	MB_A_PCI_DMCFGA = CONFIG_DMCFGA (dev, offs);			      \									      \	*rval = *(volatile c_type *)(MB_A_PCI_IO_ADDR + (offs & 0x3));	      \									      \        if (MB_A_PCI_PCISR & 0x2000) {					      \		MB_A_PCI_PCISR = 0x2000;				      \		*rval = ~0;						      \        }								      \									      \	MB_A_PCI_DMCFGA = 0;						      \									      \	restore_flags (flags);						      \									      \	return PCIBIOS_SUCCESSFUL;					      \}#define DEF_MB_PCI_WRITE_CONFIG_OP(pci_type, c_type)			      \static int								      \mb_pci_write_config_ ## pci_type (struct pci_dev *dev, int offs, c_type val)  \{									      \	int flags;							      \	save_flags_cli (flags);						      \									      \	MB_A_PCI_PCICR = 0x7;						      \	MB_A_PCI_DMCFGA = CONFIG_DMCFGA (dev, offs);			      \									      \	*(volatile c_type *)(MB_A_PCI_IO_ADDR + (offs & 0x3)) = val;	      \									      \        if (MB_A_PCI_PCISR & 0x2000)					      \		MB_A_PCI_PCISR = 0x2000;				      \									      \	MB_A_PCI_DMCFGA = 0;						      \									      \	restore_flags (flags);						      \									      \	return PCIBIOS_SUCCESSFUL;					      \}DEF_MB_PCI_READ_CONFIG_OP (byte, u8);DEF_MB_PCI_WRITE_CONFIG_OP (byte, u8);DEF_MB_PCI_READ_CONFIG_OP (word, u16);DEF_MB_PCI_WRITE_CONFIG_OP (word, u16);DEF_MB_PCI_READ_CONFIG_OP (dword, u32);DEF_MB_PCI_WRITE_CONFIG_OP (dword, u32);static struct pci_ops mb_pci_config_ops = {	mb_pci_read_config_byte,	mb_pci_read_config_word,	mb_pci_read_config_dword,	mb_pci_write_config_byte,	mb_pci_write_config_word,	mb_pci_write_config_dword};/* PCI Initialization.  */static struct pci_bus *mb_pci_bus = 0;/* Do initial PCI setup.  */void __devinit pcibios_init (void){	u32 id = MB_A_PCI_PCIHIDR;	u16 vendor = id & 0xFFFF;	u16 device = (id >> 16) & 0xFFFF;	if (vendor == PCI_VENDOR_ID_PLX && device == PCI_DEVICE_ID_PLX_9080) {		printk (KERN_INFO			"PCI: PLX Technology PCI9080 HOST/PCI bridge\n");		MB_A_PCI_PCICR = 0x147;		MB_A_PCI_DMLBAM = 0x0;		MB_A_PCI_PCIBAR0 = 0x007FFF00;		MB_A_PCI_PCIBAR1 = 0x0000FF00;		MB_A_PCI_PCIBAR2 = 0x00800000;		MB_A_PCI_PCILTR = 0x20;		MB_A_PCI_PCIPBAM |= 0x3;		MB_A_PCI_PCISR =  ~0; /* Clear errors.  */		/* Reprogram the motherboard's IO/config address space,		   as we don't support the GCS7 address space that the		   default uses.  Note that we have to give the address		   from the motherboard's point of view, which is		   different than the CPU's.  */		MB_A_PCI_DMLBAI = MB_A_PCI_IO_ADDR - GCS5_ADDR;		MB_A_PCI_DMRR = ~(MB_A_PCI_MEM_SIZE - 1);		mb_pci_bus = pci_scan_bus (0, &mb_pci_config_ops, 0);		pcibios_assign_resources ();	} else		printk (KERN_ERR "PCI: HOST/PCI bridge not found\n");}char __devinit *pcibios_setup (char *option){	/* Don't handle any options. */	return option;}int __nomods_init pcibios_enable_device(struct pci_dev *dev){	u16 cmd, old_cmd;	int idx;	struct resource *r;	pci_read_config_word(dev, PCI_COMMAND, &cmd);	old_cmd = cmd;	for (idx = 0; idx < 6; idx++) {		r = &dev->resource[idx];		if (!r->start && r->end) {			printk(KERN_ERR "PCI: Device %s not available because "			       "of resource collisions\n", dev->slot_name);			return -EINVAL;		}		if (r->flags & IORESOURCE_IO)			cmd |= PCI_COMMAND_IO;		if (r->flags & IORESOURCE_MEM)			cmd |= PCI_COMMAND_MEMORY;	}	if (cmd != old_cmd) {		printk("PCI: Enabling device %s (%04x -> %04x)\n",		       dev->slot_name, old_cmd, cmd);		pci_write_config_word(dev, PCI_COMMAND, cmd);	}	return 0;}/* Resource allocation.  */static void __devinit pcibios_assign_resources (void){	struct pci_dev *dev;	struct resource *r;	pci_for_each_dev (dev) {		int di_num;		unsigned class = dev->class >> 8;		if (class && class != PCI_CLASS_BRIDGE_HOST) {			unsigned r_num;			for(r_num = 0; r_num < 6; r_num++) {				r = &dev->resource[r_num];				if (!r->start && r->end)					pci_assign_resource (dev, r_num);			}		}		/* Assign interrupts.  */		for (di_num = 0; di_num < NUM_MB_PCI_DEV_IRQS; di_num++) {			struct mb_pci_dev_irq *di = &mb_pci_dev_irqs[di_num];			if (di->dev == PCI_SLOT (dev->devfn)) {				unsigned irq = di->irq_base;				if (di->query_pin) {					/* Find out which interrupt pin					   this device uses (each PCI					   slot has 4).  */					u8 irq_pin;					pci_read_config_byte (dev,							     PCI_INTERRUPT_PIN,							      &irq_pin);					if (irq_pin == 0)						/* Doesn't use interrupts.  */ 						continue;					else						irq += irq_pin - 1;				}				pcibios_update_irq (dev, irq);			}		}	}}void __devinit pcibios_update_irq (struct pci_dev *dev, int irq){	dev->irq = irq;	pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);}void __nomods_initpcibios_update_resource (struct pci_dev *dev, struct resource *root,			 struct resource *r, int resource){	u32 new, check;	int reg;	if (r->flags & IORESOURCE_IO)		new = (((r->start - MB_A_PCI_IO_ADDR)			& PCI_BASE_ADDRESS_IO_MASK)		       | PCI_BASE_ADDRESS_SPACE_IO);	else if (r->flags & IORESOURCE_MEM)		new = (((r->start - MB_A_PCI_MEM_ADDR)			& PCI_BASE_ADDRESS_MEM_MASK)		       | PCI_BASE_ADDRESS_MEM_TYPE_32		       | ((r->flags & IORESOURCE_PREFETCH)			  ? PCI_BASE_ADDRESS_MEM_PREFETCH			  : 0)		       | PCI_BASE_ADDRESS_SPACE_MEMORY);	else		panic ("pcibios_update_resource: unknown resource type");	if (resource < 6)		reg = PCI_BASE_ADDRESS_0 + 4*resource;	else if (resource == PCI_ROM_RESOURCE) {		r->flags |= PCI_ROM_ADDRESS_ENABLE;		new |= PCI_ROM_ADDRESS_ENABLE;		reg = dev->rom_base_reg;	} else		return;		pci_write_config_dword(dev, reg, new);	pci_read_config_dword(dev, reg, &check);	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {		printk (KERN_ERR "PCI: Error while updating region "			"%s/%d (%08x != %08x)\n", dev->slot_name, resource,			new, check);	}}/* Stubs for things we don't use.  */struct pci_fixup pcibios_fixups[] = { { 0 } };/* Called after each bus is probed, but before its children are examined. */void pcibios_fixup_bus(struct pci_bus *b){}voidpcibios_align_resource (void *data, struct resource *res, unsigned long size){}void pcibios_set_master (struct pci_dev *dev){}/* Mother-A SRAM memory allocation.  This is a simple first-fit allocator.  *//* A memory free-list node.  */struct mb_sram_free_area {	void *mem;	unsigned long size;	struct mb_sram_free_area *next;};/* The tail of the free-list, which starts out containing all the SRAM.  */static struct mb_sram_free_area mb_sram_free_tail = {	(void *)MB_A_SRAM_ADDR, MB_A_SRAM_SIZE, 0};/* The free-list.  */static struct mb_sram_free_area *mb_sram_free_areas = &mb_sram_free_tail;/* The free-list of free free-list nodes. (:-)  */static struct mb_sram_free_area *mb_sram_free_free_areas = 0;/* Spinlock protecting the above globals.  */static spinlock_t mb_sram_lock = SPIN_LOCK_UNLOCKED;/* Allocate a memory block at least SIZE bytes long in the Mother-A SRAM   space.  */static void *alloc_mb_sram (size_t size){	struct mb_sram_free_area *prev, *fa;	int flags;	void *mem = 0;	spin_lock_irqsave (mb_sram_lock, flags);	/* Look for a free area that can contain SIZE bytes.  */	for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)		if (fa->size >= size) {			/* Found one!  */			mem = fa->mem;			if (fa->size == size) {				/* In fact, it fits exactly, so remove				   this node from the free-list.  */				if (prev)					prev->next = fa->next;				else

⌨️ 快捷键说明

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