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

📄 pci_bios.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 3 页
字号:
		DBG(KERN_INFO		    "rr: BAR %d, start %lx, end %lx, flags %lx\n", idx,		    r->start, r->end, r->flags);		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) {		DBG(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n",		    dev->slot_name, old_cmd, cmd);		galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd);	}	/*	   Let's fix up the latency timer and cache line size here.  Cache line size =	   32 bytes / sizeof dword (4) = 8.	   Latency timer must be > 8.  32 is random but appears to work.	 */	galileo_pcibios_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);	if (tmp1 != 8) {		DBG(KERN_INFO		    "rr: PCI setting cache line size to 8 from %d\n",		    tmp1);		galileo_pcibios_write_config_byte(dev, PCI_CACHE_LINE_SIZE,						  8);	}	galileo_pcibios_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp1);	if (tmp1 < 32) {		DBG(KERN_INFO		    "rr: PCI setting latency timer to 32 from %d\n", tmp1);		galileo_pcibios_write_config_byte(dev, PCI_LATENCY_TIMER,						  32);	}	return 0;}int pcibios_enable_device(struct pci_dev *dev){	DBG(KERN_INFO "rr: pcibios_enable_device\n");	return pcibios_enable_resources(dev);}void pcibios_update_resource(struct pci_dev *dev, struct resource *root,			     struct resource *res, int resource){	u32 new, check;	int reg;	DBG(KERN_INFO "rr: pcibios_update_resource\n");	return;	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);	if (resource < 6) {		reg = PCI_BASE_ADDRESS_0 + 4 * resource;	} else if (resource == PCI_ROM_RESOURCE) {		res->flags |= PCI_ROM_ADDRESS_ENABLE;		reg = dev->rom_base_reg;	} else {		/* Somebody might have asked allocation of a non-standard resource */		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)) {		DBG(KERN_ERR "PCI: Error while updating region "		    "%s/%d (%08x != %08x)\n", dev->slot_name, resource,		    new, check);	}}void pcibios_align_resource(void *data, struct resource *res,			    unsigned long size, unsigned long align){	struct pci_dev *dev = data;	DBG(KERN_INFO "pcibios_align_resource\n");	if (res->flags & IORESOURCE_IO) {		unsigned long start = res->start;		/* We need to avoid collisions with `mirrored' VGA ports		   and other strange ISA hardware, so we always want the		   addresses kilobyte aligned.  */		if (size > 0x100) {			DBG(KERN_ERR "PCI: I/O Region %s/%d too large"			    " (%ld bytes)\n", dev->slot_name,			    dev->resource - res, size);		}		start = (start + 1024 - 1) & ~(1024 - 1);		res->start = start;	}}/* * structure galileo_pci_ops * * This structure holds the pointers for the PCI configuration space * access, and the fixup for the interrupts. * This structure is registered to the operating system in boot time */struct pci_ops galileo_pci_ops = {	galileo_pcibios_read_config_byte,	galileo_pcibios_read_config_word,	galileo_pcibios_read_config_dword,	galileo_pcibios_write_config_byte,	galileo_pcibios_write_config_word,	galileo_pcibios_write_config_dword};/* * galileo_pcibios_fixup_bus - * * After detecting all agents over the PCI , this function is called * in order to give an interrupt number for each PCI device starting * from IRQ 20. It does also enables master for each device. * * Inputs : * mem_start , mem_end are not relevant in MIPS architecture. * * Outpus : * return always mem_start */static void __init galileo_pcibios_fixup_bus(struct pci_bus *bus){	unsigned int Current_IRQ = 20;	struct pci_bus *current_bus = bus;	struct pci_dev *devices;	struct list_head *devices_link;	list_for_each(devices_link, &(current_bus->devices)) {		devices = pci_dev_b(devices_link);		if (devices != NULL) {			devices->irq = Current_IRQ++;			/* Assign an interrupt number for the device */			galileo_pcibios_write_config_byte(devices,							  PCI_INTERRUPT_LINE,							  Current_IRQ);			galileo_pcibios_set_master(devices);		}	}}struct pci_fixup pcibios_fixups[] = {//    { PCI_FIXUP_HEADER, 0x4620, 0x11ab, galileo_pcibios_fixup },	{0}};void __init pcibios_fixup_bus(struct pci_bus *c){	DBG(KERN_INFO "rr: pcibios_fixup_bus\n");	galileo_pcibios_fixup_bus(c);}/* * This code was derived from Galileo Technology's example * and significantly reworked. * * This is very simple.  It does not scan multiple function devices.  It does * not scan behind bridges.  Those would be simple to implement, but we don't * currently need this. */static void __init scan_and_initialize_pci(void){	struct pci_device pci_devices[MAX_PCI_DEVS];	if (scan_pci_bus(pci_devices)) {		allocate_pci_space(pci_devices);	}}/* * This is your basic PCI scan.  It goes through each slot and checks to * see if there's something that responds.  If so, then get the size and * type of each of the responding BARs.  Save them for later. */static u32 __init scan_pci_bus(struct pci_device *pci_devices){	u32 arrayCounter = 0;	u32 memType;	u32 memSize;	u32 pci_slot, bar;	u32 id;	u32 c18RegValue;	struct pci_dev device;	DBG(KERN_INFO "rr: scan_pci_bus\n");	/*	   According to PCI REV 2.1 MAX agents on the bus are 21.	   We don't bother scanning ourselves (slot 0).	 */	for (pci_slot = 1; pci_slot < 22; pci_slot++) {		device.devfn = PCI_DEVFN(pci_slot, 0);		id = pci0ReadConfigReg(PCI_VENDOR_ID, &device);		/*  Check for a PCI Master Abort (nothing responds in the slot) */		GT_READ(GT_INTRCAUSE_OFS, &c18RegValue);		/* Clearing bit 18 of in the Cause Register 0xc18 by writting 0. */		GT_WRITE(GT_INTRCAUSE_OFS, (c18RegValue & 0xfffbffff));		if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) {			DBG(KERN_INFO "rr: found device %x, slot %d\n", id,			    pci_slot);			pci_devices[arrayCounter].slot = pci_slot;			for (bar = 0; bar < 6; bar++) {				memType =				    pci0ReadConfigReg(PCI_BASE_ADDRESS_0 +						      (bar * 4), &device);				pci_devices[arrayCounter].BARtype[bar] =				    memType & 1;				pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +						   (bar * 4), &device,						   0xffffffff);				memSize =				    pci0ReadConfigReg(PCI_BASE_ADDRESS_0 +						      (bar * 4), &device);				if (memType & 1) {	/*  IO space  */					pci_devices[arrayCounter].					    BARsize[bar] =					    ~(memSize & 0xfffffffc) + 1;				} else {	/*  memory space */					pci_devices[arrayCounter].					    BARsize[bar] =					    ~(memSize & 0xfffffff0) + 1;				}				DBG(KERN_INFO				    "rr: BAR %d, type %d, size %x\n", bar,				    (memType & 1),				    pci_devices[arrayCounter].				    BARsize[bar]);			}	/*  BAR counter  */			arrayCounter++;		}		/*  found a device  */	}			/*  slot counter  */	DBG(KERN_INFO "rr: found %d devices\n", arrayCounter);	if (arrayCounter < MAX_PCI_DEVS) {		pci_devices[arrayCounter].slot = -1;	}	return (arrayCounter);}#define ALIGN(val,align)        (((val) + ((align) - 1)) & ~((align) - 1))#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))/* * This function goes through the list of devices and allocates the BARs in * either IO or MEM space.  It does it in order of size, which will limit the * amount of fragmentation we have in the IO and MEM spaces. */static void __init allocate_pci_space(struct pci_device *pci_devices){	u32 count, maxcount, bar;	u32 maxSize, maxDevice, maxBAR;	u32 alignto;	u32 base;	u32 pci0_mem_base = pci0GetMemory0Base();	u32 pci0_io_base = pci0GetIOspaceBase();	struct pci_dev device;	DBG(KERN_INFO "rr: allocate_pci_space\n");	DBG(KERN_INFO "pci0_io_base %x\n", pci0_io_base);	DBG(KERN_INFO "pci0_mem_base %x\n", pci0_mem_base);	/*  How many PCI devices do we have?  */	maxcount = MAX_PCI_DEVS;	for (count = 0; count < MAX_PCI_DEVS; count++) {		if (pci_devices[count].slot == -1) {			maxcount = count;			break;		}	}//    DBG(KERN_INFO "Found %d devices\n", maxcount);	do {		/*  Find the largest size BAR we need to allocate  */		maxSize = 0;		for (count = 0; count < maxcount; count++) {			for (bar = 0; bar < 6; bar++) {				if (pci_devices[count].BARsize[bar] >				    maxSize) {					maxSize =					    pci_devices[count].					    BARsize[bar];					maxDevice = count;					maxBAR = bar;				}			}		}		/*		   We've found the largest BAR.  Allocate it into IO or		   mem space.  We don't idiot check the bases to make		   sure they haven't overflowed the current size for that aperture.		   Don't bother to enable the device's IO or MEM space here.  That will		   be done in pci_enable_resources if the device is activated by a driver.		 */		if (maxSize) {			device.devfn =			    PCI_DEVFN(pci_devices[maxDevice].slot, 0);			if (pci_devices[maxDevice].BARtype[maxBAR] == 1) {				alignto = MAX(0x1000, maxSize);				base = ALIGN(pci0_io_base, alignto);				pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +						   (maxBAR * 4), &device,						   base | 0x1);				pci0_io_base = base + alignto;				DBG(KERN_INFO				    "Device %d BAR %d address %x\n",				    pci_devices[maxDevice].slot, maxBAR,				    base);				DBG(KERN_INFO "New IO base %x\n",				    pci0_io_base);			} else {				alignto = MAX(0x1000, maxSize);				base = ALIGN(pci0_mem_base, alignto);				pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +						   (maxBAR * 4), &device,						   base);				pci0_mem_base = base + alignto;				DBG(KERN_INFO				    "Device %d BAR %d address %x\n",				    pci_devices[maxDevice].slot, maxBAR,				    base);				DBG(KERN_INFO "New mem base %x\n",				    pci0_mem_base);			}			/*			   This entry is finished.  Remove it from the list we'll scan.			 */			pci_devices[maxDevice].BARsize[maxBAR] = 0;		}	} while (maxSize);}unsigned __init int pcibios_assign_all_busses(void){	return 1;}void __init pcibios_init(void){	u32 tmp;	struct pci_dev controller;	controller.devfn = SELF;	DBG(KERN_INFO "rr: pcibios_init\n");	GT_READ(GT_PCI0_CMD_OFS, &tmp);	DBG(KERN_INFO "rr: PCI0 command - %x\n", tmp);	GT_READ(GT_PCI0_BARE_OFS, &tmp);	DBG(KERN_INFO "rr: BAR0 - %x\n", tmp);	/*	 * You have to enable bus mastering to configure any other	 * card on the bus.	 */	tmp = pci0ReadConfigReg(PCI_COMMAND, &controller);	DBG(KERN_INFO "rr: command/status - %x\n", tmp);	tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR;	DBG(KERN_INFO "rr: new command/status - %x\n", tmp);	pci0WriteConfigReg(PCI_COMMAND, &controller, tmp);	/*  This scans the PCI bus and sets up initial values.  */	scan_and_initialize_pci();	/*	 * Reset PCI I/O and PCI MEM values to ones supported by EVM.	 */	ioport_resource.start = 0x10000000;	ioport_resource.end = 0x11ffffff;	/*  32 MB */	iomem_resource.start = 0x12000000;	iomem_resource.end = 0x13ffffff;	/* 32 MB */	pci_scan_bus(0, &galileo_pci_ops, NULL);}char *pcibios_setup(char *str){	printk(KERN_INFO "rr: pcibios_setup\n");	/* Nothing to do for now.  */	return str;}#endif /* CONFIG_PCI */

⌨️ 快捷键说明

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