diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-01-29 01:41:54 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-01-29 01:41:54 +0000 |
commit | f969d69ba9f952e5bdd38278e25e26a3e4a61a70 (patch) | |
tree | b3530d803df59d726afaabebc6626987dee1ca05 /arch/arm/kernel | |
parent | a10ce7ef2066b455d69187643ddf2073bfc4db24 (diff) |
Merge with 2.3.27.
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/armksyms.c | 10 | ||||
-rw-r--r-- | arch/arm/kernel/bios32.c | 437 | ||||
-rw-r--r-- | arch/arm/kernel/dec21285.c | 161 | ||||
-rw-r--r-- | arch/arm/kernel/ecard.c | 12 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 28 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 301 | ||||
-rw-r--r-- | arch/arm/kernel/sys_arm.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 41 |
8 files changed, 509 insertions, 483 deletions
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index ebb2f150d..43cc0574f 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -12,6 +12,7 @@ #include <asm/byteorder.h> #include <asm/elf.h> #include <asm/io.h> +#include <asm/irq.h> #include <asm/dma.h> #include <asm/pgtable.h> #include <asm/proc-fns.h> @@ -98,7 +99,8 @@ EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(system_rev); EXPORT_SYMBOL(system_serial_low); EXPORT_SYMBOL(system_serial_high); - +EXPORT_SYMBOL(__bug); +EXPORT_SYMBOL(__readwrite_bug); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); @@ -152,8 +154,8 @@ EXPORT_SYMBOL(__bus_to_virt); #ifndef CONFIG_NO_PGT_CACHE EXPORT_SYMBOL(quicklists); #endif -EXPORT_SYMBOL(__bad_pmd); -EXPORT_SYMBOL(__bad_pmd_kernel); +EXPORT_SYMBOL(__handle_bad_pmd); +EXPORT_SYMBOL(__handle_bad_pmd_kernel); /* string / mem functions */ EXPORT_SYMBOL_NOVERS(strcpy); @@ -235,3 +237,5 @@ EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_interruptible_failed); EXPORT_SYMBOL_NOVERS(__down_trylock_failed); EXPORT_SYMBOL_NOVERS(__up_wakeup); + +EXPORT_SYMBOL(get_wchan); diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 3bd7a7358..28c12d3e8 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -13,16 +13,14 @@ #include <asm/irq.h> #include <asm/system.h> -int have_isa_bridge; +#include "bios32.h" -int (*pci_irq_fixup)(struct pci_dev *dev); +static int debug_pci; +int have_isa_bridge; -extern struct pci_ops *dc21285_init(int pass); -extern void pcibios_fixup_ebsa285(struct pci_dev *dev); extern void hw_init(void); -void -pcibios_report_device_errors(void) +void pcibios_report_device_errors(void) { struct pci_dev *dev; @@ -31,16 +29,17 @@ pcibios_report_device_errors(void) pci_read_config_word(dev, PCI_STATUS, &status); - if (status & 0xf900) { - pci_write_config_word(dev, PCI_STATUS, status & 0xf900); - printk(KERN_DEBUG "PCI: %02x:%02x status = %X\n", - dev->bus->number, dev->devfn, status); - } + if ((status & 0xf900) == 0) + continue; + + pci_write_config_word(dev, PCI_STATUS, status & 0xf900); + printk(KERN_DEBUG "PCI: status %04X on %s\n", + status, dev->name); } } /* - * We don't use this to fix the device, but more our initialisation. + * We don't use this to fix the device, but initialisation of it. * It's not the correct use for this, but it works. The actions we * take are: * - enable only IO @@ -68,196 +67,108 @@ static void __init pci_fixup_83c553(struct pci_dev *dev) pci_write_config_byte(dev, 0x81, 0x01); } -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553 }, - { 0 } -}; - -/* - * Assign new address to PCI resource. We hope our resource information - * is complete. On the PC, we don't re-assign resources unless we are - * forced to do so. - * - * Expects start=0, end=size-1, flags=resource type. - */ - -int __init pcibios_assign_resource(struct pci_dev *dev, int i) +static void __init pci_fixup_unassign(struct pci_dev *dev) { - struct resource *r = &dev->resource[i]; - struct resource *pr = pci_find_parent_resource(dev, r); - unsigned long size = r->end + 1; - unsigned long flags = 0; - - if (!pr) - return -EINVAL; - if (r->flags & IORESOURCE_IO) { - if (size > 0x100) - return -EFBIG; - if (allocate_resource(pr, r, size, 0x9000, ~0, 1024)) - return -EBUSY; - flags = PCI_BASE_ADDRESS_SPACE_IO; - } else { - if (allocate_resource(pr, r, size, 0x00100000, 0x7fffffff, size)) - return -EBUSY; - } - if (i < 6) - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4*i, r->start | flags); - return 0; + dev->resource[0].end -= dev->resource[0].start; + dev->resource[0].start = 0; } /* - * Assign an address to an I/O range. + * PCI IDE controllers use non-standard I/O port + * decoding, respect it. */ -static void __init pcibios_fixup_io_addr(struct pci_dev *dev, struct resource *r, int idx) +static void __init pci_fixup_ide_bases(struct pci_dev *dev) { - unsigned int reg = PCI_BASE_ADDRESS_0 + (idx << 2); - unsigned int size = r->end - r->start + 1; - u32 try; + struct resource *r; + int i; - /* - * We need to avoid collisions with `mirrored' VGA ports and other strange - * ISA hardware, so we always want the addresses kilobyte aligned. - */ - if (!size || size > 256) { - printk(KERN_ERR "PCI: Cannot assign I/O space to %s, " - "%d bytes are too much.\n", dev->name, size); + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) return; - } - - if (allocate_resource(&ioport_resource, r, size, 0x9000, ~0, 1024)) { - printk(KERN_ERR "PCI: Unable to find free %d bytes of I/O " - "space for %s.\n", size, dev->name); - return; - } - printk("PCI: Assigning I/O space %04lx-%04lx to %s\n", - r->start, r->end, dev->name); - - pci_write_config_dword(dev, reg, r->start | PCI_BASE_ADDRESS_SPACE_IO); - pci_read_config_dword(dev, reg, &try); - - if ((try & PCI_BASE_ADDRESS_IO_MASK) != r->start) { - r->start = 0; - pci_write_config_dword(dev, reg, 0); - printk(KERN_ERR "PCI: I/O address setup failed, got %04x\n", try); + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + r = dev->resource + i; + if ((r->start & ~0x80) == 0x374) { + r->start |= 2; + r->end = r->start; + } } } +struct pci_fixup pcibios_fixups[] = { + { + PCI_FIXUP_HEADER, + PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, + pci_fixup_83c553 + }, { + PCI_FIXUP_HEADER, + PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F, + pci_fixup_unassign + }, { + PCI_FIXUP_HEADER, + PCI_ANY_ID, PCI_ANY_ID, + pci_fixup_ide_bases + }, { 0 } +}; + /* - * Assign an address to an memory range. + * Allocate resources for all PCI devices that have been enabled. + * We need to do that before we try to fix up anything. */ -static void __init pcibios_fixup_mem_addr(struct pci_dev *dev, struct resource *r, int idx) +static void __init pcibios_claim_resources(void) { - unsigned int reg = PCI_BASE_ADDRESS_0 + (idx << 2); - unsigned int size = r->end - r->start + 1; - u32 try; - - if (!size) { - printk(KERN_ERR "PCI: Cannot assign memory space to %s, " - "%d bytes are too much.\n", dev->name, size); - return; - } - - if (allocate_resource(&iomem_resource, r, size, - 0x00100000, 0x0fffffff, 1024)) { - printk(KERN_ERR "PCI: Unable to find free %d bytes of memory " - "space for %s.\n", size, dev->name); - return; - } - - printk("PCI: Assigning memory space %08lx-%08lx to %s\n", - r->start, r->end, dev->name); - - pci_write_config_dword(dev, reg, r->start); - pci_read_config_dword(dev, reg, &try); + struct pci_dev *dev; + int idx; - if (try != r->start) { - r->start = 0; - pci_write_config_dword(dev, reg, 0); - printk(KERN_ERR "PCI: memory address setup failed, " - "got %08x\n", try); - } + for (dev = pci_devices; dev; dev = dev->next) + for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) + if (dev->resource[idx].flags && + dev->resource[idx].start) + pci_claim_resource(dev, idx); } -#define _PCI_REGION_IO 1 -#define _PCI_REGION_MEM 2 - -/* - * Fix up one PCI devices regions, enables and interrupt lines - */ -static void __init pcibios_fixup_device(struct pci_dev *dev, u16 *cmd) +void __init +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) { - int i, has_regions = 0; - - /* - * Fix up the regions. Any regions which aren't allocated - * are given a free region. - */ - for (i = 0; i < 6; i++) { - struct resource *r = dev->resource + i; + unsigned long where, size; + u32 reg; - if (r->flags & IORESOURCE_IO) { - has_regions |= _PCI_REGION_IO; + if (debug_pci) + printk("PCI: Assigning %3s %08lx to %s\n", + res->flags & IORESOURCE_IO ? "IO" : "MEM", + res->start, dev->name); - if (!r->start || r->end == 0xffffffff) - pcibios_fixup_io_addr(dev, r, i); - } else if (r->end) { - has_regions |= _PCI_REGION_MEM; + where = PCI_BASE_ADDRESS_0 + resource * 4; + size = res->end - res->start; - if (!r->start) - pcibios_fixup_mem_addr(dev, r, i); - } - } - - switch (dev->class >> 8) { - case PCI_CLASS_BRIDGE_ISA: - case PCI_CLASS_BRIDGE_EISA: - /* - * If this device is an ISA bridge, set the have_isa_bridge - * flag. We will then go looking for things like keyboard, - * etc - */ - have_isa_bridge = !0; - /* FALL THROUGH */ - - default: - /* - * Don't enable VGA-compatible cards since they have - * fixed I/O and memory space. - * - * Don't enabled disabled IDE interfaces either because - * some BIOSes may reallocate the same address when they - * find that no devices are attached. - */ - if (has_regions & _PCI_REGION_IO && - !((*cmd) & PCI_COMMAND_IO)) { - printk("PCI: Enabling I/O for %s\n", dev->name); - *cmd |= PCI_COMMAND_IO; - } + pci_read_config_dword(dev, where, ®); + reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); + pci_write_config_dword(dev, where, reg); +} - if (has_regions & _PCI_REGION_MEM && - !((*cmd) & PCI_COMMAND_MEMORY)) { - printk("PCI: Enabling memory for %s\n", dev->name); - *cmd |= PCI_COMMAND_MEMORY; - } - } +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ + if (debug_pci) + printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } /* - * Fix base addresses, I/O and memory enables and IRQ's + * Called after each bus is probed, but before its children + * are examined. */ -static void __init pcibios_fixup_devices(void) +void __init pcibios_fixup_bus(struct pci_bus *bus) { struct pci_dev *dev; - for (dev = pci_devices; dev; dev = dev->next) { + for (dev = bus->devices; dev; dev = dev->sibling) { u16 cmd; /* - * architecture specific hacks. - * I don't really want this here, - * but I don't see any other place - * for it to live. + * architecture specific hacks. I don't really want + * this here, but I don't see any other place for it + * to live. Shame the device doesn't support + * capabilities */ if (machine_is_netwinder() && dev->vendor == PCI_VENDOR_ID_DEC && @@ -266,119 +177,165 @@ static void __init pcibios_fixup_devices(void) pci_write_config_dword(dev, 0x40, 0x80000000); /* + * If this device is an ISA bridge, set the have_isa_bridge + * flag. We will then go looking for things like keyboard, + * etc + */ + if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA || + dev->class >> 8 == PCI_CLASS_BRIDGE_EISA) + have_isa_bridge = !0; + + /* * Set latency timer to 32, and a cache line size to 32 bytes. * Also, set system error enable, parity error enable, and * fast back to back transaction enable. Disable ROM. */ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32); pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8); - pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0); pci_read_config_word(dev, PCI_COMMAND, &cmd); cmd |= PCI_COMMAND_FAST_BACK | PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - pcibios_fixup_device(dev, &cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0); + } +} - /* - * now fixup the IRQs, if required - */ - if (pci_irq_fixup) - dev->irq = pci_irq_fixup(dev); +static u8 __init no_swizzle(struct pci_dev *dev, u8 *pin) +{ + return 0; +} - /* - * If any remaining IRQs are weird, fix it now. - */ - if (dev->irq >= NR_IRQS) - dev->irq = 0; +/* ebsa285 host-specific stuff */ +static int irqmap_ebsa285[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 }; - /* - * catch any drivers still reading this from the - * device itself. This can be removed once - * all drivers are fixed. (are there any?) - */ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } +static u8 __init ebsa285_swizzle(struct pci_dev *dev, u8 *pin) +{ + return PCI_SLOT(dev->devfn); } -/* - * Allocate resources for all PCI devices that have been enabled. - * We need to do that before we try to fix up anything. - */ -static void __init pcibios_claim_resources(void) +static int __init ebsa285_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - struct pci_dev *dev; - int idx; + return irqmap_ebsa285[(slot + pin) & 3]; +} - for (dev = pci_devices; dev; dev = dev->next) - for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) { - struct resource *a, *r = &dev->resource[idx]; - - /* - * Ignore regions that start at 0 or - * end at 0xffffffff - */ - if (!r->start || r->end == 0xffffffff) - continue; - - if (r->flags & IORESOURCE_IO) - a = &ioport_resource; - else - a = &iomem_resource; - - if (request_resource(a, r) < 0) - printk(KERN_ERR "PCI: Address space collision " - "on region %d of %s\n", - idx, dev->name); - /* We probably should disable the region, - * shouldn't we? - */ - } +static struct hw_pci ebsa285_pci __initdata = { + dc21285_init, + 0x9000, + 0x00100000, + ebsa285_swizzle, + ebsa285_map_irq +}; + +/* cats host-specific stuff */ +static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; + +static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + if (dev->irq >= 128) + return 16 + (dev->irq & 0x1f); + + if (dev->irq >= 1 && dev->irq <= 4) + return irqmap_cats[dev->irq - 1]; + + if (dev->irq != 0) + printk("PCI: device %02x:%02x has unknown irq line %x\n", + dev->bus->number, dev->devfn, dev->irq); + + return -1; } -/* - * Called after each bus is probed, but before its children - * are examined. - * - * No fixup of bus required - */ -void __init pcibios_fixup_bus(struct pci_bus *bus) +static struct hw_pci cats_pci __initdata = { + dc21285_init, + 0x9000, + 0x00100000, + no_swizzle, + cats_map_irq +}; + +/* netwinder host-specific stuff */ +static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { +#define DEV(v,d) ((v)<<16|(d)) + switch (DEV(dev->vendor, dev->device)) { + case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142): + return IRQ_NETWINDER_ETHER100; + + case DEV(PCI_VENDOR_ID_WINBOND2, 0x5a5a): + return IRQ_NETWINDER_ETHER10; + + case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553): + return 0; + + case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105): + return IRQ_ISA_HARDDISK1; + + case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000): + return IRQ_NETWINDER_VGA; + + default: + printk(KERN_ERR "PCI: %02X:%02X [%04X:%04X] unknown device\n", + dev->bus->number, dev->devfn, + dev->vendor, dev->device); + return 0; + } } +static struct hw_pci netwinder_pci __initdata = { + dc21285_init, + 0x9000, + 0x00100000, + no_swizzle, + netwinder_map_irq +}; + void __init pcibios_init(void) { - struct pci_ops *ops; + struct hw_pci *hw_pci = NULL; + + if (machine_is_ebsa285()) + hw_pci = &ebsa285_pci; + else if (machine_is_cats()) + hw_pci = &cats_pci; + else if (machine_is_netwinder()) + hw_pci = &netwinder_pci; + + if (hw_pci == NULL) + return; /* - * Pre-initialisation. Set up the host bridge. + * Set up the host bridge, and scan the bus. */ - ops = dc21285_init(0); + hw_pci->init(); - printk("PCI: Probing PCI hardware\n"); - - pci_scan_bus(0, ops, NULL); + /* + * Other architectures don't seem to do this... should we? + */ pcibios_claim_resources(); - pcibios_fixup_devices(); /* - * Now clear down any PCI error IRQs and - * register the error handler + * Assign any unassigned resources. Note that we really ought to + * have min/max stuff here - max mem address is 0x0fffffff */ - dc21285_init(1); + pci_assign_unassigned_resources(hw_pci->io_start, hw_pci->mem_start); + pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq); + pci_set_bus_ranges(); /* - * Initialise any other hardware after we've - * got the PCI bus initialised. We may need - * the PCI bus to talk to this other hardware. + * Initialise any other hardware after we've got the PCI bus + * initialised. We may need the PCI bus to talk to this other + * hardware. */ hw_init(); } char * __init pcibios_setup(char *str) { + if (!strcmp(str, "debug")) { + debug_pci = 1; + return NULL; + } return str; } diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c index 42a9a616f..2622dec25 100644 --- a/arch/arm/kernel/dec21285.c +++ b/arch/arm/kernel/dec21285.c @@ -18,11 +18,12 @@ #include <asm/irq.h> #include <asm/system.h> +#include "bios32.h" + #define MAX_SLOTS 21 extern int setup_arm_irq(int, struct irqaction *); extern void pcibios_report_device_errors(void); -extern int (*pci_irq_fixup)(struct pci_dev *dev); static unsigned long dc21285_base_address(struct pci_dev *dev, int where) @@ -202,129 +203,53 @@ static struct irqaction dc21285_error_action = { dc21285_error, SA_INTERRUPT, 0, "PCI error", NULL, NULL }; -static int irqmap_ebsa[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 }; - -static int __init ebsa_irqval(struct pci_dev *dev) -{ - u8 pin; - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - - return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3]; -} - -static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; - -static int __init cats_irqval(struct pci_dev *dev) -{ - if (dev->irq >= 128) - return 16 + (dev->irq & 0x1f); - - switch (dev->irq) { - case 1 ... 4: - return irqmap_cats[dev->irq - 1]; - - default: - printk("PCI: device %02x:%02x has unknown irq line %x\n", - dev->bus->number, dev->devfn, dev->irq); - case 0: - break; - } - return 0; -} - -static int __init netwinder_irqval(struct pci_dev *dev) -{ -#define DEV(v,d) ((v)<<16|(d)) - switch (DEV(dev->vendor, dev->device)) { - case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142): - return IRQ_NETWINDER_ETHER100; - - case DEV(PCI_VENDOR_ID_WINBOND2, 0x5a5a): - return IRQ_NETWINDER_ETHER10; - - case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553): - return 0; - - case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105): - return IRQ_ISA_HARDDISK1; - - case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000): - return IRQ_NETWINDER_VGA; - - default: - printk(KERN_ERR "PCI: %02X:%02X [%04X:%04X] unknown device\n", - dev->bus->number, dev->devfn, - dev->vendor, dev->device); - return 0; - } -} - -struct pci_ops * __init dc21285_init(int pass) +void __init dc21285_init(void) { unsigned int mem_size; unsigned long cntl; - if (pass == 0) { - mem_size = (unsigned int)high_memory - PAGE_OFFSET; - *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000; - *CSR_SDRAMBASEOFFSET = 0; - *CSR_ROMBASEMASK = 0x80000000; - *CSR_CSRBASEMASK = 0; - *CSR_CSRBASEOFFSET = 0; - *CSR_PCIADDR_EXTN = 0; + mem_size = (unsigned int)high_memory - PAGE_OFFSET; + *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000; + *CSR_SDRAMBASEOFFSET = 0; + *CSR_ROMBASEMASK = 0x80000000; + *CSR_CSRBASEMASK = 0; + *CSR_CSRBASEOFFSET = 0; + *CSR_PCIADDR_EXTN = 0; #ifdef CONFIG_HOST_FOOTBRIDGE - /* - * Map our SDRAM at a known address in PCI space, just in case - * the firmware had other ideas. Using a nonzero base is - * necessary, since some VGA cards forcefully use PCI addresses - * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards). - */ - *CSR_PCICACHELINESIZE = 0x00002008; - *CSR_PCICSRBASE = 0; - *CSR_PCICSRIOBASE = 0; - *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET); - *CSR_PCIROMBASE = 0; - *CSR_PCICMD = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK | - PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | - (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24); + /* + * Map our SDRAM at a known address in PCI space, just in case + * the firmware had other ideas. Using a nonzero base is + * necessary, since some VGA cards forcefully use PCI addresses + * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards). + */ + *CSR_PCICACHELINESIZE = 0x00002008; + *CSR_PCICSRBASE = 0; + *CSR_PCICSRIOBASE = 0; + *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET); + *CSR_PCIROMBASE = 0; + *CSR_PCICMD = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK | + PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | + (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24); #endif - printk(KERN_DEBUG"PCI: DC21285 footbridge, revision %02lX\n", - *CSR_CLASSREV & 0xff); - - switch (machine_arch_type) { - case MACH_TYPE_EBSA285: - pci_irq_fixup = ebsa_irqval; - break; - - case MACH_TYPE_CATS: - pci_irq_fixup = cats_irqval; - break; - - case MACH_TYPE_NETWINDER: - pci_irq_fixup = netwinder_irqval; - break; - } - - return &dc21285_ops; - } else { - /* - * Clear any existing errors - we aren't - * interested in historical data... - */ - cntl = *CSR_SA110_CNTL & 0xffffde07; - *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR; - cntl = *CSR_PCICMD & 0x0000ffff; - *CSR_PCICMD = cntl | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24; - - /* - * Initialise PCI error IRQ after we've finished probing - */ - setup_arm_irq(IRQ_PCI_ERR, &dc21285_error_action); - - return NULL; - } + printk(KERN_DEBUG"PCI: DC21285 footbridge, revision %02lX\n", + *CSR_CLASSREV & 0xff); + + pci_scan_bus(0, &dc21285_ops, NULL); + + /* + * Clear any existing errors - we aren't + * interested in historical data... + */ + cntl = *CSR_SA110_CNTL & 0xffffde07; + *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR; + cntl = *CSR_PCICMD & 0x0000ffff; + *CSR_PCICMD = cntl | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24; + + /* + * Initialise PCI error IRQ after we've finished probing + */ + setup_arm_irq(IRQ_PCI_ERR, &dc21285_error_action); } diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index 99b2b2b1d..c777db993 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -888,19 +888,13 @@ int get_ecard_dev_info(char *buf, char **start, off_t pos, int count, int wr) return (count > cnt) ? cnt : count; } -static struct proc_dir_entry proc_ecard_devices = { - PROC_BUS_ECARD_DEVICES, 7, "devices", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations, - get_ecard_dev_info -}; - -static struct proc_dir_entry *proc_bus_ecard_dir; +static struct proc_dir_entry *proc_bus_ecard_dir = NULL; static void ecard_proc_init(void) { proc_bus_ecard_dir = create_proc_entry("ecard", S_IFDIR, proc_bus); - proc_register(proc_bus_ecard_dir, &proc_ecard_devices); + create_proc_info_entry("devices", 0, proc_bus_ecard_dir, + get_ecard_dev_info); } /* diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index ab92aae52..3c82ee68c 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -337,3 +337,31 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) return __ret; } +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long fp, lr; + unsigned long stack_page; + int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + stack_page = 4096 + (unsigned long)p; + fp = get_css_fp(&p->thread); + do { + if (fp < stack_page || fp > 4092+stack_page) + return 0; + lr = pc_pointer (((unsigned long *)fp)[-1]); + if (lr < first_sched || lr > last_sched) + return lr; + fp = *(unsigned long *) (fp - 12); + } while (count ++ < 16); + return 0; +} diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b09b3798b..340700dbe 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -20,6 +20,7 @@ #include <linux/blk.h> #include <linux/console.h> #include <linux/init.h> +#include <linux/bootmem.h> #include <asm/elf.h> #include <asm/hardware.h> @@ -42,50 +43,74 @@ extern void reboot_setup(char *str, int *ints); extern void disable_hlt(void); - -struct drive_info_struct { char dummy[32]; } drive_info; -struct screen_info screen_info = { - orig_video_lines: 30, - orig_video_cols: 80, - orig_video_mode: 0, - orig_video_ega_bx: 0, - orig_video_isVGA: 1, - orig_video_points: 8 -}; - extern int root_mountflags; -extern int _text, _etext, _edata, _end; - -unsigned char aux_device_present; - char elf_platform[ELF_PLATFORM_SIZE]; -unsigned int elf_hwcap; +extern int _stext, _text, _etext, _edata, _end; -/* - * From head-armv.S - */ unsigned int processor_id; unsigned int __machine_arch_type; unsigned int vram_size; unsigned int system_rev; unsigned int system_serial_low; unsigned int system_serial_high; -#ifdef MULTI_CPU -struct processor processor; -#endif +unsigned int elf_hwcap; + #ifdef CONFIG_ARCH_ACORN unsigned int memc_ctrl_reg; unsigned int number_mfm_drives; #endif +struct meminfo meminfo; + +#ifdef MULTI_CPU +struct processor processor; +#endif + +struct drive_info_struct { char dummy[32]; } drive_info; + +struct screen_info screen_info = { + orig_video_lines: 30, + orig_video_cols: 80, + orig_video_mode: 0, + orig_video_ega_bx: 0, + orig_video_isVGA: 1, + orig_video_points: 8 +}; + +unsigned char aux_device_present; +char elf_platform[ELF_PLATFORM_SIZE]; +char saved_command_line[COMMAND_LINE_SIZE]; + static struct proc_info_item proc_info; +static char command_line[COMMAND_LINE_SIZE] = { 0, }; + +static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; #define ENDIANNESS ((char)endian_test.l) -/*------------------------------------------------------------------------- - * Early initialisation routines for various configurable items in the - * kernel. Each one either supplies a setup_ function, or defines this - * symbol to be empty if not configured. +/* + * Standard memory resources */ +static struct resource mem_res[] = { + { "System RAM", 0, 0, IORESOURCE_MEM | IORESOURCE_BUSY }, + { "Video RAM", 0, 0, IORESOURCE_MEM }, + { "Kernel code", 0, 0, IORESOURCE_MEM }, + { "Kernel data", 0, 0, IORESOURCE_MEM } +}; + +#define system_ram mem_res[0] +#define video_ram mem_res[1] +#define kernel_code mem_res[2] +#define kernel_data mem_res[3] + +static struct resource io_res[] = { + { "reserved", 0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY }, + { "reserved", 0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY }, + { "reserved", 0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY } +}; + +#define lp0 io_res[0] +#define lp1 io_res[1] +#define lp2 io_res[2] static void __init setup_processor(void) { @@ -124,55 +149,69 @@ static void __init setup_processor(void) cpu_proc_init(); } -static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; -static char command_line[COMMAND_LINE_SIZE] = { 0, }; - char saved_command_line[COMMAND_LINE_SIZE]; +static unsigned long __init memparse(char *ptr, char **retptr) +{ + unsigned long ret = simple_strtoul(ptr, retptr, 0); + + switch (**retptr) { + case 'M': + case 'm': + ret <<= 10; + case 'K': + case 'k': + ret <<= 10; + (*retptr)++; + default: + break; + } + return ret; +} +/* + * Initial parsing of the command line. We need to pick out the + * memory size. We look for mem=size@start, where start and size + * are "size[KkMm]" + */ static void __init -setup_mem(char *cmd_line, unsigned long *mem_sz) +parse_cmdline(char **cmdline_p, char *from) { char c = ' ', *to = command_line; - int len = 0; - - if (!*mem_sz) - *mem_sz = MEM_SIZE; + int usermem = 0, len = 0; for (;;) { - if (c == ' ') { - if (cmd_line[0] == 'm' && - cmd_line[1] == 'e' && - cmd_line[2] == 'm' && - cmd_line[3] == '=') { - *mem_sz = simple_strtoul(cmd_line+4, &cmd_line, 0); - switch(*cmd_line) { - case 'M': - case 'm': - *mem_sz <<= 10; - case 'K': - case 'k': - *mem_sz <<= 10; - cmd_line++; - } - } - /* if there are two spaces, remove one */ - if (*cmd_line == ' ') { - cmd_line++; - continue; + if (c == ' ' && !memcmp(from, "mem=", 4)) { + unsigned long size, start; + + if (to != command_line) + to -= 1; + + /* If the user specifies memory size, we + * blow away any automatically generated + * size. + */ + if (usermem == 0) { + usermem = 1; + meminfo.nr_banks = 0; } + + start = 0; + size = memparse(from + 4, &from); + if (*from == '@') + start = memparse(from + 1, &from); + + meminfo.bank[meminfo.nr_banks].start = start; + meminfo.bank[meminfo.nr_banks].size = size; + meminfo.nr_banks += 1; } - c = *cmd_line++; + c = *from++; if (!c) break; if (COMMAND_LINE_SIZE <= ++len) break; *to++ = c; } - *to = '\0'; - - /* remove trailing spaces */ - while (*--to == ' ' && to != command_line) - *to = '\0'; + *cmdline_p = command_line; } static void __init @@ -199,51 +238,90 @@ setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) static void __init setup_initrd(unsigned int start, unsigned int size) { #ifdef CONFIG_BLK_DEV_INITRD - if (start) { - initrd_start = start; - initrd_end = start + size; - } else { - initrd_start = 0; - initrd_end = 0; - } + if (start == 0) + size = 0; + initrd_start = start; + initrd_end = start + size; #endif } -static void __init check_initrd(unsigned long mem_end) +/* + * Work out our memory regions. Note that "pfn" is the physical page number + * relative to the first physical page, not the physical address itself. + */ +static void __init setup_bootmem(void) { + unsigned int end_pfn, bootmem_end; + int bank; + + /* + * Calculate the end of memory. + */ + for (bank = 0; bank < meminfo.nr_banks; bank++) { + if (meminfo.bank[bank].size) { + unsigned long end; + + end = meminfo.bank[bank].start + + meminfo.bank[bank].size; + if (meminfo.end < end) + meminfo.end = end; + } + } + + bootmem_end = __pa(PAGE_ALIGN((unsigned long)&_end)); + end_pfn = meminfo.end >> PAGE_SHIFT; + + /* + * Initialise the boot-time allocator + */ + bootmem_end += init_bootmem(bootmem_end >> PAGE_SHIFT, end_pfn); + + /* + * Register all available RAM with the bootmem allocator. + * The address is relative to the start of physical memory. + */ + for (bank = 0; bank < meminfo.nr_banks; bank ++) + free_bootmem(meminfo.bank[bank].start, meminfo.bank[bank].size); + + /* + * reserve the following regions: + * physical page 0 - it contains the exception vectors + * kernel and the bootmem structure + * swapper page directory (if any) + * initrd (if any) + */ + reserve_bootmem(0, PAGE_SIZE); +#ifdef CONFIG_CPU_32 + reserve_bootmem(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(void *)); +#endif + reserve_bootmem(__pa(&_stext), bootmem_end - __pa(&_stext)); #ifdef CONFIG_BLK_DEV_INITRD - if (initrd_end > mem_end) { + if (__pa(initrd_end) > (end_pfn << PAGE_SHIFT)) { printk ("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx) - disabling initrd\n", - initrd_end, mem_end); + "(0x%08lx > 0x%08x) - disabling initrd\n", + __pa(initrd_end), end_pfn << PAGE_SHIFT); initrd_start = 0; } + + if (initrd_start) + reserve_bootmem(__pa(initrd_start), + initrd_end - initrd_start); #endif } -/* - * Standard memory resources - */ -static struct resource system_ram = { "System RAM", 0, 0, IORESOURCE_MEM | IORESOURCE_BUSY }; -static struct resource video_ram = { "Video RAM", 0, 0, IORESOURCE_MEM }; -static struct resource kernel_code = { "Kernel code", 0, 0, IORESOURCE_MEM }; -static struct resource kernel_data = { "Kernel data", 0, 0, IORESOURCE_MEM }; -static struct resource lpt1 = { "reserved", 0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY }; -static struct resource lpt2 = { "reserved", 0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY }; -static struct resource lpt3 = { "reserved", 0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY }; - -static void __init request_standard_resources(unsigned long end) +static void __init request_standard_resources(void) { kernel_code.start = __virt_to_bus((unsigned long) &_text); kernel_code.end = __virt_to_bus((unsigned long) &_etext - 1); kernel_data.start = __virt_to_bus((unsigned long) &_etext); kernel_data.end = __virt_to_bus((unsigned long) &_edata - 1); system_ram.start = __virt_to_bus(PAGE_OFFSET); - system_ram.end = __virt_to_bus(end - 1); + system_ram.end = __virt_to_bus(meminfo.end + PAGE_OFFSET - 1); request_resource(&iomem_resource, &system_ram); request_resource(&system_ram, &kernel_code); request_resource(&system_ram, &kernel_data); + if (video_ram.start != video_ram.end) request_resource(&iomem_resource, &video_ram); @@ -253,17 +331,16 @@ static void __init request_standard_resources(unsigned long end) */ if (machine_is_ebsa110() || machine_is_riscpc() || machine_is_netwinder()) - request_resource(&ioport_resource, &lpt1); + request_resource(&ioport_resource, &lp0); if (machine_is_riscpc()) - request_resource(&ioport_resource, &lpt2); + request_resource(&ioport_resource, &lp1); if (machine_is_ebsa110() || machine_is_netwinder()) - request_resource(&ioport_resource, &lpt3); + request_resource(&ioport_resource, &lp2); } -void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p) +void __init setup_arch(char **cmdline_p) { struct param_struct *params = (struct param_struct *)PARAMS_BASE; - unsigned long memory_end = 0; char *from = default_command_line; #if defined(CONFIG_ARCH_ARC) @@ -296,10 +373,6 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne case MACH_TYPE_RISCPC: /* RiscPC can't handle half-word loads and stores */ elf_hwcap &= ~HWCAP_HALF; - { - extern void init_dram_banks(struct param_struct *); - init_dram_banks(params); - } switch (params->u1.s.pages_in_vram) { case 512: @@ -309,6 +382,17 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne default: break; } + { + int i; + + for (i = 0; i < 4; i++) { + meminfo.bank[i].start = i << 26; + meminfo.bank[i].size = + params->u1.s.pages_in_bank[i] * + params->u1.s.page_size; + } + meminfo.nr_banks = 4; + } #endif case MACH_TYPE_ARCHIMEDES: case MACH_TYPE_A5K: @@ -347,7 +431,7 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne */ reboot_setup("s", NULL); params = NULL; - ORIG_VIDEO_LINES = 25; + ORIG_VIDEO_LINES = 25; ORIG_VIDEO_POINTS = 16; ORIG_Y = 24; video_ram.start = 0x0a0000; @@ -393,7 +477,11 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne } if (params) { - memory_end = PAGE_SIZE * params->u1.s.nr_pages; + if (meminfo.nr_banks == 0) { + meminfo.nr_banks = 1; + meminfo.bank[0].start = 0; + meminfo.bank[0].size = params->u1.s.nr_pages << PAGE_SHIFT; + } ROOT_DEV = to_kdev_t(params->u1.s.rootdev); system_rev = params->u1.s.system_rev; system_serial_low = params->u1.s.system_serial_low; @@ -413,24 +501,23 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne from = params->commandline; } - /* Save unparsed command line copy for /proc/cmdline */ - memcpy(saved_command_line, from, COMMAND_LINE_SIZE); - saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; - - setup_mem(from, &memory_end); - - memory_end += PAGE_OFFSET; + if (meminfo.nr_banks == 0) { + meminfo.nr_banks = 1; + meminfo.bank[0].start = 0; + meminfo.bank[0].size = MEM_SIZE; + } - *cmdline_p = command_line; init_mm.start_code = (unsigned long) &_text; init_mm.end_code = (unsigned long) &_etext; init_mm.end_data = (unsigned long) &_edata; init_mm.brk = (unsigned long) &_end; - *memory_start_p = (unsigned long) &_end; - *memory_end_p = memory_end; - request_standard_resources(memory_end); - check_initrd(memory_end); + /* Save unparsed command line copy for /proc/cmdline */ + memcpy(saved_command_line, from, COMMAND_LINE_SIZE); + saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; + parse_cmdline(cmdline_p, from); + setup_bootmem(); + request_standard_resources(); #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 3d39c8d39..f25544c14 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -29,8 +29,6 @@ /* * Constant strings used in inlined functions in header files */ -/* proc/system.h */ -const char xchg_str[] = "xchg"; /* * sys_pipe() is the normal C calling standard for creating diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index da0d464f6..038946e9c 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -34,7 +34,10 @@ char *processor_modes[]= "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" }; -static char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; +/* proc/system.h */ +const char xchg_str[] = "xchg"; + +static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; static inline void console_verbose(void) { @@ -335,10 +338,11 @@ asmlinkage void deferred(int n, struct pt_regs *regs) } #ifdef CONFIG_DEBUG_USER - printk(KERN_ERR "[%d] %s: old system call.\n", current->pid, - current->comm); + printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", current->pid, + current->comm, n); #endif force_sig(SIGILL, current); + die_if_kernel("Oops", regs, n); } asmlinkage void arm_malalignedptr(const char *str, void *pc, volatile void *ptr) @@ -385,8 +389,37 @@ asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs } #endif +void __bug(const char *file, int line, void *data) +{ + printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line); + if (data) + printk(KERN_CRIT"extra data = %p\n", data); + *(int *)0 = 0; +} + +void __readwrite_bug(const char *fn) +{ + printk("%s called, but not implemented", fn); + *(int *)0 = 0; +} + +void __pte_error(const char *file, int line, unsigned long val) +{ + printk("%s:%d: bad pte %08lx.\n", file, line, val); +} + +void __pmd_error(const char *file, int line, unsigned long val) +{ + printk("%s:%d: bad pmd %08lx.\n", file, line, val); +} + +void __pgd_error(const char *file, int line, unsigned long val) +{ + printk("%s:%d: bad pgd %08lx.\n", file, line, val); +} + asmlinkage void __div0(void) { - printk("Awooga, division by zero in kernel.\n"); + printk("Division by zero in kernel.\n"); __backtrace(); } |