URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [ppc/] [kernel/] [pci.c] - Rev 1765
Compare with Previous | Blame | View Log
/* * PCI support * -- rough emulation of "PCI BIOS" functions * * Note: these are very motherboard specific! Some way needs to * be worked out to handle the differences. */ #include <linux/types.h> #include <linux/bios32.h> #include <linux/pci.h> /* * PCI interrupt configuration. This is motherboard specific. */ /* Which PCI interrupt line does a given device [slot] use? */ /* Note: This really should be two dimensional based in slot/pin used */ unsigned char *Motherboard_map; /* How is the 82378 PIRQ mapping setup? */ unsigned char *Motherboard_routes; /* Tables for known hardware */ /* Motorola PowerStack */ static char Blackhawk_pci_IRQ_map[16] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ 0, /* Slot 2 - unused */ 0, /* Slot 3 - unused */ 0, /* Slot 4 - unused */ 0, /* Slot 5 - unused */ 0, /* Slot 6 - unused */ 0, /* Slot 7 - unused */ 0, /* Slot 8 - unused */ 0, /* Slot 9 - unused */ 0, /* Slot 10 - unused */ 0, /* Slot 11 - unused */ 3, /* Slot 12 - SCSI */ 0, /* Slot 13 - unused */ 1, /* Slot 14 - Ethernet */ 0, /* Slot 15 - unused */ }; static char Blackhawk_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 9, /* Line 1 */ 11, /* Line 2 */ 14, /* Line 3 */ 15 /* Line 4 */ }; /* Motorola MVME16xx */ static char Genesis_pci_IRQ_map[16] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ 0, /* Slot 2 - unused */ 0, /* Slot 3 - unused */ 0, /* Slot 4 - unused */ 0, /* Slot 5 - unused */ 0, /* Slot 6 - unused */ 0, /* Slot 7 - unused */ 0, /* Slot 8 - unused */ 0, /* Slot 9 - unused */ 0, /* Slot 10 - unused */ 0, /* Slot 11 - unused */ 3, /* Slot 12 - SCSI */ 0, /* Slot 13 - unused */ 1, /* Slot 14 - Ethernet */ 0, /* Slot 15 - unused */ }; static char Genesis_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 10, /* Line 1 */ 11, /* Line 2 */ 14, /* Line 3 */ 15 /* Line 4 */ }; /* Motorola Series-E */ static char Comet_pci_IRQ_map[16] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ 0, /* Slot 2 - unused */ 0, /* Slot 3 - unused */ 0, /* Slot 4 - unused */ 0, /* Slot 5 - unused */ 0, /* Slot 6 - unused */ 0, /* Slot 7 - unused */ 0, /* Slot 8 - unused */ 0, /* Slot 9 - unused */ 0, /* Slot 10 - unused */ 0, /* Slot 11 - unused */ 3, /* Slot 12 - SCSI */ 0, /* Slot 13 - unused */ 1, /* Slot 14 - Ethernet */ 0, /* Slot 15 - unused */ }; static char Comet_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 10, /* Line 1 */ 11, /* Line 2 */ 14, /* Line 3 */ 15 /* Line 4 */ }; /* BeBox */ static char BeBox_pci_IRQ_map[16] = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ 0, /* Slot 2 - unused */ 0, /* Slot 3 - unused */ 0, /* Slot 4 - unused */ 0, /* Slot 5 - unused */ 0, /* Slot 6 - unused */ 0, /* Slot 7 - unused */ 0, /* Slot 8 - unused */ 0, /* Slot 9 - unused */ 0, /* Slot 10 - unused */ 0, /* Slot 11 - unused */ 16, /* Slot 12 - SCSI */ 0, /* Slot 13 - unused */ 0, /* Slot 14 - unused */ 0, /* Slot 15 - unused */ }; static char BeBox_pci_IRQ_routes[] = { 0, /* Line 0 - Unused */ 9, /* Line 1 */ 11, /* Line 2 */ 14, /* Line 3 */ 15 /* Line 4 */ }; /* #define PCI_DEBUG */ #ifdef PCI_STATS int PCI_conversions[2]; #endif unsigned long pcibios_init(unsigned long mem_start, unsigned long mem_end) { return mem_start; } unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end) { return mem_start; } unsigned long _LE_to_BE_long(unsigned long val) { unsigned char *p = (unsigned char *)&val; #ifdef PCI_STATS PCI_conversions[0]++; #endif return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | (p[0] << 0)); } unsigned short _LE_to_BE_short(unsigned long val) { unsigned char *p = (unsigned char *)&val; #ifdef PCI_STATS PCI_conversions[1]++; #endif return ((p[3] << 8) | (p[2] << 0)); } int pcibios_present (void) { #ifdef PCI_DEBUG printk("PCI [BIOS] present?\n"); #endif return (1); } int pcibios_read_config_dword (unsigned char bus, unsigned char dev, unsigned char offset, unsigned int *val) { unsigned long _val; unsigned long *ptr; dev >>= 3; #ifdef PCI_DEBUG printk("PCI Read config dword[%d.%d.%x] = ", bus, dev, offset); #endif if ((bus != 0) || (dev < 11) || (dev > 16)) { *val = 0xFFFFFFFF; return PCIBIOS_DEVICE_NOT_FOUND; } else { ptr = (unsigned long *)(0x80800000 | (1<<dev) | offset); #ifdef PCI_DEBUG printk("[%x] ", ptr); #endif _val = _LE_to_BE_long(*ptr); } #ifdef PCI_DEBUG printk("%x\n", _val); #endif *val = _val; return PCIBIOS_SUCCESSFUL; } int pcibios_read_config_word (unsigned char bus, unsigned char dev, unsigned char offset, unsigned short *val) { unsigned short _val; unsigned short *ptr; dev >>= 3; #ifdef PCI_DEBUG printk("PCI Read config word[%d.%d.%x] = ", bus, dev, offset); #endif if ((bus != 0) || (dev < 11) || (dev > 16)) { *val = 0xFFFFFFFF; return PCIBIOS_DEVICE_NOT_FOUND; } else { ptr = (unsigned short *)(0x80800000 | (1<<dev) | offset); #ifdef PCI_DEBUG printk("[%x] ", ptr); #endif _val = _LE_to_BE_short(*ptr); } #ifdef PCI_DEBUG printk("%x\n", _val); #endif *val = _val; return PCIBIOS_SUCCESSFUL; } int pcibios_read_config_byte (unsigned char bus, unsigned char dev, unsigned char offset, unsigned char *val) { unsigned char _val; volatile unsigned char *ptr; dev >>= 3; /* Note: the configuration registers don't always have this right! */ if (offset == PCI_INTERRUPT_LINE) { if (Motherboard_map[dev] <= 4) { *val = Motherboard_routes[Motherboard_map[dev]]; } else { /* Pseudo interrupts [for BeBox] */ *val = Motherboard_map[dev]; } #ifdef PCI_DEBUG printk("PCI Read Interrupt Line[%d.%d] = %d\n", bus, dev, *val); #endif return PCIBIOS_SUCCESSFUL; } #ifdef PCI_DEBUG printk("PCI Read config byte[%d.%d.%x] = ", bus, dev, offset); #endif if ((bus != 0) || (dev < 11) || (dev > 16)) { *val = 0xFFFFFFFF; return PCIBIOS_DEVICE_NOT_FOUND; } else { ptr = (unsigned char *)(0x80800000 | (1<<dev) | offset ^ 1); #ifdef PCI_DEBUG printk("[%x] ", ptr); #endif _val = *ptr; } #ifdef PCI_DEBUG printk("%x\n", _val); #endif *val = _val; return PCIBIOS_SUCCESSFUL; } int pcibios_write_config_dword (unsigned char bus, unsigned char dev, unsigned char offset, unsigned int val) { unsigned long _val; unsigned long *ptr; dev >>= 3; _val = _LE_to_BE_long(val); #ifdef PCI_DEBUG printk("PCI Write config dword[%d.%d.%x] = %x\n", bus, dev, offset, _val); #endif if ((bus != 0) || (dev < 11) || (dev > 16)) { return PCIBIOS_DEVICE_NOT_FOUND; } else { ptr = (unsigned long *)(0x80800000 | (1<<dev) | offset); *ptr = _val; } return PCIBIOS_SUCCESSFUL; } int pcibios_write_config_word (unsigned char bus, unsigned char dev, unsigned char offset, unsigned short val) { unsigned short _val; unsigned short *ptr; dev >>= 3; _val = _LE_to_BE_short(val); #ifdef PCI_DEBUG printk("PCI Write config word[%d.%d.%x] = %x\n", bus, dev, offset, _val); #endif if ((bus != 0) || (dev < 11) || (dev > 16)) { return PCIBIOS_DEVICE_NOT_FOUND; } else { ptr = (unsigned short *)(0x80800000 | (1<<dev) | offset); *ptr = _val; } return PCIBIOS_SUCCESSFUL; } int pcibios_write_config_byte (unsigned char bus, unsigned char dev, unsigned char offset, unsigned char val) { unsigned char _val; unsigned char *ptr; dev >>= 3; _val = val; #ifdef PCI_DEBUG printk("PCI Write config byte[%d.%d.%x] = %x\n", bus, dev, offset, _val); #endif if ((bus != 0) || (dev < 11) || (dev > 16)) { return PCIBIOS_DEVICE_NOT_FOUND; } else { ptr = (unsigned char *)(0x80800000 | (1<<dev) | offset ^ 1); *ptr = _val; } return PCIBIOS_SUCCESSFUL; } int pcibios_find_device (unsigned short vendor, unsigned short device_id, unsigned short index, unsigned char *bus, unsigned char *dev) { unsigned long w, desired = (device_id << 16) | vendor; int devnr; if (vendor == 0xffff) { return PCIBIOS_BAD_VENDOR_ID; } for (devnr = 11; devnr < 16; devnr++) { pcibios_read_config_dword(0, devnr<<3, PCI_VENDOR_ID, &w); if (w == desired) { if (index == 0) { *bus = 0; *dev = devnr<<3; return PCIBIOS_SUCCESSFUL; } --index; } } return PCIBIOS_DEVICE_NOT_FOUND; } int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *dev) { int dev_nr, class, indx; indx = 0; #ifdef PCI_DEBUG printk("pcibios_find_class - class: %x, index: %x", class_code, index); #endif for (dev_nr = 11; dev_nr < 16; dev_nr++) { pcibios_read_config_dword(0, dev_nr<<3, PCI_CLASS_REVISION, &class); if ((class>>8) == class_code) { if (index == indx) { *bus = 0; *dev = dev_nr<<3; #ifdef PCI_DEBUG printk(" - device: %x\n", dev_nr); #endif return (0); } indx++; } } #ifdef PCI_DEBUG printk(" - not found\n"); #endif return PCIBIOS_DEVICE_NOT_FOUND; } const char *pcibios_strerror(int error) { static char buf[32]; switch (error) { case PCIBIOS_SUCCESSFUL: return ("PCI BIOS: no error"); case PCIBIOS_FUNC_NOT_SUPPORTED: return ("PCI BIOS: function not supported"); case PCIBIOS_BAD_VENDOR_ID: return ("PCI BIOS: bad vendor ID"); case PCIBIOS_DEVICE_NOT_FOUND: return ("PCI BIOS: device not found"); case PCIBIOS_BAD_REGISTER_NUMBER: return ("PCI BIOS: bad register number"); case PCIBIOS_SET_FAILED: return ("PCI BIOS: set failed"); case PCIBIOS_BUFFER_TOO_SMALL: return ("PCI BIOS: buffer too small"); default: sprintf(buf, "PCI BIOS: invalid error #%d", error); return(buf); } } /* * Note: This routine has to access the PCI configuration space * for the PCI bridge chip (Intel 82378). */ void route_PCI_interrupts(void) { unsigned char *ibc_pirq = (unsigned char *)0x80800860; unsigned char *ibc_pcicon = (unsigned char *)0x80800840; extern unsigned long isBeBox[]; int i; /* Decide which motherboard this is & how the PCI interrupts are routed */ if (isBeBox[0]) { Motherboard_map = BeBox_pci_IRQ_map; Motherboard_routes = BeBox_pci_IRQ_routes; } else { /* Motorola hardware */ switch (inb(0x800) & 0xF0) { case 0x10: /* MVME16xx */ Motherboard_map = Genesis_pci_IRQ_map; Motherboard_routes = Genesis_pci_IRQ_routes; break; case 0x20: /* Series E */ Motherboard_map = Comet_pci_IRQ_map; Motherboard_routes = Comet_pci_IRQ_routes; break; case 0x40: /* PowerStack */ default: /* Can't hurt, can it? */ Motherboard_map = Blackhawk_pci_IRQ_map; Motherboard_routes = Blackhawk_pci_IRQ_routes; break; } } /* Set up mapping from slots */ for (i = 1; i <= 4; i++) { ibc_pirq[i-1] = Motherboard_routes[i]; } /* Enable PCI interrupts */ *ibc_pcicon |= 0x20; }