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

📄 pci-sd0001.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
{	sd0001_writel(0, INT_ENABLE);		/* all Interrupt = Mask */	sd0001_bus_reset();	/*	 * PCIバス扩告の瓢侯モ〖ド(MCW0レジスタ)肋年	 * ˇPCIバスのリトライ搀眶 : 痰嘎搀	 * ˇバスグランドの娃贿なし	 */#if __LITTLE_ENDIAN__	sd0001_writel(0x0000, PCI_CTL);#else	sd0001_writel(SD0001_CTL_MASTER_SWAP | SD0001_CTL_PCI_EDCONV, PCI_CTL);#endif	sd0001_writel(0, PCI_IO_OFFSET);	sd0001_writel(PCIBIOS_MIN_MEM, PCI_MEM_OFFSET);	if (request_irq(CONFIG_PCI_SD0001_IRQ, &sd0001_int_pcierr, SA_SHIRQ, "PCI Bus Error", NULL))		printk(KERN_ERR "Can't Setup PCI Bus Error Interrupt\n");	/* FIXME: Enable INT[ABCD] only when devices actually want them.	   We should probably demux them so they appear to the kernel as	   separate IRQs */	sd0001_writel(SD0001_INT_INTEN|SD0001_INT_BUSERR		|SD0001_INT_INTD|SD0001_INT_INTC|SD0001_INT_INTB		|SD0001_INT_INTA, INT_ENABLE);	return PCIBIOS_SUCCESSFUL;}void __initpcibios_fixup_pbus_ranges(struct pci_bus * bus,	struct pbus_set_ranges_data * ranges){	ranges->io_start -= bus->resource[0]->start;	ranges->io_end -= bus->resource[0]->start;	ranges->mem_start -= bus->resource[1]->start;	ranges->mem_end -= bus->resource[1]->start;}static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin){        return PCI_SLOT(dev->devfn);}static int __init sd0001_map_irq(struct pci_dev *dev, u8 slot, u8 pin){	return CONFIG_PCI_SD0001_IRQ;}void __init pcibios_init(void){	printk(KERN_NOTICE "Linux/SH SD0001 PCI Initialise\n");		ioport_resource.end = 0xffff;	iomem_resource.end = 0xfeffffff;	pci_setup_sd0001();	pci_scan_bus(0, &sd0001_pci_ops, NULL);	pci_assign_unassigned_resources();	pci_fixup_irqs(no_swizzle, sd0001_map_irq);}char * __init pcibios_setup(char *str){        return str;}extern unsigned long memory_start, memory_end;void __init pcibios_fixup_bus(struct pci_bus *bus){	struct list_head *list;	list_for_each(list, &bus->devices) {		struct pci_dev *dev = pci_dev_b(list);		u16 cmd;		if (dev->class >> 8 == PCI_CLASS_BRIDGE_HOST) {			memset(&dev->resource[1], 0, sizeof(struct resource));			dev->resource[1].start = __pa(memory_start);			dev->resource[1].end = __pa(memory_end)-1;			dev->resource[1].flags = IORESOURCE_MEM|IORESOURCE_PREFETCH;			dev->resource[1].name = "PCI Host RAM";			request_resource(&iomem_resource, &dev->resource[1]);#if 0			printk("res1 (@%p) %s %08lx %08lx %x %p %p %p\n", 			       &dev->resource[1],			       dev->resource[1].name,			       dev->resource[1].start,			       dev->resource[1].end,			       dev->resource[1].flags,			       dev->resource[1].parent,			       dev->resource[1].sibling,			       dev->resource[1].child);#endif			pcibios_update_resource(dev, bus->resource[1], 						&dev->resource[1], 1);			cmd = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;			pci_write_config_word(dev, PCI_COMMAND, cmd);			pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);		}	}}/* Add future fixups here... */struct pci_fixup pcibios_fixups[] = {        { 0 }};        /*         * Mapping for PCI Devices.	 * The SD0001 has a 48MiB window onto the PCI memory space, mapped	 * into the CPU's address space at 0xb1000000-0xb3ffffff. 	 * The range of the PCI space which is accessible is controlled	 * by the SD0001's PCI_MEM_OFFSET register, which has a granularity	 * of 64MiB. 	 *	 * As far as I can tell from the little I can understand of	 * the SD0001 documentation and from the behaviour of the	 * device, you have a 48MiB window which can only be moved	 * with 64MiB granularity. Therefore to the best of my	 * knowledge, you cannot access any PCI memory address where	 * (<addr> & 0x03000000) == 0x03000000, except by going 	 * indirectly through the PCI bridge like we do for configuration	 * and I/O cycles.	 *	 * Hopefully, this is untrue and there's some way of doing it that	 * I just don't know because I can't read the docs. For now, we	 * allow only access to the first 48MiB of PCI memory space.	 *	 * In addition to that joy, it appears that when accessing PCI	 * memory space directly, the SD0001 swaps address lines #21	 * and #22, hence the macro below to swap addresses back	 * again.	 *	 * Me and my baseball bat want a quiet word with someone. 	 *	 * dwmw2.         */#define unmunge(x) (((x) & ~0x00300000) | ( ((x)&0x00100000) << 1) | ( ((x)&0x00200000) >> 1))void *sd0001_ioremap(unsigned long phys_addr, unsigned long size){        unsigned long offset;	if ((phys_addr & 0xFFF00000) == ((phys_addr+size) & 0xFFF00000)) {		/* It fits within a single mebibyte we can still use the 		   directly-mapped region... */		return (void *)(SD0001_MEM_BASE-(PCIBIOS_MIN_MEM&0xfc000000)+unmunge(phys_addr));	}	/* It crosses a mebibyte boundary and hence we have to	   play VM tricks to make the region which is physically	   contiguous on the PCI bus but not physically contiguous	   on the SH3 bus appear virtually contiguous to the kernel.	   Got that? Did I mention my baseball bat yet? */	void * addr;	struct vm_struct * area;			offset = phys_addr & ~PAGE_MASK;	phys_addr &= PAGE_MASK;	size = PAGE_ALIGN(phys_addr + size - 1) - phys_addr;	area = get_vm_area(size, VM_IOREMAP);	if (!area)		return NULL;	addr = area->addr;	phys_addr += SD0001_MEM_BASE;	while (size) {		unsigned long this_size;		this_size = 0x100000 - (phys_addr & 0xfffff);		this_size = min(this_size, size);		if (remap_area_pages(VMALLOC_VMADDR(addr),				     unmunge(phys_addr), this_size, 				     _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_FLAGS_HARD)) {			vfree(area->addr);			return NULL;		}		size -= this_size;		phys_addr += this_size;		addr += this_size;	}	return (void *) (offset + (char *)area->addr);}void sd0001_iounmap(void *addr){	if ((unsigned long)addr >= VMALLOC_START && 	    (unsigned long)addr < VMALLOC_END)		vfree((void *)((unsigned long)addr & ~PAGE_MASK));}static void sd0001_indirect_access_wait(unsigned long i){	while((sd0001_readl(INDIRECT_STS) & SD0001_INDRCTF_INDFLG)	      && --i)		;	if (i == 0) {		printk("##### Long Indirect access wait #####\n");		mdelay(20);	}}static inline void delay(void){	ctrl_inw(0xa0000000);}/* PCI IO read long word cycle */unsigned long sd0001_inl(unsigned long port){	return *(volatile unsigned long *) (SD0001_IO_BASE+port);}void sd0001_outl(unsigned long value, unsigned long port){	*(volatile unsigned long *)(SD0001_IO_BASE+port) = value;}/* The SD0001 doesn't correctly handle byte enables for sub-word   accesses, so we have to do it indirectly like we do configuration   cycles *//* PCI IO read byte cycle */unsigned char sd0001_inb(unsigned long port){	unsigned long work, val, byte_e;	unsigned long flags;	spin_lock_irqsave(&sd0001_indirect_lock, flags);	val = 0;	byte_e = 0x00010000;	work = (port & 0x00000003);	byte_e <<= work;	port &= 0xFFFFFFFC;	sd0001_writel(port, INDIRECT_ADR);	sd0001_writel(0x00008204 | byte_e, INDIRECT_CTL); /* I/O read cycle */	sd0001_indirect_access_wait(100);	val = sd0001_readl(INDIRECT_DATA);	val >>= (work*8);	val &= 0x000000FF;	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);	return val;}/* PCI IO write byte cycle */void sd0001_outb(unsigned char value, unsigned long port){	unsigned long work, data, byte_e;	unsigned long flags;	spin_lock_irqsave(&sd0001_indirect_lock, flags);	byte_e = 0x00010000;	work = (port & 0x00000003);	byte_e <<= work;	data = value;	data <<= (work*8);	port &= 0xFFFFFFFC;	sd0001_writel(data, INDIRECT_DATA);	sd0001_writel(port, INDIRECT_ADR);	sd0001_writel((0x00008308 | byte_e), INDIRECT_CTL);	/* I/O write cycle */	sd0001_indirect_access_wait(100);	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);}/* PCI IO read word cycle */unsigned short sd0001_inw(unsigned long port){	unsigned long work, val, byte_e;	unsigned long flags;	spin_lock_irqsave(&sd0001_indirect_lock, flags);	val = 0;	byte_e = 0x00030000;	work = (port & 0x00000003);	byte_e <<= (work & 0x00000002);	work >>= 1;	port &= 0xFFFFFFFC;	sd0001_writel(port, INDIRECT_ADR);	sd0001_writel((0x00008204 | byte_e), INDIRECT_CTL);	/* I/O read cycle */	sd0001_indirect_access_wait(100);	val = sd0001_readl(INDIRECT_DATA) ;	val >>= (work*16);	val &= 0x0000FFFF;	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);	return val;}/* PCI IO write word cycle */void sd0001_outw(unsigned short value, unsigned long port){	unsigned long work, data, byte_e;	unsigned long flags;	spin_lock_irqsave(&sd0001_indirect_lock, flags);	byte_e = 0x00030000;	work = (port & 0x00000003);	byte_e <<= (work & 0x00000002);	work >>= 1;	port &= 0xFFFFFFFC;	data = value;	data <<= (work*16);	sd0001_writel(data, INDIRECT_DATA);	sd0001_writel(port, INDIRECT_ADR);	sd0001_writel((0x00008308 | byte_e), INDIRECT_CTL);	/* I/O write cycle */	sd0001_indirect_access_wait(100);	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);}void sd0001_insb(unsigned long port, void *addr, unsigned long count){	while (count--)		*((unsigned char *) addr)++ = (unsigned char)sd0001_inb(port);}void sd0001_insw(unsigned long port, void *addr, unsigned long count){	while (count--)		*((unsigned short *) addr)++ = (unsigned short)sd0001_inw(port);}void sd0001_insl(unsigned long port, void *addr, unsigned long count){	while (count--)		*((unsigned long *) addr)++ = sd0001_inl(port);}void sd0001_outsb(unsigned long port, const void *addr, unsigned long count){	while (count--)		sd0001_outb(*((unsigned char *)addr)++, port);}void sd0001_outsw(unsigned long port, const void *addr, unsigned long count){	while (count--)		sd0001_outw(*((unsigned short *)addr)++, port);}void sd0001_outsl(unsigned long port, const void *addr, unsigned long count){	while (count--)		sd0001_outl(*((unsigned long *)addr)++, port);}unsigned char sd0001_inb_p(unsigned long port){	unsigned long v;	v = sd0001_inb(port);	delay();	return v;}void sd0001_outb_p(unsigned char value, unsigned long port){	sd0001_outb(value, port);	delay();}

⌨️ 快捷键说明

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