diff options
| author | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 18:24:48 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 18:24:48 -0800 |
| commit | c9df1e203d7efe8c93d3cdc04093f44f040f8e83 (patch) | |
| tree | 9bc86b9aeee5576677e5c8415ef5b757201dc2bc | |
| parent | 560e89962e32171585dd95af9ac9911ebc0e02ce (diff) | |
v2.4.4.5 -> v2.4.4.6
- Johannes Erdfelt: OHCI hash-chain corruption fix, USB updates
- Richard Henderson, Ivan Kokshaysky: alpha PCI iommu fixes
- Tim Waugh: parport changelogs and printk levels
- Andrew Morton: vmalloc off-by-one (overly sensitive) test
- Al Viro: VFS layer cleanups
- Cort Dougan: PPC updates (big bootloader re-org)
- Alan Cox: more merges, remove phillips camera conversion code
- Andrea Arkangeli: alpha fixups
- OGAWA Hirofumi: big-sector support with FAT
- Neil Brown: more md fixes
186 files changed, 5119 insertions, 4570 deletions
@@ -3025,8 +3025,8 @@ N: Jonathan Woithe E: jwoithe@physics.adelaide.edu.au W: http://www.physics.adelaide.edu.au/~jwoithe D: ALS-007 sound card extensions to Sound Blaster driver -S: 4/36 Trevelyan St -S: Wayville SA 5034 +S: 20 Jordan St +S: Valley View, SA 5093 S: Australia N: Clifford Wolf diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 239a2e02c1fc..d96aee925ea8 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -11502,6 +11502,16 @@ CONFIG_UMSDOS_FS (the one containing the directory /) cannot be a module, so saying M could be dangerous. If unsure, say N. +PReP residual data support +CONFIG_PREP_RESIDUAL + Some PReP systems have residual data passed to the kernel by the + firmware. This allows detection of memory size, devices present and + other useful pieces of information. Sometimes this information is not + present or incorrect. + + Unless you expect to boot on a PReP system, there is not need to select + yes. + /proc file system support CONFIG_PROC_FS This is a virtual file system providing information about the status @@ -13228,6 +13238,14 @@ CONFIG_MS_BUSMOUSE say M here and read Documentation/modules.txt. The module will be called msbusmouse.o. +Apple Desktop Bus support +CONFIG_ADB + Apple Desktop Bus (ADB) support is for support of devices which + are connected to the to an ADB port. ADB devices tend to have + 4 pins. If you have an Apple Macintosh prior to the iMac, or a + "Blue and White G3", you probably want to say Y here. Otherwise + say N. + Apple Desktop Bus mouse support CONFIG_ADBMOUSE Say Y here if you have this type of bus mouse (4 pin connector) as @@ -16273,22 +16291,45 @@ CONFIG_DIO Processor Type CONFIG_6xx There are four types of PowerPC chips supported. The more common - types (601, 603, 604, 740, 750), the Motorola embedded versions - (821, 823, 850, 855, 860), the IBM embedded versions (403 and + types (601, 603, 604, 740, 750, 7400), the Motorola embedded versions + (821, 823, 850, 855, 860, 8260), the IBM embedded versions (403 and 405) and the high end 64 bit Power processors (Power 3, Power 4). - Unless you are building a kernel for one of the embedded - processor systems, or a 64 bit IBM RS/6000, choose 6xx. Note that - the kernel runs in 32-bit mode even on 64-bit chips. + Unless you are building a kernel for one of the embedded processor + systems, or a 64 bit IBM RS/6000, choose 6xx. Note that the kernel + runs in 32-bit mode even on 64-bit chips. Also note that because + the 82xx family has a 603e core, specific support for that chipset + is asked later on. + +Motorola MPC8260 CPM support +CONFIG_8260 + The MPC8260 CPM (Communications Processor Module) is a typically + embedded CPU made by Motorola. Selecting this option means that + you wish to build a kernel for a machine with specifically an 8260 + for a CPU. + + If in doubt, say N. + +Workarounds for PPC601 bugs +CONFIG_PPC601_SYNC_FIX + Some versions of the PPC601 (the first PowerPC chip) have bugs which + mean that extra synchronization instructions are required near certain + instructions, typically those that make major changes to the CPU state. + These extra instructions reduce performance slightly. If you say N + here, these extra instructions will not be included, resulting in a + kernel which will run faster but may not run at all on some systems + with the PPC601 chip. + + If in doubt, say Y here. Machine Type -CONFIG_PMAC +CONFIG_ALL_PPC Linux currently supports several different kinds of PowerPC-based machines: Apple Power Macintoshes and clones (such as the Motorola Starmax series), PReP (PowerPC Reference Platform) machines such as - the Motorola PowerStack, Amiga Power-Up systems (APUS), CHRP and the - embedded MBX boards from Motorola. Currently, a single kernel binary - only supports one type or the other. However, there is very early - work on support for CHRP, PReP and PowerMac's from a single binary. + the Motorola PowerStack, CHRP (Common Hardware Reference Platform), + the embedded MBX boards from Motorola and many others. Currently, + the default option is to build a kernel which works on the first + three. Support for other machines is currently incomplete. Power management support for PowerBooks CONFIG_PMAC_PBOOK @@ -16348,6 +16389,37 @@ CONFIG_PROC_DEVICETREE an image of the device tree that the kernel copies from Open Firmware. If unsure, say Y here. +RTAS proc interface +CONFIG_PPC_RTAS + When you use this option, you will be able to use RTAS from + userspace. + + RTAS stands for RunTime Abstraction Services and should + provide a portable way to access and set system information. This is + commonly used on RS/6000 (pSeries) computers. + + You can access RTAS via the special proc filesystem entry rtas. + Don't confuse this rtas entry with the one in /proc/device-tree/rtas + which is readonly. + + If you don't know if you can use RTAS look into + /proc/device-tree/rtas. If there are some entries, it is very likely + that you will be able to use RTAS. + + You can do cool things with rtas. To print out information about + various sensors in the system, just do a + + $ cat /proc/rtas/sensors + + or if you power off your machine at night but want it running when + you enter your office at 7:45 am, do a + + # date -d 'tomorrow 7:30' +%s > /proc/rtas/poweron + + and shutdown. + + If unsure, say Y + MESH (Power Mac internal SCSI) support CONFIG_SCSI_MESH Many Power Macintoshes and clones have a MESH (Macintosh Enhanced @@ -16392,6 +16464,16 @@ CONFIG_MACE whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +Use AAUI port instead of TP by default +CONFIG_MACE_AAUI_PORT + Some Apple machines (notably the Apple Network Server) which use the + MACE ethernet chip have an Apple AUI port (small 15-pin connector), + instead of an 8-pin RJ45 connector for twisted-pair ethernet. Say + Y here if you have such a machine. If unsure, say N. + The driver will default to AAUI on ANS anyway, and if you use it as + a module, you can provide the port_aaui=0|1 to force the driver + setting. + BMAC (G3 ethernet) support CONFIG_BMAC Say Y for support of BMAC Ethernet interfaces. These are used on G3 diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 42aaa6d05a19..40bb76f62031 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -41,8 +41,9 @@ !Iinclude/linux/init.h </sect1> - <sect1><title>Atomics</title> + <sect1><title>Atomic and pointer manipulation</title> !Iinclude/asm-i386/atomic.h +!Iinclude/asm-i386/unaligned.h </sect1> <sect1><title>Delaying, scheduling, and timer routines</title> diff --git a/Documentation/fb/framebuffer.txt b/Documentation/fb/framebuffer.txt index 94da7175dbb7..b8d0b78f4a78 100644 --- a/Documentation/fb/framebuffer.txt +++ b/Documentation/fb/framebuffer.txt @@ -2,7 +2,7 @@ ----------------------- Maintained by Geert Uytterhoeven <geert@linux-m68k.org> -Last revised: January 2, 2000 +Last revised: May 10, 2001 0. Introduction @@ -296,7 +296,7 @@ under "xc/programs/Xserver/hw/xfree86/doc/modeDB.txt". For more specific information about the frame buffer device and its applications, please refer to the Linux-fbdev website: - http://www.linux-fbdev.org/ + http://linux-fbdev.sourceforge.net/ and to the following documentation: @@ -312,13 +312,13 @@ and to the following documentation: 8. Mailing list --------------- -There's a _development_ mailing list at linux-fbdev@vuser.vu.union.edu, -controlled by majordomo. Send an email with `help' in the message body to -majordomo@vuser.vu.union.edu for subscription information. +There are several frame buffer device related mailing lists at SourceForge: + - linux-fbdev-announce@lists.sourceforge.net, for announcements, + - linux-fbdev-user@lists.sourceforge.net, for generic user support, + - linux-fbdev-devel@lists.sourceforge.net, for project developers. -The mailing list is archived at - - http://www.mail-archive.com/linux-fbdev@vuser.vu.union.edu/ +Point your web browser to http://sourceforge.net/projects/linux-fbdev/ for +subscription information and archive browsing. 9. Downloading diff --git a/Documentation/s390/3270.txt b/Documentation/s390/3270.txt index 829f9092eaad..2261e3f23501 100644 --- a/Documentation/s390/3270.txt +++ b/Documentation/s390/3270.txt @@ -100,9 +100,9 @@ Here are the installation steps in detail: you will see login prompts appear on your 3270s as soon as boot is complete (or with emulated 3270s, as soon as you dial into your vm guest using the command "DIAL <vmguestname>"). - Since the line-mode major number is 212, the line to add to + Since the line-mode major number is 227, the line to add to /etc/modules.conf should be: - alias char-major-212 tub3270 + alias char-major-227 tub3270 3. Define graphic devices to your vm guest machine, if you haven't already. Define them before you reboot (reipl): @@ -175,7 +175,7 @@ Here are the testing steps in detail: C. Are the device special files created, as in installation step 2 above? Use the ls -l command to find out; for instance, issue "ls -l /dev/3270/tty620". The output should start with the - letter "c" meaning character device and should contain "212, 1" + letter "c" meaning character device and should contain "227, 1" just to the left of the device name. No such file? no "c"? Wrong major number? Wrong minor number? There's your problem! diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index 763d48cb1c94..5c53ac206f70 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -29,7 +29,8 @@ On the serial console (PC style standard serial ports only) - You send a BREAK, then within 5 seconds a command key. Sending BREAK twice is interpreted as a normal BREAK. -On Mac - Press 'Keypad+-F13-<command key>' +On PowerPC - Press 'ALT - Print Screen (or F13) - <command key>, + Print Screen (or F13) - <command key> may suffice. On other - If you know of the key combos for other architectures, please let me know so I can add them to this section. @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 5 -EXTRAVERSION =-pre5 +EXTRAVERSION =-pre6 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff --git a/arch/alpha/config.in b/arch/alpha/config.in index 74ed60ad436a..f36050a42e7a 100644 --- a/arch/alpha/config.in +++ b/arch/alpha/config.in @@ -59,7 +59,7 @@ choice 'Alpha system type' \ Wildfire CONFIG_ALPHA_WILDFIRE" Generic # clear all implied options (don't want default values for those): -unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6 CONFIG_ALPHA_EV67 +unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6 unset CONFIG_ALPHA_EISA unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS CONFIG_ALPHA_POLARIS @@ -141,12 +141,10 @@ if [ "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_EIGER" = "y" ] then define_bool CONFIG_ALPHA_EV6 y define_bool CONFIG_ALPHA_TSUNAMI y - bool 'EV67 (or later) CPU (speed > 600MHz)?' CONFIG_ALPHA_EV67 fi if [ "$CONFIG_ALPHA_WILDFIRE" = "y" -o "$CONFIG_ALPHA_TITAN" = "y" ] then define_bool CONFIG_ALPHA_EV6 y - define_bool CONFIG_ALPHA_EV67 y fi if [ "$CONFIG_ALPHA_RAWHIDE" = "y" ] then @@ -166,7 +164,6 @@ if [ "$CONFIG_ALPHA_NAUTILUS" = "y" ] then define_bool CONFIG_ALPHA_IRONGATE y define_bool CONFIG_ALPHA_EV6 y - define_bool CONFIG_ALPHA_EV67 y fi if [ "$CONFIG_ALPHA_JENSEN" = "y" -o "$CONFIG_ALPHA_MIKASA" = "y" \ @@ -209,6 +206,13 @@ then bool 'Symmetric multi-processing support' CONFIG_SMP fi +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'Discontiguous Memory Support' CONFIG_DISCONTIGMEM + if [ "$CONFIG_DISCONTIGMEM" = "y" ]; then + bool ' NUMA Support' CONFIG_NUMA + fi +fi + # The machine must be able to support more than 8GB physical memory # before large vmalloc might even pretend to be an issue. if [ "$CONFIG_ALPHA_GENERIC" = "y" -o "$CONFIG_ALPHA_DP264" = "y" \ diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index d6409ef02903..e427a26b044f 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -188,6 +188,7 @@ EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(flush_tlb_all); EXPORT_SYMBOL(flush_tlb_mm); EXPORT_SYMBOL(flush_tlb_range); +EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL(smp_imb); EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(__cpu_number_map); @@ -231,4 +232,3 @@ EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL(get_wchan); -EXPORT_SYMBOL(flush_tlb_page); diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c index e2d957c981a1..e7afaf1cd647 100644 --- a/arch/alpha/kernel/core_cia.c +++ b/arch/alpha/kernel/core_cia.c @@ -308,66 +308,29 @@ cia_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) } /* - * Fixup attempt number 1. - * - * Write zeros directly into the tag registers. + * On PYXIS, even if the tbia works, we cannot use it. It effectively locks + * the chip (as well as direct write to the tag registers) if there is a + * SG DMA operation in progress. This is true at least for PYXIS rev. 1, + * so always use the method below. */ - -static void -cia_pci_tbi_try1(struct pci_controller *hose, - dma_addr_t start, dma_addr_t end) -{ - wmb(); - *(vip)CIA_IOC_TB_TAGn(0) = 0; - *(vip)CIA_IOC_TB_TAGn(1) = 0; - *(vip)CIA_IOC_TB_TAGn(2) = 0; - *(vip)CIA_IOC_TB_TAGn(3) = 0; - *(vip)CIA_IOC_TB_TAGn(4) = 0; - *(vip)CIA_IOC_TB_TAGn(5) = 0; - *(vip)CIA_IOC_TB_TAGn(6) = 0; - *(vip)CIA_IOC_TB_TAGn(7) = 0; - mb(); - *(vip)CIA_IOC_TB_TAGn(0); -} - -#if 0 /* - * Fixup attempt number 2. This is the method NT and NetBSD use. + * This is the method NT and NetBSD use. * * Allocate mappings, and put the chip into DMA loopback mode to read a * garbage page. This works by causing TLB misses, causing old entries to * be purged to make room for the new entries coming in for the garbage page. */ -#define CIA_BROKEN_TBI_TRY2_BASE 0xE0000000 - -static void __init -cia_enable_broken_tbi_try2(void) -{ - unsigned long *ppte, pte; - long i; - - ppte = __alloc_bootmem(PAGE_SIZE, 32768, 0); - pte = (virt_to_phys(ppte) >> (PAGE_SHIFT - 1)) | 1; - - for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); ++i) - ppte[i] = pte; +#define CIA_BROKEN_TBIA_BASE 0xE0000000 +#define CIA_BROKEN_TBIA_SIZE 1024 - *(vip)CIA_IOC_PCI_W3_BASE = CIA_BROKEN_TBI_TRY2_BASE | 3; - *(vip)CIA_IOC_PCI_W3_MASK = (PAGE_SIZE - 1) & 0xfff00000; - *(vip)CIA_IOC_PCI_T3_BASE = virt_to_phys(ppte) >> 2; -} - -static void +/* Always called with interrupts disabled */ +void cia_pci_tbi_try2(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) { - unsigned long flags; unsigned long bus_addr; int ctrl; - long i; - - __save_and_cli(flags); /* Put the chip into PCI loopback mode. */ mb(); @@ -382,10 +345,19 @@ cia_pci_tbi_try2(struct pci_controller *hose, TLB entries are not quite LRU, meaning that we need to read more times than there are actual tags. The 2117x docs claim strict round-robin. Oh well, we've come this far... */ + /* Even better - as seen on the PYXIS rev 1 the TLB tags 0-3 can + be filled by the TLB misses *only once* after being invalidated + (by tbia or direct write). Next misses won't update them even + though the lock bits are cleared. Tags 4-7 are "quite LRU" though, + so use them and read at window 3 base exactly 4 times. Reading + more sometimes makes the chip crazy. -ink */ + + bus_addr = cia_ioremap(CIA_BROKEN_TBIA_BASE); - bus_addr = cia_ioremap(CIA_BROKEN_TBI_TRY2_BASE); - for (i = 0; i < 12; ++i, bus_addr += 32768) - cia_readl(bus_addr); + cia_readl(bus_addr + 0x00000); + cia_readl(bus_addr + 0x08000); + cia_readl(bus_addr + 0x10000); + cia_readl(bus_addr + 0x18000); /* Restore normal PCI operation. */ mb(); @@ -393,10 +365,26 @@ cia_pci_tbi_try2(struct pci_controller *hose, mb(); *(vip)CIA_IOC_CIA_CTRL; mb(); +} - __restore_flags(flags); +static inline void +cia_prepare_tbia_workaround(void) +{ + unsigned long *ppte, pte; + long i; + + /* Use minimal 1K map. */ + ppte = __alloc_bootmem(CIA_BROKEN_TBIA_SIZE, 32768, 0); + pte = (virt_to_phys(ppte) >> (PAGE_SHIFT - 1)) | 1; + + for (i = 0; i < CIA_BROKEN_TBIA_SIZE / sizeof(unsigned long); ++i) + ppte[i] = pte; + + *(vip)CIA_IOC_PCI_W3_BASE = CIA_BROKEN_TBIA_BASE | 3; + *(vip)CIA_IOC_PCI_W3_MASK = (CIA_BROKEN_TBIA_SIZE*1024 - 1) + & 0xfff00000; + *(vip)CIA_IOC_PCI_T3_BASE = virt_to_phys(ppte) >> 2; } -#endif static void __init verify_tb_operation(void) @@ -407,7 +395,11 @@ verify_tb_operation(void) struct pci_iommu_arena *arena = pci_isa_hose->sg_isa; int ctrl, addr0, tag0, pte0, data0; - int temp; + int temp, use_tbia_try2 = 0; + + /* pyxis -- tbia is broken */ + if (pci_isa_hose->dense_io_base) + use_tbia_try2 = 1; /* Put the chip into PCI loopback mode. */ mb(); @@ -489,22 +481,15 @@ verify_tb_operation(void) /* Third, try to invalidate the TLB. */ - cia_pci_tbi(arena->hose, 0, -1); - temp = *(vip)CIA_IOC_TB_TAGn(0); - if (temp & 1) { - cia_pci_tbi_try1(arena->hose, 0, -1); - + if (! use_tbia_try2) { + cia_pci_tbi(arena->hose, 0, -1); temp = *(vip)CIA_IOC_TB_TAGn(0); if (temp & 1) { - printk("pci: failed tbia test; " - "no usable workaround\n"); - goto failed; + use_tbia_try2 = 1; + printk("pci: failed tbia test; workaround available\n"); + } else { + printk("pci: passed tbia test\n"); } - - alpha_mv.mv_pci_tbi = cia_pci_tbi_try1; - printk("pci: failed tbia test; workaround 1 succeeded\n"); - } else { - printk("pci: passed tbia test\n"); } /* Fourth, verify the TLB snoops the EV5's caches when @@ -574,6 +559,19 @@ verify_tb_operation(void) /* Clean up after the tests. */ arena->ptes[4] = 0; arena->ptes[5] = 0; + + if (use_tbia_try2) { + alpha_mv.mv_pci_tbi = cia_pci_tbi_try2; + + /* Tags 0-3 must be disabled if we use this workaraund. */ + wmb(); + *(vip)CIA_IOC_TB_TAGn(0) = 2; + *(vip)CIA_IOC_TB_TAGn(1) = 2; + *(vip)CIA_IOC_TB_TAGn(2) = 2; + *(vip)CIA_IOC_TB_TAGn(3) = 2; + + printk("pci: tbia workaround enabled\n"); + } alpha_mv.mv_pci_tbi(arena->hose, 0, -1); exit: @@ -706,7 +704,8 @@ do_init_arch(int is_pyxis) *(vip)CIA_IOC_PCI_W2_MASK = (0x40000000 - 1) & 0xfff00000; *(vip)CIA_IOC_PCI_T2_BASE = 0x40000000 >> 2; - *(vip)CIA_IOC_PCI_W3_BASE = 0; + /* Prepare workaround for apparently broken tbia. */ + cia_prepare_tbia_workaround(); } void __init diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c index 282eb0347a17..32a1d3a2fa3c 100644 --- a/arch/alpha/kernel/core_tsunami.c +++ b/arch/alpha/kernel/core_tsunami.c @@ -11,6 +11,7 @@ #include <linux/pci.h> #include <linux/sched.h> #include <linux/init.h> +#include <linux/bootmem.h> #include <asm/ptrace.h> #include <asm/system.h> @@ -222,7 +223,6 @@ tsunami_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) it's the shifted tag bits. */ value = (start & 0xffff0000) >> 12; - wmb(); *csr = value; mb(); *csr; @@ -278,6 +278,16 @@ tsunami_probe_write(volatile unsigned long *vaddr) #define FN __FUNCTION__ static void __init +tsunami_monster_window_enable(tsunami_pchip * pchip) +{ + volatile unsigned long * csr = &pchip->pctl.csr; + + *csr |= pctl_m_mwin; + mb(); + *csr; +} + +static void __init tsunami_init_one_pchip(tsunami_pchip *pchip, int index) { struct pci_controller *hose; @@ -358,7 +368,13 @@ tsunami_init_one_pchip(tsunami_pchip *pchip, int index) * address range. */ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0); - hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x08000000, 0); + { + unsigned long size = 0x08000000; + if (max_low_pfn > (0x80000000 >> PAGE_SHIFT)) + size = 0x40000000; + hose->sg_pci = iommu_arena_new(hose, 0xc0000000, size, 0); + } + __direct_map_base = 0x40000000; __direct_map_size = 0x80000000; @@ -379,6 +395,9 @@ tsunami_init_one_pchip(tsunami_pchip *pchip, int index) pchip->tba[3].csr = virt_to_phys(hose->sg_pci->ptes); tsunami_pci_tbi(hose, 0, -1); + + /* Enable the Monster Window to make DAC pci64 possible. */ + tsunami_monster_window_enable(pchip); } void __init diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 5035d2ca38d5..8c848fbe5dbd 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -10,7 +10,7 @@ #define SIGCHLD 20 -#define NR_SYSCALLS 377 +#define NR_SYSCALLS 378 /* * These offsets must match with alpha_mv in <asm/machvec.h>. @@ -709,16 +709,14 @@ signal_return: br restore_all .end entSys -#ifdef CONFIG_SMP - .globl ret_from_smp_fork + .globl ret_from_fork .align 3 -.ent ret_from_smp_fork -ret_from_smp_fork: +.ent ret_from_fork +ret_from_fork: lda $26,ret_from_sys_call mov $17,$16 jsr $31,schedule_tail -.end ret_from_smp_fork -#endif /* CONFIG_SMP */ +.end ret_from_fork .align 3 .ent reschedule diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index 66ffe7d12e60..a63e16310252 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -175,7 +175,7 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size, int direction) /* If the machine doesn't define a pci_tbi routine, we have to assume it doesn't support sg mapping. */ if (! alpha_mv.mv_pci_tbi) { - printk(KERN_INFO "pci_map_single failed: no hw sg\n"); + printk(KERN_WARNING "pci_map_single failed: no hw sg\n"); return 0; } @@ -186,7 +186,7 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size, int direction) npages = calc_npages((paddr & ~PAGE_MASK) + size); dma_ofs = iommu_arena_alloc(arena, npages); if (dma_ofs < 0) { - printk(KERN_INFO "pci_map_single failed: " + printk(KERN_WARNING "pci_map_single failed: " "could not allocate dma page tables\n"); return 0; } @@ -215,6 +215,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size, int direction) { + unsigned long flags; struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose; struct pci_iommu_arena *arena; long dma_ofs, npages; @@ -248,6 +249,9 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size, } npages = calc_npages((dma_addr & ~PAGE_MASK) + size); + + spin_lock_irqsave(&arena->lock, flags); + iommu_arena_free(arena, dma_ofs, npages); @@ -259,6 +263,8 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size, if (dma_ofs >= arena->next_entry) alpha_mv.mv_pci_tbi(hose, dma_addr, dma_addr + size - 1); + spin_unlock_irqrestore(&arena->lock, flags); + DBGA("pci_unmap_single: sg [%x,%lx] np %ld from %p\n", dma_addr, size, npages, __builtin_return_address(0)); } @@ -410,7 +416,7 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end, /* Otherwise, break up the remaining virtually contiguous hunks into individual direct maps. */ for (sg = leader; sg < end; ++sg) - if (sg->dma_address == 2 || sg->dma_address == -2) + if (sg->dma_address == 1 || sg->dma_address == -2) sg->dma_address = 0; /* Retry. */ @@ -515,13 +521,13 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, out->dma_length = 0; if (out - start == 0) - printk(KERN_INFO "pci_map_sg failed: no entries?\n"); + printk(KERN_WARNING "pci_map_sg failed: no entries?\n"); DBGA("pci_map_sg: %ld entries\n", out - start); return out - start; error: - printk(KERN_INFO "pci_map_sg failed: " + printk(KERN_WARNING "pci_map_sg failed: " "could not allocate dma page tables\n"); /* Some allocation failed while mapping the scatterlist @@ -540,6 +546,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, int direction) { + unsigned long flags; struct pci_controller *hose; struct pci_iommu_arena *arena; struct scatterlist *end; @@ -559,6 +566,9 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, arena = hose->sg_isa; fbeg = -1, fend = 0; + + spin_lock_irqsave(&arena->lock, flags); + for (end = sg + nents; sg < end; ++sg) { unsigned long addr, size; long npages, ofs; @@ -599,6 +609,8 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, if ((fend - arena->dma_base) >> PAGE_SHIFT >= arena->next_entry) alpha_mv.mv_pci_tbi(hose, fbeg, fend); + spin_unlock_irqrestore(&arena->lock, flags); + DBGA("pci_unmap_sg: %d entries\n", nents - (end - sg)); } diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 2dd505e10bb0..8ba53c522719 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -83,10 +83,11 @@ cpu_idle(void) /* Although we are an idle CPU, we do not want to get into the scheduler unnecessarily. */ - if (current->need_resched) { - schedule(); - check_pgt_cache(); - } + long oldval = xchg(¤t->need_resched, -1UL); + if (!oldval) + while (current->need_resched < 0); + schedule(); + check_pgt_cache(); } } @@ -303,7 +304,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * regs) { extern void ret_from_sys_call(void); - extern void ret_from_smp_fork(void); + extern void ret_from_fork(void); struct pt_regs * childregs; struct switch_stack * childstack, *stack; @@ -322,11 +323,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, stack = ((struct switch_stack *) regs) - 1; childstack = ((struct switch_stack *) childregs) - 1; *childstack = *stack; -#ifdef CONFIG_SMP - childstack->r26 = (unsigned long) ret_from_smp_fork; -#else - childstack->r26 = (unsigned long) ret_from_sys_call; -#endif + childstack->r26 = (unsigned long) ret_from_fork; p->thread.usp = usp; p->thread.ksp = (unsigned long) childstack; p->thread.pal_flags = 1; /* set FEN, clear everything else */ diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 663a6613ede3..1554457af019 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -87,18 +87,6 @@ static struct alpha_machine_vector *get_sysvec(long, long, long); static struct alpha_machine_vector *get_sysvec_byname(const char *); static void get_sysnames(long, long, char **, char **); -/* - * This is setup by the secondary bootstrap loader. Because - * the zero page is zeroed out as soon as the vm system is - * initialized, we need to copy things out into a more permanent - * place. - */ -#define PARAM ZERO_PGE -#define COMMAND_LINE ((char*)(PARAM + 0x0000)) -#define COMMAND_LINE_SIZE 256 -#define INITRD_START (*(unsigned long *) (PARAM+0x100)) -#define INITRD_SIZE (*(unsigned long *) (PARAM+0x108)) - static char command_line[COMMAND_LINE_SIZE]; char saved_command_line[COMMAND_LINE_SIZE]; @@ -245,6 +233,7 @@ get_mem_size_limit(char *s) return end >> PAGE_SHIFT; /* Return the PFN of the limit. */ } +#ifndef CONFIG_DISCONTIGMEM static void __init setup_memory(void *kernel_end) { @@ -362,6 +351,7 @@ setup_memory(void *kernel_end) /* Reserve the bootmap memory. */ reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size); + printk("reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size)); #ifdef CONFIG_BLK_DEV_INITRD initrd_start = INITRD_START; @@ -383,6 +373,9 @@ setup_memory(void *kernel_end) } #endif /* CONFIG_BLK_DEV_INITRD */ } +#else +extern void setup_memory(void *); +#endif /* !CONFIG_DISCONTIGMEM */ int __init page_is_ram(unsigned long pfn) diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 4f877b10bb1a..49070ebddb6d 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -123,6 +123,22 @@ smp_setup_percpu_timer(int cpuid) cpu_data[cpuid].prof_multiplier = 1; } +static void __init +wait_boot_cpu_to_stop(int cpuid) +{ + long stop = jiffies + 10*HZ; + + while (time_before(jiffies, stop)) { + if (!smp_secondary_alive) + return; + barrier(); + } + + printk("wait_boot_cpu_to_stop: FAILED on CPU %d, hanging now\n", cpuid); + for (;;) + barrier(); +} + /* * Where secondaries begin a life of C. */ @@ -131,6 +147,11 @@ smp_callin(void) { int cpuid = hard_smp_processor_id(); + if (current != init_tasks[cpu_number_map(cpuid)]) { + printk("BUG: smp_calling: cpu %d current %p init_tasks[cpu_number_map(cpuid)] %p\n", + cpuid, current, init_tasks[cpu_number_map(cpuid)]); + } + DBGS(("CALLIN %d state 0x%lx\n", cpuid, current->state)); /* Turn on machine checks. */ @@ -154,12 +175,22 @@ smp_callin(void) /* Must have completely accurate bogos. */ __sti(); + + /* + * Wait boot CPU to stop with irq enabled before + * running calibrate_delay(). + */ + wait_boot_cpu_to_stop(cpuid); + mb(); calibrate_delay(); - smp_store_cpu_info(cpuid); - /* Allow master to continue. */ + smp_store_cpu_info(cpuid); + /* + * Allow master to continue only after we written + * the loops_per_jiffy. + */ wmb(); - smp_secondary_alive = cpuid; + smp_secondary_alive = 1; /* Wait for the go code. */ while (!smp_threads_ready) @@ -203,6 +234,7 @@ smp_tune_scheduling (void) break; case EV6_CPU: + case EV67_CPU: on_chip_cache = 64 + 64; break; @@ -246,7 +278,7 @@ send_secondary_console_msg(char *str, int cpuid) + hwrpb->processor_offset + cpuid * hwrpb->processor_size); - cpumask = (1L << cpuid); + cpumask = (1UL << cpuid); if (hwrpb->txrdy & cpumask) goto delay1; ready1: @@ -267,8 +299,8 @@ send_secondary_console_msg(char *str, int cpuid) return; delay1: - /* Wait one second. Note that jiffies aren't ticking yet. */ - for (timeout = 100000; timeout > 0; --timeout) { + /* Wait 10 seconds. Note that jiffies aren't ticking yet. */ + for (timeout = 1000000; timeout > 0; --timeout) { if (!(hwrpb->txrdy & cpumask)) goto ready1; udelay(10); @@ -277,8 +309,8 @@ delay1: goto timeout; delay2: - /* Wait one second. */ - for (timeout = 100000; timeout > 0; --timeout) { + /* Wait 10 seconds. */ + for (timeout = 1000000; timeout > 0; --timeout) { if (!(hwrpb->txrdy & cpumask)) goto ready2; udelay(10); @@ -307,7 +339,7 @@ recv_secondary_console_msg(void) mycpu = hard_smp_processor_id(); for (i = 0; i < NR_CPUS; i++) { - if (!(txrdy & (1L << i))) + if (!(txrdy & (1UL << i))) continue; DBGS(("recv_secondary_console_msg: " @@ -375,7 +407,7 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) #if 0 DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n", - hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwcpb->unique)); + hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwpcb->unique)); #endif DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n", cpuid, idle->state, idle->thread.pal_flags)); @@ -398,9 +430,9 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) send_secondary_console_msg("START\r\n", cpuid); - /* Wait 1 second for an ACK from the console. Note that jiffies + /* Wait 10 seconds for an ACK from the console. Note that jiffies aren't ticking yet. */ - for (timeout = 100000; timeout > 0; timeout--) { + for (timeout = 1000000; timeout > 0; timeout--) { if (cpu->flags & 1) goto started; udelay(10); @@ -447,6 +479,8 @@ smp_boot_one_cpu(int cpuid, int cpunum) idle = init_task.prev_task; if (!idle) panic("No idle process for CPU %d", cpuid); + if (idle == &init_task) + panic("idle process is init_task for CPU %d", cpuid); idle->processor = cpuid; __cpu_logical_map[cpunum] = cpuid; @@ -468,10 +502,14 @@ smp_boot_one_cpu(int cpuid, int cpunum) if (secondary_cpu_start(cpuid, idle)) return -1; + mb(); + /* Notify the secondary CPU it can run calibrate_delay() */ + smp_secondary_alive = 0; + /* We've been acked by the console; wait one second for the task to start up for real. Note that jiffies aren't ticking yet. */ - for (timeout = 0; timeout < 100000; timeout++) { - if (smp_secondary_alive != -1) + for (timeout = 0; timeout < 1000000; timeout++) { + if (smp_secondary_alive == 1) goto alive; udelay(10); barrier(); @@ -523,7 +561,7 @@ setup_smp(void) if ((cpu->flags & 0x1cc) == 0x1cc) { smp_num_probed++; /* Assume here that "whami" == index */ - hwrpb_cpu_present_mask |= (1L << i); + hwrpb_cpu_present_mask |= (1UL << i); cpu->pal_revision = boot_cpu_palrev; } @@ -534,9 +572,9 @@ setup_smp(void) } } else { smp_num_probed = 1; - hwrpb_cpu_present_mask = (1L << boot_cpuid); + hwrpb_cpu_present_mask = (1UL << boot_cpuid); } - cpu_present_mask = 1L << boot_cpuid; + cpu_present_mask = 1UL << boot_cpuid; printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n", smp_num_probed, hwrpb_cpu_present_mask); @@ -589,7 +627,7 @@ smp_boot_cpus(void) if (smp_boot_one_cpu(i, cpu_count)) continue; - cpu_present_mask |= 1L << i; + cpu_present_mask |= 1UL << i; cpu_count++; } @@ -600,7 +638,7 @@ smp_boot_cpus(void) bogosum = 0; for (i = 0; i < NR_CPUS; i++) { - if (cpu_present_mask & (1L << i)) + if (cpu_present_mask & (1UL << i)) bogosum += cpu_data[i].loops_per_jiffy; } printk(KERN_INFO "SMP: Total of %d processors activated " @@ -798,13 +836,13 @@ smp_send_reschedule(int cpu) printk(KERN_WARNING "smp_send_reschedule: Sending IPI to self.\n"); #endif - send_ipi_message(1L << cpu, IPI_RESCHEDULE); + send_ipi_message(1UL << cpu, IPI_RESCHEDULE); } void smp_send_stop(void) { - unsigned long to_whom = cpu_present_mask ^ (1L << smp_processor_id()); + unsigned long to_whom = cpu_present_mask ^ (1UL << smp_processor_id()); #if DEBUG_IPI_MSG if (hard_smp_processor_id() != boot_cpu_id) printk(KERN_WARNING "smp_send_stop: Not on boot cpu.\n"); @@ -827,7 +865,7 @@ smp_send_stop(void) int smp_call_function (void (*func) (void *info), void *info, int retry, int wait) { - unsigned long to_whom = cpu_present_mask ^ (1L << smp_processor_id()); + unsigned long to_whom = cpu_present_mask ^ (1UL << smp_processor_id()); struct smp_call_struct data; long timeout; @@ -1060,7 +1098,7 @@ debug_spin_lock(spinlock_t * lock, const char *base_file, int line_no) int printed = 0; int cpu = smp_processor_id(); - stuck = 1L << 28; + stuck = 1L << 30; try_again: /* Use sub-sections to put the actual loop at the end @@ -1137,8 +1175,8 @@ void write_lock(rwlock_t * lock) try_again: - stuck_lock = 1<<26; - stuck_reader = 1<<26; + stuck_lock = 1<<30; + stuck_reader = 1<<30; __asm__ __volatile__( "1: ldl_l %1,%0\n" @@ -1182,7 +1220,7 @@ void read_lock(rwlock_t * lock) try_again: - stuck_lock = 1<<26; + stuck_lock = 1<<30; __asm__ __volatile__( "1: ldl_l %1,%0;" diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index ed7d2f68e1a6..ad3feb7b04fc 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -291,12 +291,40 @@ dik_show_trace(unsigned long *sp) * is interesting. */ printk("%6x%c", (int)tmp & 0xffffff, (++i % 11) ? ' ' : '\n'); +#if 0 if (i > 40) { printk(" ..."); break; } +#endif + } + printk("\n"); +} + +int kstack_depth_to_print = 24; + +void show_stack(unsigned long *sp) +{ + unsigned long *stack; + int i; + + /* + * debugging aid: "show_stack(NULL);" prints the + * back trace for this cpu. + */ + if(sp==NULL) + sp=(unsigned long*)&sp; + + stack = sp; + for(i=0; i < kstack_depth_to_print; i++) { + if (((long) stack & (THREAD_SIZE-1)) == 0) + break; + if (i && ((i % 4) == 0)) + printk("\n "); + printk("%016lx ", *stack++); } printk("\n"); + dik_show_trace(sp); } void diff --git a/arch/alpha/mm/Makefile b/arch/alpha/mm/Makefile index d9614a7c5067..109c4cf1d1b8 100644 --- a/arch/alpha/mm/Makefile +++ b/arch/alpha/mm/Makefile @@ -7,9 +7,10 @@ # # Note 2! The CFLAGS definition is now in the main makefile... -OBJS = init.o fault.o extable.o +O_TARGET := mm.o -mm.o: $(OBJS) - $(LD) -r -o mm.o $(OBJS) +obj-y := init.o fault.o extable.o + +obj-$(CONFIG_DISCONTIGMEM) += numa.o include $(TOPDIR)/Rules.make diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index 5390bd4ec4ba..98435ea3ef09 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c @@ -45,20 +45,26 @@ search_exception_table_without_gp(unsigned long addr) /* There is only the kernel to search. */ ret = search_one_table(__start___ex_table, __stop___ex_table - 1, addr - gp); - if (ret) return ret; #else + extern spinlock_t modlist_lock; + unsigned long flags; /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; + + ret = 0; + spin_lock_irqsave(&modlist_lock, flags); for (mp = module_list; mp ; mp = mp->next) { - if (!mp->ex_table_start) + if (!mp->ex_table_start || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING))) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr - mp->gp); - if (ret) return ret; + if (ret) + break; } + spin_unlock_irqrestore(&modlist_lock, flags); #endif - return 0; + return ret; } unsigned @@ -71,15 +77,23 @@ search_exception_table(unsigned long addr, unsigned long exc_gp) addr - exc_gp); if (ret) return ret; #else + extern spinlock_t modlist_lock; + unsigned long flags; /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; + + ret = 0; + spin_lock_irqsave(&modlist_lock, flags); for (mp = module_list; mp ; mp = mp->next) { - if (!mp->ex_table_start) + if (!mp->ex_table_start || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING))) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr - exc_gp); - if (ret) return ret; + if (ret) + break; } + spin_unlock_irqrestore(&modlist_lock, flags); + if (ret) return ret; #endif /* diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index eb8ab75e2a1f..421df1c2eef0 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -33,7 +33,7 @@ #include <asm/mmu_context.h> #include <asm/console.h> -static unsigned long totalram_pages; +unsigned long totalram_pages; extern void die_if_kernel(char *,struct pt_regs *,long); @@ -115,6 +115,7 @@ __bad_page(void) return pte_mkdirty(mk_pte(virt_to_page(EMPTY_PGE), PAGE_SHARED)); } +#ifndef CONFIG_DISCONTIGMEM void show_mem(void) { @@ -144,6 +145,7 @@ show_mem(void) printk("%ld pages in page table cache\n",pgtable_cache_size); show_buffers(); } +#endif static inline unsigned long load_PCB(struct thread_struct * pcb) @@ -275,6 +277,7 @@ callback_init(void * kernel_end) } +#ifndef CONFIG_DISCONTIGMEM /* * paging_init() sets up the memory map. */ @@ -287,16 +290,7 @@ paging_init(void) dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; high_pfn = max_low_pfn; -#define ORDER_MASK (~((1L << (MAX_ORDER-1))-1)) -#define ORDER_ALIGN(n) (((n) + ~ORDER_MASK) & ORDER_MASK) - - dma_pfn = ORDER_ALIGN(dma_pfn); - high_pfn = ORDER_ALIGN(high_pfn); - -#undef ORDER_MASK -#undef ORDER_ALIGN - - if (dma_pfn > high_pfn) + if (dma_pfn >= high_pfn) zones_size[ZONE_DMA] = high_pfn; else { zones_size[ZONE_DMA] = dma_pfn; @@ -309,6 +303,7 @@ paging_init(void) /* Initialize the kernel's ZERO_PGE. */ memset((void *)ZERO_PGE, 0, PAGE_SIZE); } +#endif /* CONFIG_DISCONTIGMEM */ #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM) void @@ -327,6 +322,7 @@ srm_paging_stop (void) } #endif +#ifndef CONFIG_DISCONTIGMEM static void __init printk_memory_info(void) { @@ -366,6 +362,7 @@ mem_init(void) printk_memory_info(); } +#endif /* CONFIG_DISCONTIGMEM */ void free_initmem (void) @@ -388,13 +385,14 @@ free_initmem (void) void free_initrd_mem(unsigned long start, unsigned long end) { + unsigned long __start = start; for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; } - printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); + printk ("Freeing initrd memory: %ldk freed\n", (end - __start) >> 10); } #endif diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c new file mode 100644 index 000000000000..e1aa359050cd --- /dev/null +++ b/arch/alpha/mm/numa.c @@ -0,0 +1,430 @@ +/* + * linux/arch/alpha/mm/numa.c + * + * DISCONTIGMEM NUMA alpha support. + * + * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE + */ + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/bootmem.h> +#include <linux/swap.h> +#ifdef CONFIG_BLK_DEV_INITRD +#include <linux/blk.h> +#endif + +#include <asm/hwrpb.h> +#include <asm/pgalloc.h> + +plat_pg_data_t *plat_node_data[MAX_NUMNODES]; +bootmem_data_t plat_node_bdata[MAX_NUMNODES]; + +#undef DEBUG_DISCONTIG +#ifdef DEBUG_DISCONTIG +#define DBGDCONT(args...) printk(args) +#else +#define DBGDCONT(args...) +#endif + +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) +#define PFN_PHYS(x) ((x) << PAGE_SHIFT) +#define for_each_mem_cluster(memdesc, cluster, i) \ + for ((cluster) = (memdesc)->cluster, (i) = 0; \ + (i) < (memdesc)->numclusters; (i)++, (cluster)++) + +static void __init show_mem_layout(void) +{ + struct memclust_struct * cluster; + struct memdesc_struct * memdesc; + int i; + + /* Find free clusters, and init and free the bootmem accordingly. */ + memdesc = (struct memdesc_struct *) + (hwrpb->mddt_offset + (unsigned long) hwrpb); + + printk("Raw memory layout:\n"); + for_each_mem_cluster(memdesc, cluster, i) { + printk(" memcluster %2d, usage %1lx, start %8lu, end %8lu\n", + i, cluster->usage, cluster->start_pfn, + cluster->start_pfn + cluster->numpages); + } +} + +static void __init +setup_memory_node(int nid, void *kernel_end) +{ + extern unsigned long mem_size_limit; + struct memclust_struct * cluster; + struct memdesc_struct * memdesc; + unsigned long start_kernel_pfn, end_kernel_pfn; + unsigned long bootmap_size, bootmap_pages, bootmap_start; + unsigned long start, end; + unsigned long node_pfn_start, node_pfn_end; + int i; + unsigned long node_datasz = PFN_UP(sizeof(plat_pg_data_t)); + int show_init = 0; + + /* Find the bounds of current node */ + node_pfn_start = (nid * NODE_MAX_MEM_SIZE) >> PAGE_SHIFT; + node_pfn_end = node_pfn_start + (NODE_MAX_MEM_SIZE >> PAGE_SHIFT); + + /* Find free clusters, and init and free the bootmem accordingly. */ + memdesc = (struct memdesc_struct *) + (hwrpb->mddt_offset + (unsigned long) hwrpb); + + /* find the bounds of this node (min_low_pfn/max_low_pfn) */ + min_low_pfn = ~0UL; + for_each_mem_cluster(memdesc, cluster, i) { + /* Bit 0 is console/PALcode reserved. Bit 1 is + non-volatile memory -- we might want to mark + this for later. */ + if (cluster->usage & 3) + continue; + + start = cluster->start_pfn; + end = start + cluster->numpages; + + if (start >= node_pfn_end || end <= node_pfn_start) + continue; + + if (!show_init) { + show_init = 1; + printk("Initialing bootmem allocator on Node ID %d\n", nid); + } + printk(" memcluster %2d, usage %1lx, start %8lu, end %8lu\n", + i, cluster->usage, cluster->start_pfn, + cluster->start_pfn + cluster->numpages); + + if (start < node_pfn_start) + start = node_pfn_start; + if (end > node_pfn_end) + end = node_pfn_end; + + if (start < min_low_pfn) + min_low_pfn = start; + if (end > max_low_pfn) + max_low_pfn = end; + } + + if (mem_size_limit && max_low_pfn >= mem_size_limit) { + printk("setup: forcing memory size to %ldK (from %ldK).\n", + mem_size_limit << (PAGE_SHIFT - 10), + max_low_pfn << (PAGE_SHIFT - 10)); + max_low_pfn = mem_size_limit; + } + + if (min_low_pfn >= max_low_pfn) + return; + + num_physpages += max_low_pfn - min_low_pfn; + + /* Cute trick to make sure our local node data is on local memory */ + PLAT_NODE_DATA(nid) = (plat_pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT)); + /* Quasi-mark the plat_pg_data_t as in-use */ + min_low_pfn += node_datasz; + if (min_low_pfn >= max_low_pfn) { + printk(" not enough mem to reserve PLAT_NODE_DATA"); + return; + } + NODE_DATA(nid)->bdata = &plat_node_bdata[nid]; + + printk(" Detected node memory: start %8lu, end %8lu\n", + min_low_pfn, max_low_pfn); + + DBGDCONT(" DISCONTIG: plat_node_data[%d] is at 0x%p\n", nid, PLAT_NODE_DATA(nid)); + DBGDCONT(" DISCONTIG: NODE_DATA(%d)->bdata is at 0x%p\n", nid, NODE_DATA(nid)->bdata); + + /* Find the bounds of kernel memory. */ + start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS); + end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end)); + bootmap_start = -1; + + if (!nid && (max_low_pfn < end_kernel_pfn || min_low_pfn > start_kernel_pfn)) + panic("kernel loaded out of ram"); + + /* Zone start phys-addr must be 2^(MAX_ORDER-1) aligned */ + min_low_pfn = (min_low_pfn + ((1UL << (MAX_ORDER-1))-1)) & ~((1UL << (MAX_ORDER-1))-1); + + /* We need to know how many physically contiguous pages + we'll need for the bootmap. */ + bootmap_pages = bootmem_bootmap_pages(max_low_pfn-min_low_pfn); + + /* Now find a good region where to allocate the bootmap. */ + for_each_mem_cluster(memdesc, cluster, i) { + if (cluster->usage & 3) + continue; + + start = cluster->start_pfn; + end = start + cluster->numpages; + + if (start >= max_low_pfn || end <= min_low_pfn) + continue; + + if (end > max_low_pfn) + end = max_low_pfn; + if (start < min_low_pfn) + start = min_low_pfn; + + if (start < start_kernel_pfn) { + if (end > end_kernel_pfn + && end - end_kernel_pfn >= bootmap_pages) { + bootmap_start = end_kernel_pfn; + break; + } else if (end > start_kernel_pfn) + end = start_kernel_pfn; + } else if (start < end_kernel_pfn) + start = end_kernel_pfn; + if (end - start >= bootmap_pages) { + bootmap_start = start; + break; + } + } + + if (bootmap_start == -1) + panic("couldn't find a contigous place for the bootmap"); + + /* Allocate the bootmap and mark the whole MM as reserved. */ + bootmap_size = init_bootmem_node(NODE_DATA(nid), bootmap_start, + min_low_pfn, max_low_pfn); + DBGDCONT(" bootmap_start %lu, bootmap_size %lu, bootmap_pages %lu\n", + bootmap_start, bootmap_size, bootmap_pages); + + /* Mark the free regions. */ + for_each_mem_cluster(memdesc, cluster, i) { + if (cluster->usage & 3) + continue; + + start = cluster->start_pfn; + end = cluster->start_pfn + cluster->numpages; + + if (start >= max_low_pfn || end <= min_low_pfn) + continue; + + if (end > max_low_pfn) + end = max_low_pfn; + if (start < min_low_pfn) + start = min_low_pfn; + + if (start < start_kernel_pfn) { + if (end > end_kernel_pfn) { + free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start), + (PFN_PHYS(start_kernel_pfn) + - PFN_PHYS(start))); + printk(" freeing pages %ld:%ld\n", + start, start_kernel_pfn); + start = end_kernel_pfn; + } else if (end > start_kernel_pfn) + end = start_kernel_pfn; + } else if (start < end_kernel_pfn) + start = end_kernel_pfn; + if (start >= end) + continue; + + free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start)); + printk(" freeing pages %ld:%ld\n", start, end); + } + + /* Reserve the bootmap memory. */ + reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(bootmap_start), bootmap_size); + printk(" reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size)); + + numnodes++; +} + +void __init +setup_memory(void *kernel_end) +{ + int nid; + + show_mem_layout(); + + numnodes = 0; + for (nid = 0; nid < MAX_NUMNODES; nid++) + setup_memory_node(nid, kernel_end); + +#ifdef CONFIG_BLK_DEV_INITRD + initrd_start = INITRD_START; + if (initrd_start) { + initrd_end = initrd_start+INITRD_SIZE; + printk("Initial ramdisk at: 0x%p (%lu bytes)\n", + (void *) initrd_start, INITRD_SIZE); + + if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) { + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%p)\ndisabling initrd\n", + initrd_end, + phys_to_virt(PFN_PHYS(max_low_pfn))); + initrd_start = initrd_end = 0; + } else { + /* Assume the initrd to be in the first node */ + reserve_bootmem_node(NODE_DATA(nid), virt_to_phys((void *)initrd_start), + INITRD_SIZE); + } + } +#endif /* CONFIG_BLK_DEV_INITRD */ +} + +void __init paging_init(void) +{ + unsigned int nid; + unsigned long zones_size[MAX_NR_ZONES] = {0, }; + unsigned long dma_local_pfn; + + /* + * The old global MAX_DMA_ADDRESS per-arch API doesn't fit + * in the NUMA model, for now we convert it to a pfn and + * we interpret this pfn as a local per-node information. + * This issue isn't very important since none of these machines + * have legacy ISA slots anyways. + */ + dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; + + for (nid = 0; nid < numnodes; nid++) { + unsigned long start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT; + unsigned long end_pfn = plat_node_bdata[nid].node_low_pfn; + unsigned long lmax_mapnr; + + if (dma_local_pfn >= end_pfn - start_pfn) + zones_size[ZONE_DMA] = end_pfn - start_pfn; + else { + zones_size[ZONE_DMA] = dma_local_pfn; + zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn; + } + free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn<<PAGE_SHIFT, NULL); + lmax_mapnr = PLAT_NODE_DATA_STARTNR(nid) + PLAT_NODE_DATA_SIZE(nid); + if (lmax_mapnr > max_mapnr) { + max_mapnr = lmax_mapnr; + DBGDCONT("Grow max_mapnr to %ld\n", max_mapnr); + } + } + + /* Initialize the kernel's ZERO_PGE. */ + memset((void *)ZERO_PGE, 0, PAGE_SIZE); +} + +#define printkdot() \ +do { \ + if (!(i++ % ((100UL*1024*1024)>>PAGE_SHIFT))) \ + printk("."); \ +} while(0) + +#define clobber(p, size) memset((p)->virtual, 0xaa, (size)) + +void __init mem_stress(void) +{ + LIST_HEAD(x); + LIST_HEAD(xx); + struct page * p; + unsigned long i = 0; + + printk("starting memstress"); + while ((p = alloc_pages(GFP_ATOMIC, 1))) { + clobber(p, PAGE_SIZE*2); + list_add(&p->list, &x); + printkdot(); + } + while ((p = alloc_page(GFP_ATOMIC))) { + clobber(p, PAGE_SIZE); + list_add(&p->list, &xx); + printkdot(); + } + while (!list_empty(&x)) { + p = list_entry(x.next, struct page, list); + clobber(p, PAGE_SIZE*2); + list_del(x.next); + __free_pages(p, 1); + printkdot(); + } + while (!list_empty(&xx)) { + p = list_entry(xx.next, struct page, list); + clobber(p, PAGE_SIZE); + list_del(xx.next); + __free_pages(p, 0); + printkdot(); + } + printk("I'm still alive duh!\n"); +} + +#undef printkdot +#undef clobber + +void __init mem_init(void) +{ + unsigned long codesize, reservedpages, datasize, initsize, pfn; + extern int page_is_ram(unsigned long) __init; + extern char _text, _etext, _data, _edata; + extern char __init_begin, __init_end; + extern unsigned long totalram_pages; + unsigned long nid, i; + mem_map_t * lmem_map; + + high_memory = (void *) __va(max_mapnr <<PAGE_SHIFT); + + reservedpages = 0; + for (nid = 0; nid < numnodes; nid++) { + /* + * This will free up the bootmem, ie, slot 0 memory + */ + totalram_pages += free_all_bootmem_node(NODE_DATA(nid)); + + lmem_map = NODE_MEM_MAP(nid); + pfn = NODE_DATA(nid)->node_start_paddr >> PAGE_SHIFT; + for (i = 0; i < PLAT_NODE_DATA_SIZE(nid); i++, pfn++) + if (page_is_ram(pfn) && PageReserved(lmem_map+i)) + reservedpages++; + } + + codesize = (unsigned long) &_etext - (unsigned long) &_text; + datasize = (unsigned long) &_edata - (unsigned long) &_data; + initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + + printk("Memory: %luk/%luk available (%luk kernel code, %luk reserved, " + "%luk data, %luk init)\n", + nr_free_pages() << (PAGE_SHIFT-10), + num_physpages << (PAGE_SHIFT-10), + codesize >> 10, + reservedpages << (PAGE_SHIFT-10), + datasize >> 10, + initsize >> 10); +#if 0 + mem_stress(); +#endif +} + +void +show_mem(void) +{ + long i,free = 0,total = 0,reserved = 0; + long shared = 0, cached = 0; + int nid; + + printk("\nMem-info:\n"); + show_free_areas(); + printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + for (nid = 0; nid < numnodes; nid++) { + mem_map_t * lmem_map = NODE_MEM_MAP(nid); + i = PLAT_NODE_DATA_SIZE(nid); + while (i-- > 0) { + total++; + if (PageReserved(lmem_map+i)) + reserved++; + else if (PageSwapCache(lmem_map+i)) + cached++; + else if (!page_count(lmem_map+i)) + free++; + else + shared += atomic_read(&lmem_map[i].count) - 1; + } + } + printk("%ld pages of RAM\n",total); + printk("%ld free pages\n",free); + printk("%ld reserved pages\n",reserved); + printk("%ld pages shared\n",shared); + printk("%ld pages swap cached\n",cached); + printk("%ld pages in page table cache\n",pgtable_cache_size); + show_buffers(); +} diff --git a/arch/i386/config.in b/arch/i386/config.in index dbc054855acd..a6b167b17b31 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -33,7 +33,7 @@ choice 'Processor family' \ Pentium-Classic CONFIG_M586TSC \ Pentium-MMX CONFIG_M586MMX \ Pentium-Pro/Celeron/Pentium-II CONFIG_M686 \ - Pentium-III/Celeron-Coppermine CONFIG_MPENTIUMIII \ + Pentium-III/Celeron(Coppermine) CONFIG_MPENTIUMIII \ Pentium-4 CONFIG_MPENTIUM4 \ K6/K6-II/K6-III CONFIG_MK6 \ Athlon/Duron/K7 CONFIG_MK7 \ diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c index 102d7e6f9d44..fa815a804220 100644 --- a/arch/i386/kernel/mtrr.c +++ b/arch/i386/kernel/mtrr.c @@ -1997,47 +1997,40 @@ static void __init cyrix_arr_init(void) if ( ccrc[6] ) printk ("mtrr: ARR3 was write protected, unprotected\n"); } /* End Function cyrix_arr_init */ -static void __init centaur_mcr_init(void) +/* + * Initialise the later (saner) Winchip MCR variant. In this version + * the BIOS can pass us the registers it has used (but not their values) + * and the control register is read/write + */ + +static void __init centaur_mcr1_init(void) { unsigned i; - struct set_mtrr_context ctxt; u32 lo, hi; - int wc2 = -1; - set_mtrr_prepare (&ctxt); /* Unfortunately, MCR's are read-only, so there is no way to * find out what the bios might have done. */ - /* - * Enable MCR key if we are using a winchip2 - */ - - if(boot_cpu_data.x86_model==4) - wc2 = 0; - - if(boot_cpu_data.x86_model==8 || boot_cpu_data.x86_model == 9) + rdmsr(0x120, lo, hi); + if(((lo>>17)&7)==1) /* Type 1 Winchip2 MCR */ { - rdmsr(0x120, lo, hi); - if(((lo>>17)&7)==1) /* Type 1 Winchip2 MCR */ - { - lo&= ~0x1C0; /* clear key */ - lo|= 0x040; /* set key to 1 */ - wrmsr(0x120, lo, hi); /* unlock MCR */ - wc2 = 1; - centaur_mcr_type = 1; - } + lo&= ~0x1C0; /* clear key */ + lo|= 0x040; /* set key to 1 */ + wrmsr(0x120, lo, hi); /* unlock MCR */ } - /* Clear any unconfigured MCR's. - * This way we are sure that the centaur_mcr array contains the actual - * values. The disadvantage is that any BIOS tweaks are thus undone. - * + + centaur_mcr_type = 1; + + /* + * Clear any unconfigured MCR's. */ + for (i = 0; i < 8; ++i) { if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0) { - if(wc2 == 0 || ( wc2 == 1 && !(lo & (1<<(9+i))))) + if(!(lo & (1<<(9+i)))) wrmsr (0x110 + i , 0, 0); else /* @@ -2047,18 +2040,58 @@ static void __init centaur_mcr_init(void) centaur_mcr_reserved |= (1<<i); } } - /* Throw the main write-combining switch... - However if OOSTORE is enabled then people have already done far - cleverer things and we should behave. + /* + * Throw the main write-combining switch... + * However if OOSTORE is enabled then people have already done far + * cleverer things and we should behave. */ - if(wc2 == 1) - { - lo |= 15; /* Write combine enables */ - wrmsr(0x120, lo, hi); + lo |= 15; /* Write combine enables */ + wrmsr(0x120, lo, hi); +} /* End Function centaur_mcr1_init */ + +/* + * Initialise the original winchip with read only MCR registers + * no used bitmask for the BIOS to pass on and write only control + */ + +static void __init centaur_mcr0_init(void) +{ + unsigned i; + + /* Unfortunately, MCR's are read-only, so there is no way to + * find out what the bios might have done. + */ + + /* Clear any unconfigured MCR's. + * This way we are sure that the centaur_mcr array contains the actual + * values. The disadvantage is that any BIOS tweaks are thus undone. + * + */ + for (i = 0; i < 8; ++i) + { + if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0) + wrmsr (0x110 + i , 0, 0); } - else if(wc2 == 0) - wrmsr(0x120, 0x01F0001F, 0); /* Write only */ + + wrmsr(0x120, 0x01F0001F, 0); /* Write only */ +} /* End Function centaur_mcr0_init */ + +/* + * Initialise Winchip series MCR registers + */ + +static void __init centaur_mcr_init(void) +{ + struct set_mtrr_context ctxt; + + set_mtrr_prepare (&ctxt); + + if(boot_cpu_data.x86_model==4) + centaur_mcr0_init(); + else if(boot_cpu_data.x86_model==8 || boot_cpu_data.x86_model == 9) + centaur_mcr1_init(); + set_mtrr_done (&ctxt); } /* End Function centaur_mcr_init */ diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index 595c2226c902..328d247ce702 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -67,10 +67,6 @@ CORE_FILES += arch/ppc/xmon/x.o endif MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot -MAKECOFFBOOT = $(MAKE) -C arch/$(ARCH)/coffboot -MAKECHRPBOOT = $(MAKE) -C arch/$(ARCH)/chrpboot -MAKEMBXBOOT = $(MAKE) -C arch/$(ARCH)/mbxboot -MAKETREEBOOT = $(MAKE) -C arch/$(ARCH)/treeboot ifdef CONFIG_8xx SUBDIRS += arch/ppc/8xx_io @@ -91,57 +87,10 @@ endif checks: @$(MAKE) -C arch/$(ARCH)/kernel checks -BOOT_TARGETS = zImage znetboot.initrd zImage.initrd +BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd -ifdef CONFIG_4xx -$(BOOT_TARGETS): $(CHECKS) vmlinux - @$(MAKETREEBOOT) $@ -endif - -ifdef CONFIG_8xx -$(BOOT_TARGETS): $(CHECKS) vmlinux - @$(MAKECOFFBOOT) $@ - @$(MAKEMBXBOOT) $@ -endif - -ifdef CONFIG_6xx -ifndef CONFIG_8260 -$(BOOT_TARGETS): $(CHECKS) vmlinux - @$(MAKECOFFBOOT) $@ - @$(MAKEBOOT) $@ - @$(MAKECHRPBOOT) $@ - -znetboot: $(CHECKS) vmlinux -ifdef CONFIG_ALL_PPC -ifdef CONFIG_SMP - cp -f vmlinux /tftpboot/vmlinux.smp -else - cp -f vmlinux /tftpboot/vmlinux -endif -endif - @$(MAKECOFFBOOT) $@ - @$(MAKEBOOT) $@ - @$(MAKECHRPBOOT) $@ -else -# 8260 is custom 6xx -$(BOOT_TARGETS): $(CHECKS) vmlinux - @$(MAKECOFFBOOT) $@ - @$(MAKEMBXBOOT) $@ -endif -endif - -ifdef CONFIG_PPC64BRIDGE $(BOOT_TARGETS): $(CHECKS) vmlinux - @$(MAKECOFFBOOT) $@ @$(MAKEBOOT) $@ - @$(MAKECHRPBOOT) $@ - -znetboot: $(CHECKS) vmlinux - cp -f vmlinux /tftpboot/vmlinux.64 - @$(MAKECOFFBOOT) $@ - @$(MAKEBOOT) $@ - @$(MAKECHRPBOOT) $@ -endif %_config: arch/ppc/configs/%_defconfig rm -f .config arch/ppc/defconfig @@ -149,14 +98,9 @@ endif archclean: rm -f arch/ppc/kernel/{mk_defs,ppc_defs.h,find_name,checks} - @$(MAKECOFFBOOT) clean @$(MAKEBOOT) clean - @$(MAKECHRPBOOT) clean - @$(MAKEMBXBOOT) clean - @$(MAKETREEBOOT) clean archmrproper: archdep: - $(MAKEBOOT) fastdep - $(MAKECHRPBOOT) fastdep + $(MAKEBOOT) dep diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile index 0ce99dc00d34..3a9cef93cf9c 100644 --- a/arch/ppc/boot/Makefile +++ b/arch/ppc/boot/Makefile @@ -9,27 +9,24 @@ # Adapted for PowerPC by Gary Thomas # modified by Cort (cort@cs.nmt.edu) # + .c.s: $(CC) $(CFLAGS) -S -o $*.s $< .s.o: $(AS) -o $*.o $< .c.o: - $(CC) $(CFLAGS) -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -D__BOOTER__ -c -o $*.o $< + $(CC) $(CFLAGS) -c -o $*.o $< .S.s: $(CPP) $(AFLAGS) -traditional -o $*.o $< .S.o: $(CC) $(AFLAGS) -traditional -c -o $*.o $< -ZOFF = 0 -ZSZ = 0 -IOFF = 0 -ISZ = 0 +GZIP_FLAGS = -v9f -ifeq ($(CONFIG_SMP),y) -TFTPIMAGE=/tftpboot/zImage.prep.smp$(MSIZE) -else -TFTPIMAGE=/tftpboot/zImage.prep$(MSIZE) -endif +CFLAGS := $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -D__BOOTER__ \ + -I$(TOPDIR)/arch/$(ARCH)/boot/include +AFLAGS += -D__BOOTER__ +OBJCOPY_ARGS = -O elf32-powerpc ifeq ($(CONFIG_SMP),y) TFTPSIMAGE=/tftpboot/sImage.smp @@ -37,145 +34,63 @@ else TFTPSIMAGE=/tftpboot/sImage endif -ifeq ($(CONFIG_PPC64BRIDGE),y) -MSIZE=.64 -else -MSIZE= -endif - -ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00800000 -GZIP_FLAGS = -v9f - -OBJECTS := head.o misc.o ../coffboot/zlib.o -CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -OBJCOPY_ARGS = -O elf32-powerpc - -OBJECTS += vreset.o kbd.o of1275.o -ifeq ($(CONFIG_SERIAL_CONSOLE),y) -OBJECTS += ns16550.o -endif +lib/zlib.a: + $(MAKE) -C lib -all: zImage +images/vmlinux.gz: $(TOPDIR)/vmlinux + $(MAKE) -C images vmlinux.gz -zvmlinux.initrd: zvmlinux - $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=initrd=ramdisk.image.gz \ - --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.initrd.tmp zvmlinux.initrd - $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \ - -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \ - -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \ - -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \ - -D__BOOTER__ \ - -c -o misc.o misc.c - $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=initrd=ramdisk.image.gz \ - --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.initrd.tmp $@ - rm zvmlinux.initrd.tmp +# Since gemini doesn't need/have it's own directory, we do znetboot* here ifdef CONFIG_GEMINI - $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) - $(OBJCOPY) -I elf32-powerpc -O binary zvmlinux.initrd.tmp svmlinux.initrd.tmp - ./mksimage svmlinux.initrd.tmp ../coffboot/vmlinux.gz ramdisk.image.gz \ - -o svmlinux.initrd > sImage.map - $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh sioffset initrd` \ - -DINITRD_SIZE=`sh sisize initrd` \ - -DZIMAGE_OFFSET=`sh sioffset zimage` \ - -DZIMAGE_SIZE=`sh sisize zimage` \ - -c -o misc.o misc.c - $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) - $(OBJCOPY) -I elf32-powerpc -O binary zvmlinux.initrd.tmp svmlinux.initrd.tmp - ./mksimage svmlinux.initrd.tmp ../coffboot/vmlinux.gz ramdisk.image.gz \ - -o svmlinux.initrd > /dev/null - rm svmlinux.initrd.tmp zvmlinux.initrd.tmp sImage.map +BOOT_TARGETS = zImage zImage.initrd +else +BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd endif -zImage: zvmlinux mkprep sImage mksimage +# We go into the utils dir by hand to ensure HOSTCC builds +$(BOOT_TARGETS): sImage vmapus lib/zlib.a images/vmlinux.gz +ifneq ("xx$(CONFIG_8260)$(CONFIG_8xx)","xx") + $(MAKE) -C mbx $@ +endif ifdef CONFIG_ALL_PPC - ./mkprep -pbp zvmlinux zImage + $(MAKE) -C utils addnote piggyback mknote hack-coff mkprep + $(MAKE) -C chrp $@ + $(MAKE) -C pmac $@ + $(MAKE) -C prep $@ endif -ifdef CONFIG_APUS - $(STRIP) ../../../vmlinux -o vmapus - gzip $(GZIP_FLAGS) vmapus +ifdef CONFIG_4xx + $(MAKE) -C tree $@ endif -sImage: ../../../vmlinux +sImage: $(TOPDIR)/vmlinux ifdef CONFIG_GEMINI - $(OBJCOPY) -I elf32-powerpc -O binary ../../../vmlinux sImage + $(OBJCOPY) -I elf32-powerpc -O binary $(TOPDIR)/vmlinux images/sImage endif -zImage.initrd: zvmlinux.initrd mkprep -ifdef CONFIG_ALL_PPC - ./mkprep -pbp zvmlinux.initrd zImage.initrd +vmapus: $(TOPDIR)/vmlinux +ifdef CONFIG_APUS + $(STRIP) $(TOPDIR)/vmlinux -o images/vmapus + gzip $(GZIP_FLAGS) images/vmapus endif -zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz mksimage -# -# build the boot loader image and then compute the offset into it -# for the kernel image -# - $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.tmp $@ -# -# then with the offset rebuild the bootloader so we know where the kernel is -# - $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \ - -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \ - -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \ - -D__BOOTER__ \ - -c -o misc.o misc.c - $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.tmp $@ - rm zvmlinux.tmp ifdef CONFIG_GEMINI - $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) - $(OBJCOPY) -I elf32-powerpc -O binary zvmlinux.tmp svmlinux.tmp - ./mksimage svmlinux.tmp ../coffboot/vmlinux.gz -o svmlinux > sImage.map - $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \ - -DZIMAGE_OFFSET=`sh sioffset zimage` \ - -DZIMAGE_SIZE=`sh sisize zimage` \ - -c -o misc.o misc.c - $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) - $(OBJCOPY) -I elf32-powerpc -O binary zvmlinux.tmp svmlinux.tmp - ./mksimage svmlinux.tmp ../coffboot/vmlinux.gz -o svmlinux > /dev/null - rm svmlinux.tmp sImage.map zvmlinux.tmp -endif - -floppy: $(TOPDIR)/vmlinux zImage - dd if=zImage of=/dev/fd0H1440 bs=64b - -mkprep : mkprep.c - $(HOSTCC) -o mkprep mkprep.c - -mksimage: mksimage.c - $(HOSTCC) -o mksimage mksimage.c - znetboot : zImage -ifdef CONFIG_ALL_PPC - cp zImage $(TFTPIMAGE) -endif -ifdef CONFIG_GEMINI - cp sImage $(TFTPSIMAGE) + cp images/sImage $(TFTPSIMAGE) endif -znetboot.initrd : zImage.initrd - cp zImage.initrd $(TFTPIMAGE) - +# Do the dirs clean: - rm -f vmlinux* zvmlinux* mkprep zImage* sImage* mksimage - -fastdep: - $(TOPDIR)/scripts/mkdep *.[Sch] > .depend + $(MAKE) -C images clean + $(MAKE) -C tree clean + $(MAKE) -C utils clean dep: - $(CPP) $(CPPFLAGS) -M *.S *.c > .depend - -# just here to match coffboot/Makefile -vmlinux.coff: - -vmlinux.coff.initrd: + $(MAKE) -C mbx fastdep + $(MAKE) -C chrp fastdep + $(MAKE) -C common fastdep + $(MAKE) -C pmac fastdep + $(MAKE) -C prep fastdep + $(MAKE) -C common fastdep + +include $(TOPDIR)/Rules.make diff --git a/arch/ppc/boot/chrp/Makefile b/arch/ppc/boot/chrp/Makefile new file mode 100644 index 000000000000..cf2e6d4c88ec --- /dev/null +++ b/arch/ppc/boot/chrp/Makefile @@ -0,0 +1,73 @@ +# BK Id: SCCS/s.Makefile 1.8 05/18/01 06:20:29 patch +# +# Makefile for making ELF bootable images for booting on CHRP +# using Open Firmware. +# +# Geert Uytterhoeven September 1997 +# +# Based on coffboot by Paul Mackerras + +ifeq ($(CONFIG_PPC64BRIDGE),y) +MSIZE=.64 +AFLAGS += -Wa,-mppc64bridge +else +MSIZE= +endif + +.c.o: + $(CC) $(CFLAGS) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $< +.S.o: + $(CC) $(AFLAGS) -traditional -c -o $*.o $< + +LD_ARGS = -Ttext 0x00400000 + +OBJS = ../common/crt0.o start.o main.o misc.o ../common/string.o image.o +LIBS = $(TOPDIR)/lib/lib.a ../lib/zlib.a +ADDNOTE = ../utils/addnote +PIGGYBACK = ../utils/piggyback + +ifeq ($(CONFIG_SMP),y) +TFTPIMAGE=/tftpboot/zImage.chrp.smp$(MSIZE) +else +TFTPIMAGE=/tftpboot/zImage.chrp$(MSIZE) +endif + +all: zImage + +znetboot: zImage +ifdef CONFIG_SMP + cp -f $(TOPDIR)/vmlinux /tftpboot/vmlinux.smp +else + cp -f $(TOPDIR)/vmlinux /tftpboot/vmlinux +endif +ifdef CONFIG_PPC64BRIDGE + cp -f $(TOPDIR)/vmlinux /tftpboot/vmlinux.64 +endif + cp ../images/zImage.chrp $(TFTPIMAGE) + +znetboot.initrd: zImage.initrd + cp ../images/zImage.initrd.chrp $(TFTPIMAGE) + +floppy: zImage + mcopy zImage a:zImage + +image.o: $(PIGGYBACK) ../images/vmlinux.gz + $(PIGGYBACK) image < ../images/vmlinux.gz | $(AS) -o $@ + +sysmap.o: $(PIGGYBACK) $(TOPDIR)/System.map + $(PIGGYBACK) sysmap < $(TOPDIR)/System.map | $(AS) -o $@ + +initrd.o: ../images/ramdisk.image.gz $(PIGGYBACK) + $(PIGGYBACK) initrd < ../images/ramdisk.image.gz | $(AS) -o $@ + +zImage: $(OBJS) $(LIBS) ../common/no_initrd.o $(ADDNOTE) ../images/vmlinux.gz + $(LD) $(LD_ARGS) -o ../images/$@.chrp $(OBJS) ../common/no_initrd.o $(LIBS) + cp ../images/$@.chrp ../images/$@.chrp-rs6k + $(ADDNOTE) ../images/$@.chrp-rs6k + +zImage.initrd: $(OBJS) $(LIBS) initrd.o $(ADDNOTE) ../images/vmlinux.gz + $(LD) $(LD_ARGS) -o ../images/$@.chrp $(OBJS) initrd.o $(LIBS) + cp ../images/$@.chrp ../images/$@.chrp-rs6k + $(ADDNOTE) ../images/$@.chrp-rs6k + +include $(TOPDIR)/Rules.make diff --git a/arch/ppc/chrpboot/main.c b/arch/ppc/boot/chrp/main.c index a080f5ac61c0..14c4ff6f4274 100644 --- a/arch/ppc/chrpboot/main.c +++ b/arch/ppc/boot/chrp/main.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.main.c 1.7 05/18/01 06:20:29 patch + */ +/* * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or @@ -6,8 +9,8 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include "../coffboot/nonstdio.h" -#include "../coffboot/zlib.h" +#include "nonstdio.h" +#include "zlib.h" #include <asm/bootinfo.h> #include <asm/processor.h> #include <asm/page.h> diff --git a/arch/ppc/chrpboot/misc.S b/arch/ppc/boot/chrp/misc.S index b2094b9d3df4..ccb970e47338 100644 --- a/arch/ppc/chrpboot/misc.S +++ b/arch/ppc/boot/chrp/misc.S @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.misc.S 1.6 05/18/01 15:16:59 cort + */ +/* * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or diff --git a/arch/ppc/chrpboot/start.c b/arch/ppc/boot/chrp/start.c index 308f4fcd3492..b43385d52f48 100644 --- a/arch/ppc/chrpboot/start.c +++ b/arch/ppc/boot/chrp/start.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.start.c 1.6 05/18/01 15:16:59 cort + */ +/* * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or diff --git a/arch/ppc/boot/common/Makefile b/arch/ppc/boot/common/Makefile new file mode 100644 index 000000000000..144a63685bb6 --- /dev/null +++ b/arch/ppc/boot/common/Makefile @@ -0,0 +1,27 @@ +# +# arch/ppc/boot/common/Makefile +# +# 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. +# +# Tom Rini January 2001 +# + +.c.s: + $(CC) $(CFLAGS) -S -o $*.s $< +.s.o: + $(AS) -o $*.o $< +.c.o: + $(CC) $(CFLAGS) -c -o $*.o $< +.S.s: + $(CPP) $(AFLAGS) -traditional -o $*.o $< +.S.o: + $(CC) $(AFLAGS) -traditional -c -o $*.o $< + +OBJCOPY_ARGS = -O elf32-powerpc + +coffcrt0.o: + $(CC) $(AFLAGS) -DXCOFF -traditional -c -o coffcrt0.o crt0.S + +include $(TOPDIR)/Rules.make diff --git a/arch/ppc/boot/common/crt0.S b/arch/ppc/boot/common/crt0.S new file mode 100644 index 000000000000..f6843d7c28ad --- /dev/null +++ b/arch/ppc/boot/common/crt0.S @@ -0,0 +1,84 @@ +/* + * BK Id: SCCS/s.crt0.S 1.10 05/21/01 00:49:49 cort + */ +/* Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au> + * Initial Power Macintosh COFF version. + * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> + * Modifications for IBM PowerPC 400-class processor evaluation + * boards. + * + * Module name: crt0.S + * + * Description: + * Boot loader execution entry point. Clears out .bss section as per + * ANSI C requirements. Invalidates and flushes the caches over the + * range covered by the boot loader's .text section. Sets up a stack + * below the .text section entry point. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/config.h> +#include "../../kernel/ppc_asm.tmpl" + + .text + + .globl _start +_start: +#ifdef XCOFF + .long __start,0,0 + + .globl __start +__start: +#endif +#ifdef CONFIG_4xx + ## Clear out the BSS as per ANSI C requirements + + lis r7,_end@ha + addi r7,r7,_end@l # r7 = &_end + lis r8,__bss_start@ha # + addi r8,r8,__bss_start@l # r8 = &_bss_start + + ## Determine how large an area, in number of words, to clear + + subf r7,r8,r7 # r7 = &_end - &_bss_start + 1 + addi r7,r7,3 # r7 += 3 + srwi. r7,r7,2 # r7 = size in words. + beq 2f # If the size is zero, do not bother + addi r8,r8,-4 # r8 -= 4 + mtctr r7 # SPRN_CTR = number of words to clear + li r0,0 # r0 = 0 +1: stwu r0,4(r8) # Clear out a word + bdnz 1b # If we are not done yet, keep clearing +#endif + + ## Flush and invalidate the caches for the range in memory covering + ## the .text section of the boot loader + +2: lis r9,_start@h # r9 = &_start + lis r8,_etext@ha # + addi r8,r8,_etext@l # r8 = &_etext +3: dcbf r0,r9 # Flush the data cache + icbi r0,r9 # Invalidate the instruction cache + addi r9,r9,0x10 # Increment by one cache line + cmplw cr0,r9,r8 # Are we at the end yet? + blt 3b # No, keep flushing and invalidating + sync # sync ; isync after flushing the icache + isync + +#ifdef CONFIG_4xx + ## Set up the stack + + lis r9,_start@h # r9 = &_start (text section entry) + addi r9,r9,_start@l + subi r1,r9,64 # Start the stack 64 bytes below _start + clrrwi r1,r1,4 # Make sure it is aligned on 16 bytes. + li r0,0 + stwu r0,-16(r1) + mtlr r9 +#endif + + b start # All done, start the real work. diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c new file mode 100644 index 000000000000..c2ccecf969b6 --- /dev/null +++ b/arch/ppc/boot/common/misc-common.c @@ -0,0 +1,539 @@ +/* + * arch/ppc/boot/common/misc-common.c + * + * Misc. bootloader code (almost) all platforms can use + * + * Author: Johnnie Peters <jpeters@mvista.com> + * Editor: Tom Rini <trini@mvista.com> + * + * Derived from arch/ppc/boot/prep/misc.c + * + * Copyright 2000-2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/config.h> +#include "zlib.h" +#include <linux/pci.h> + +/* If we're on a ALL_PPC, assume we have a keyboard controller + * Also note, if we're not ALL_PPC, we assume you are a serial + * console - Tom */ +#ifdef CONFIG_ALL_PPC +extern void cursor(int x, int y); +extern void scroll(void); +extern char *vidmem; +extern int lines, cols; +extern int orig_x, orig_y; +extern int keyb_present; +extern int CRT_tstc(void); +extern int CRT_getc(void); +#else +int cursor(int x, int y) {return 0;} +void scroll(void) {} +char vidmem[1]; +#define lines 0 +#define cols 0 +int orig_x = 0; +int orig_y = 0; +#define keyb_present 0 +int CRT_tstc(void) {return 0;} +int CRT_getc(void) {return 0;} +#endif + +extern char *avail_ram; +extern char *end_avail; +extern char _end[]; + +void puts(const char *); +void putc(const char c); +void puthex(unsigned long val); +void _bcopy(char *src, char *dst, int len); +void gunzip(void *, int, unsigned char *, int *); +static int _cvt(unsigned long val, char *buf, long radix, char *digits); + +void _vprintk(void(*)(const char), const char *, va_list); + +#if defined(CONFIG_SERIAL_CONSOLE) +struct NS16550 *com_port; + +int serial_tstc(volatile struct NS16550 *); +unsigned char serial_getc(volatile struct NS16550 *); +void serial_putc(volatile struct NS16550 *, unsigned char); +#endif + +void pause(void) +{ + puts("pause\n"); +} + +void exit(void) +{ + puts("exit\n"); + while(1); +} + +int tstc(void) +{ +#if defined(CONFIG_SERIAL_CONSOLE) + if(keyb_present) + return (CRT_tstc() || serial_tstc(com_port)); + else + return (serial_tstc(com_port)); +#else + return CRT_tstc(); +#endif +} + +int getc(void) +{ + while (1) { +#if defined(CONFIG_SERIAL_CONSOLE) + if (serial_tstc(com_port)) + return (serial_getc(com_port)); +#endif /* CONFIG_SERIAL_CONSOLE */ + if (keyb_present) + if(CRT_tstc()) + return (CRT_getc()); + } +} + +void +putc(const char c) +{ + int x,y; + +#if defined(CONFIG_SERIAL_CONSOLE) + serial_putc(com_port, c); + if ( c == '\n' ) + serial_putc(com_port, '\r'); +#endif /* CONFIG_SERIAL_CONSOLE */ + + x = orig_x; + y = orig_y; + + if ( c == '\n' ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } else if (c == '\r') { + x = 0; + } else if (c == '\b') { + if (x > 0) { + x--; + } + } else { + vidmem [ ( x + cols * y ) * 2 ] = c; + if ( ++x >= cols ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } + } + + cursor(x, y); + + orig_x = x; + orig_y = y; +} + +void puts(const char *s) +{ + int x,y; + char c; + + x = orig_x; + y = orig_y; + + while ( ( c = *s++ ) != '\0' ) { +#if defined(CONFIG_SERIAL_CONSOLE) + serial_putc(com_port, c); + if ( c == '\n' ) serial_putc(com_port, '\r'); +#endif /* CONFIG_SERIAL_CONSOLE */ + + if ( c == '\n' ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } else if (c == '\b') { + if (x > 0) { + x--; + } + } else { + vidmem [ ( x + cols * y ) * 2 ] = c; + if ( ++x >= cols ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } + } + } + + cursor(x, y); + + orig_x = x; + orig_y = y; +} + +void error(char *x) +{ + puts("\n\n"); + puts(x); + puts("\n\n -- System halted"); + + while(1); /* Halt */ +} + +void *zalloc(void *x, unsigned items, unsigned size) +{ + void *p = avail_ram; + + size *= items; + size = (size + 7) & -8; + avail_ram += size; + if (avail_ram > end_avail) { + puts("oops... out of memory\n"); + pause(); + } + return p; +} + +void zfree(void *x, void *addr, unsigned nb) +{ +} + +#define HEAD_CRC 2 +#define EXTRA_FIELD 4 +#define ORIG_NAME 8 +#define COMMENT 0x10 +#define RESERVED 0xe0 + +#define DEFLATED 8 + +void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) +{ + z_stream s; + int r, i, flags; + + /* skip header */ + i = 10; + flags = src[3]; + if (src[2] != DEFLATED || (flags & RESERVED) != 0) { + puts("bad gzipped data\n"); + exit(); + } + if ((flags & EXTRA_FIELD) != 0) + i = 12 + src[10] + (src[11] << 8); + if ((flags & ORIG_NAME) != 0) + while (src[i++] != 0) + ; + if ((flags & COMMENT) != 0) + while (src[i++] != 0) + ; + if ((flags & HEAD_CRC) != 0) + i += 2; + if (i >= *lenp) { + puts("gunzip: ran out of data in header\n"); + exit(); + } + + s.zalloc = zalloc; + s.zfree = zfree; + r = inflateInit2(&s, -MAX_WBITS); + if (r != Z_OK) { + puts("inflateInit2 returned %d\n"); + exit(); + } + s.next_in = src + i; + s.avail_in = *lenp - i; + s.next_out = dst; + s.avail_out = dstlen; + r = inflate(&s, Z_FINISH); + if (r != Z_OK && r != Z_STREAM_END) { + puts("inflate returned %d\n"); + exit(); + } + *lenp = s.next_out - (unsigned char *) dst; + inflateEnd(&s); +} + +void +puthex(unsigned long val) +{ + + unsigned char buf[10]; + int i; + for (i = 7; i >= 0; i--) + { + buf[i] = "0123456789ABCDEF"[val & 0x0F]; + val >>= 4; + } + buf[8] = '\0'; + puts(buf); +} + +#define FALSE 0 +#define TRUE 1 +#include <stdarg.h> + +void +_printk(char const *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _vprintk(putc, fmt, ap); + va_end(ap); + return; +} + +#define is_digit(c) ((c >= '0') && (c <= '9')) + +void +_vprintk(void(*putc)(const char), const char *fmt0, va_list ap) +{ + char c, sign, *cp = 0; + int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right; + char buf[32]; + long val; + while ((c = *fmt0++)) + { + if (c == '%') + { + c = *fmt0++; + left_prec = right_prec = pad_on_right = 0; + if (c == '-') + { + c = *fmt0++; + pad_on_right++; + } + if (c == '0') + { + zero_fill = TRUE; + c = *fmt0++; + } else + { + zero_fill = FALSE; + } + while (is_digit(c)) + { + left_prec = (left_prec * 10) + (c - '0'); + c = *fmt0++; + } + if (c == '.') + { + c = *fmt0++; + zero_fill++; + while (is_digit(c)) + { + right_prec = (right_prec * 10) + (c - '0'); + c = *fmt0++; + } + } else + { + right_prec = left_prec; + } + sign = '\0'; + switch (c) + { + case 'd': + case 'x': + case 'X': + val = va_arg(ap, long); + switch (c) + { + case 'd': + if (val < 0) + { + sign = '-'; + val = -val; + } + length = _cvt(val, buf, 10, "0123456789"); + break; + case 'x': + length = _cvt(val, buf, 16, "0123456789abcdef"); + break; + case 'X': + length = _cvt(val, buf, 16, "0123456789ABCDEF"); + break; + } + cp = buf; + break; + case 's': + cp = va_arg(ap, char *); + length = strlen(cp); + break; + case 'c': + c = va_arg(ap, long /*char*/); + (*putc)(c); + continue; + default: + (*putc)('?'); + } + pad = left_prec - length; + if (sign != '\0') + { + pad--; + } + if (zero_fill) + { + c = '0'; + if (sign != '\0') + { + (*putc)(sign); + sign = '\0'; + } + } else + { + c = ' '; + } + if (!pad_on_right) + { + while (pad-- > 0) + { + (*putc)(c); + } + } + if (sign != '\0') + { + (*putc)(sign); + } + while (length-- > 0) + { + (*putc)(c = *cp++); + if (c == '\n') + { + (*putc)('\r'); + } + } + if (pad_on_right) + { + while (pad-- > 0) + { + (*putc)(c); + } + } + } else + { + (*putc)(c); + if (c == '\n') + { + (*putc)('\r'); + } + } + } +} + +int +_cvt(unsigned long val, char *buf, long radix, char *digits) +{ + char temp[80]; + char *cp = temp; + int length = 0; + if (val == 0) + { /* Special case */ + *cp++ = '0'; + } else + while (val) + { + *cp++ = digits[val % radix]; + val /= radix; + } + while (cp != temp) + { + *buf++ = *--cp; + length++; + } + *buf = '\0'; + return (length); +} + +void +_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base) +{ + int i, c; + if ((unsigned int)s > (unsigned int)p) + { + s = (unsigned int)s - (unsigned int)p; + } + while (s > 0) + { + if (base) + { + _printk("%06X: ", (int)p - (int)base); + } else + { + _printk("%06X: ", p); + } + for (i = 0; i < 16; i++) + { + if (i < s) + { + _printk("%02X", p[i] & 0xFF); + } else + { + _printk(" "); + } + if ((i % 2) == 1) _printk(" "); + if ((i % 8) == 7) _printk(" "); + } + _printk(" |"); + for (i = 0; i < 16; i++) + { + if (i < s) + { + c = p[i] & 0xFF; + if ((c < 0x20) || (c >= 0x7F)) c = '.'; + } else + { + c = ' '; + } + _printk("%c", c); + } + _printk("|\n"); + s -= 16; + p += 16; + } +} + +void +_dump_buf(unsigned char *p, int s) +{ + _printk("\n"); + _dump_buf_with_offset(p, s, 0); +} + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/arch/ppc/boot/common/misc-simple.c b/arch/ppc/boot/common/misc-simple.c new file mode 100644 index 000000000000..035e9d59ec4f --- /dev/null +++ b/arch/ppc/boot/common/misc-simple.c @@ -0,0 +1,182 @@ +/* + * arch/ppc/common/misc-simple.c + * + * Misc. bootloader code for many machines. This assumes you have are using + * a 6xx/7xx/74xx CPU in your machine. This assumes the chunk of memory + * below 8MB is free. Finally, it assumes you have a NS16550-style uart for + * your serial console. If a machine meets these requirements, it can quite + * likely use this code during boot. + * + * Author: Matt Porter <mporter@mvista.com> + * Derived from arch/ppc/boot/prep/misc.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/types.h> +#include <linux/elf.h> +#include <linux/config.h> + +#include <asm/page.h> +#include <asm/processor.h> +#include <asm/mmu.h> + +#include "zlib.h" + +unsigned long com_port; + +char *avail_ram; +char *end_avail; +extern char _end[]; + +#ifdef CONFIG_CMDLINE +#define CMDLINE CONFIG_CMDLINE +#else +#define CMDLINE "" +#endif +char cmd_preset[] = CMDLINE; +char cmd_buf[256]; +char *cmd_line = cmd_buf; + +unsigned long initrd_start = 0, initrd_end = 0; +char *zimage_start; +int zimage_size; + +extern void puts(const char *); +extern void putc(const char c); +extern void puthex(unsigned long val); +extern void *memcpy(void * __dest, __const void * __src, + __kernel_size_t __n); +extern void gunzip(void *, int, unsigned char *, int *); +extern void udelay(long delay); +extern int tstc(void); +extern int getc(void); +extern volatile unsigned long serial_init(int chan); + +void +decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) +{ + + int timer = 0; + extern unsigned long start; + char *cp, ch; + + com_port = serial_init(0); + + /* assume the chunk below 8M is free */ + end_avail = (char *)0x00800000; + + /* + * Reveal where we were loaded at and where we + * were relocated to. + */ + puts("loaded at: "); puthex(load_addr); + puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); + if ( (unsigned long)load_addr != (unsigned long)&start ) + { + puts("relocated to: "); puthex((unsigned long)&start); + puts(" "); + puthex((unsigned long)((unsigned long)&start + (4*num_words))); + puts("\n"); + } + + /* we have to subtract 0x10000 here to correct for objdump including + the size of the elf header which we strip -- Cort */ + zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET); + zimage_size = ZIMAGE_SIZE; + + if ( INITRD_OFFSET ) + initrd_start = load_addr - 0x10000 + INITRD_OFFSET; + else + initrd_start = 0; + initrd_end = INITRD_SIZE + initrd_start; + + /* + * Find a place to stick the zimage and initrd and + * relocate them if we have to. -- Cort + */ + avail_ram = (char *)PAGE_ALIGN((unsigned long)_end); + puts("zimage at: "); puthex((unsigned long)zimage_start); + puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n"); + if ( (unsigned long)zimage_start <= 0x00800000 ) + { + memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size ); + zimage_start = (char *)avail_ram; + puts("relocated to: "); puthex((unsigned long)zimage_start); + puts(" "); + puthex((unsigned long)zimage_size+(unsigned long)zimage_start); + puts("\n"); + + /* relocate initrd */ + if ( initrd_start ) + { + puts("initrd at: "); puthex(initrd_start); + puts(" "); puthex(initrd_end); puts("\n"); + avail_ram = (char *)PAGE_ALIGN( + (unsigned long)zimage_size+(unsigned long)zimage_start); + memcpy ((void *)avail_ram, (void *)initrd_start, INITRD_SIZE ); + initrd_start = (unsigned long)avail_ram; + initrd_end = initrd_start + INITRD_SIZE; + puts("relocated to: "); puthex(initrd_start); + puts(" "); puthex(initrd_end); puts("\n"); + } + } else if ( initrd_start ) { + puts("initrd at: "); puthex(initrd_start); + puts(" "); puthex(initrd_end); puts("\n"); + } + + avail_ram = (char *)0x00400000; + end_avail = (char *)0x00800000; + puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); + puthex((unsigned long)end_avail); puts("\n"); + + /* Display standard Linux/PPC boot prompt for kernel args */ + puts("\nLinux/PPC load: "); + cp = cmd_line; + memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); + while ( *cp ) putc(*cp++); + while (timer++ < 5*1000) { + if (tstc()) { + while ((ch = getc()) != '\n' && ch != '\r') { + /* Test for backspace/delete */ + if (ch == '\b' || ch == '\177') { + if (cp != cmd_line) { + cp--; + puts("\b \b"); + } + /* Test for ^x/^u (and wipe the line) */ + } else if (ch == '\030' || ch == '\025') { + while (cp != cmd_line) { + cp--; + puts("\b \b"); + } + } else { + *cp++ = ch; + putc(ch); + } + } + break; /* Exit 'timer' loop */ + } + udelay(1000); /* 1 msec */ + } + *cp = 0; + puts("\n"); + + /* mappings on early boot can only handle 16M */ + if ( (int)(cmd_line[0]) > (16<<20)) + puts("cmd_line located > 16M\n"); + if ( initrd_start > (16<<20)) + puts("initrd_start located > 16M\n"); + + puts("Uncompressing Linux..."); + + gunzip(0, 0x400000, zimage_start, &zimage_size); + puts("done.\n"); + + puts("Now booting the kernel\n"); +} diff --git a/arch/ppc/boot/common/no_initrd.c b/arch/ppc/boot/common/no_initrd.c new file mode 100644 index 000000000000..b7191ca747cf --- /dev/null +++ b/arch/ppc/boot/common/no_initrd.c @@ -0,0 +1,5 @@ +/* + * BK Id: SCCS/s.no_initrd.c 1.7 05/18/01 15:17:23 cort + */ +char initrd_data[1]; +int initrd_len = 0; diff --git a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c new file mode 100644 index 000000000000..b2c6f9cd951f --- /dev/null +++ b/arch/ppc/boot/common/ns16550.c @@ -0,0 +1,80 @@ +/* + * BK Id: SCCS/s.ns16550.c 1.7 05/18/01 06:20:29 patch + */ +/* + * COM1 NS16550 support + */ + +#include <linux/config.h> +#include <linux/serialP.h> +#include <linux/serial_reg.h> +#include <asm/serial.h> + +/* Some machines, such as ones with a PReP memory map, initally have + * their serial port at an offset of 0x80000000 from where they are + * in <asm/serial.h>. This tries to take that into account. */ +#ifndef IOOFFSET +#define IOOFFSET 0 +#endif + +static struct serial_state rs_table[RS_TABLE_SIZE] = { + SERIAL_PORT_DFNS /* Defined in <asm/serial.h> */ +}; + +static int shift; + +volatile unsigned long serial_init(int chan) { + unsigned long com_port; + + /* Get the base, and add any offset we need to deal with. */ + com_port = rs_table[chan].port + IOOFFSET; + + /* How far apart the registers are. */ + shift = rs_table[chan].iomem_reg_shift; + + /* See if port is present */ + *((unsigned char *)com_port + (UART_LCR << shift)) = 0x00; + *((unsigned char *)com_port + (UART_IER << shift)) = 0x00; + /* Access baud rate */ + *((unsigned char *)com_port + (UART_LCR << shift)) = 0x00; +#ifdef CONFIG_SERIAL_CONSOLE_NONSTD + /* Input clock. */ + *((unsigned char *)com_port + (UART_DLL << shift)) = + (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD); + *((unsigned char *)com_port + (UART_DLM << shift)) = + (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD) >> 8; +#endif + /* 8 data, 1 stop, no parity */ + *((unsigned char *)com_port + (UART_LCR << shift)) = 0x03; + /* RTS/DTR */ + *((unsigned char *)com_port + (UART_MCR << shift)) = 0x03; + /* Clear & enable FIFOs */ + *((unsigned char *)com_port + (UART_FCR << shift)) = 0x07; + + return (com_port); +} + +void +serial_putc(volatile unsigned long com_port, unsigned char c) +{ + while ((*((volatile unsigned char *)com_port + (UART_LSR << shift)) & + UART_LSR_THRE) == 0) + ; + *(volatile unsigned char *)com_port = c; +} + +unsigned char +serial_getc(volatile unsigned long com_port) +{ + while ((*((volatile unsigned char *)com_port + (UART_LSR << shift)) + & UART_LSR_DR) == 0) + ; + return (*(volatile unsigned char *)com_port); +} + +int +serial_tstc(volatile unsigned long com_port) +{ + return ((*((volatile unsigned char *)com_port + (UART_LSR << shift)) + & UART_LSR_DR) != 0); +} diff --git a/arch/ppc/coffboot/string.S b/arch/ppc/boot/common/string.S index ba83591b76f0..a2453681d4d8 100644 --- a/arch/ppc/coffboot/string.S +++ b/arch/ppc/boot/common/string.S @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.string.S 1.8 05/18/01 06:20:29 patch + */ +/* * String handling functions for PowerPC. * * Copyright (C) 1996 Paul Mackerras. @@ -16,55 +19,6 @@ #define r7 7 #define r8 8 - .globl strcpy -strcpy: - addi r5,r3,-1 - addi r4,r4,-1 -1: lbzu r0,1(r4) - cmpwi 0,r0,0 - stbu r0,1(r5) - bne 1b - blr - - .globl strncpy -strncpy: - cmpwi 0,r5,0 - beqlr - mtctr r5 - addi r6,r3,-1 - addi r4,r4,-1 -1: lbzu r0,1(r4) - cmpwi 0,r0,0 - stbu r0,1(r6) - bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */ - blr - - .globl strcat -strcat: - addi r5,r3,-1 - addi r4,r4,-1 -1: lbzu r0,1(r5) - cmpwi 0,r0,0 - bne 1b - addi r5,r5,-1 -1: lbzu r0,1(r4) - cmpwi 0,r0,0 - stbu r0,1(r5) - bne 1b - blr - - .globl strcmp -strcmp: - addi r5,r3,-1 - addi r4,r4,-1 -1: lbzu r3,1(r5) - cmpwi 1,r3,0 - lbzu r0,1(r4) - subf. r3,r0,r3 - beqlr 1 - beq 1b - blr - .globl strlen strlen: addi r4,r3,-1 @@ -100,13 +54,6 @@ memset: bdnz 8b blr - .globl bcopy -bcopy: - mr r6,r3 - mr r3,r4 - mr r4,r6 - b memcpy - .globl memmove memmove: cmplw 0,r3,r4 diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile new file mode 100644 index 000000000000..d6ee957b9081 --- /dev/null +++ b/arch/ppc/boot/images/Makefile @@ -0,0 +1,12 @@ +# +# This dir holds all of the images for PPC machines. +# Tom Rini January 2001 + +include $(TOPDIR)/Rules.make + +vmlinux.gz: $(TOPDIR)/vmlinux + $(OBJCOPY) -S -O binary $(TOPDIR)/vmlinux vmlinux + gzip -vf9 vmlinux + +clean: + rm -f sImage vmapus vmlinux.* miboot.image* zImage* zvmlinux.* diff --git a/arch/ppc/coffboot/nonstdio.h b/arch/ppc/boot/include/nonstdio.h index 664b8384ab83..ef9ac755b5d8 100644 --- a/arch/ppc/coffboot/nonstdio.h +++ b/arch/ppc/boot/include/nonstdio.h @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.nonstdio.h 1.7 05/18/01 15:17:23 cort + */ +/* * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or diff --git a/arch/ppc/coffboot/rs6000.h b/arch/ppc/boot/include/rs6000.h index 0def1d95d15a..fc446af98a50 100644 --- a/arch/ppc/coffboot/rs6000.h +++ b/arch/ppc/boot/include/rs6000.h @@ -1,3 +1,6 @@ +/* + * BK Id: SCCS/s.rs6000.h 1.7 05/18/01 15:17:23 cort + */ /* IBM RS/6000 "XCOFF" file definitions for BFD. Copyright (C) 1990, 1991 Free Software Foundation, Inc. FIXME: Can someone provide a transliteration of this name into ASCII? diff --git a/arch/ppc/coffboot/zlib.h b/arch/ppc/boot/include/zlib.h index f3bee01a76ea..c58e8bc9c2d0 100644 --- a/arch/ppc/coffboot/zlib.h +++ b/arch/ppc/boot/include/zlib.h @@ -1,5 +1,6 @@ -/* $Id: zlib.h,v 1.1 1997/07/31 07:16:15 paulus Exp $ */ - +/* + * BK Id: SCCS/s.zlib.h 1.8 05/18/01 15:17:23 cort + */ /* * This file is derived from zlib.h and zconf.h from the zlib-0.95 * distribution by Jean-loup Gailly and Mark Adler, with some additions diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile new file mode 100644 index 000000000000..0e7c20f5ad8f --- /dev/null +++ b/arch/ppc/boot/lib/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for some libs needed by zImage. +# + +L_TARGET := zlib.a + +obj-y := zlib.o + +include $(TOPDIR)/Rules.make diff --git a/arch/ppc/coffboot/zlib.c b/arch/ppc/boot/lib/zlib.c index ebab73cc64a4..a6127edf3f9b 100644 --- a/arch/ppc/coffboot/zlib.c +++ b/arch/ppc/boot/lib/zlib.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.zlib.c 1.8 05/18/01 15:17:24 cort + */ +/* * This file is derived from various .h and .c files from the zlib-0.95 * distribution by Jean-loup Gailly and Mark Adler, with some additions * by Paul Mackerras to aid in implementing Deflate compression and @@ -11,7 +14,6 @@ * - added Z_PACKET_FLUSH (see zlib.h for details) * - added inflateIncomp * - * $Id: zlib.c,v 1.3 1999/05/27 22:22:54 cort Exp $ */ /*+++++*/ diff --git a/arch/ppc/boot/mbx/Makefile b/arch/ppc/boot/mbx/Makefile new file mode 100644 index 000000000000..6f7b673e4014 --- /dev/null +++ b/arch/ppc/boot/mbx/Makefile @@ -0,0 +1,127 @@ +# BK Id: SCCS/s.Makefile 1.5 05/18/01 06:20:29 patch +# +# +# arch/ppc/mbxboot/Makefile +# +# 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. +# +# Copyright (C) 1994 by Linus Torvalds +# Adapted for PowerPC by Gary Thomas +# modified by Cort (cort@cs.nmt.edu) +# +.c.s: + $(CC) $(CFLAGS) -S -o $*.s $< +.s.o: + $(AS) -o $*.o $< +.c.o: + $(CC) $(CFLAGS) -c -o $*.o $< +.S.s: + $(CPP) $(AFLAGS) -traditional -o $*.o $< +.S.o: + $(CC) $(AFLAGS) -traditional -c -o $*.o $< + +TFTPIMAGE := /tftpboot/zImage.embedded + +OFFSET := ../utils/offset +SIZE := ../utils/size + +LIBS := ../lib/zlib.a +OBJCOPY_ARGS := -O elf32-powerpc + +ifdef CONFIG_8xx +ZLINKFLAGS := -T $(TOPDIR)/arch/$(ARCH)/vmlinux.lds -Ttext 0x00180000 +OBJECTS := head.o m8xx_tty.o +CFLAGS += -DCONFIG_8xx +endif + +ifdef CONFIG_8260 +ZLINKFLAGS := -T $(TOPDIR)/arch/$(ARCH)/vmlinux.lds -Ttext 0x00400000 +OBJECTS := head_8260.o m8260_tty.o embed_config.o +CFLAGS += -DCONFIG_8260 +endif + +OBJECTS += ../common/misc-common.o misc.o ../common/string.o +OBJCOPY_ARGS = -O elf32-powerpc + +ifeq ($(CONFIG_MBX),y) +OBJECTS += iic.o embed_config.o pci.o qspan_pci.o +CFLAGS += -DCONFIG_MBX +endif +ifeq ($(CONFIG_RPXLITE),y) +CFLAGS += -DCONFIG_RPXLITE +OBJECTS += iic.o embed_config.o +endif +ifeq ($(CONFIG_RPXCLASSIC),y) +CFLAGS += -DCONFIG_RPXCLASSIC +OBJECTS += iic.o embed_config.o pci.o qspan_pci.o +endif +ifeq ($(CONFIG_BSEIP),y) +CFLAGS += -DCONFIG_BSEIP +OBJECTS += iic.o embed_config.o +endif +ifeq ($(CONFIG_FADS),y) +CFLAGS += -DCONFIG_FADS +OBJECTS += embed_config.o +endif + +all: zImage + +misc.o: misc.c + $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ + -DZIMAGE_SIZE=0 -c -o $@ $*.c + +zvmlinux.initrd: $(OBJECTS) $(LIBS) ../images/vmlinux.gz + $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=initrd=../images/ramdisk.image.gz \ + --add-section=image=../images/vmlinux.gz \ + $@.tmp $@ + $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh $(OFFSET) $(OBJDUMP) $@ initrd` \ + -DINITRD_SIZE=`sh $(SIZE) $(OBJDUMP) $@ initrd` \ + -DZIMAGE_OFFSET=`sh $(OFFSET) $(OBJDUMP) $@ image` \ + -DZIMAGE_SIZE=`sh $(SIZE) $(OBJDUMP) $@ image` \ + -c -o misc.o misc.c + $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=initrd=../images/ramdisk.image.gz \ + --add-section=image=../images/vmlinux.gz \ + $@.tmp ../images/$@.mbx + +zImage: zvmlinux + ln -sf zvmlinux.mbx ../images/zImage.mbx + +zImage.initrd: zvmlinux.initrd + ln -sf zvmlinux.initrd.mbx ../images/zImage.initrd.mbx + +zvmlinux: $(OBJECTS) $(LIBS) ../images/vmlinux.gz +# +# build the boot loader image and then compute the offset into it +# for the kernel image +# + $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=image=../images/vmlinux.gz \ + $@.tmp $@ +# +# then with the offset rebuild the bootloader so we know where the kernel is +# + $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \ + -DZIMAGE_OFFSET=`sh $(OFFSET) $(OBJDUMP) $@ image` \ + -DZIMAGE_SIZE=`sh $(SIZE) $(OBJDUMP) $@ image` \ + -c -o misc.o misc.c + $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=image=../images/vmlinux.gz \ + $@.tmp ../images/$@.mbx +# Remove zvmlinux and zvmlinux.temp, we have ../images/zvmlinux.mbx + rm -f $@.tmp $@ + +znetboot : zImage + cp ../images/zImage.mbx $(TFTPIMAGE) + +znetboot.initrd : zImage.initrd + cp ../images/zImage.initrd.mbx $(TFTPIMAGE) + +include $(TOPDIR)/Rules.make diff --git a/arch/ppc/boot/mbx/embed_config.c b/arch/ppc/boot/mbx/embed_config.c new file mode 100644 index 000000000000..18a381cdd2a1 --- /dev/null +++ b/arch/ppc/boot/mbx/embed_config.c @@ -0,0 +1,593 @@ +/* + * BK Id: SCCS/s.embed_config.c 1.7 05/18/01 07:54:04 patch + */ + +/* Board specific functions for those embedded 8xx boards that do + * not have boot monitor support for board information. + */ +#include <linux/types.h> +#include <linux/config.h> +#ifdef CONFIG_8xx +#include <asm/mpc8xx.h> +#endif +#ifdef CONFIG_8260 +#include <asm/mpc8260.h> +#include <asm/immap_8260.h> +#endif + + +/* IIC functions. + * These are just the basic master read/write operations so we can + * examine serial EEPROM. + */ +extern void iic_read(uint devaddr, u_char *buf, uint offset, uint count); +static u_char aschex_to_byte(u_char *cp); + +/* Supply a default Ethernet address for those eval boards that don't + * ship with one. This is an address from the MBX board I have, so + * it is unlikely you will find it on your network. + */ +static ushort def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 }; + +#if defined(CONFIG_MBX) + +/* The MBX hands us a pretty much ready to go board descriptor. This + * is where the idea started in the first place. + */ +void +embed_config(bd_t *bd) +{ + u_char *mp; + u_char eebuf[128]; + int i; + + /* Read the first 128 bytes of the EEPROM. There is more, + * but this is all we need. + */ + iic_read(0xa4, eebuf, 0, 128); + + /* All we are looking for is the Ethernet MAC address. The + * first 8 bytes are 'MOTOROLA', so check for part of that. + * If it's there, assume we have a valid MAC address. If not, + * grab our default one. + */ + if ((*(uint *)eebuf) == 0x4d4f544f) + mp = &eebuf[0x4c]; + else + mp = (u_char *)def_enet_addr; + + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *mp++; + } + + /* The boot rom passes these to us in MHz. Linux now expects + * them to be in Hz. + */ + bd->bi_intfreq *= 1000000; + bd->bi_busfreq *= 1000000; + + /* Stuff a baud rate here as well. + */ + bd->bi_baudrate = 9600; +} +#endif /* CONFIG_MBX */ + +#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPX6) + +/* Helper functions for Embedded Planet boards. +*/ +static void +rpx_eth(bd_t *bd, u_char *cp) +{ + int i; + + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = aschex_to_byte(cp); + cp += 2; + } +} + +static uint +rpx_baseten(u_char *cp) +{ + uint retval; + + retval = 0; + + while (*cp != '\n') { + retval *= 10; + retval += (*cp) - '0'; + cp++; + } + return(retval); +} + +static void +rpx_brate(bd_t *bd, u_char *cp) +{ + uint rate; + + rate = 0; + + while (*cp != '\n') { + rate *= 10; + rate += (*cp) - '0'; + cp++; + } + + bd->bi_baudrate = rate * 100; +} + +static void +rpx_memsize(bd_t *bd, u_char *cp) +{ + uint size; + + size = 0; + + while (*cp != '\n') { + size *= 10; + size += (*cp) - '0'; + cp++; + } + + bd->bi_memsize = size * 1024 * 1024; +} + +static void +rpx_cpuspeed(bd_t *bd, u_char *cp) +{ + uint num, den; + + num = den = 0; + + while (*cp != '\n') { + num *= 10; + num += (*cp) - '0'; + cp++; + if (*cp == '/') { + cp++; + den = (*cp) - '0'; + break; + } + } + + /* I don't know why the RPX just can't state the actual + * CPU speed..... + */ + if (den) { + num /= den; + num *= den; + } + bd->bi_intfreq = bd->bi_busfreq = num * 1000000; + + /* The 8xx can only run a maximum 50 MHz bus speed (until + * Motorola changes this :-). Greater than 50 MHz parts + * run internal/2 for bus speed. + */ + if (num > 50) + bd->bi_busfreq /= 2; +} + +/* Because I didn't find anything that would do this....... +*/ +u_char +aschex_to_byte(u_char *cp) +{ + u_char byte, c; + + c = *cp++; + + if ((c >= 'A') && (c <= 'F')) { + c -= 'A'; + c += 10; + } + else if ((c >= 'a') && (c <= 'f')) { + c -= 'a'; + c += 10; + } + else { + c -= '0'; + } + + byte = c * 16; + + c = *cp; + + if ((c >= 'A') && (c <= 'F')) { + c -= 'A'; + c += 10; + } + else if ((c >= 'a') && (c <= 'f')) { + c -= 'a'; + c += 10; + } + else { + c -= '0'; + } + + byte += c; + + return(byte); +} +#endif + +#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) + +/* Read the EEPROM on the RPX-Lite board. +*/ +void +embed_config(bd_t *bd) +{ + u_char eebuf[256], *cp; + + /* Read the first 256 bytes of the EEPROM. I think this + * is really all there is, and I hope if it gets bigger the + * info we want is still up front. + */ +#if 1 + iic_read(0xa8, eebuf, 0, 128); + iic_read(0xa8, &eebuf[128], 128, 128); + + /* We look for two things, the Ethernet address and the + * serial baud rate. The records are separated by + * newlines. + */ + cp = eebuf; + for (;;) { + if (*cp == 'E') { + cp++; + if (*cp == 'A') { + cp += 2; + rpx_eth(bd, cp); + } + } + if (*cp == 'S') { + cp++; + if (*cp == 'B') { + cp += 2; + rpx_brate(bd, cp); + } + } + if (*cp == 'D') { + cp++; + if (*cp == '1') { + cp += 2; + rpx_memsize(bd, cp); + } + } + if (*cp == 'H') { + cp++; + if (*cp == 'Z') { + cp += 2; + rpx_cpuspeed(bd, cp); + } + } + + /* Scan to the end of the record. + */ + while ((*cp != '\n') && (*cp != 0xff)) + cp++; + + /* If the next character is a 0 or ff, we are done. + */ + cp++; + if ((*cp == 0) || (*cp == 0xff)) + break; + } + bd->bi_memstart = 0; +#else + /* For boards without initialized EEPROM. + */ + bd->bi_memstart = 0; + bd->bi_memsize = (8 * 1024 * 1024); + bd->bi_intfreq = 48000000; + bd->bi_busfreq = 48000000; + bd->bi_baudrate = 9600; +#endif +} +#endif /* RPXLITE || RPXCLASSIC */ + +#ifdef CONFIG_BSEIP +/* Build a board information structure for the BSE ip-Engine. + * There is more to come since we will add some environment + * variables and a function to read them. + */ +void +embed_config(bd_t *bd) +{ + u_char *cp; + int i; + + /* Baud rate and processor speed will eventually come + * from the environment variables. + */ + bd->bi_baudrate = 9600; + + /* Get the Ethernet station address from the Flash ROM. + */ + cp = (u_char *)0xfe003ffa; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } + + /* The rest of this should come from the environment as well. + */ + bd->bi_memstart = 0; + bd->bi_memsize = (16 * 1024 * 1024); + bd->bi_intfreq = 48000000; + bd->bi_busfreq = 48000000; +} +#endif /* BSEIP */ + +#ifdef CONFIG_FADS +/* Build a board information structure for the FADS. + */ +void +embed_config(bd_t *bd) +{ + u_char *cp; + int i; + + /* Just fill in some known values. + */ + bd->bi_baudrate = 9600; + + /* Use default enet. + */ + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } + + bd->bi_memstart = 0; + bd->bi_memsize = (8 * 1024 * 1024); + bd->bi_intfreq = 40000000; + bd->bi_busfreq = 40000000; +} +#endif /* FADS */ + +#ifdef CONFIG_8260 +/* Compute 8260 clock values if the rom doesn't provide them. + * We can't compute the internal core frequency (I don't know how to + * do that). + */ +static void +clk_8260(bd_t *bd) +{ + uint scmr, vco_out, clkin; + uint plldf, pllmf, busdf, brgdf, cpmdf; + volatile immap_t *ip; + + ip = (immap_t *)IMAP_ADDR; + scmr = ip->im_clkrst.car_scmr; + + /* The clkin is always bus frequency. + */ + clkin = bd->bi_busfreq; + + /* Collect the bits from the scmr. + */ + plldf = (scmr >> 12) & 1; + pllmf = scmr & 0xfff; + cpmdf = (scmr >> 16) & 0x0f; + busdf = (scmr >> 20) & 0x0f; + + /* This is arithmetic from the 8260 manual. + */ + vco_out = clkin / (plldf + 1); + vco_out *= 2 * (pllmf + 1); + bd->bi_vco = vco_out; /* Save for later */ + + bd->bi_cpmfreq = vco_out / 2; /* CPM Freq, in MHz */ + + /* Set Baud rate divisor. The power up default is divide by 16, + * but we set it again here in case it was changed. + */ + ip->im_clkrst.car_sccr = 1; /* DIV 16 BRG */ + bd->bi_brgfreq = vco_out / 16; +} +#endif + +#ifdef CONFIG_EST8260 +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + + bd = *bdp; +#if 0 + /* This is actually provided by my boot rom. I have it + * here for those people that may load the kernel with + * a JTAG/COP tool and not the rom monitor. + */ + bd->bi_baudrate = 115200; + bd->bi_intfreq = 200000000; + bd->bi_busfreq = 66666666; + bd->bi_cpmfreq = 66666666; + bd->bi_brgfreq = 33333333; + bd->bi_memsize = 16 * 1024 * 1024; +#else + /* The boot rom passes these to us in MHz. Linux now expects + * them to be in Hz. + */ + bd->bi_intfreq *= 1000000; + bd->bi_busfreq *= 1000000; + bd->bi_cpmfreq *= 1000000; + bd->bi_brgfreq *= 1000000; +#endif + + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } +} +#endif /* EST8260 */ + +#ifdef CONFIG_SBS8260 +/* We have to fill in everything. +*/ +static bd_t bdinfo; + +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + + /* This should provided by the boot rom. + */ + bd = &bdinfo; + *bdp = bd; + bd->bi_baudrate = 9600; + bd->bi_memsize = 64 * 1024 * 1024; + + /* Set all of the clocks. We have to know the speed of the + * external clock. The development board had 66 MHz. + */ + bd->bi_busfreq = 66666666; + clk_8260(bd); + + /* I don't know how to compute this yet. + */ + bd->bi_intfreq = 133000000; + + + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } +} +#endif /* SBS8260 */ + +#ifdef CONFIG_RPX6 +/* The pointer we are given is for the string of key values. + */ +static bd_t bdinfo; + +void +embed_config(bd_t **bdp) +{ + u_char *cp, *keyvals; + int i; + bd_t *bd; + + keyvals = (u_char *)*bdp; + + bd = &bdinfo; + *bdp = bd; + + /* This is almost identical to the RPX-Lite/Classic functions + * on the 8xx boards. It would be nice to have a key lookup + * function in a string, but the format of all of the fields + * is slightly different. + */ + cp = keyvals; + for (;;) { + if (*cp == 'E') { + cp++; + if (*cp == 'A') { + cp += 2; + rpx_eth(bd, cp); + } + } + if (*cp == 'S') { + cp++; + if (*cp == 'B') { + cp += 2; + bd->bi_baudrate = rpx_baseten(cp); + } + } + if (*cp == 'D') { + cp++; + if (*cp == '1') { + cp += 2; + bd->bi_memsize = rpx_baseten(cp) * 1024 * 1024; + } + } + if (*cp == 'X') { + cp++; + if (*cp == 'T') { + cp += 2; + bd->bi_busfreq = rpx_baseten(cp); + } + } + if (*cp == 'N') { + cp++; + if (*cp == 'V') { + cp += 2; + bd->bi_nvsize = rpx_baseten(cp) * 1024 * 1024; + } + } + + /* Scan to the end of the record. + */ + while ((*cp != '\n') && (*cp != 0xff)) + cp++; + + /* If the next character is a 0 or ff, we are done. + */ + cp++; + if ((*cp == 0) || (*cp == 0xff)) + break; + } + bd->bi_memstart = 0; + + /* The memory size includes both the 60x and local bus DRAM. + * I don't want to use the local bus DRAM for real memory, + * so subtract it out. It would be nice if they were separate + * keys. + */ + bd->bi_memsize -= 32 * 1024 * 1024; + + /* Set all of the clocks. We have to know the speed of the + * external clock. + */ + clk_8260(bd); + + /* I don't know how to compute this yet. + */ + bd->bi_intfreq = 200000000; +} +#endif /* RPX6 for testing */ + +#ifdef CONFIG_ADS8260 +/* We have to fill in everything. +*/ +static bd_t bdinfo; + +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + + /* This should provided by the boot rom. + */ + bd = &bdinfo; + *bdp = bd; + bd->bi_baudrate = 9600; + bd->bi_memsize = 16 * 1024 * 1024; + + /* Set all of the clocks. We have to know the speed of the + * external clock. The development board had 66 MHz. + */ + bd->bi_busfreq = 66666666; + clk_8260(bd); + + /* I don't know how to compute this yet. + */ + bd->bi_intfreq = 200000000; + + + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } +} +#endif /* ADS8260 */ + diff --git a/arch/ppc/mbxboot/gzimage.c b/arch/ppc/boot/mbx/gzimage.c index 11ce5be8ea4b..954e6592b9a8 100644 --- a/arch/ppc/mbxboot/gzimage.c +++ b/arch/ppc/boot/mbx/gzimage.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.gzimage.c 1.6 05/18/01 15:17:06 cort + */ +/* * gzimage.c * * Dummy file to allow a compressed zImage to be added diff --git a/arch/ppc/mbxboot/head.S b/arch/ppc/boot/mbx/head.S index 87ed12725f8b..ba26d1360e85 100644 --- a/arch/ppc/mbxboot/head.S +++ b/arch/ppc/boot/mbx/head.S @@ -1,14 +1,15 @@ +/* + * BK Id: SCCS/s.head.S 1.9 05/18/01 07:54:04 patch + */ #include <linux/config.h> -#include "../kernel/ppc_defs.h" -#include "../kernel/ppc_asm.tmpl" +#include "../../kernel/ppc_defs.h" +#include "../../kernel/ppc_asm.tmpl" #include <asm/processor.h> #include <asm/cache.h> .text /* - * $Id: head.S,v 1.6 1999/09/15 00:02:25 dmalek Exp $ - * * This code is loaded by the ROM loader at some arbitrary location. * Move it to high memory so that it can load the kernel at 0x0000. * @@ -57,6 +58,9 @@ start_: andc r3,r3,r4 mtmsr r3 + li r4,0 /* Zero DER to prevent FRZ */ + mtspr SPRN_DER,r4 + /* check if we need to relocate ourselves to the link addr or were we loaded there to begin with -- Cort */ lis r4,start@h @@ -131,14 +135,8 @@ start_ldr: mr r23, r7 mr r24, r6 -#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) - bl rpx_cfg + bl embed_config mr r3, r21 -#endif -#ifdef CONFIG_BSEIP - bl bseip_cfg - mr r3, r21 -#endif bl serial_init /* Init MBX serial port */ mr r11, r21 @@ -147,10 +145,6 @@ start_ldr: mr r6, r24 #ifdef CONFIG_MBX - lis r18, 0xfa200000@h /* Disable Ethernet SCC */ - li r0, 0 - stw r0, 0x0a00(r18) - /* On the MBX (or anything that will TFTP load an ELF image), * we have to find the intermediate address. The ELF loader * only moves the Linux boostrap/decompress, not the zImage. diff --git a/arch/ppc/mbxboot/head_8260.S b/arch/ppc/boot/mbx/head_8260.S index 3e4bf700aade..6a063802f677 100644 --- a/arch/ppc/mbxboot/head_8260.S +++ b/arch/ppc/boot/mbx/head_8260.S @@ -1,13 +1,14 @@ -#include "../kernel/ppc_defs.h" -#include "../kernel/ppc_asm.tmpl" +/* + * BK Id: SCCS/s.head_8260.S 1.8 05/18/01 07:54:04 patch + */ +#include "../../kernel/ppc_defs.h" +#include "../../kernel/ppc_asm.tmpl" #include <asm/processor.h> #include <asm/cache.h> .text /* - * $Id: head.S,v 1.33 1999/09/08 01:06:58 cort Exp $ - * * Boot loader philosophy: * * ROM loads us to some arbitrary location diff --git a/arch/ppc/mbxboot/iic.c b/arch/ppc/boot/mbx/iic.c index 27de804a63b3..c47fd7c3832b 100644 --- a/arch/ppc/mbxboot/iic.c +++ b/arch/ppc/boot/mbx/iic.c @@ -1,3 +1,6 @@ +/* + * BK Id: SCCS/s.iic.c 1.8 05/18/01 07:54:04 patch + */ /* Minimal support functions to read configuration from IIC EEPROMS * on MPC8xx boards. Originally written for RPGC RPX-Lite. @@ -5,8 +8,8 @@ */ #include <linux/types.h> #include <asm/uaccess.h> -#include "asm/mpc8xx.h" -#include "../8xx_io/commproc.h" +#include <asm/mpc8xx.h> +#include "../../8xx_io/commproc.h" /* IIC functions. @@ -14,7 +17,6 @@ * examine serial EEPROM. */ void iic_read(uint devaddr, u_char *buf, uint offset, uint count); -u_char aschex_to_byte(u_char *cp); static int iic_init_done; @@ -23,7 +25,6 @@ iic_init() { volatile iic_t *iip; volatile i2c8xx_t *i2c; - volatile cbd_t *tbdf, *rbdf; volatile cpm8xx_t *cp; volatile immap_t *immap; uint dpaddr; @@ -116,13 +117,13 @@ static u_char iitemp[32]; void iic_read(uint devaddr, u_char *buf, uint offset, uint count) { - volatile iic_t *iip; - volatile i2c8xx_t *i2c; - volatile cbd_t *tbdf, *rbdf; + volatile iic_t *iip; + volatile i2c8xx_t *i2c; + volatile cbd_t *tbdf, *rbdf; volatile cpm8xx_t *cp; volatile immap_t *immap; u_char *tb; - uint dpaddr, temp; + uint temp; /* If the interface has not been initialized, do that now. */ @@ -145,7 +146,7 @@ iic_read(uint devaddr, u_char *buf, uint offset, uint count) */ tb = iitemp; tb = (u_char *)(((uint)tb + 15) & ~15); - tbdf->cbd_bufaddr = tb; + tbdf->cbd_bufaddr = (int)tb; *tb = devaddr & 0xfe; /* Device address */ *(tb+1) = offset; /* Offset */ tbdf->cbd_datlen = 2; /* Length */ @@ -185,7 +186,7 @@ iic_read(uint devaddr, u_char *buf, uint offset, uint count) * All that is used is the first byte for address, the remainder * is just used for timing (and doesn't really have to exist). */ - tbdf->cbd_bufaddr = tb; + tbdf->cbd_bufaddr = (int)tb; *tb = devaddr | 1; /* Device address */ rbdf->cbd_bufaddr = (uint)buf; /* Desination buffer */ tbdf->cbd_datlen = rbdf->cbd_datlen = count + 1; /* Length */ @@ -215,45 +216,3 @@ iic_read(uint devaddr, u_char *buf, uint offset, uint count) */ i2c->i2c_i2mod = 0; } - -/* Because I didn't find anything that would do this....... -*/ -u_char -aschex_to_byte(u_char *cp) -{ - u_char byte, c; - - c = *cp++; - - if ((c >= 'A') && (c <= 'F')) { - c -= 'A'; - c += 10; - } - else if ((c >= 'a') && (c <= 'f')) { - c -= 'a'; - c += 10; - } - else { - c -= '0'; - } - - byte = c * 16; - - c = *cp; - - if ((c >= 'A') && (c <= 'F')) { - c -= 'A'; - c += 10; - } - else if ((c >= 'a') && (c <= 'f')) { - c -= 'a'; - c += 10; - } - else { - c -= '0'; - } - - byte += c; - - return(byte); -} diff --git a/arch/ppc/mbxboot/m8260_tty.c b/arch/ppc/boot/mbx/m8260_tty.c index 167abbdccdc2..0035c14db7a4 100644 --- a/arch/ppc/mbxboot/m8260_tty.c +++ b/arch/ppc/boot/mbx/m8260_tty.c @@ -1,11 +1,14 @@ +/* + * BK Id: SCCS/s.m8260_tty.c 1.7 05/18/01 07:54:04 patch + */ /* Minimal serial functions needed to send messages out the serial * port on SMC1. */ #include <linux/types.h> -#include "asm/mpc8260.h" -#include "asm/cpm_8260.h" +#include <asm/mpc8260.h> +#include <asm/cpm_8260.h> uint no_print; extern char *params[]; @@ -13,11 +16,21 @@ extern int nparams; static u_char cons_hold[128], *sgptr; static int cons_hold_cnt; +/* If defined, enables serial console. The value (1 through 4) + * should designate which SCC is used, but this isn't complete. Only + * SCC1 is known to work at this time. + */ +#ifdef CONFIG_SCC_CONSOLE +#define SCC_CONSOLE 1 +#endif + void serial_init(bd_t *bd) { volatile smc_t *sp; volatile smc_uart_t *up; + volatile scc_t *sccp; + volatile scc_uart_t *sup; volatile cbd_t *tbdf, *rbdf; volatile immap_t *ip; volatile iop8260_t *io; @@ -25,14 +38,43 @@ serial_init(bd_t *bd) uint dpaddr, memaddr; ip = (immap_t *)IMAP_ADDR; + cp = &ip->im_cpm; + io = &ip->im_ioport; + + /* Perform a reset. + */ + cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG); + + /* Wait for it. + */ + while (cp->cp_cpcr & CPM_CR_FLG); + +#ifdef CONFIG_ADS8260 + /* Enable the RS-232 transceivers. + */ + *(volatile uint *)(BCSR_ADDR + 4) &= + ~(BCSR1_RS232_EN1 | BCSR1_RS232_EN2); +#endif + +#ifdef SCC_CONSOLE + sccp = (scc_t *)&(ip->im_scc[SCC_CONSOLE-1]); + sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)]; + sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); + sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); + /* Use Port D for SCC1 instead of other functions. + */ + io->iop_ppard |= 0x00000003; + io->iop_psord &= ~0x00000001; /* Rx */ + io->iop_psord |= 0x00000002; /* Tx */ + io->iop_pdird &= ~0x00000001; /* Rx */ + io->iop_pdird |= 0x00000002; /* Tx */ + +#else sp = (smc_t*)&(ip->im_smc[0]); *(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1; up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1]; - cp = &ip->im_cpm; - io = &ip->im_ioport; - /* Disable transmitter/receiver. */ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); @@ -43,6 +85,7 @@ serial_init(bd_t *bd) io->iop_pdird |= 0x00400000; io->iop_pdird &= ~0x00800000; io->iop_psord &= ~0x00c00000; +#endif /* Allocate space for two buffer descriptors in the DP ram. * For now, this address seems OK, but it may have to @@ -52,11 +95,7 @@ serial_init(bd_t *bd) /* Grab a few bytes from the top of memory. */ -#if 1 memaddr = (bd->bi_memsize - 256) & ~15; -#else - memaddr = 0x0f002c00; -#endif /* Set the physical address of the host memory buffers in * the buffer descriptors. @@ -70,6 +109,62 @@ serial_init(bd_t *bd) /* Set up the uart parameters in the parameter ram. */ +#ifdef SCC_CONSOLE + sup->scc_genscc.scc_rbase = dpaddr; + sup->scc_genscc.scc_tbase = dpaddr + sizeof(cbd_t); + + /* Set up the uart parameters in the + * parameter ram. + */ + sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB; + sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB; + + sup->scc_genscc.scc_mrblr = 128; + sup->scc_maxidl = 8; + sup->scc_brkcr = 1; + sup->scc_parec = 0; + sup->scc_frmec = 0; + sup->scc_nosec = 0; + sup->scc_brkec = 0; + sup->scc_uaddr1 = 0; + sup->scc_uaddr2 = 0; + sup->scc_toseq = 0; + sup->scc_char1 = 0x8000; + sup->scc_char2 = 0x8000; + sup->scc_char3 = 0x8000; + sup->scc_char4 = 0x8000; + sup->scc_char5 = 0x8000; + sup->scc_char6 = 0x8000; + sup->scc_char7 = 0x8000; + sup->scc_char8 = 0x8000; + sup->scc_rccm = 0xc0ff; + + /* Send the CPM an initialize command. + */ + cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0, + CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sccp->scc_gsmrh = 0; + sccp->scc_gsmrl = + (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); + + /* Disable all interrupts and clear all pending + * events. + */ + sccp->scc_sccm = 0; + sccp->scc_scce = 0xffff; + sccp->scc_dsr = 0x7e7e; + sccp->scc_pmsr = 0x3000; + + /* Wire BRG1 to SCC1. The console driver will take care of + * others. + */ + ip->im_cpmux.cmx_scr = 0; +#else up->smc_rbase = dpaddr; up->smc_tbase = dpaddr+sizeof(cbd_t); up->smc_rfcr = CPMFCR_EB; @@ -77,6 +172,8 @@ serial_init(bd_t *bd) up->smc_brklen = 0; up->smc_brkec = 0; up->smc_brkcr = 0; + up->smc_mrblr = 128; + up->smc_maxidl = 8; /* Set UART mode, 8 bit, no parity, one stop. * Enable receive and transmit. @@ -90,10 +187,13 @@ serial_init(bd_t *bd) /* Set up the baud rate generator. */ - ip->im_clkrst.car_sccr = 0; /* DIV 4 BRG */ ip->im_cpmux.cmx_smr = 0; +#endif + + /* The baud rate divisor needs to be coordinated with clk_8260(). + */ ip->im_brgc1 = - ((((bd->bi_brgfreq * 1000000)/16) / bd->bi_baudrate) << 1) | + (((bd->bi_brgfreq/16) / bd->bi_baudrate) << 1) | CPM_BRG_EN; /* Make the first buffer the only buffer. @@ -101,38 +201,38 @@ serial_init(bd_t *bd) tbdf->cbd_sc |= BD_SC_WRAP; rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; -#if 0 - /* Single character receive. - */ - up->smc_mrblr = 1; - up->smc_maxidl = 0; -#else - up->smc_mrblr = 128; - up->smc_maxidl = 8; -#endif - /* Initialize Tx/Rx parameters. */ +#ifdef SCC_CONSOLE + sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#else cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG; while (cp->cp_cpcr & CPM_CR_FLG); /* Enable transmitter/receiver. */ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; +#endif } void -serial_putchar(const char c) +serial_putc(void *ignored, const char c) { volatile cbd_t *tbdf; volatile char *buf; volatile smc_uart_t *up; + volatile scc_uart_t *sup; volatile immap_t *ip; extern bd_t *board_info; ip = (immap_t *)IMAP_ADDR; +#ifdef SCC_CONSOLE + sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)]; + tbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_tbase]; +#else up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]); tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase]; +#endif /* Wait for last character to go. */ @@ -145,7 +245,7 @@ serial_putchar(const char c) } char -serial_getc() +serial_getc(void *ignored) { char c; @@ -165,13 +265,19 @@ serial_readbuf(u_char *cbuf) volatile cbd_t *rbdf; volatile char *buf; volatile smc_uart_t *up; + volatile scc_uart_t *sup; volatile immap_t *ip; int i, nc; ip = (immap_t *)IMAP_ADDR; +#ifdef SCC_CONSOLE + sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)]; + rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase]; +#else up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]); rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase]; +#endif /* Wait for character to show up. */ @@ -186,16 +292,21 @@ serial_readbuf(u_char *cbuf) } int -serial_tstc() +serial_tstc(void *ignored) { volatile cbd_t *rbdf; volatile smc_uart_t *up; + volatile scc_uart_t *sup; volatile immap_t *ip; ip = (immap_t *)IMAP_ADDR; +#ifdef SCC_CONSOLE + sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)]; + rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase]; +#else up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]); rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase]; +#endif return(!(rbdf->cbd_sc & BD_SC_EMPTY)); } - diff --git a/arch/ppc/mbxboot/m8xx_tty.c b/arch/ppc/boot/mbx/m8xx_tty.c index 811a1379613c..992800e01d72 100644 --- a/arch/ppc/mbxboot/m8xx_tty.c +++ b/arch/ppc/boot/mbx/m8xx_tty.c @@ -1,3 +1,6 @@ +/* + * BK Id: SCCS/s.m8xx_tty.c 1.8 05/18/01 07:54:04 patch + */ /* Minimal serial functions needed to send messages out the serial @@ -14,7 +17,7 @@ #include <linux/types.h> #include <asm/uaccess.h> #include <asm/mpc8xx.h> -#include "../8xx_io/commproc.h" +#include "../../8xx_io/commproc.h" #ifdef CONFIG_MBX #define MBX_CSR1 ((volatile u_char *)0xfa100000) @@ -41,7 +44,7 @@ serial_init(bd_t *bd) volatile smc_uart_t *up; volatile cbd_t *tbdf, *rbdf; volatile cpm8xx_t *cp; - uint dpaddr, memaddr; + uint dpaddr, memaddr, ui; cp = cpmp; sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]); @@ -51,6 +54,12 @@ serial_init(bd_t *bd) */ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); +#ifdef CONFIG_FADS + /* Enable SMC1/2 transceivers. + */ + *((volatile uint *)BCSR1) &= ~(BCSR1_RS232EN_1|BCSR1_RS232EN_2); +#endif + #ifndef CONFIG_MBX { /* Initialize SMCx and use it for the console port. @@ -116,12 +125,15 @@ serial_init(bd_t *bd) * This wires BRG1 to SMC1 and BRG2 to SMC2; */ cp->cp_simode = 0x10000000; + ui = bd->bi_intfreq / 16 / bd->bi_baudrate; #ifdef TQM_SMC2_CONSOLE cp->cp_brgc2 = #else cp->cp_brgc1 = #endif - ((((bd->bi_intfreq * 1000000)/16) / bd->bi_baudrate) << 1) | CPM_BRG_EN; + ((ui - 1) < 4096) + ? (((ui - 1) << 1) | CPM_BRG_EN) + : ((((ui / 16) - 1) << 1) | CPM_BRG_EN | CPM_BRG_DIV16); #else /* CONFIG_MBX */ if (*MBX_CSR1 & CSR1_COMEN) { @@ -182,7 +194,7 @@ serial_init(bd_t *bd) */ cp->cp_simode = 0x10000000; cp->cp_brgc1 = - ((((bd->bi_intfreq * 1000000)/16) / 9600) << 1) | CPM_BRG_EN; + (((bd->bi_intfreq/16) / 9600) << 1) | CPM_BRG_EN; /* Enable SMC1 for console output. */ @@ -223,7 +235,7 @@ serial_init(bd_t *bd) } void -serial_putchar(const char c) +serial_putc(void *ignored, const char c) { volatile cbd_t *tbdf; volatile char *buf; @@ -243,7 +255,7 @@ serial_putchar(const char c) } char -serial_getc() +serial_getc(void *ignored) { volatile cbd_t *rbdf; volatile char *buf; @@ -264,7 +276,7 @@ serial_getc() } int -serial_tstc() +serial_tstc(void *ignored) { volatile cbd_t *rbdf; volatile smc_uart_t *up; diff --git a/arch/ppc/mbxboot/misc.c b/arch/ppc/boot/mbx/misc.c index ac400b8c68f7..846d8877f152 100644 --- a/arch/ppc/mbxboot/misc.c +++ b/arch/ppc/boot/mbx/misc.c @@ -1,19 +1,18 @@ /* - * misc.c - * - * $Id: misc.c,v 1.2 1999/09/14 05:55:29 dmalek Exp $ - * + * BK Id: SCCS/s.misc.c 1.9 05/18/01 07:54:04 patch + */ +/* * Adapted for PowerPC by Gary Thomas * * Rewritten by Cort Dougan (cort@cs.nmt.edu) * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort */ +#include <linux/config.h> #include <linux/types.h> -#include "../coffboot/zlib.h" -#include "asm/residual.h" +#include "zlib.h" +#include <asm/residual.h> #include <linux/elf.h> -#include <linux/config.h> #include <asm/page.h> #include <asm/processor.h> #include <asm/mmu.h> @@ -58,15 +57,14 @@ unsigned int initrd_offset, initrd_size; char cmd_buf[256]; char *cmd_line = cmd_buf; -char *root_string = "root=/dev/nfs rw"; -char *nfsaddrs_string = "nfsaddrs="; -char *nfsroot_string = "nfsroot="; -char *defroot_string = "/sys/mbxroot"; -char *ramroot_string = "root=/dev/ram"; -int do_ipaddrs(char **cmd_cp, int echo); -void do_nfsroot(char **cmd_cp, char *dp); -int strncmp(const char * cs,const char * ct,size_t count); -char *strrchr(const char * s, int c); +/* This is the default cmdline that will be given to the user at boot time.. + * If none was specified at compile time, we'll give it one that should work. + * -- Tom */ +#ifdef CONFIG_CMDLINE_BOOL +char compiled_string[] = CONFIG_CMDLINE; +#endif +char ramroot_string[] = "root=/dev/ram"; +char netroot_string[] = "root=/dev/nfs rw"; bd_t hold_resid_buf; bd_t *hold_residual = &hold_resid_buf; @@ -74,167 +72,14 @@ unsigned long initrd_start = 0, initrd_end = 0; char *zimage_start; int zimage_size; -void puts(const char *); -void putc(const char c); -void puthex(unsigned long val); -void _bcopy(char *src, char *dst, int len); -void * memcpy(void * __dest, __const void * __src, - int __n); -void gunzip(void *, int, unsigned char *, int *); - -void pause() -{ - puts("pause\n"); -} - -void exit() -{ - puts("exit\n"); - while(1); -} - -/* The MPC8xx is just the serial port. -*/ -tstc(void) -{ - return (serial_tstc()); -} - -getc(void) -{ - while (1) { - if (serial_tstc()) return (serial_getc()); - } -} - -void -putc(const char c) -{ - serial_putchar(c); -} - -void puts(const char *s) -{ - char c; - - while ( ( c = *s++ ) != '\0' ) { - serial_putchar(c); - if ( c == '\n' ) - serial_putchar('\r'); - } -} - -void * memcpy(void * __dest, __const void * __src, - int __n) -{ - int i; - char *d = (char *)__dest, *s = (char *)__src; - - for (i=0;i<__n;i++) d[i] = s[i]; -} - -int memcmp(__const void * __dest, __const void * __src, - int __n) -{ - int i; - char *d = (char *)__dest, *s = (char *)__src; - - for (i=0;i<__n;i++, d++, s++) - { - if (*d != *s) - { - return (*s - *d); - } - } - return (0); -} - -void error(char *x) -{ - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); - - while(1); /* Halt */ -} - -void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p = avail_ram; - - size *= items; - size = (size + 7) & -8; - avail_ram += size; - if (avail_ram > end_avail) { - puts("oops... out of memory\n"); - pause(); - } - return p; -} - -void zfree(void *x, void *addr, unsigned nb) -{ -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - - -void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - puts("bad gzipped data\n"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - puts("gunzip: ran out of data in header\n"); - exit(); - } - - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - puts("inflateInit2 returned %d\n"); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - puts("inflate returned "); - puthex(r); - puts("\n"); - exit(); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); -} - -unsigned char sanity[0x2000]; +extern void puts(const char *); +extern void putc(const char c); +extern void udelay(long x); +extern void puthex(unsigned long val); +extern void * memcpy(void * __dest, __const void * __src, __kernel_size_t __n); +extern void gunzip(void *, int, unsigned char *, int *); +extern int tstc(void); +extern int getc(void); unsigned long decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp) @@ -242,13 +87,11 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, b int timer; extern unsigned long start; char *cp, ch; - unsigned long i; - char *dp; #ifdef CONFIG_8260 /* I don't know why I didn't do it this way on the 8xx....... */ - embed_config(bp); + embed_config(&bp); serial_init(bp); #endif @@ -375,19 +218,36 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, b puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); puthex((unsigned long)end_avail); puts("\n"); - puts("\nLinux/PPC load: "); timer = 0; cp = cmd_line; - + /* This is where we try and pick the right command line for booting. + * If we were given one at compile time, use it. It Is Right. + * If we weren't, see if we have a ramdisk. If so, thats root. + * When in doubt, give them the netroot (root=/dev/nfs rw) -- Tom */ +#ifdef CONFIG_CMDLINE_BOOL + memcpy (cmd_line, compiled_string, sizeof(compiled_string)); +#else + if (initrd_start) + memcpy (cmd_line, ramroot_string, sizeof(ramroot_string)); + else + memcpy (cmd_line, netroot_string, sizeof(netroot_string)); +#endif + while ( *cp ) putc(*cp++); while (timer++ < 5*1000) { if (tstc()) { while ((ch = getc()) != '\n' && ch != '\r') { - if (ch == '\b') { + if (ch == '\b' || ch == '\177') { if (cp != cmd_line) { cp--; puts("\b \b"); } + } else if (ch == '\030' /* ^x */ + || ch == '\025') { /* ^u */ + while (cp != cmd_line) { + cp--; + puts("\b \b"); + } } else { *cp++ = ch; putc(ch); @@ -398,28 +258,7 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, b udelay(1000); /* 1 msec */ } *cp = 0; - - /* If the command line is not filled in, we will automatically - * create the default boot. - */ - if (cmd_line[0] == 0) { - - /* An initrd on these boards means we booted from Flash - * ROM and want to use the ramdisk as the root file system. - * Otherwise, we perform a diskless NFS boot. - */ - if (initrd_start) - dp = ramroot_string; - else - dp = root_string; - while (*dp != 0) - *cp++ = *dp++; - *cp = 0; - } - - puts("\n"); - - puts("Uncompressing Linux..."); + puts("\nUncompressing Linux..."); gunzip(0, 0x400000, zimage_start, &zimage_size); puts("done.\n"); @@ -427,19 +266,6 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, b return (unsigned long)hold_residual; } -void puthex(unsigned long val) -{ - unsigned char buf[10]; - int i; - for (i = 7; i >= 0; i--) - { - buf[i] = "0123456789ABCDEF"[val & 0x0F]; - val >>= 4; - } - buf[8] = '\0'; - puts(buf); -} - /* * PCI/ISA I/O support */ @@ -468,9 +294,3 @@ local_to_PCI(unsigned long addr) { return ((addr & 0x7FFFFFFF) | 0x80000000); } - -void -_bcopy(char *src, char *dst, int len) -{ - while (len--) *dst++ = *src++; -} diff --git a/arch/ppc/mbxboot/pci.c b/arch/ppc/boot/mbx/pci.c index 4c3332ef8998..85309d68c8cc 100644 --- a/arch/ppc/mbxboot/pci.c +++ b/arch/ppc/boot/mbx/pci.c @@ -1,3 +1,6 @@ +/* + * BK Id: SCCS/s.pci.c 1.6 05/18/01 15:17:06 cort + */ /* Stand alone funtions for QSpan Tundra support. */ #include <linux/types.h> diff --git a/arch/ppc/mbxboot/qspan_pci.c b/arch/ppc/boot/mbx/qspan_pci.c index f94105b2a4f7..d3bf2f1dc345 100644 --- a/arch/ppc/mbxboot/qspan_pci.c +++ b/arch/ppc/boot/mbx/qspan_pci.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.qspan_pci.c 1.6 05/18/01 15:17:06 cort + */ +/* * LinuxPPC arch/ppc/kernel/qspan_pci.c Dan Malek (dmalek@jlc.net) * * QSpan Motorola bus to PCI bridge. The config address register diff --git a/arch/ppc/mbxboot/rdimage.c b/arch/ppc/boot/mbx/rdimage.c index e40fd1e2e94a..ffc577ec8e8d 100644 --- a/arch/ppc/mbxboot/rdimage.c +++ b/arch/ppc/boot/mbx/rdimage.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.rdimage.c 1.6 05/18/01 15:17:06 cort + */ +/* * rdimage.c * * Dummy file to allow a compressed initrd to be added diff --git a/arch/ppc/boot/misc.c b/arch/ppc/boot/misc.c deleted file mode 100644 index d25f732b8e5b..000000000000 --- a/arch/ppc/boot/misc.c +++ /dev/null @@ -1,845 +0,0 @@ -/* - * misc.c - * - * $Id: misc.c,v 1.68 1999/10/20 22:08:08 cort Exp $ - * - * Adapted for PowerPC by Gary Thomas - * - * Rewritten by Cort Dougan (cort@cs.nmt.edu) - * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort - */ - -#include <linux/types.h> -#include "../coffboot/zlib.h" -#include "asm/residual.h" -#include <linux/elf.h> -#include <linux/config.h> -#include <asm/page.h> -#include <asm/processor.h> -#include <asm/bootinfo.h> -#include <asm/mmu.h> -#if defined(CONFIG_SERIAL_CONSOLE) -#include "ns16550.h" -struct NS16550 *com_port; -#endif /* CONFIG_SERIAL_CONSOLE */ - -/* - * Please send me load/board info and such data for hardware not - * listed here so I can keep track since things are getting tricky - * with the different load addrs with different firmware. This will - * help to avoid breaking the load/boot process. - * -- Cort - */ -char *avail_ram; -char *end_avail; -extern char _end[]; - -#ifdef CONFIG_CMDLINE -#define CMDLINE CONFIG_CMDLINE -#else -#define CMDLINE ""; -#endif -char cmd_preset[] = CMDLINE; -char cmd_buf[256]; -char *cmd_line = cmd_buf; - -int keyb_present = 1; /* keyboard controller is present by default */ -RESIDUAL hold_resid_buf; -RESIDUAL *hold_residual = &hold_resid_buf; -unsigned long initrd_start = 0, initrd_end = 0; -char *zimage_start; -int zimage_size; - -char *vidmem = (char *)0xC00B8000; -int lines, cols; -int orig_x, orig_y; - -void puts(const char *); -void putc(const char c); -void puthex(unsigned long val); -void _bcopy(char *src, char *dst, int len); -void * memcpy(void * __dest, __const void * __src, - int __n); -void gunzip(void *, int, unsigned char *, int *); -static int _cvt(unsigned long val, char *buf, long radix, char *digits); -unsigned char inb(int); - -void pause() -{ - puts("pause\n"); -} - -void exit() -{ - puts("exit\n"); - while(1); -} - -static void clear_screen() -{ - int i, j; - for (i = 0; i < lines; i++) { - for (j = 0; j < cols; j++) { - vidmem[((i*cols)+j)*2] = ' '; - vidmem[((i*cols)+j)*2+1] = 0x07; - } - } -} - -static void scroll() -{ - int i; - - memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 ); - for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) - vidmem[i] = ' '; -} - -tstc(void) -{ -#if defined(CONFIG_SERIAL_CONSOLE) - if (keyb_present) - return (CRT_tstc() || NS16550_tstc(com_port)); - else - NS16550_tstc(com_port); -#else - return (CRT_tstc() ); -#endif /* CONFIG_SERIAL_CONSOLE */ -} - -getc(void) -{ - while (1) { -#if defined(CONFIG_SERIAL_CONSOLE) - if (NS16550_tstc(com_port)) return (NS16550_getc(com_port)); -#endif /* CONFIG_SERIAL_CONSOLE */ - if (keyb_present) - if (CRT_tstc()) return (CRT_getc()); - } -} - -void -putc(const char c) -{ - int x,y; - -#if defined(CONFIG_SERIAL_CONSOLE) - NS16550_putc(com_port, c); - if ( c == '\n' ) NS16550_putc(com_port, '\r'); -#endif /* CONFIG_SERIAL_CONSOLE */ - - x = orig_x; - y = orig_y; - - if ( c == '\n' ) { - x = 0; - if ( ++y >= lines ) { - scroll(); - y--; - } - } else if (c == '\r') { - x = 0; - } else if (c == '\b') { - if (x > 0) { - x--; - } - } else { - vidmem [ ( x + cols * y ) * 2 ] = c; - if ( ++x >= cols ) { - x = 0; - if ( ++y >= lines ) { - scroll(); - y--; - } - } - } - - cursor(x, y); - - orig_x = x; - orig_y = y; -} - -void puts(const char *s) -{ - int x,y; - char c; - - x = orig_x; - y = orig_y; - - while ( ( c = *s++ ) != '\0' ) { -#if defined(CONFIG_SERIAL_CONSOLE) - NS16550_putc(com_port, c); - if ( c == '\n' ) NS16550_putc(com_port, '\r'); -#endif /* CONFIG_SERIAL_CONSOLE */ - - if ( c == '\n' ) { - x = 0; - if ( ++y >= lines ) { - scroll(); - y--; - } - } else if (c == '\b') { - if (x > 0) { - x--; - } - } else { - vidmem [ ( x + cols * y ) * 2 ] = c; - if ( ++x >= cols ) { - x = 0; - if ( ++y >= lines ) { - scroll(); - y--; - } - } - } - } - - cursor(x, y); - - orig_x = x; - orig_y = y; -} - -void * memcpy(void * __dest, __const void * __src, - int __n) -{ - int i; - char *d = (char *)__dest, *s = (char *)__src; - - for (i=0;i<__n;i++) d[i] = s[i]; -} - -int memcmp(__const void * __dest, __const void * __src, - int __n) -{ - int i; - char *d = (char *)__dest, *s = (char *)__src; - - for (i=0;i<__n;i++, d++, s++) - { - if (*d != *s) - { - return (*s - *d); - } - } - return (0); -} - -void error(char *x) -{ - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); - - while(1); /* Halt */ -} - -void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p = avail_ram; - - size *= items; - size = (size + 7) & -8; - avail_ram += size; - if (avail_ram > end_avail) { - puts("oops... out of memory\n"); - pause(); - } - return p; -} - -void zfree(void *x, void *addr, unsigned nb) -{ -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - - -void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - puts("bad gzipped data\n"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - puts("gunzip: ran out of data in header\n"); - exit(); - } - - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - puts("inflateInit2 returned %d\n"); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - puts("inflate returned %d\n"); - exit(); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); -} - -unsigned long -decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, - RESIDUAL *residual, void *OFW_interface) -{ - int timer; - extern unsigned long start; - char *cp, ch; - unsigned long i; - BATU *u; - BATL *l; - unsigned long TotalMemory; - unsigned long orig_MSR; - int dev_handle; - int mem_info[2]; - int res, size; - unsigned char board_type; - unsigned char base_mod; - - lines = 25; - cols = 80; - orig_x = 0; - orig_y = 24; - - /* - * IBM's have the MMU on, so we have to disable it or - * things get really unhappy in the kernel when - * trying to setup the BATs with the MMU on - * -- Cort - */ - flush_instruction_cache(); - _put_HID0(_get_HID0() & ~0x0000C000); - _put_MSR((orig_MSR = _get_MSR()) & ~0x0030); - -#if defined(CONFIG_SERIAL_CONSOLE) - com_port = (struct NS16550 *)NS16550_init(0); -#endif /* CONFIG_SERIAL_CONSOLE */ - vga_init(0xC0000000); - - if (residual) - { - /* Is this Motorola PPCBug? */ - if ((1 & residual->VitalProductData.FirmwareSupports) && - (1 == residual->VitalProductData.FirmwareSupplier)) { - board_type = inb(0x800) & 0xF0; - - /* If this is genesis 2 board then check for no - * keyboard controller and more than one processor. - */ - if (board_type == 0xe0) { - base_mod = inb(0x803); - /* if a MVME2300/2400 or a Sitka then no keyboard */ - if((base_mod == 0xFA) || (base_mod == 0xF9) || - (base_mod == 0xE1)) { - keyb_present = 0; /* no keyboard */ - } - } - } - memcpy(hold_residual,residual,sizeof(RESIDUAL)); - } else { - /* Assume 32M in the absence of more info... */ - TotalMemory = 0x02000000; - /* - * This is a 'best guess' check. We want to make sure - * we don't try this on a PReP box without OF - * -- Cort - */ - while (OFW_interface && ((unsigned long)OFW_interface < 0x10000000) ) - { - /* The MMU needs to be on when we call OFW */ - _put_MSR(orig_MSR); - of_init(OFW_interface); - - /* get handle to memory description */ - res = of_finddevice("/memory@0", - &dev_handle); - // puthex(res); puts("\n"); - if (res) break; - - /* get the info */ - // puts("get info = "); - res = of_getprop(dev_handle, - "reg", - mem_info, - sizeof(mem_info), - &size); - // puthex(res); puts(", info = "); puthex(mem_info[0]); - // puts(" "); puthex(mem_info[1]); puts("\n"); - if (res) break; - - TotalMemory = mem_info[1]; - break; - } - hold_residual->TotalMemory = TotalMemory; - residual = hold_residual; - /* Turn MMU back off */ - _put_MSR(orig_MSR & ~0x0030); - } - - /* assume the chunk below 8M is free */ - end_avail = (char *)0x00800000; - - /* tell the user where we were loaded at and where we - * were relocated to for debugging this process - */ - puts("loaded at: "); puthex(load_addr); - puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); - if ( (unsigned long)load_addr != (unsigned long)&start ) - { - puts("relocated to: "); puthex((unsigned long)&start); - puts(" "); - puthex((unsigned long)((unsigned long)&start + (4*num_words))); - puts("\n"); - } - - if ( residual ) - { - puts("board data at: "); puthex((unsigned long)residual); - puts(" "); - puthex((unsigned long)((unsigned long)residual + sizeof(RESIDUAL))); - puts("\n"); - puts("relocated to: "); - puthex((unsigned long)hold_residual); - puts(" "); - puthex((unsigned long)((unsigned long)hold_residual + sizeof(RESIDUAL))); - puts("\n"); - } - - /* we have to subtract 0x10000 here to correct for objdump including the - size of the elf header which we strip -- Cort */ - zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET); - zimage_size = ZIMAGE_SIZE; - - if ( INITRD_OFFSET ) - initrd_start = load_addr - 0x10000 + INITRD_OFFSET; - else - initrd_start = 0; - initrd_end = INITRD_SIZE + initrd_start; - - /* - * Find a place to stick the zimage and initrd and - * relocate them if we have to. -- Cort - */ - avail_ram = (char *)PAGE_ALIGN((unsigned long)_end); - puts("zimage at: "); puthex((unsigned long)zimage_start); - puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n"); - if ( (unsigned long)zimage_start <= 0x00800000 ) - { - memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size ); - zimage_start = (char *)avail_ram; - puts("relocated to: "); puthex((unsigned long)zimage_start); - puts(" "); - puthex((unsigned long)zimage_size+(unsigned long)zimage_start); - puts("\n"); - avail_ram += zimage_size; - } - - /* relocate initrd */ - if ( initrd_start ) - { - puts("initrd at: "); puthex(initrd_start); - puts(" "); puthex(initrd_end); puts("\n"); - if ( (unsigned long)initrd_start <= 0x00800000 ) - { - memcpy( (void *)avail_ram, - (void *)initrd_start, initrd_end-initrd_start ); - puts("relocated to: "); - initrd_end = (unsigned long) avail_ram + (initrd_end-initrd_start); - initrd_start = (unsigned long)avail_ram; - puthex((unsigned long)initrd_start); - puts(" "); - puthex((unsigned long)initrd_end); - puts("\n"); - } - avail_ram = (char *)PAGE_ALIGN((unsigned long)initrd_end); - } - - avail_ram = (char *)0x00400000; - end_avail = (char *)0x00800000; - puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); - puthex((unsigned long)end_avail); puts("\n"); - - if (keyb_present) - CRT_tstc(); /* Forces keyboard to be initialized */ - - puts("\nLinux/PPC load: "); - timer = 0; - cp = cmd_line; - memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); - while ( *cp ) putc(*cp++); - while (timer++ < 5*1000) { - if (tstc()) { - while ((ch = getc()) != '\n' && ch != '\r') { - if (ch == '\b') { - if (cp != cmd_line) { - cp--; - puts("\b \b"); - } - } else { - *cp++ = ch; - putc(ch); - } - } - break; /* Exit 'timer' loop */ - } - udelay(1000); /* 1 msec */ - } - *cp = 0; - puts("\n"); - - puts("Uncompressing Linux..."); - gunzip(0, 0x400000, zimage_start, &zimage_size); - puts("done.\n"); - - { - struct bi_record *rec; - - rec = (struct bi_record *)PAGE_ALIGN(zimage_size); - - rec->tag = BI_FIRST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_BOOTLOADER_ID; - memcpy( (void *)rec->data, "prepboot", 9); - rec->size = sizeof(struct bi_record) + 8 + 1; - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_MACHTYPE; - rec->data[0] = _MACH_prep; - rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_CMD_LINE; - memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); - rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; - rec = (struct bi_record *)((ulong)rec + rec->size); - - rec->tag = BI_LAST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - } - puts("Now booting the kernel\n"); - return (unsigned long)hold_residual; -} - -void puthex(unsigned long val) -{ - unsigned char buf[10]; - int i; - for (i = 7; i >= 0; i--) - { - buf[i] = "0123456789ABCDEF"[val & 0x0F]; - val >>= 4; - } - buf[8] = '\0'; - puts(buf); -} - -/* - * PCI/ISA I/O support - */ - -volatile unsigned char *ISA_io = (unsigned char *)0x80000000; -volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000; - -void -outb(int port, char val) -{ - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - ISA_io[port] = val; -} - -unsigned char -inb(int port) -{ - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - return (ISA_io[port]); -} - -unsigned long -local_to_PCI(unsigned long addr) -{ - return ((addr & 0x7FFFFFFF) | 0x80000000); -} - -void -_bcopy(char *src, char *dst, int len) -{ - while (len--) *dst++ = *src++; -} - - -#define FALSE 0 -#define TRUE 1 -#include <stdarg.h> - -int -strlen(char *s) -{ - int len = 0; - while (*s++) len++; - return len; -} - -_printk(char const *fmt, ...) -{ - int ret; - va_list ap; - - va_start(ap, fmt); - ret = _vprintk(putc, fmt, ap); - va_end(ap); - return (ret); -} - -#define is_digit(c) ((c >= '0') && (c <= '9')) - -int -_vprintk(putc, fmt0, ap) -int (*putc)(); -const char *fmt0; -va_list ap; -{ - char c, sign, *cp; - int left_prec, right_prec, zero_fill, length, pad, pad_on_right; - char buf[32]; - long val; - while (c = *fmt0++) - { - if (c == '%') - { - c = *fmt0++; - left_prec = right_prec = pad_on_right = 0; - if (c == '-') - { - c = *fmt0++; - pad_on_right++; - } - if (c == '0') - { - zero_fill = TRUE; - c = *fmt0++; - } else - { - zero_fill = FALSE; - } - while (is_digit(c)) - { - left_prec = (left_prec * 10) + (c - '0'); - c = *fmt0++; - } - if (c == '.') - { - c = *fmt0++; - zero_fill++; - while (is_digit(c)) - { - right_prec = (right_prec * 10) + (c - '0'); - c = *fmt0++; - } - } else - { - right_prec = left_prec; - } - sign = '\0'; - switch (c) - { - case 'd': - case 'x': - case 'X': - val = va_arg(ap, long); - switch (c) - { - case 'd': - if (val < 0) - { - sign = '-'; - val = -val; - } - length = _cvt(val, buf, 10, "0123456789"); - break; - case 'x': - length = _cvt(val, buf, 16, "0123456789abcdef"); - break; - case 'X': - length = _cvt(val, buf, 16, "0123456789ABCDEF"); - break; - } - cp = buf; - break; - case 's': - cp = va_arg(ap, char *); - length = strlen(cp); - break; - case 'c': - c = va_arg(ap, long /*char*/); - (*putc)(c); - continue; - default: - (*putc)('?'); - } - pad = left_prec - length; - if (sign != '\0') - { - pad--; - } - if (zero_fill) - { - c = '0'; - if (sign != '\0') - { - (*putc)(sign); - sign = '\0'; - } - } else - { - c = ' '; - } - if (!pad_on_right) - { - while (pad-- > 0) - { - (*putc)(c); - } - } - if (sign != '\0') - { - (*putc)(sign); - } - while (length-- > 0) - { - (*putc)(c = *cp++); - if (c == '\n') - { - (*putc)('\r'); - } - } - if (pad_on_right) - { - while (pad-- > 0) - { - (*putc)(c); - } - } - } else - { - (*putc)(c); - if (c == '\n') - { - (*putc)('\r'); - } - } - } -} - -int _cvt(unsigned long val, char *buf, long radix, char *digits) -{ - char temp[80]; - char *cp = temp; - int length = 0; - if (val == 0) - { /* Special case */ - *cp++ = '0'; - } else - while (val) - { - *cp++ = digits[val % radix]; - val /= radix; - } - while (cp != temp) - { - *buf++ = *--cp; - length++; - } - *buf = '\0'; - return (length); -} - -_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base) -{ - int i, c; - if ((unsigned int)s > (unsigned int)p) - { - s = (unsigned int)s - (unsigned int)p; - } - while (s > 0) - { - if (base) - { - _printk("%06X: ", (int)p - (int)base); - } else - { - _printk("%06X: ", p); - } - for (i = 0; i < 16; i++) - { - if (i < s) - { - _printk("%02X", p[i] & 0xFF); - } else - { - _printk(" "); - } - if ((i % 2) == 1) _printk(" "); - if ((i % 8) == 7) _printk(" "); - } - _printk(" |"); - for (i = 0; i < 16; i++) - { - if (i < s) - { - c = p[i] & 0xFF; - if ((c < 0x20) || (c >= 0x7F)) c = '.'; - } else - { - c = ' '; - } - _printk("%c", c); - } - _printk("|\n"); - s -= 16; - p += 16; - } -} - -_dump_buf(unsigned char *p, int s) -{ - _printk("\n"); - _dump_buf_with_offset(p, s, 0); -} diff --git a/arch/ppc/boot/ns16550.c b/arch/ppc/boot/ns16550.c deleted file mode 100644 index db0b94d0395d..000000000000 --- a/arch/ppc/boot/ns16550.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * COM1 NS16550 support - */ - -#include "ns16550.h" -typedef struct NS16550 *NS16550_t; - -const NS16550_t COM_PORTS[] = { (NS16550_t) COM1, - (NS16550_t) COM2, - (NS16550_t) COM3, - (NS16550_t) COM4 }; - -volatile struct NS16550 * -NS16550_init(int chan) -{ - volatile struct NS16550 *com_port; - volatile unsigned char xx; - com_port = (struct NS16550 *) COM_PORTS[chan]; - /* See if port is present */ - com_port->lcr = 0x00; - com_port->ier = 0xFF; -#if 0 - if (com_port->ier != 0x0F) return ((struct NS16550 *)0); -#endif - com_port->ier = 0x00; - com_port->lcr = 0x80; /* Access baud rate */ - com_port->dll = 0xc; /* 9600 baud */ - com_port->dlm = 0xc >> 8; - com_port->lcr = 0x03; /* 8 data, 1 stop, no parity */ - com_port->mcr = 0x03; /* RTS/DTR */ - com_port->fcr = 0x07; /* Clear & enable FIFOs */ - return (com_port); -} - - -NS16550_putc(volatile struct NS16550 *com_port, unsigned char c) -{ - volatile int i; - while ((com_port->lsr & LSR_THRE) == 0) ; - com_port->thr = c; -} - -unsigned char -NS16550_getc(volatile struct NS16550 *com_port) -{ - while ((com_port->lsr & LSR_DR) == 0) ; - return (com_port->rbr); -} - -NS16550_tstc(volatile struct NS16550 *com_port) -{ - return ((com_port->lsr & LSR_DR) != 0); -} - - - diff --git a/arch/ppc/boot/ns16550.h b/arch/ppc/boot/ns16550.h deleted file mode 100644 index 4baf4c1c5f4e..000000000000 --- a/arch/ppc/boot/ns16550.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * NS16550 Serial Port - */ - -struct NS16550 - { - unsigned char rbr; /* 0 */ - unsigned char ier; /* 1 */ - unsigned char fcr; /* 2 */ - unsigned char lcr; /* 3 */ - unsigned char mcr; /* 4 */ - unsigned char lsr; /* 5 */ - unsigned char msr; /* 6 */ - unsigned char scr; /* 7 */ - }; - -#define thr rbr -#define iir fcr -#define dll rbr -#define dlm ier - -#define LSR_DR 0x01 /* Data ready */ -#define LSR_OE 0x02 /* Overrun */ -#define LSR_PE 0x04 /* Parity error */ -#define LSR_FE 0x08 /* Framing error */ -#define LSR_BI 0x10 /* Break */ -#define LSR_THRE 0x20 /* Xmit holding register empty */ -#define LSR_TEMT 0x40 /* Xmitter empty */ -#define LSR_ERR 0x80 /* Error */ - -#define COM1 0x800003F8 -#define COM2 0x800002F8 -#define COM3 0x800003F8 -#define COM4 0x80000388 diff --git a/arch/ppc/boot/pmac/Makefile b/arch/ppc/boot/pmac/Makefile new file mode 100644 index 000000000000..0de8bbad8b89 --- /dev/null +++ b/arch/ppc/boot/pmac/Makefile @@ -0,0 +1,115 @@ +# BK Id: SCCS/s.Makefile 1.8 05/21/01 09:10:38 trini +# +# Makefile for making XCOFF bootable images for booting on PowerMacs +# using Open Firmware. +# +# Paul Mackerras January 1997 +# +# Cleaned up, moved into arch/ppc/boot/pmac +# Tom Rini January 2001 + +OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment +COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic +CHRP_LD_ARGS = -Ttext 0x01000000 + +COMMONOBJS = start.o misc.o ../common/string.o image.o +COFFOBJS = ../common/coffcrt0.o $(COMMONOBJS) coffmain.o +CHRPOBJS = ../common/crt0.o $(COMMONOBJS) chrpmain.o +LIBS = $(TOPDIR)/lib/lib.a ../lib/zlib.a + +MKNOTE := ../utils/mknote +SIZE := ../utils/size +OFFSET := ../utils/offset +PIGGYBACK := ../utils/piggyback +HACKCOFF := ../utils/hack-coff + +ifeq ($(CONFIG_PPC64BRIDGE),y) +MSIZE=.64 +else +MSIZE= +endif + +ifeq ($(CONFIG_SMP),y) +TFTPIMAGE=/tftpboot/zImage.pmac.smp$(MSIZE) +else +TFTPIMAGE=/tftpboot/zImage.pmac$(MSIZE) +endif + +../common/crt0.o: + $(MAKE) -C ../common crt0.o + +../common/coffcrt0.o: + $(MAKE) -C ../common coffcrt0.o + +chrpmain.o: chrpmain.c + $(CC) $(CFLAGS) -DSYSMAP_OFFSET=0 -DSYSMAP_SIZE=0 -c chrpmain.c + +znetboot: vmlinux.coff vmlinux.elf-pmac zImage + cp ../images/vmlinux.coff $(TFTPIMAGE) + cp ../images/vmlinux.elf-pmac $(TFTPIMAGE).elf + +znetboot.initrd: vmlinux.coff.initrd vmlinux.initrd.elf-pmac + cp ../images/vmlinux.coff.initrd $(TFTPIMAGE) + cp ../images/vmlinux.elf-pmac.initrd $(TFTPIMAGE).elf + +#floppy: zImage +# mount -t hfs /dev/fd0 /mnt +# cp vmlinux.coff /mnt +# umount /mnt + +miboot.image: dummy.o ../images/vmlinux.gz + $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=../images/vmlinux.gz \ + dummy.o ../images/$@ + +miboot.image.initrd: miboot.image ../images/ramdisk.image.gz + $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=initrd=../images/ramdisk.image.gz \ + ../images/miboot.image ../images/$@ + +coffboot: $(COFFOBJS) $(LIBS) ../common/no_initrd.o ld.script ../images/vmlinux.gz + $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) ../common/no_initrd.o $(LIBS) + +coffboot.initrd: $(COFFOBJS) $(LIBS) initrd.o ld.script ../images/vmlinux.gz + $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) initrd.o $(LIBS) + +image.o: $(PIGGYBACK) ../images/vmlinux.gz + $(PIGGYBACK) image < ../images/vmlinux.gz | $(AS) -o $@ + +initrd.o: ../images/ramdisk.image.gz $(PIGGYBACK) + $(PIGGYBACK) initrd < ../images/ramdisk.image.gz | $(AS) -o $@ + +vmlinux.coff: coffboot $(HACKCOFF) + $(OBJCOPY) $(OBJCOPY_ARGS) coffboot ../images/$@ + $(HACKCOFF) ../images/$@ + rm -f coffboot + ln -sf vmlinux.coff ../images/zImage.pmac + +vmlinux.coff.initrd: coffboot.initrd $(HACKCOFF) + $(OBJCOPY) $(OBJCOPY_ARGS) coffboot.initrd ../images/$@ + $(HACKCOFF) ../images/$@ + rm -f coffboot.initrd + ln -sf vmlinux.coff.initrd ../images/zImage.initrd.pmac + +vmlinux.elf-pmac: $(CHRPOBJS) $(LIBS) ../common/no_initrd.o $(MKNOTE) ../images/vmlinux.gz + $(LD) $(CHRP_LD_ARGS) -o ../images/$@ $(CHRPOBJS) ../common/no_initrd.o $(LIBS) + $(MKNOTE) > note + $(OBJCOPY) ../images/$@ ../images/$@ --add-section=.note=note \ + --add-section=sysmap=$(TOPDIR)/System.map -R .comment + $(CC) $(CFLAGS) chrpmain.c -c -o chrpmain.o \ + -DSYSMAP_OFFSET=`sh $(OFFSET) $(OBJDUMP) ../images/$@ sysmap` \ + -DSYSMAP_SIZE=`sh $(SIZE) $(OBJDUMP) ../images/$@ sysmap` + $(LD) $(CHRP_LD_ARGS) -o ../images/$@ $(CHRPOBJS) ../common/no_initrd.o $(LIBS) + $(OBJCOPY) ../images/$@ ../images/$@ --add-section=.note=note \ + --add-section=sysmap=$(TOPDIR)/System.map -R .comment + rm -f note + +vmlinux.initrd.elf-pmac: $(CHRPOBJS) $(LIBS) initrd.o $(MKNOTE) ../images/vmlinux.gz + $(LD) $(CHRP_LD_ARGS) -o ../images/$@ $(CHRPOBJS) initrd.o $(LIBS) + $(MKNOTE) > note + $(OBJCOPY) ../images/$@ ../images/$@ --add-section=.note=note -R .comment + rm -f note + +zImage: vmlinux.coff vmlinux.elf-pmac miboot.image + +zImage.initrd: vmlinux.coff.initrd vmlinux.initrd.elf-pmac miboot.image.initrd + +include $(TOPDIR)/Rules.make diff --git a/arch/ppc/coffboot/chrpmain.c b/arch/ppc/boot/pmac/chrpmain.c index c2912bc61f84..67d53a7891db 100644 --- a/arch/ppc/coffboot/chrpmain.c +++ b/arch/ppc/boot/pmac/chrpmain.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.chrpmain.c 1.9 05/18/01 06:20:29 patch + */ +/* * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or @@ -31,6 +34,15 @@ void stop_imac_usb(void); #define SCRATCH_SIZE (128 << 10) +#ifdef CONFIG_CMDLINE +#define CMDLINE CONFIG_CMDLINE +#else +#define CMDLINE "" +#endif +char cmd_preset[] = CMDLINE; +char cmd_buf[256]; +char *cmd_line = cmd_buf; + char *avail_ram; char *begin_avail, *end_avail; char *avail_high; @@ -86,6 +98,7 @@ boot(int a1, int a2, void *prom) } flush_cache(dst, len); + memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); make_bi_recs((unsigned long) dst + len); sa = (unsigned long)PROG_START; @@ -122,7 +135,12 @@ void make_bi_recs(unsigned long addr) rec->data[1] = 1; rec->size = sizeof(struct bi_record) + sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); - + + rec->tag = BI_CMD_LINE; + memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); + rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; + rec = (struct bi_record *)((unsigned long)rec + rec->size); + #ifdef SYSMAP_OFFSET rec->tag = BI_SYSMAP; rec->data[0] = SYSMAP_OFFSET; diff --git a/arch/ppc/coffboot/coffmain.c b/arch/ppc/boot/pmac/coffmain.c index 49e769f2240e..025123c38caf 100644 --- a/arch/ppc/coffboot/coffmain.c +++ b/arch/ppc/boot/pmac/coffmain.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.coffmain.c 1.9 05/18/01 06:20:29 patch + */ +/* * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or @@ -29,6 +32,15 @@ void gunzip(void *, int, unsigned char *, int *); #define SCRATCH_SIZE (128 << 10) +#ifdef CONFIG_CMDLINE +#define CMDLINE CONFIG_CMDLINE +#else +#define CMDLINE "" +#endif +char cmd_preset[] = CMDLINE; +char cmd_buf[256]; +char *cmd_line = cmd_buf; + char *avail_ram; char *begin_avail, *end_avail; char *avail_high; @@ -83,6 +95,7 @@ boot(int a1, int a2, void *prom) } flush_cache(dst, len); + memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); make_bi_recs((unsigned long)dst + len); sa = (unsigned long)PROG_START; @@ -99,8 +112,13 @@ void make_bi_recs(unsigned long addr) { struct bi_record *rec; - rec = (struct bi_record *)PAGE_ALIGN(addr); - + addr = _ALIGN(addr+ (1<<20) - 1, (1<<20)); +#if 0 + if (addr >= PROG_START + PROG_SIZE) + claim(addr, 0x1000, 0); +#endif + + rec = (struct bi_record *)addr; rec->tag = BI_FIRST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); @@ -115,7 +133,12 @@ void make_bi_recs(unsigned long addr) rec->data[1] = 1; rec->size = sizeof(struct bi_record) + sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); - + + rec->tag = BI_CMD_LINE; + memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); + rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; + rec = (struct bi_record *)((unsigned long)rec + rec->size); + rec->tag = BI_LAST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); diff --git a/arch/ppc/boot/pmac/dummy.c b/arch/ppc/boot/pmac/dummy.c new file mode 100644 index 000000000000..a35ff8f451e8 --- /dev/null +++ b/arch/ppc/boot/pmac/dummy.c @@ -0,0 +1,7 @@ +/* + * BK Id: SCCS/s.dummy.c 1.6 05/18/01 15:17:15 cort + */ +int main(void) +{ + return 0; +} diff --git a/arch/ppc/coffboot/ld.script b/arch/ppc/boot/pmac/ld.script index 2469ed65dcb3..2469ed65dcb3 100644 --- a/arch/ppc/coffboot/ld.script +++ b/arch/ppc/boot/pmac/ld.script diff --git a/arch/ppc/coffboot/misc.S b/arch/ppc/boot/pmac/misc.S index 05639bdd1c24..841f58c2c32a 100644 --- a/arch/ppc/coffboot/misc.S +++ b/arch/ppc/boot/pmac/misc.S @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.misc.S 1.6 05/18/01 15:17:15 cort + */ +/* * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or diff --git a/arch/ppc/coffboot/start.c b/arch/ppc/boot/pmac/start.c index e9d9f3a6f5ca..02ee7c92e63c 100644 --- a/arch/ppc/coffboot/start.c +++ b/arch/ppc/boot/pmac/start.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.start.c 1.8 05/18/01 15:17:15 cort + */ +/* * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or diff --git a/arch/ppc/boot/prep/Makefile b/arch/ppc/boot/prep/Makefile new file mode 100644 index 000000000000..d2a08340e9a7 --- /dev/null +++ b/arch/ppc/boot/prep/Makefile @@ -0,0 +1,114 @@ +# BK Id: SCCS/s.Makefile 1.15 05/21/01 11:51:32 trini +# +# arch/ppc/boot/Makefile +# +# 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. +# +# Tom Rini January 2001 +# +# Originally: +# arch/ppc/boot/Makefile +# Copyright (C) 1994 by Linus Torvalds +# Adapted for PowerPC by Gary Thomas +# modified by Cort (cort@cs.nmt.edu) +# + +.c.s: + $(CC) $(CFLAGS) -S -o $*.s $< +.s.o: + $(AS) -o $*.o $< +.c.o: + $(CC) $(CFLAGS) -c -o $*.o $< +.S.s: + $(CPP) $(AFLAGS) -traditional -o $*.o $< +.S.o: + $(CC) $(AFLAGS) -traditional -c -o $*.o $< + +ifeq ($(CONFIG_SMP),y) +TFTPIMAGE=/tftpboot/zImage.prep.smp +else +TFTPIMAGE=/tftpboot/zImage.prep +endif + +ZLINKFLAGS = -T $(TOPDIR)/arch/$(ARCH)/vmlinux.lds -Ttext 0x00800000 +OBJECTS := head.o misc.o vreset.o kbd.o ../common/misc-common.o \ + ../common/string.o of1275.o +OBJCOPY_ARGS = -O elf32-powerpc +LIBS = ../lib/zlib.a + +ifeq ($(CONFIG_SERIAL_CONSOLE),y) +OBJECTS += ns16550.o +endif + +# Tools +MKPREP := ../utils/mkprep +SIZE := ../utils/size +OFFSET := ../utils/offset + +all: zImage + +misc.o: misc.c + $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ + -DZIMAGE_SIZE=0 -c -o $@ $*.c + +ns16550.o: ../common/ns16550.c + $(CC) $(CFLAGS) -DIOOFFSET=0x80000000 -c -o $@ ../common/$*.c + +zvmlinux.initrd: zvmlinux ../images/vmlinux.gz + $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=initrd=../images/ramdisk.image.gz \ + --add-section=image=../images/vmlinux.gz \ + $@.tmp $@ + $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh $(OFFSET) $(OBJDUMP) $@ initrd` \ + -DINITRD_SIZE=`sh $(SIZE) $(OBJDUMP) $@ initrd` \ + -DZIMAGE_OFFSET=`sh $(OFFSET) $(OBJDUMP) $@ image` \ + -DZIMAGE_SIZE=`sh $(SIZE) $(OBJDUMP) $@ image` \ + -c -o misc.o misc.c + $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=initrd=../images/ramdisk.image.gz \ + --add-section=image=../images/vmlinux.gz \ + $@.tmp $@ + rm -f $@.tmp zvmlinux + +zImage: zvmlinux $(MKPREP) + $(MKPREP) -pbp zvmlinux ../images/$@.prep + rm -f zvmlinux + +zImage.initrd: zvmlinux.initrd $(MKPREP) + $(MKPREP) -pbp zvmlinux.initrd ../images/$@.prep + rm -f zvmlinux.initrd + +zvmlinux: $(OBJECTS) $(LIBS) ../images/vmlinux.gz +# +# build the boot loader image and then compute the offset into it +# for the kernel image +# + $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) $(LIBS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=image=../images/vmlinux.gz zvmlinux.tmp $@ +# +# then with the offset rebuild the bootloader so we know where the kernel is +# + $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \ + -DZIMAGE_OFFSET=`sh $(OFFSET) $(OBJDUMP) zvmlinux image` \ + -DZIMAGE_SIZE=`sh $(SIZE) $(OBJDUMP) zvmlinux image` \ + -c -o misc.o misc.c + $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) $(LIBS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=image=../images/vmlinux.gz $@.tmp $@ + rm $@.tmp + +floppy: zImage + dd if=../images/zImage.prep of=/dev/fd0H1440 bs=64b + +znetboot : zImage + cp ../images/zImage.prep $(TFTPIMAGE) + +znetboot.initrd : zImage.initrd + cp ../images/zImage.initrd.prep $(TFTPIMAGE) + +include $(TOPDIR)/Rules.make diff --git a/arch/ppc/boot/head.S b/arch/ppc/boot/prep/head.S index cc9339c8eee0..bd9c27e3b59b 100644 --- a/arch/ppc/boot/head.S +++ b/arch/ppc/boot/prep/head.S @@ -1,13 +1,14 @@ -#include "../kernel/ppc_defs.h" -#include "../kernel/ppc_asm.tmpl" +/* + * BK Id: SCCS/s.head.S 1.8 05/18/01 06:20:29 patch + */ +#include "../../kernel/ppc_defs.h" +#include "../../kernel/ppc_asm.tmpl" #include <asm/processor.h> #include <asm/cache.h> .text /* - * $Id: head.S,v 1.33 1999/09/08 01:06:58 cort Exp $ - * * Boot loader philosophy: * ROM loads us to some arbitrary location * Move the boot code to the link address (8M) @@ -112,6 +113,15 @@ start_ldr: cmpi 0,r2,0 bne 00b + /* r4,r5 have initrd_start, size */ + lis r2,initrd_start@h + ori r2,r2,initrd_start@l + lwz r4,0(r2) + lis r2,initrd_end@h + ori r2,r2,initrd_end@l + lwz r5,0(r2) + + /* tell kernel we're prep */ /* * get start address of kernel code which is stored as a coff diff --git a/arch/ppc/boot/iso_font.h b/arch/ppc/boot/prep/iso_font.h index bff050e002b7..7b5fa56af8f0 100644 --- a/arch/ppc/boot/iso_font.h +++ b/arch/ppc/boot/prep/iso_font.h @@ -1,3 +1,6 @@ +/* + * BK Id: SCCS/s.iso_font.h 1.6 05/18/01 15:16:42 cort + */ static const unsigned char font[] = { /* 0x00 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x01 */ 0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00, diff --git a/arch/ppc/boot/kbd.c b/arch/ppc/boot/prep/kbd.c index 49a102e9c88c..a3208751d6c5 100644 --- a/arch/ppc/boot/kbd.c +++ b/arch/ppc/boot/prep/kbd.c @@ -1,3 +1,6 @@ +/* + * BK Id: SCCS/s.kbd.c 1.7 05/18/01 06:20:29 patch + */ #include <linux/keyboard.h> #include <../drivers/char/defkeymap.c> /* yeah I know it's bad -- Cort */ @@ -11,6 +14,11 @@ unsigned char shfts, ctls, alts, caps; #define KBINRDY 0x01 #define KBOUTRDY 0x02 +extern unsigned char inb(int port); +extern void outb(int port, char val); +extern void puts(const char *); +extern void puthex(unsigned long val); +extern void udelay(long x); static int kbd(int noblock) { diff --git a/arch/ppc/boot/prep/misc.c b/arch/ppc/boot/prep/misc.c new file mode 100644 index 000000000000..c18a88965fda --- /dev/null +++ b/arch/ppc/boot/prep/misc.c @@ -0,0 +1,453 @@ +/* + * BK Id: SCCS/s.misc.c 1.8 05/18/01 06:20:29 patch + */ +/* + * misc.c + * + * Adapted for PowerPC by Gary Thomas + * + * Rewritten by Cort Dougan (cort@cs.nmt.edu) + * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort + */ + +#include <linux/types.h> +#include "zlib.h" +#include <asm/residual.h> +#include <linux/elf.h> +#include <linux/config.h> +#include <linux/pci_ids.h> +#include <asm/page.h> +#include <asm/processor.h> +#include <asm/bootinfo.h> +#include <asm/mmu.h> +#include <asm/byteorder.h> +#if defined(CONFIG_SERIAL_CONSOLE) +unsigned long com_port; +#endif /* CONFIG_SERIAL_CONSOLE */ + +/* + * Please send me load/board info and such data for hardware not + * listed here so I can keep track since things are getting tricky + * with the different load addrs with different firmware. This will + * help to avoid breaking the load/boot process. + * -- Cort + */ +char *avail_ram; +char *end_avail; +extern char _end[]; + +#ifdef CONFIG_CMDLINE +#define CMDLINE CONFIG_CMDLINE +#else +#define CMDLINE ""; +#endif +char cmd_preset[] = CMDLINE; +char cmd_buf[256]; +char *cmd_line = cmd_buf; + +int keyb_present = 1; /* keyboard controller is present by default */ +RESIDUAL hold_resid_buf; +RESIDUAL *hold_residual = &hold_resid_buf; +unsigned long initrd_start = 0, initrd_end = 0; +char *zimage_start; +int zimage_size; + +char *vidmem = (char *)0xC00B8000; +int lines, cols; +int orig_x, orig_y; + +extern void puts(const char *); +extern void putc(const char c); +extern int tstc(void); +extern int getc(void); +extern void puthex(unsigned long val); +extern void * memcpy(void * __dest, __const void * __src, __kernel_size_t __n); +extern int CRT_tstc(void); +extern void of_init(void *handler); +extern int of_finddevice(const char *device_specifier, int *phandle); +extern int of_getprop(int phandle, const char *name, void *buf, int buflen, + int *size); +extern __kernel_size_t strlen(const char *s); +extern int vga_init(unsigned char *ISA_mem); +extern void udelay(long x); +void gunzip(void *, int, unsigned char *, int *); +unsigned char inb(int); + +void +writel(unsigned int val, unsigned int address) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + *(unsigned int *)address = cpu_to_le32(val); +} + +unsigned int +readl(unsigned int address) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + return le32_to_cpu(*(unsigned int *)address); +} + +#define PCI_CFG_ADDR(dev,off) ((0x80<<24) | (dev<<8) | (off&0xfc)) +#define PCI_CFG_DATA(off) (0x80000cfc+(off&3)) + +static void +pci_read_config_32(unsigned char devfn, + unsigned char offset, + unsigned int *val) +{ + writel(PCI_CFG_ADDR(devfn,offset), 0x80000cf8); + *val = readl(PCI_CFG_DATA(offset)); + return; +} + +void +scroll() +{ + int i; + + memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 ); + for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) + vidmem[i] = ' '; +} + +/* + * This routine is used to control the second processor on the + * Motorola dual processor platforms. + */ +void +park_cpus() +{ + volatile void (*go)(RESIDUAL *, int, int, char *, int); + unsigned int i; + volatile unsigned long *smp_iar = &(hold_residual->VitalProductData.SmpIar); + + /* Wait for indication to continue. If the kernel + was not compiled with SMP support then the second + processor will spin forever here makeing the kernel + multiprocessor safe. */ + while (*smp_iar == 0) { + for (i=0; i < 512; i++); + } + + (unsigned long)go = hold_residual->VitalProductData.SmpIar; + go(hold_residual, 0, 0, cmd_line, sizeof(cmd_preset)); +} + +unsigned long +decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, + RESIDUAL *residual, void *OFW_interface) +{ + int timer; + extern unsigned long start; + char *cp, ch; + unsigned long TotalMemory; + unsigned long orig_MSR; + int dev_handle; + int mem_info[2]; + int res, size; + unsigned char board_type; + unsigned char base_mod; + int start_multi = 0; + unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base; + + lines = 25; + cols = 80; + orig_x = 0; + orig_y = 24; + + /* + * IBM's have the MMU on, so we have to disable it or + * things get really unhappy in the kernel when + * trying to setup the BATs with the MMU on + * -- Cort + */ + flush_instruction_cache(); + _put_HID0(_get_HID0() & ~0x0000C000); + _put_MSR((orig_MSR = _get_MSR()) & ~0x0030); + +#if defined(CONFIG_SERIAL_CONSOLE) + com_port = serial_init(0); +#endif /* CONFIG_SERIAL_CONSOLE */ + vga_init((char)0xC0000000); + + if (residual) + { + /* Is this Motorola PPCBug? */ + if ((1 & residual->VitalProductData.FirmwareSupports) && + (1 == residual->VitalProductData.FirmwareSupplier)) { + board_type = inb(0x800) & 0xF0; + + /* + * Reset the onboard 21x4x Ethernet + * Motorola Ethernet is at IDSEL 14 (devfn 0x70) + */ + pci_read_config_32(0x70, 0x00, &pci_viddid); + pci_did = (pci_viddid & 0xffff0000) >> 16; + /* Be sure we've really found a 21x4x chip */ + if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_DEC) && + ((pci_did == PCI_DEVICE_ID_DEC_TULIP_FAST) || + (pci_did == PCI_DEVICE_ID_DEC_TULIP) || + (pci_did == PCI_DEVICE_ID_DEC_TULIP_PLUS) || + (pci_did == PCI_DEVICE_ID_DEC_21142))) + { + pci_read_config_32(0x70, + 0x10, + &tulip_pci_base); + /* Get the physical base address */ + tulip_base = + (tulip_pci_base & ~0x03UL) + 0x80000000; + /* Strobe the 21x4x reset bit in CSR0 */ + writel(0x1, tulip_base); + } + + /* If this is genesis 2 board then check for no + * keyboard controller and more than one processor. + */ + if (board_type == 0xe0) { + base_mod = inb(0x803); + /* if a MVME2300/2400 or a Sitka then no keyboard */ + if((base_mod == 0xFA) || (base_mod == 0xF9) || + (base_mod == 0xE1)) { + keyb_present = 0; /* no keyboard */ + } + } + /* If this is a multiprocessor system then + * park the other processor so that the + * kernel knows where to find them. + */ + if (residual->MaxNumCpus > 1) { + start_multi = 1; + } + } + memcpy(hold_residual,residual,sizeof(RESIDUAL)); + } else { + /* Assume 32M in the absence of more info... */ + TotalMemory = 0x02000000; + /* + * This is a 'best guess' check. We want to make sure + * we don't try this on a PReP box without OF + * -- Cort + */ + while (OFW_interface && ((unsigned long)OFW_interface < 0x10000000) ) + { + /* The MMU needs to be on when we call OFW */ + _put_MSR(orig_MSR); + of_init(OFW_interface); + + /* get handle to memory description */ + res = of_finddevice("/memory@0", + &dev_handle); + // puthex(res); puts("\n"); + if (res) break; + + /* get the info */ + // puts("get info = "); + res = of_getprop(dev_handle, + "reg", + mem_info, + sizeof(mem_info), + &size); + // puthex(res); puts(", info = "); puthex(mem_info[0]); + // puts(" "); puthex(mem_info[1]); puts("\n"); + if (res) break; + + TotalMemory = mem_info[1]; + break; + } + hold_residual->TotalMemory = TotalMemory; + residual = hold_residual; + /* Turn MMU back off */ + _put_MSR(orig_MSR & ~0x0030); + } + + if (start_multi) { + hold_residual->VitalProductData.SmpIar = 0; + hold_residual->Cpus[1].CpuState = CPU_GOOD_FW; + residual->VitalProductData.SmpIar = (unsigned long)park_cpus; + residual->Cpus[1].CpuState = CPU_GOOD; + hold_residual->VitalProductData.Reserved5 = 0xdeadbeef; + } + + /* assume the chunk below 8M is free */ + end_avail = (char *)0x00800000; + + /* tell the user where we were loaded at and where we + * were relocated to for debugging this process + */ + puts("loaded at: "); puthex(load_addr); + puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); + if ( (unsigned long)load_addr != (unsigned long)&start ) + { + puts("relocated to: "); puthex((unsigned long)&start); + puts(" "); + puthex((unsigned long)((unsigned long)&start + (4*num_words))); + puts("\n"); + } + + if ( residual ) + { + puts("board data at: "); puthex((unsigned long)residual); + puts(" "); + puthex((unsigned long)((unsigned long)residual + sizeof(RESIDUAL))); + puts("\n"); + puts("relocated to: "); + puthex((unsigned long)hold_residual); + puts(" "); + puthex((unsigned long)((unsigned long)hold_residual + sizeof(RESIDUAL))); + puts("\n"); + } + + /* we have to subtract 0x10000 here to correct for objdump including the + size of the elf header which we strip -- Cort */ + zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET); + zimage_size = ZIMAGE_SIZE; + + if ( INITRD_OFFSET ) + initrd_start = load_addr - 0x10000 + INITRD_OFFSET; + else + initrd_start = 0; + initrd_end = INITRD_SIZE + initrd_start; + + /* + * Find a place to stick the zimage and initrd and + * relocate them if we have to. -- Cort + */ + avail_ram = (char *)PAGE_ALIGN((unsigned long)_end); + puts("zimage at: "); puthex((unsigned long)zimage_start); + puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n"); + if ( (unsigned long)zimage_start <= 0x00800000 ) + { + memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size ); + zimage_start = (char *)avail_ram; + puts("relocated to: "); puthex((unsigned long)zimage_start); + puts(" "); + puthex((unsigned long)zimage_size+(unsigned long)zimage_start); + puts("\n"); + + /* relocate initrd */ + if ( initrd_start ) + { + puts("initrd at: "); puthex(initrd_start); + puts(" "); puthex(initrd_end); puts("\n"); + avail_ram = (char *)PAGE_ALIGN( + (unsigned long)zimage_size+(unsigned long)zimage_start); + memcpy ((void *)avail_ram, (void *)initrd_start, INITRD_SIZE ); + initrd_start = (unsigned long)avail_ram; + initrd_end = initrd_start + INITRD_SIZE; + puts("relocated to: "); puthex(initrd_start); + puts(" "); puthex(initrd_end); puts("\n"); + } + } else if ( initrd_start ) { + puts("initrd at: "); puthex(initrd_start); + puts(" "); puthex(initrd_end); puts("\n"); + } + + avail_ram = (char *)0x00400000; + end_avail = (char *)0x00800000; + puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); + puthex((unsigned long)end_avail); puts("\n"); + + if (keyb_present) + CRT_tstc(); /* Forces keyboard to be initialized */ + + puts("\nLinux/PPC load: "); + timer = 0; + cp = cmd_line; + memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); + while ( *cp ) putc(*cp++); + while (timer++ < 5*1000) { + if (tstc()) { + while ((ch = getc()) != '\n' && ch != '\r') { + if (ch == '\b') { + if (cp != cmd_line) { + cp--; + puts("\b \b"); + } + } else { + *cp++ = ch; + putc(ch); + } + } + break; /* Exit 'timer' loop */ + } + udelay(1000); /* 1 msec */ + } + *cp = 0; + puts("\n"); + + /* mappings on early boot can only handle 16M */ + if ( (int)(cmd_line[0]) > (16<<20)) + puts("cmd_line located > 16M\n"); + if ( (int)hold_residual > (16<<20)) + puts("hold_residual located > 16M\n"); + if ( initrd_start > (16<<20)) + puts("initrd_start located > 16M\n"); + + puts("Uncompressing Linux..."); + + gunzip(0, 0x400000, zimage_start, &zimage_size); + puts("done.\n"); + + { + struct bi_record *rec; + + rec = (struct bi_record *)PAGE_ALIGN(zimage_size); + + rec->tag = BI_FIRST; + rec->size = sizeof(struct bi_record); + rec = (struct bi_record *)((unsigned long)rec + rec->size); + + rec->tag = BI_BOOTLOADER_ID; + memcpy( (void *)rec->data, "prepboot", 9); + rec->size = sizeof(struct bi_record) + 8 + 1; + rec = (struct bi_record *)((unsigned long)rec + rec->size); + + rec->tag = BI_MACHTYPE; + rec->data[0] = _MACH_prep; + rec->data[1] = 1; + rec->size = sizeof(struct bi_record) + sizeof(unsigned long); + rec = (struct bi_record *)((unsigned long)rec + rec->size); + + rec->tag = BI_CMD_LINE; + memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); + rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; + rec = (struct bi_record *)((ulong)rec + rec->size); + + rec->tag = BI_LAST; + rec->size = sizeof(struct bi_record); + rec = (struct bi_record *)((unsigned long)rec + rec->size); + } + puts("Now booting the kernel\n"); + return (unsigned long)hold_residual; +} + +/* + * PCI/ISA I/O support + */ + +volatile unsigned char *ISA_io = (unsigned char *)0x80000000; +volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000; + +void +outb(int port, char val) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + ISA_io[port] = val; +} + +unsigned char +inb(int port) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + return (ISA_io[port]); +} + +unsigned long +local_to_PCI(unsigned long addr) +{ + return ((addr & 0x7FFFFFFF) | 0x80000000); +} diff --git a/arch/ppc/boot/of1275.c b/arch/ppc/boot/prep/of1275.c index b82fa7a4695f..9e7270d12da9 100644 --- a/arch/ppc/boot/of1275.c +++ b/arch/ppc/boot/prep/of1275.c @@ -1,3 +1,6 @@ +/* + * BK Id: SCCS/s.of1275.c 1.6 05/18/01 15:16:42 cort + */ /* Open Firmware Client Interface */ diff --git a/arch/ppc/boot/of1275.h b/arch/ppc/boot/prep/of1275.h index bc050d32b7b0..c88de95f1e81 100644 --- a/arch/ppc/boot/of1275.h +++ b/arch/ppc/boot/prep/of1275.h @@ -1,3 +1,6 @@ +/* + * BK Id: SCCS/s.of1275.h 1.6 05/18/01 15:16:42 cort + */ /* 6.3.2.1 Client interface */ diff --git a/arch/ppc/boot/vreset.c b/arch/ppc/boot/prep/vreset.c index dfabd72e73f9..83beb8516d01 100644 --- a/arch/ppc/boot/vreset.c +++ b/arch/ppc/boot/prep/vreset.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.vreset.c 1.9 05/18/01 06:20:29 patch + */ +/* * vreset.c * * Initialize the VGA control registers to 80x25 text mode. @@ -22,12 +25,10 @@ extern char *vidmem; extern int lines, cols; - -static void mdelay(int ms) -{ - for (; ms > 0; --ms) - udelay(1000); -} +extern void udelay(long x); +extern void outb(int port, char val); +extern unsigned char inb(int port); +struct VaRegs; /* * VGA Register @@ -39,6 +40,18 @@ struct VgaRegs unsigned char io_value; }; +void unlockVideo(int slot); +void setTextRegs(struct VgaRegs *svp); +void setTextCLUT(int shift); +void clearVideoMemory(); +void loadFont(unsigned char *ISA_mem); + +static void mdelay(int ms) +{ + for (; ms > 0; --ms) + udelay(1000); +} + /* * Default console text mode registers used to reset * graphics adapter. @@ -419,12 +432,14 @@ unsigned char AC[21] = { static int scanPCI(int start_slt); static int PCIVendor(int); +#ifdef DEBUG static void printslots(void); +#endif extern void puthex(unsigned long); extern void puts(const char *); static void unlockS3(void); -static inline +static void inline outw(int port, unsigned short val) { outb(port, val >> 8); @@ -433,6 +448,7 @@ outw(int port, unsigned short val) #define PPC_601 1 +int vga_init(unsigned char *ISA_mem) { int slot; @@ -445,7 +461,10 @@ vga_init(unsigned char *ISA_mem) /* See if VGA already in TEXT mode - exit if so! */ outb(0x3CE, 0x06); - if ((inb(0x3CF) & 0x01) == 0){puts("VGA already in text mode\n"); return;} + if ((inb(0x3CF) & 0x01) == 0){ + puts("VGA already in text mode\n"); + return 0; + } /* If no VGA responding in text mode, then we have some work to do... */ @@ -527,10 +546,8 @@ vga_init(unsigned char *ISA_mem) /* * Write to VGA Attribute registers. */ -writeAttr(index, data, videoOn) - unsigned char index; - unsigned char data; - unsigned char videoOn; /* video on flag */ +void +writeAttr(unsigned char index, unsigned char data, unsigned char videoOn) { unsigned char v; v = inb(0x3da); /* reset attr. address toggle */ @@ -541,6 +558,7 @@ writeAttr(index, data, videoOn) outb(0x3c0, data); } +void setTextRegs(struct VgaRegs *svp) { int i; @@ -566,6 +584,7 @@ setTextRegs(struct VgaRegs *svp) writeAttr(0x14, 0x00, 1); /* color select; video on */ } +void setTextCLUT(int shift) { int i; @@ -582,7 +601,7 @@ setTextCLUT(int shift) } } - +void loadFont(unsigned char *ISA_mem) { int i, j; @@ -701,6 +720,7 @@ cursor(int x, int y) outb(0x3D5, pos); } +void clearVideoMemory() { int i, j; @@ -745,7 +765,8 @@ struct PCI_ConfigInfo { * The following code modifies the PCI Command register * to enable memory and I/O accesses. */ -unlockVideo(slot) +void +unlockVideo(int slot) { volatile unsigned char * ppci; @@ -819,11 +840,14 @@ int PCIVendor(int slotnum) { return (pslot->regs[DEVID] & 0xFFFF); } +#ifdef DEBUG static void printslots(void) { int i; +#if 0 struct PCI_ConfigInfo *pslot; +#endif for(i=0; i < NSLOTS; i++) { #if 0 pslot = &PCI_slots[i]; @@ -836,3 +860,4 @@ void printslots(void) #endif } } +#endif /* DEBUG */ diff --git a/arch/ppc/treeboot/Makefile b/arch/ppc/boot/tree/Makefile index 7d42a674182d..309616eac225 100644 --- a/arch/ppc/treeboot/Makefile +++ b/arch/ppc/boot/tree/Makefile @@ -1,5 +1,5 @@ +# BK Id: SCCS/s.Makefile 1.5 05/18/01 06:20:29 patch # -# Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> # # Module name: Makefile # @@ -7,29 +7,42 @@ # Makefile for the IBM "tree" evaluation board Linux kernel # boot loaders. # +# +# Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> +# +# PPC-405 modification +# Copyright 2000-2001 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# frank_rowand@mvista.com or source@mvista.com +# debbie_chu@mvista.com +# HOSTCFLAGS = -O -I$(TOPDIR)/include +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump + GZIP = gzip -vf9 RM = rm -f -MKEVIMG = mkevimg -l -MKIRIMG = mkirimg - -CFLAGS = -O -fno-builtin -I$(TOPDIR)/include +MKEVIMG = ../utils/mkevimg -l +MKIRIMG = ../utils/mkirimg LD_ARGS = -e _start -T ld.script -Ttext 0x00200000 -Bstatic -OBJS = crt0.o main.o misc.o irSect.o ../coffboot/string.o ../coffboot/zlib.o -LIBS = +OBJS = ../common/crt0.o main.o misc.o irSect.o ../common/string.o \ + ../common/misc-common.o +LIBS = ../lib/zlib.a -treeboot: $(OBJS) ld.script +treeboot: $(OBJS) $(LIBS) ld.script $(LD) -o $@ $(LD_ARGS) $(OBJS) $(LIBS) zImage: vmlinux.img zImage.initrd: vmlinux.initrd.img -treeboot.image: treeboot vmlinux.gz - $(OBJCOPY) --add-section=image=vmlinux.gz treeboot $@ +treeboot.image: treeboot + $(OBJCOPY) --add-section=image=../images/vmlinux.gz treeboot $@ treeboot.initrd: treeboot.image ramdisk.image.gz $(OBJCOPY) --add-section=initrd=ramdisk.image.gz treeboot.image $@ @@ -37,21 +50,16 @@ treeboot.initrd: treeboot.image ramdisk.image.gz vmlinux.img: treeboot.image $(OBJDUMP) --syms treeboot.image | grep irSectStart > irSectStart.txt $(MKIRIMG) treeboot.image treeboot.image.out irSectStart.txt - $(MKEVIMG) treeboot.image.out $@ + $(MKEVIMG) treeboot.image.out ../images/vmlinux.tree.img $(RM) treeboot.image treeboot.image.out irSectStart.txt vmlinux.initrd.img: treeboot.initrd $(OBJDUMP) --all-headers treeboot.initrd | grep irSectStart > irSectStart.txt $(MKIRIMG) treeboot.initrd treeboot.initrd.out irSectStart.txt - $(MKEVIMG) treeboot.initrd.out $@ + $(MKEVIMG) treeboot.initrd.out ../images/vmlinux.tree.initrd.img $(RM) treeboot.initrd treeboot.initrd.out irSectStart.txt -vmlinux.gz: $(TOPDIR)/vmlinux - $(OBJCOPY) -S -O binary $(TOPDIR)/vmlinux vmlinux - $(GZIP) vmlinux - clean: - rm -f treeboot treeboot.image treeboot.initrd irSectStart.txt vmlinux.* *.o - -fastdep: + rm -f treeboot treeboot.image treeboot.initrd irSectStart.txt vmlinux.* +include $(TOPDIR)/Rules.make diff --git a/arch/ppc/treeboot/irSect.c b/arch/ppc/boot/tree/irSect.c index 7f4c7f6abe9d..80ecca8b3f74 100644 --- a/arch/ppc/treeboot/irSect.c +++ b/arch/ppc/boot/tree/irSect.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.irSect.c 1.6 05/18/01 15:17:22 cort + */ +/* * * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> * diff --git a/arch/ppc/treeboot/irSect.h b/arch/ppc/boot/tree/irSect.h index 801c3b42ee3d..849be573be3a 100644 --- a/arch/ppc/treeboot/irSect.h +++ b/arch/ppc/boot/tree/irSect.h @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.irSect.h 1.6 05/18/01 15:17:22 cort + */ +/* * * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> * diff --git a/arch/ppc/treeboot/ld.script b/arch/ppc/boot/tree/ld.script index 2469ed65dcb3..2469ed65dcb3 100644 --- a/arch/ppc/treeboot/ld.script +++ b/arch/ppc/boot/tree/ld.script diff --git a/arch/ppc/treeboot/main.c b/arch/ppc/boot/tree/main.c index 277b77047e60..367aca873cdb 100644 --- a/arch/ppc/treeboot/main.c +++ b/arch/ppc/boot/tree/main.c @@ -1,8 +1,16 @@ /* + * BK Id: SCCS/s.main.c 1.7 05/18/01 06:20:29 patch + */ +/* * Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au> * Initial Power Macintosh COFF version. * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> * Modifications for an ELF-based IBM evaluation board version. + * Copyright 2000-2001 MontaVista Software Inc. + * PPC405GP modifications + * Author: MontaVista Software, Inc. + * frank_rowand@mvista.com or source@mvista.com + * debbie_chu@mvista.com * * Module name: main.c * @@ -24,11 +32,14 @@ * */ -#include <asm/board.h> +#include <linux/config.h> +#include <asm/ppc4xx.h> -#include "../coffboot/nonstdio.h" -#include "../coffboot/zlib.h" +#include "nonstdio.h" #include "irSect.h" +#if defined(CONFIG_SERIAL_CONSOLE) +#include "ns16550.h" +#endif /* CONFIG_SERIAL_CONSOLE */ /* Preprocessor Defines */ @@ -40,7 +51,11 @@ #define BOARD_INFO_VECTOR 0xFFFE0B50 -#define RAM_SIZE (4 * 1024 * 1024) +/* + * Warning: the board_info doesn't contain valid data until get_board_info() + * gets called in start(). + */ +#define RAM_SIZE board_info.bi_memsize #define RAM_PBASE 0x00000000 #define RAM_PEND (RAM_PBASE + RAM_SIZE) @@ -59,6 +74,15 @@ #define ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) +#define stringify(s) tostring(s) +#define tostring(s) #s + +#define mtdcr(rn, v) asm volatile("mtdcr " stringify(rn) ",%0" : : "r" (v)) +#define mfdcr(rn) ({unsigned int rval; \ + asm volatile("mfdcr %0," stringify(rn) \ + : "=r" (rval)); rval;}) +#define DCRN_MALCR 0x180 /* MAL Configuration */ +#define MALCR_SR 0x80000000 /* Software Reset */ /* Global Variables */ @@ -76,19 +100,49 @@ bd_t board_info; * (e.g. console=tty0). */ -static char *cmdline = ""; +/* +** The bootrom may change bootrom_cmdline to point to a buffer in the +** bootrom. +*/ +char *bootrom_cmdline = ""; +char treeboot_bootrom_cmdline[512]; + +#ifdef CONFIG_CMDLINE +char *cmdline = CONFIG_CMDLINE; +#else +char *cmdline = ""; +#endif /* Function Prototypes */ -void *zalloc(void *x, unsigned items, unsigned size); -void zfree(void *x, void *addr, unsigned nb); +extern void *zalloc(void *x, unsigned items, unsigned size); -void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp); +/* serial I/O functions. + * These should have generic names, although this is similar to 16550.... + */ +static volatile unsigned char *uart0_lsr = (unsigned char *)0xef600305; +static volatile unsigned char *uart0_xcvr = (unsigned char *)0xef600300; + +void +serial_putc(void *unused, unsigned char c) +{ + while ((*uart0_lsr & LSR_THRE) == 0); + *uart0_xcvr = c; +} + +unsigned char +serial_getc(void *unused) +{ + while ((*uart0_lsr & LSR_DR) == 0); + return (*uart0_xcvr); +} -void printf () {} -void pause () {} -void exit () {} +int +serial_tstc(void *unused) +{ + return ((*uart0_lsr & LSR_DR) != 0); +} void start(void) @@ -102,18 +156,44 @@ void start(void) bd_t *(*get_board_info)(void) = (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR); bd_t *bip = NULL; + volatile unsigned long *em0mr0 = (long *)0xEF600800; /* ftr fixup */ + + + +#if defined(CONFIG_WALNUT) + /* turn off ethernet */ + /* This is to fix a problem with early walnut bootrom. */ + + mtdcr(DCRN_MALCR, MALCR_SR); /* 1st reset MAL */ + + while (mfdcr(DCRN_MALCR) & MALCR_SR) {}; /* wait for the reset */ + + *em0mr0 = 0x20000000; /* then reset EMAC */ +#endif + + +#if 0 + /* ftr revisit - remove printf()s */ + + printf("\n\nbootrom_cmdline = >%s<\n\n", bootrom_cmdline); + if (*bootrom_cmdline != '\0') { + printf("bootrom_cmdline != NULL, copying it into cmdline\n\n"); + *treeboot_bootrom_cmdline = '\0'; + strcat(treeboot_bootrom_cmdline, bootrom_cmdline); + cmdline = treeboot_bootrom_cmdline; + } +#endif + if ((bip = get_board_info()) != NULL) memcpy(&board_info, bip, sizeof(bd_t)); - /* setup_bats(RAM_START); */ - /* Init RAM disk (initrd) section */ if (initrdSect_start != 0 && (initrd_size = initrdSect_size) != 0) { initrd_start = (RAM_END - initrd_size) & ~0xFFF; - printf("Initial RAM disk at 0x%08x (%u bytes)\n", + _printk("Initial RAM disk at 0x%08x (%u bytes)\n", initrd_start, initrd_size); memcpy((char *)initrd_start, @@ -139,16 +219,21 @@ void start(void) /* The gunzip routine needs everything nice and aligned */ void *cp = (void *)ALIGN_UP(RAM_FREE, 8); - avail_ram = (void *)(cp + ALIGN_UP(len, 8)); + avail_ram = (void *)(cp + ALIGN_UP(len, 8)); /* used by zalloc() */ memcpy(cp, im, len); /* I'm not sure what the 0x200000 parameter is for, but it works. */ + /* It tells gzip the end of the area you wish to reserve, and it + * can use data past that point....unfortunately, this value + * isn't big enough (luck ran out). -- Dan + */ - gunzip(dst, 0x200000, cp, (int *)&len); + gunzip(dst, 0x400000, cp, (int *)&len); } else { memmove(dst, im, len); } + flush_cache(dst, len); sa = (unsigned long)dst; @@ -161,80 +246,3 @@ void start(void) pause(); } - -void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p = avail_ram; - - size *= items; - size = ALIGN_UP(size, 8); - avail_ram += size; - if (avail_ram > end_avail) { - printf("oops... out of memory\n"); - pause(); - } - return p; -} - -void zfree(void *x, void *addr, unsigned nb) -{ - -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - -void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - printf("bad gzipped data\n"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - printf("gunzip: ran out of data in header\n"); - exit(); - } - printf("done 1\n"); - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf("inflateInit2 returned %d\n", r); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - printf("doing inflate\n"); - r = inflate(&s, Z_FINISH); - printf("done inflate\n"); - if (r != Z_OK && r != Z_STREAM_END) { - printf("inflate returned %d\n", r); - exit(); - } - *lenp = s.next_out - (unsigned char *) dst; - printf("doing end\n"); - inflateEnd(&s); -} diff --git a/arch/ppc/treeboot/misc.S b/arch/ppc/boot/tree/misc.S index c51844329adf..7d3f6ae885fb 100644 --- a/arch/ppc/treeboot/misc.S +++ b/arch/ppc/boot/tree/misc.S @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.misc.S 1.7 05/18/01 06:20:29 patch + */ +/* * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or @@ -7,7 +10,7 @@ * 2 of the License, or (at your option) any later version. */ -#include "../kernel/ppc_asm.tmpl" +#include "../../kernel/ppc_asm.tmpl" .text diff --git a/arch/ppc/boot/utils/Makefile b/arch/ppc/boot/utils/Makefile new file mode 100644 index 000000000000..c90c9ea1c60a --- /dev/null +++ b/arch/ppc/boot/utils/Makefile @@ -0,0 +1,19 @@ +# +# arch/ppc/boot/utils/Makefile +# +# 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. + +HOSTCFLAGS += -I$(TOPDIR)/arch/$(ARCH)/boot/include + +# Simple programs with 1 file and no extra CFLAGS +UTILS = addnote hack-coff mkprep mksimage mknote piggyback mkpmon mkbugboot + +$(UTILS): + $(HOSTCC) $(HOSTCFLAGS) -o $@ $@.c + +clean: + rm -f $(UTILS) + +include $(TOPDIR)/Rules.make diff --git a/arch/ppc/chrpboot/addnote.c b/arch/ppc/boot/utils/addnote.c index b2374df7c1d9..e18d44709ec0 100644 --- a/arch/ppc/chrpboot/addnote.c +++ b/arch/ppc/boot/utils/addnote.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.addnote.c 1.7 05/18/01 15:17:23 cort + */ +/* * Program to hack in a PT_NOTE program header entry in an ELF file. * This is needed for OF on RS/6000s to load an image correctly. * Note that OF needs a program header entry for the note, not an diff --git a/arch/ppc/treeboot/elf.pl b/arch/ppc/boot/utils/elf.pl index d3e9d9d5b84e..d3e9d9d5b84e 100644 --- a/arch/ppc/treeboot/elf.pl +++ b/arch/ppc/boot/utils/elf.pl diff --git a/arch/ppc/coffboot/hack-coff.c b/arch/ppc/boot/utils/hack-coff.c index 3dfa8d800e6a..f6395d1899f5 100644 --- a/arch/ppc/coffboot/hack-coff.c +++ b/arch/ppc/boot/utils/hack-coff.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.hack-coff.c 1.8 05/18/01 06:20:29 patch + */ +/* * hack-coff.c - hack the header of an xcoff file to fill in * a few fields needed by the Open Firmware xcoff loader on * Power Macs but not initialized by objcopy. @@ -11,6 +14,8 @@ * 2 of the License, or (at your option) any later version. */ #include <stdio.h> +#include <unistd.h> +#include <fcntl.h> #include "rs6000.h" #define AOUT_MAGIC 0x010b @@ -24,6 +29,7 @@ + (((unsigned char *)(x))[2] << 8) \ + ((unsigned char *)(x))[3]) +int main(int ac, char **av) { int fd; diff --git a/arch/ppc/treeboot/mkevimg b/arch/ppc/boot/utils/mkevimg index ca3ca0e8fbea..195fd37d4916 100644 --- a/arch/ppc/treeboot/mkevimg +++ b/arch/ppc/boot/utils/mkevimg @@ -187,7 +187,7 @@ sub decode_options { # ELF file and section header field numbers # -require 'elf.pl'; +require '../utils/elf.pl'; # # Main program body diff --git a/arch/ppc/treeboot/mkirimg b/arch/ppc/boot/utils/mkirimg index 17a6f23281b3..fa1b5bbb0a5a 100644 --- a/arch/ppc/treeboot/mkirimg +++ b/arch/ppc/boot/utils/mkirimg @@ -184,7 +184,7 @@ sub decode_options { # ELF file and section header field numbers # -require 'elf.pl'; +require '../utils/elf.pl'; # # Main program body diff --git a/arch/ppc/chrpboot/mknote.c b/arch/ppc/boot/utils/mknote.c index 120cc1d89739..608752e70004 100644 --- a/arch/ppc/chrpboot/mknote.c +++ b/arch/ppc/boot/utils/mknote.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.mknote.c 1.7 05/18/01 15:17:23 cort + */ +/* * Copyright (C) Cort Dougan 1999. * * This program is free software; you can redistribute it and/or diff --git a/arch/ppc/boot/mkprep.c b/arch/ppc/boot/utils/mkprep.c index 0a596b0ff444..3930f24aff04 100644 --- a/arch/ppc/boot/mkprep.c +++ b/arch/ppc/boot/utils/mkprep.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.mkprep.c 1.7 05/18/01 06:20:29 patch + */ +/* * Makes a prep bootable image which can be dd'd onto * a disk device to make a bootdisk. Will take * as input a elf executable, strip off the header @@ -14,10 +17,12 @@ * Modified for x86 hosted builds by Matt Porter <porter@neta.com> */ -#include <unistd.h> -#include <sys/stat.h> +#include <fcntl.h> #include <stdio.h> -#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> #define cpu_to_le32(x) le32_to_cpu((x)) unsigned long le32_to_cpu(unsigned long x) diff --git a/arch/ppc/boot/mksimage.c b/arch/ppc/boot/utils/mksimage.c index 6caf70063db0..721856a9b382 100644 --- a/arch/ppc/boot/mksimage.c +++ b/arch/ppc/boot/utils/mksimage.c @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.mksimage.c 1.6 05/18/01 15:16:42 cort + */ +/* * * * diff --git a/arch/ppc/boot/offset b/arch/ppc/boot/utils/offset index 52a1b5546e6f..52a1b5546e6f 100644 --- a/arch/ppc/boot/offset +++ b/arch/ppc/boot/utils/offset diff --git a/arch/ppc/chrpboot/piggyback.c b/arch/ppc/boot/utils/piggyback.c index 304bc8f11d40..6edfbaaa092e 100644 --- a/arch/ppc/chrpboot/piggyback.c +++ b/arch/ppc/boot/utils/piggyback.c @@ -1,3 +1,6 @@ +/* + * BK Id: SCCS/s.piggyback.c 1.7 05/18/01 15:17:23 cort + */ #include <stdio.h> #include <unistd.h> diff --git a/arch/ppc/boot/sioffset b/arch/ppc/boot/utils/sioffset index b5245be6c7b1..b5245be6c7b1 100644 --- a/arch/ppc/boot/sioffset +++ b/arch/ppc/boot/utils/sioffset diff --git a/arch/ppc/boot/sisize b/arch/ppc/boot/utils/sisize index 7e8180125dd4..7e8180125dd4 100644 --- a/arch/ppc/boot/sisize +++ b/arch/ppc/boot/utils/sisize diff --git a/arch/ppc/boot/size b/arch/ppc/boot/utils/size index 6c48f8d1468d..6c48f8d1468d 100644 --- a/arch/ppc/boot/size +++ b/arch/ppc/boot/utils/size diff --git a/arch/ppc/chrpboot/Makefile b/arch/ppc/chrpboot/Makefile deleted file mode 100644 index 9dbb7909dc51..000000000000 --- a/arch/ppc/chrpboot/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -# Makefile for making ELF bootable images for booting on CHRP -# using Open Firmware. -# -# Geert Uytterhoeven September 1997 -# -# Based on coffboot by Paul Mackerras - -ifeq ($(CONFIG_PPC64BRIDGE),y) -MSIZE=.64 -AFLAGS += -Wa,-mppc64bridge -else -MSIZE= -endif - -.c.o: - $(CC) $(CFLAGS) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $< -.S.o: - $(CC) $(AFLAGS) -traditional -c -o $*.o $< - -CFLAGS = $(CPPFLAGS) -O -fno-builtin -DSTDC_HEADERS -LD_ARGS = -Ttext 0x00400000 - -OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o -LIBS = $(TOPDIR)/lib/lib.a - -ifeq ($(CONFIG_SMP),y) -TFTPIMAGE=/tftpboot/zImage.chrp.smp$(MSIZE) -else -TFTPIMAGE=/tftpboot/zImage.chrp$(MSIZE) -endif - -all: $(TOPDIR)/zImage - -# -# Only build anything here if we're configured for ALL_PPC -# -- cort -# -ifeq ($(CONFIG_ALL_PPC),y) -znetboot: zImage - cp zImage $(TFTPIMAGE) - -znetboot.initrd: zImage.initrd - cp zImage.initrd $(TFTPIMAGE) - -floppy: zImage - mcopy zImage a:zImage - -piggyback: piggyback.c - $(HOSTCC) $(HOSTCFLAGS) -DKERNELBASE=$(KERNELBASE) -o piggyback piggyback.c - -addnote: addnote.c - $(HOSTCC) $(HOSTCFLAGS) -o addnote addnote.c - -image.o: piggyback ../coffboot/vmlinux.gz - ./piggyback image < ../coffboot/vmlinux.gz | $(AS) -o image.o - -sysmap.o: piggyback ../../../System.map - ./piggyback sysmap < ../../../System.map | $(AS) -o sysmap.o - -initrd.o: ramdisk.image.gz piggyback - ./piggyback initrd < ramdisk.image.gz | $(AS) -o initrd.o - -zImage: $(OBJS) no_initrd.o addnote - $(LD) $(LD_ARGS) -o $@ $(OBJS) no_initrd.o $(LIBS) - cp $@ $@.rs6k - ./addnote $@.rs6k - -zImage.initrd: $(OBJS) initrd.o addnote - $(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS) - cp $@ $@.rs6k - ./addnote $@.rs6k - -else -znetboot: - -znetboot.initrd: - -floppy: - -zImage: - -zImage.initrd: - -endif - -# just here to match coffboot/Makefile -vmlinux.coff: - -vmlinux.coff.initrd: - - -clean: - rm -f piggyback note addnote $(OBJS) zImage - rm -f zImage.rs6k zImage.initrd zImage.initrd.rs6k - -fastdep: - $(TOPDIR)/scripts/mkdep *.[Sch] > .depend - -dep: - $(CPP) $(CPPFLAGS) -M *.S *.c > .depend - diff --git a/arch/ppc/chrpboot/crt0.S b/arch/ppc/chrpboot/crt0.S deleted file mode 100644 index 2a984b69d087..000000000000 --- a/arch/ppc/chrpboot/crt0.S +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) Paul Mackerras 1997. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - .text - .globl _start -_start: - lis 9,_start@h - lis 8,_etext@ha - addi 8,8,_etext@l -1: dcbf 0,9 - icbi 0,9 - addi 9,9,0x20 - cmplw 0,9,8 - blt 1b - sync - isync - b start diff --git a/arch/ppc/chrpboot/no_initrd.c b/arch/ppc/chrpboot/no_initrd.c deleted file mode 100644 index ed5dcdb1f469..000000000000 --- a/arch/ppc/chrpboot/no_initrd.c +++ /dev/null @@ -1,2 +0,0 @@ -char initrd_data[1]; -int initrd_len = 0; diff --git a/arch/ppc/coffboot/Makefile b/arch/ppc/coffboot/Makefile deleted file mode 100644 index 2835e1f8966e..000000000000 --- a/arch/ppc/coffboot/Makefile +++ /dev/null @@ -1,131 +0,0 @@ -# Makefile for making XCOFF bootable images for booting on PowerMacs -# using Open Firmware. -# -# Paul Mackerras January 1997 - -HOSTCFLAGS = -O -I$(TOPDIR)/include - -CFLAGS = $(CPPFLAGS) -O -fno-builtin -OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment -COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic -CHRP_LD_ARGS = -Ttext 0x01000000 - -COFFOBJS = coffcrt0.o start.o coffmain.o misc.o string.o zlib.o image.o -CHRPOBJS = crt0.o start.o chrpmain.o misc.o string.o zlib.o image.o -LIBS = $(TOPDIR)/lib/lib.a - -ifeq ($(CONFIG_PPC64BRIDGE),y) -MSIZE=.64 -else -MSIZE= -endif - -ifeq ($(CONFIG_SMP),y) -TFTPIMAGE=/tftpboot/zImage.pmac.smp$(MSIZE) -else -TFTPIMAGE=/tftpboot/zImage.pmac$(MSIZE) -endif - -ifeq ($(CONFIG_ALL_PPC),y) -chrpmain.o: chrpmain.c - $(CC) $(CFLAGS) -DSYSMAP_OFFSET=0 -DSYSMAP_SIZE=0 -c chrpmain.c - -hack-coff: hack-coff.c - $(HOSTCC) $(HOSTCFLAGS) -o hack-coff hack-coff.c - -znetboot: vmlinux.coff vmlinux.elf zImage - cp vmlinux.coff $(TFTPIMAGE) - cp vmlinux.elf $(TFTPIMAGE).elf - -znetboot.initrd: vmlinux.coff.initrd vmlinux.elf.initrd - cp vmlinux.coff.initrd $(TFTPIMAGE) - cp vmlinux.elf.initrd $(TFTPIMAGE).elf - -floppy: zImage -# mount -t hfs /dev/fd0 /mnt -# cp vmlinux.coff /mnt -# umount /mnt - -miboot.image: dummy.o vmlinux.gz - $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=vmlinux.gz dummy.o $@ - -miboot.image.initrd: miboot.image ramdisk.image.gz - $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=initrd=ramdisk.image.gz miboot.image $@ - -coffboot: $(COFFOBJS) no_initrd.o ld.script - $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) no_initrd.o $(LIBS) - -coffboot.initrd: $(COFFOBJS) initrd.o ld.script - $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) initrd.o $(LIBS) - -piggyback: piggyback.c - $(HOSTCC) $(HOSTCFLAGS) -DKERNELBASE=$(KERNELBASE) -o piggyback piggyback.c - -mknote: mknote.c - $(HOSTCC) $(HOSTCFLAGS) -o mknote mknote.c - -image.o: piggyback vmlinux.gz - ./piggyback image < vmlinux.gz | $(AS) -o image.o - -initrd.o: ramdisk.image.gz piggyback - ./piggyback initrd < ramdisk.image.gz | $(AS) -o initrd.o - -vmlinux.coff: coffboot hack-coff - $(OBJCOPY) $(OBJCOPY_ARGS) coffboot $@ - ./hack-coff $@ - ln -sf vmlinux.coff zImage - -vmlinux.coff.initrd: coffboot.initrd hack-coff - $(OBJCOPY) $(OBJCOPY_ARGS) coffboot.initrd $@ - ./hack-coff $@ - -vmlinux.elf: $(CHRPOBJS) no_initrd.o mknote - $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) no_initrd.o $(LIBS) - ./mknote > note - $(OBJCOPY) $@ $@ --add-section=.note=note \ - --add-section=sysmap=../../../System.map -R .comment - $(CC) $(CFLAGS) chrpmain.c -c -o chrpmain.o \ - -DSYSMAP_OFFSET=`sh ../boot/offset $(OBJDUMP) $@ sysmap` \ - -DSYSMAP_SIZE=`sh ../boot/size $(OBJDUMP) $@ sysmap` - $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) no_initrd.o $(LIBS) - $(OBJCOPY) $@ $@ --add-section=.note=note \ - --add-section=sysmap=../../../System.map -R .comment - -vmlinux.elf.initrd: $(CHRPOBJS) initrd.o mknote - $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) initrd.o $(LIBS) - ./mknote > note - $(OBJCOPY) $@ $@ --add-section=.note=note -R .comment - -zImage: vmlinux.coff vmlinux.elf miboot.image - -zImage.initrd: vmlinux.coff.initrd vmlinux.elf.initrd miboot.image.initrd - -else -znetboot: vmlinux.gz - -znetboot.initrd: vmlinux.gz - -coffboot: vmlinux.gz - -zImage: vmlinux.gz - -zImage.initrd: vmlinux.gz - -vmlinux.coff: vmlinux.gz - -vmlinux.coff.initrd: vmlinux.gz - -floppy: vmlinux.gz - -endif - -vmlinux.gz: $(TOPDIR)/vmlinux - $(OBJCOPY) -S -O binary $(TOPDIR)/vmlinux vmlinux - gzip -vf9 vmlinux - -clean: - rm -f hack-coff coffboot zImage vmlinux.coff vmlinux.gz - rm -f mknote piggyback vmlinux.elf note - rm -f miboot.image miboot.image.initrd - -fastdep: diff --git a/arch/ppc/coffboot/coffcrt0.S b/arch/ppc/coffboot/coffcrt0.S deleted file mode 100644 index 43ae4e0ec4a7..000000000000 --- a/arch/ppc/coffboot/coffcrt0.S +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) Paul Mackerras 1997. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - .text - .globl _start -_start: - .long __start,0,0 - - .globl __start -__start: - lis 9,_start@h - lis 8,_etext@ha - addi 8,8,_etext@l -1: dcbf 0,9 - icbi 0,9 - addi 9,9,0x20 - cmplwi 0,9,8 - blt 1b - b start diff --git a/arch/ppc/coffboot/crt0.S b/arch/ppc/coffboot/crt0.S deleted file mode 100644 index c43340594032..000000000000 --- a/arch/ppc/coffboot/crt0.S +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) Paul Mackerras 1997. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - .text - .globl _start -_start: - lis 9,_start@h - lis 8,_etext@ha - addi 8,8,_etext@l -1: dcbf 0,9 - icbi 0,9 - addi 9,9,0x20 - cmplwi 0,9,8 - blt 1b - b start diff --git a/arch/ppc/coffboot/dummy.c b/arch/ppc/coffboot/dummy.c deleted file mode 100644 index 31dbf45bf99c..000000000000 --- a/arch/ppc/coffboot/dummy.c +++ /dev/null @@ -1,4 +0,0 @@ -int main(void) -{ - return 0; -} diff --git a/arch/ppc/coffboot/mknote.c b/arch/ppc/coffboot/mknote.c deleted file mode 100644 index 120cc1d89739..000000000000 --- a/arch/ppc/coffboot/mknote.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) Cort Dougan 1999. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Generate a note section as per the CHRP specification. - * - */ - -#include <stdio.h> - -#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff ); - -int main(void) -{ -/* header */ - /* namesz */ - PL(strlen("PowerPC")+1); - /* descrsz */ - PL(6*4); - /* type */ - PL(0x1275); - /* name */ - printf("PowerPC"); printf("%c", 0); - -/* descriptor */ - /* real-mode */ - PL(0xffffffff); - /* real-base */ - PL(0x00c00000); - /* real-size */ - PL(0xffffffff); - /* virt-base */ - PL(0xffffffff); - /* virt-size */ - PL(0xffffffff); - /* load-base */ - PL(0x4000); - return 0; -} diff --git a/arch/ppc/coffboot/no_initrd.c b/arch/ppc/coffboot/no_initrd.c deleted file mode 100644 index ed5dcdb1f469..000000000000 --- a/arch/ppc/coffboot/no_initrd.c +++ /dev/null @@ -1,2 +0,0 @@ -char initrd_data[1]; -int initrd_len = 0; diff --git a/arch/ppc/coffboot/piggyback.c b/arch/ppc/coffboot/piggyback.c deleted file mode 100644 index 304bc8f11d40..000000000000 --- a/arch/ppc/coffboot/piggyback.c +++ /dev/null @@ -1,66 +0,0 @@ -#include <stdio.h> -#include <unistd.h> - -extern long ce_exec_config[]; - -int main(int argc, char *argv[]) -{ - int i, cnt, pos, len; - unsigned int cksum, val; - unsigned char *lp; - unsigned char buf[8192]; - if (argc != 2) - { - fprintf(stderr, "usage: %s name <in-file >out-file\n", - argv[0]); - exit(1); - } - fprintf(stdout, "#\n"); - fprintf(stdout, "# Miscellaneous data structures:\n"); - fprintf(stdout, "# WARNING - this file is automatically generated!\n"); - fprintf(stdout, "#\n"); - fprintf(stdout, "\n"); - fprintf(stdout, "\t.data\n"); - fprintf(stdout, "\t.globl %s_data\n", argv[1]); - fprintf(stdout, "%s_data:\n", argv[1]); - pos = 0; - cksum = 0; - while ((len = read(0, buf, sizeof(buf))) > 0) - { - cnt = 0; - lp = (unsigned char *)buf; - len = (len + 3) & ~3; /* Round up to longwords */ - for (i = 0; i < len; i += 4) - { - if (cnt == 0) - { - fprintf(stdout, "\t.long\t"); - } - fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]); - val = *(unsigned long *)lp; - cksum ^= val; - lp += 4; - if (++cnt == 4) - { - cnt = 0; - fprintf(stdout, " # %x \n", pos+i-12); - fflush(stdout); - } else - { - fprintf(stdout, ","); - } - } - if (cnt) - { - fprintf(stdout, "0\n"); - } - pos += len; - } - fprintf(stdout, "\t.globl %s_len\n", argv[1]); - fprintf(stdout, "%s_len:\t.long\t0x%x\n", argv[1], pos); - fflush(stdout); - fclose(stdout); - fprintf(stderr, "cksum = %x\n", cksum); - exit(0); -} - diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 300d862a1877..0e9eb82f09d9 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.head.S 1.18 05/21/01 11:49:59 paulus + * BK Id: SCCS/s.head.S 1.21 05/23/01 00:38:42 cort */ /* * PowerPC version @@ -135,9 +135,12 @@ __start: mr r28,r6 mr r27,r7 li r24,0 /* cpu # */ - /* N.B. prom_init clears the BSS even if it doesn't do - * anything else -- paulus. */ - bl prom_init +/* + * early_init() does the early machine identification and does + * the necessary low-level setup and clears the BSS + * -- Cort <cort@fsmlabs.com> + */ + bl early_init #ifdef CONFIG_APUS /* On APUS the __va/__pa constants need to be set to the correct @@ -1697,7 +1700,7 @@ cmd_line: .globl intercept_table intercept_table: - .long 0, i0x100, i0x200, i0x300, i0x400, 0, i0x600, i0x700 + .long 0, 0, i0x200, i0x300, i0x400, 0, i0x600, i0x700 .long i0x800, 0, 0, 0, 0, i0xd00, 0, 0 .long 0, 0, 0, i0x1300, 0, 0, 0, 0 .long 0, 0, 0, 0, 0, 0, 0, 0 diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c index cbfc064565ca..70cda638d25d 100644 --- a/arch/ppc/kernel/prom.c +++ b/arch/ppc/kernel/prom.c @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prom.c 1.17 05/17/01 18:14:22 cort + * BK Id: SCCS/s.prom.c 1.20 05/23/01 00:38:42 cort */ /* * Procedures for interfacing to the Open Firmware PROM on @@ -32,7 +32,7 @@ #include <asm/mmu.h> #include <asm/pgtable.h> #include <asm/bitops.h> -/* for openpic_to_irq */ +#include <asm/bootinfo.h> #include "open_pic.h" #ifdef CONFIG_FB @@ -183,26 +183,6 @@ boot_infos_t fake_bi; #endif unsigned long dev_tree_size; -/* - * prom_init() is called very early on, before the kernel text - * and data have been mapped to KERNELBASE. At this point the code - * is running at whatever address it has been loaded at, so - * references to extern and static variables must be relocated - * explicitly. The procedure reloc_offset() returns the address - * we're currently running at minus the address we were linked at. - * (Note that strings count as static variables.) - * - * Because OF may have mapped I/O devices into the area starting at - * KERNELBASE, particularly on CHRP machines, we can't safely call - * OF once the kernel has been mapped to KERNELBASE. Therefore all - * OF calls should be done within prom_init(), and prom_init() - * and all routines called within it must be careful to relocate - * references as necessary. - */ -#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) -#define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) - offset)) -#define RELOC(x) (*PTRRELOC(&(x))) - #define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long)) /* Is boot-info compatible ? */ @@ -617,30 +597,10 @@ prom_init(int r3, int r4, prom_entry pp) char *p, *d; int prom_version = 0; unsigned long phys; - extern char __bss_start, _end; - - /* First zero the BSS -- use memset, some arches don't have - * caches on yet */ - memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start); /* Default */ phys = offset + KERNELBASE; - /* check if we're apus, return if we are */ - if ( r3 == 0x61707573 ) - return phys; - - /* If we came here from BootX, clear the screen, - * set up some pointers and return. */ - if (r3 == 0x426f6f58 && pp == NULL) { - bootx_init(r4, phys); - return phys; - } - - /* check if we're prep, return if we are */ - if ( *(unsigned long *)(0) == 0xdeadc0de ) - return phys; - /* First get a handle for the stdout device */ RELOC(prom) = pp; RELOC(prom_chosen) = call_prom(RELOC("finddevice"), 1, 1, diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 31a2c02ff0d5..b39dae8a9fec 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.setup.c 1.23 05/21/01 16:08:53 cort + * BK Id: SCCS/s.setup.c 1.32 05/23/01 00:38:42 cort */ /* * Common prep/pmac/chrp boot and setup code. @@ -81,6 +81,10 @@ extern void gemini_init(unsigned long r3, unsigned long r6, unsigned long r7); + +extern void bootx_init(unsigned long r4, unsigned long phys); +extern unsigned long reloc_offset(void); + #ifdef CONFIG_XMON extern void xmon_map_scc(void); #endif @@ -437,6 +441,79 @@ intuit_machine_type(void) } #endif /* CONFIG_ALL_PPC */ +#ifdef CONFIG_6xx +/* + * We're called here very early in the boot. We determine the machine + * type and call the appropriate low-level setup functions. + * -- Cort <cort@fsmlabs.com> + */ +__init +unsigned long +early_init(int r3, int r4, int r5) +{ + extern char __bss_start, _end; + unsigned long phys; + unsigned long offset = reloc_offset(); + unsigned long local_have_of = 1, local_machine; + struct bi_record *rec; + + /* Default */ + phys = offset + KERNELBASE; + +#if defined(CONFIG_APUS) + return phys; +#endif + + /* First zero the BSS -- use memset, some arches don't have + * caches on yet */ + memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start); + +#if defined(CONFIG_ALL_PPC) || defined(CONFIG_GEMINI) + /* If we came here from BootX, clear the screen, + * set up some pointers and return. */ +#if defined(CONFIG_ALL_PPC) + if ((r3 == 0x426f6f58) && (r5 == 0)) { + bootx_init(r4, phys); + return phys; + } +#endif + + /* check if we're prep, return if we are */ + if ( *(unsigned long *)(0) == 0xdeadc0de ) + return phys; + + /* + * See if we have any bootloader info passed along. If we do, + * get the machine type and find out if we have OF. + * + * The strategy here is to assume that we want to call prom_init() + * unless the bootinfo data passed to us tell us that we don't + * have OF. + * -- Cort <cort@fsmlabs.com> + */ + rec = (struct bi_record *)_ALIGN((ulong)PTRRELOC(&__bss_start)+(1<<20)-1,(1<<20)); + if ( rec->tag == BI_FIRST ) + { + for ( ; rec->tag != BI_LAST ; + rec = (struct bi_record *)((ulong)rec + rec->size) ) + { + ulong *data = rec->data; + if ( rec->tag == BI_MACHTYPE ) + { + local_machine = data[0]; + local_have_of = data[1]; + } + } + } + + if ( local_have_of ) + phys = prom_init( r3, r4, (prom_entry)r5); +#endif + + return phys; +} +#endif /* CONFIG_6xx */ + /* * Find out what kind of machine we're on and save any data we need * from the early boot process (devtree is copied on pmac by prom_init() ) @@ -480,7 +557,6 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, * are used for initrd_start and initrd_size, * otherwise they contain 0xdeadbeef. */ - cmd_line[0] = 0; if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) { strncpy(cmd_line, (char *)r3 + KERNELBASE, sizeof(cmd_line)); @@ -517,7 +593,7 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, chosen = find_devices("chosen"); if (chosen != NULL) { p = get_property(chosen, "bootargs", NULL); - if (p != NULL) { + if (p && *p) { cmd_line[0] = 0; strncpy(cmd_line, p, sizeof(cmd_line)); } diff --git a/arch/ppc/mbxboot/Makefile b/arch/ppc/mbxboot/Makefile deleted file mode 100644 index 9dd5d64f36cd..000000000000 --- a/arch/ppc/mbxboot/Makefile +++ /dev/null @@ -1,124 +0,0 @@ -# -# arch/ppc/mbxboot/Makefile -# -# 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. -# -# Copyright (C) 1994 by Linus Torvalds -# Adapted for PowerPC by Gary Thomas -# modified by Cort (cort@cs.nmt.edu) -# -.c.s: - $(CC) $(CFLAGS) -S -o $*.s $< -.s.o: - $(AS) -o $*.o $< -.c.o: - $(CC) $(CFLAGS) -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -c -o $*.o $< -.S.s: - $(CPP) $(AFLAGS) -traditional -o $*.o $< -.S.o: - $(CC) $(AFLAGS) -traditional -c -o $*.o $< - -ZOFF = 0 -ZSZ = 0 -IOFF = 0 -ISZ = 0 - -TFTPIMAGE=/tftpboot/zImage.embedded - -ifdef CONFIG_8xx -ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000 -OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o -CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx -endif - -ifdef CONFIG_8260 -ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00400000 -OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o -CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8260 -endif - -OBJCOPY_ARGS = -O elf32-powerpc - -ifeq ($(CONFIG_MBX),y) -OBJECTS += pci.o qspan_pci.o -CFLAGS += -DCONFIG_MBX -endif -ifeq ($(CONFIG_RPXLITE),y) -CFLAGS += -DCONFIG_RPXLITE -OBJECTS += iic.o embed_config.o -endif -ifeq ($(CONFIG_RPXCLASSIC),y) -CFLAGS += -DCONFIG_RPXCLASSIC -OBJECTS += iic.o embed_config.o pci.o qspan_pci.o -endif -ifeq ($(CONFIG_BSEIP),y) -CFLAGS += -DCONFIG_BSEIP -OBJECTS += iic.o embed_config.o -endif - -all: zImage - -zvmlinux.initrd: zvmlinux - $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp1 $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=initrd=ramdisk.image.gz \ - --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.initrd.tmp1 zvmlinux.initrd1 - $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 initrd` \ - -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 initrd` \ - -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 image` \ - -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 image` \ - -c -o misc.o misc.c - $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=initrd=ramdisk.image.gz \ - --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.initrd.tmp $@ - -zImage: zvmlinux - ln -sf zvmlinux zImage - -zImage.initrd: zvmlinux.initrd - ln -sf zvmlinux.initrd zImage.initrd - -zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz -# -# build the boot loader image and then compute the offset into it -# for the kernel image -# - $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.tmp $@ -# -# then with the offset rebuild the bootloader so we know where the kernel is -# - $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \ - -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \ - -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \ - -c -o misc.o misc.c - $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.tmp $@ - rm zvmlinux.tmp - -znetboot : zImage - cp zImage $(TFTPIMAGE) - -znetboot.initrd : zImage.initrd - cp zImage.initrd $(TFTPIMAGE) - -clean: - rm -f vmlinux* zvmlinux* zImage* - -fastdep: - $(TOPDIR)/scripts/mkdep *.[Sch] > .depend - -dep: - $(CPP) $(CPPFLAGS) -M *.S *.c > .depend - -# just here to match coffboot/Makefile -vmlinux.coff: - -vmlinux.coff.initrd: diff --git a/arch/ppc/mbxboot/embed_config.c b/arch/ppc/mbxboot/embed_config.c deleted file mode 100644 index b9a37a76cb12..000000000000 --- a/arch/ppc/mbxboot/embed_config.c +++ /dev/null @@ -1,253 +0,0 @@ - -/* Board specific functions for those embedded 8xx boards that do - * not have boot monitor support for board information. - */ -#include <sys/types.h> -#include <linux/config.h> -#ifdef CONFIG_8xx -#include <asm/mpc8xx.h> -#endif -#ifdef CONFIG_8260 -#include <asm/mpc8260.h> -#endif - - -/* IIC functions. - * These are just the basic master read/write operations so we can - * examine serial EEPROM. - */ -extern void iic_read(uint devaddr, u_char *buf, uint offset, uint count); -extern u_char aschex_to_byte(u_char *cp); - -/* Supply a default Ethernet address for those eval boards that don't - * ship with one. This is an address from the MBX board I have, so - * it is unlikely you will find it on your network. - */ -static ushort def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 }; - -#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) - -static void rpx_eth(bd_t *bd, u_char *cp); -static void rpx_brate(bd_t *bd, u_char *cp); -static void rpx_memsize(bd_t *bd, u_char *cp); -static void rpx_cpuspeed(bd_t *bd, u_char *cp); - -/* Read the EEPROM on the RPX-Lite board. -*/ -void -rpx_cfg(bd_t *bd) -{ - u_char eebuf[256], *cp; - - /* Read the first 256 bytes of the EEPROM. I think this - * is really all there is, and I hope if it gets bigger the - * info we want is still up front. - */ -#if 1 - iic_read(0xa8, eebuf, 0, 128); - iic_read(0xa8, &eebuf[128], 128, 128); - { - int i; - cp = (u_char *)0xfa000000; - - for (i=0; i<256; i++) - *cp++ = eebuf[i]; - } - - /* We look for two things, the Ethernet address and the - * serial baud rate. The records are separated by - * newlines. - */ - cp = eebuf; - for (;;) { - if (*cp == 'E') { - cp++; - if (*cp == 'A') { - cp += 2; - rpx_eth(bd, cp); - } - } - if (*cp == 'S') { - cp++; - if (*cp == 'B') { - cp += 2; - rpx_brate(bd, cp); - } - } - if (*cp == 'D') { - cp++; - if (*cp == '1') { - cp += 2; - rpx_memsize(bd, cp); - } - } - if (*cp == 'H') { - cp++; - if (*cp == 'Z') { - cp += 2; - rpx_cpuspeed(bd, cp); - } - } - - /* Scan to the end of the record. - */ - while ((*cp != '\n') && (*cp != 0xff)) - cp++; - - /* If the next character is a 0 or ff, we are done. - */ - cp++; - if ((*cp == 0) || (*cp == 0xff)) - break; - } - bd->bi_memstart = 0; - -#else - /* For boards without initialized EEPROM. - */ - bd->bi_memstart = 0; - bd->bi_memsize = (8 * 1024 * 1024); - bd->bi_intfreq = 48; - bd->bi_busfreq = 48; - bd->bi_baudrate = 9600; -#endif -} - -static void -rpx_eth(bd_t *bd, u_char *cp) -{ - int i; - - for (i=0; i<6; i++) { - bd->bi_enetaddr[i] = aschex_to_byte(cp); - cp += 2; - } -} - -static void -rpx_brate(bd_t *bd, u_char *cp) -{ - uint rate; - - rate = 0; - - while (*cp != '\n') { - rate *= 10; - rate += (*cp) - '0'; - cp++; - } - - bd->bi_baudrate = rate * 100; -} - -static void -rpx_memsize(bd_t *bd, u_char *cp) -{ - uint size; - - size = 0; - - while (*cp != '\n') { - size *= 10; - size += (*cp) - '0'; - cp++; - } - - bd->bi_memsize = size * 1024 * 1024; -} - -static void -rpx_cpuspeed(bd_t *bd, u_char *cp) -{ - uint num, den; - - num = den = 0; - - while (*cp != '\n') { - num *= 10; - num += (*cp) - '0'; - cp++; - if (*cp == '/') { - cp++; - den = (*cp) - '0'; - break; - } - } - - /* I don't know why the RPX just can't state the actual - * CPU speed..... - */ - if (den) { - num /= den; - num *= den; - } - bd->bi_intfreq = bd->bi_busfreq = num; - - /* The 8xx can only run a maximum 50 MHz bus speed (until - * Motorola changes this :-). Greater than 50 MHz parts - * run internal/2 for bus speed. - */ - if (num > 50) - bd->bi_busfreq /= 2; -} -#endif /* RPXLITE || RPXCLASSIC */ - -#ifdef CONFIG_BSEIP -/* Build a board information structure for the BSE ip-Engine. - * There is more to come since we will add some environment - * variables and a function to read them. - */ -void -bseip_cfg(bd_t *bd) -{ - u_char *cp; - int i; - - /* Baud rate and processor speed will eventually come - * from the environment variables. - */ - bd->bi_baudrate = 9600; - - /* Get the Ethernet station address from the Flash ROM. - */ - cp = (u_char *)0xfe003ffa; - for (i=0; i<6; i++) { - bd->bi_enetaddr[i] = *cp++; - } - - /* The rest of this should come from the environment as well. - */ - bd->bi_memstart = 0; - bd->bi_memsize = (16 * 1024 * 1024); - bd->bi_intfreq = 48; - bd->bi_busfreq = 48; -} -#endif /* BSEIP */ - -#ifdef CONFIG_EST8260 -void -embed_config(bd_t *bd) -{ - u_char *cp; - int i; - -#if 0 - /* This is actually provided by my boot rom. I have it - * here for those people that may load the kernel with - * a JTAG/COP tool and not the rom monitor. - */ - bd->bi_baudrate = 115200; - bd->bi_intfreq = 200; - bd->bi_busfreq = 66; - bd->bi_cpmfreq = 66; - bd->bi_brgfreq = 33; - bd->bi_memsize = 16 * 1024 * 1024; -#endif - - cp = (u_char *)def_enet_addr; - for (i=0; i<6; i++) { - bd->bi_enetaddr[i] = *cp++; - } -} -#endif /* EST8260 */ - diff --git a/arch/sh/kernel/rtc.c b/arch/sh/kernel/rtc.c index 94dd764bf85d..a6586bd0d98f 100644 --- a/arch/sh/kernel/rtc.c +++ b/arch/sh/kernel/rtc.c @@ -143,7 +143,6 @@ void sh_rtc_gettimeofday(struct timeval *tv) static int set_rtc_time(unsigned long nowtime) { - extern int abs (int); int retval = 0; int real_seconds, real_minutes, cmos_minutes; diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index f5dddbae57d2..4a4684fbd84c 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -454,6 +454,7 @@ CONFIG_RAMFS=m CONFIG_ISO9660_FS=m CONFIG_JOLIET=y CONFIG_MINIX_FS=m +CONFIG_VXFS_FS=m # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set CONFIG_HPFS_FS=m @@ -617,6 +618,7 @@ CONFIG_USB_MICROTEK=m # CONFIG_USB_IBMCAM=m CONFIG_USB_OV511=m +CONFIG_USB_PWC=m CONFIG_USB_DSBR=m CONFIG_USB_DABUSB=m diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 5e21a9649f08..f16d406d8093 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -1,4 +1,4 @@ -/* $Id: pci_iommu.c,v 1.13 2001/03/14 08:42:38 davem Exp $ +/* $Id: pci_iommu.c,v 1.14 2001/05/23 03:06:51 davem Exp $ * pci_iommu.c: UltraSparc PCI controller IOM/STC support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -58,7 +58,7 @@ static void __iommu_flushall(struct pci_iommu *iommu) static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages) { - iopte_t *iopte, *limit; + iopte_t *iopte, *limit, *first; unsigned long cnum, ent, flush_point; cnum = 0; @@ -77,6 +77,7 @@ static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long n iopte += ((ent = iommu->alloc_info[cnum].next) << cnum); flush_point = iommu->alloc_info[cnum].flush; + first = iopte; for (;;) { if (iopte_val(*iopte) == 0UL) { if ((iopte + (1 << cnum)) >= limit) @@ -98,10 +99,17 @@ static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long n } if (ent == flush_point) __iommu_flushall(iommu); + if (iopte == first) + goto bad; } /* I've got your streaming cluster right here buddy boy... */ return iopte; + +bad: + printk(KERN_EMERG "pci_iommu: alloc_streaming_cluster of npages(%ld) failed!\n", + npages); + return NULL; } static void free_streaming_cluster(struct pci_iommu *iommu, dma_addr_t base, @@ -319,6 +327,8 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct spin_lock_irqsave(&iommu->lock, flags); base = alloc_streaming_cluster(iommu, npages); + if (base == NULL) + goto bad; bus_addr = (iommu->page_table_map_base + ((base - iommu->page_table) << PAGE_SHIFT)); ret = bus_addr | (oaddr & ~PAGE_MASK); @@ -339,6 +349,11 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct spin_unlock_irqrestore(&iommu->lock, flags); return ret; + +bad: + spin_unlock_irqrestore(&iommu->lock, flags); + BUG(); + return 0; } /* Unmap a single streaming mode DMA translation. */ @@ -517,6 +532,8 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int spin_lock_irqsave(&iommu->lock, flags); base = alloc_streaming_cluster(iommu, npages); + if (base == NULL) + goto bad; dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << PAGE_SHIFT); /* Step 3: Normalize DMA addresses. */ @@ -550,6 +567,11 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int spin_unlock_irqrestore(&iommu->lock, flags); return used; + +bad: + spin_unlock_irqrestore(&iommu->lock, flags); + BUG(); + return 0; } /* Unmap a set of streaming mode DMA translations. */ diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 30cac5e008a9..08bbe2b57fe6 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.13 2001/02/13 01:16:44 davem Exp $ +/* $Id: sbus.c,v 1.14 2001/05/23 03:06:51 davem Exp $ * sbus.c: UltraSparc SBUS controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -133,7 +133,7 @@ static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npage static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) { - iopte_t *iopte, *limit; + iopte_t *iopte, *limit, *first; unsigned long cnum, ent, flush_point; cnum = 0; @@ -150,6 +150,7 @@ static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long iopte += ((ent = iommu->alloc_info[cnum].next) << cnum); flush_point = iommu->alloc_info[cnum].flush; + first = iopte; for (;;) { if (iopte_val(*iopte) == 0UL) { if ((iopte + (1 << cnum)) >= limit) @@ -169,10 +170,17 @@ static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long } if (ent == flush_point) __iommu_flushall(iommu); + if (iopte == first) + goto bad; } /* I've got your streaming cluster right here buddy boy... */ return iopte; + +bad: + printk(KERN_EMERG "sbus: alloc_streaming_cluster of npages(%ld) failed!\n", + npages); + return NULL; } static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages) @@ -332,6 +340,8 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int di spin_lock_irqsave(&iommu->lock, flags); npages = size >> PAGE_SHIFT; iopte = alloc_streaming_cluster(iommu, npages); + if (iopte == NULL) + goto bad; dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); npages = size >> PAGE_SHIFT; iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE; @@ -345,6 +355,11 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int di spin_unlock_irqrestore(&iommu->lock, flags); return (dma_base | offset); + +bad: + spin_unlock_irqrestore(&iommu->lock, flags); + BUG(); + return 0; } void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, int direction) @@ -455,6 +470,8 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int di spin_lock_irqsave(&iommu->lock, flags); iopte = alloc_streaming_cluster(iommu, npages); + if (iopte == NULL) + goto bad; dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); /* Normalize DVMA addresses. */ @@ -479,6 +496,11 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int di spin_unlock_irqrestore(&iommu->lock, flags); return used; + +bad: + spin_unlock_irqrestore(&iommu->lock, flags); + BUG(); + return 0; } void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction) diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c index 5098cd18acdd..05be1eb2cd7b 100644 --- a/drivers/block/ps2esdi.c +++ b/drivers/block/ps2esdi.c @@ -953,10 +953,10 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) break; } if(ending != -1) { - spin_lock_irqsave(io_request_lock, flags); + spin_lock_irqsave(&io_request_lock, flags); end_request(ending); do_ps2esdi_request(BLK_DEFAULT_QUEUE(MAJOR_NR)); - spin_unlock_irqrestore(io_request_lock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); } } /* handle interrupts */ diff --git a/drivers/block/xd.c b/drivers/block/xd.c index 2c86f589f63a..b611664451af 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -1154,8 +1154,6 @@ int init_module(void) void cleanup_module(void) { - int partition,dev,start; - devfs_unregister_blkdev(MAJOR_NR, "xd"); xd_done(); devfs_unregister (devfs_handle); diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 59a417384bfb..3069ee52a757 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -1118,7 +1118,7 @@ static int tst_Attention(void) return (0); } /*==========================================================================*/ -#endif 00000 +#endif /*==========================================================================*/ static int ResponseInfo(void) { diff --git a/drivers/char/i810-tco.c b/drivers/char/i810-tco.c index bfd75d6ea647..6c935491c460 100644 --- a/drivers/char/i810-tco.c +++ b/drivers/char/i810-tco.c @@ -181,8 +181,10 @@ static int i810tco_release (struct inode *inode, struct file *file) /* * Shut off the timer. */ +#ifdef CONFIG_WATCHDOG_NOWAYOUT tco_timer_stop (); timer_alive = 0; +#endif return 0; } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index ba7b3a1ea14e..164cb42525e6 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -73,7 +73,6 @@ extern void streamable_init(void); extern int rtc_DP8570A_init(void); extern int rtc_MK48T08_init(void); extern int ds1286_init(void); -extern int radio_init(void); extern int pmu_device_init(void); extern int tosh_init(void); @@ -262,9 +261,6 @@ int __init misc_init(void) #ifdef CONFIG_SGI_DS1286 ds1286_init(); #endif -#ifdef CONFIG_MISC_RADIO - radio_init(); -#endif #ifdef CONFIG_PMAC_PBOOK pmu_device_init(); #endif diff --git a/drivers/char/pcwd.c b/drivers/char/pcwd.c index 4b28f32b8996..509b5342aa94 100644 --- a/drivers/char/pcwd.c +++ b/drivers/char/pcwd.c @@ -506,6 +506,8 @@ static inline char *get_firmware(void) char *ret; ret = kmalloc(6, GFP_KERNEL); + if(ret == NULL) + return NULL; while((count < 3) && (!found)) { outb_p(0x80, current_readport + 2); @@ -527,10 +529,8 @@ static inline char *get_firmware(void) ten = send_command(0x82); hund = send_command(0x83); minor = send_command(0x84); - } - - if (found) sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); + } else sprintf(ret, "ERROR"); @@ -642,12 +642,12 @@ static int __init pcwatchdog_init(void) static void __exit pcwatchdog_exit(void) { + misc_deregister(&pcwd_miscdev); /* Disable the board */ if (revision == PCWD_REVISION_C) { outb_p(0xA5, current_readport + 3); outb_p(0xA5, current_readport + 3); } - misc_deregister(&pcwd_miscdev); if (supports_temp) misc_deregister(&temp_miscdev); diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index a8bd488044e5..d84f373a7f87 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -302,13 +302,13 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int ctx, int num_desc, d = (struct dma_iso_ctx *)kmalloc(sizeof(struct dma_iso_ctx), GFP_KERNEL); - memset(d, 0, sizeof(struct dma_iso_ctx)); - if (d==NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate dma_iso_ctx"); return NULL; } + memset(d, 0, sizeof(struct dma_iso_ctx)); + d->ohci = (void *)ohci; d->ctx = ctx; d->channel = channel; diff --git a/drivers/isdn/avmb1/capifs.c b/drivers/isdn/avmb1/capifs.c index 80cc062c35af..e3079b400a73 100644 --- a/drivers/isdn/avmb1/capifs.c +++ b/drivers/isdn/avmb1/capifs.c @@ -1,86 +1,9 @@ /* - * $Id: capifs.c,v 1.14.6.5 2001/03/21 08:52:21 kai Exp $ - * + * $Id: capifs.c,v 1.14.6.7 2001/05/24 08:29:08 kai Exp $ + * * (c) Copyright 2000 by Carsten Paeth (calle@calle.de) * * Heavily based on devpts filesystem from H. Peter Anvin - * - * $Log: capifs.c,v $ - * Revision 1.14.6.5 2001/03/21 08:52:21 kai - * merge from main branch: fix buffer for revision string (calle) - * - * Revision 1.14.6.4 2001/03/15 15:11:24 kai - * *** empty log message *** - * - * Revision 1.14.6.3 2001/02/13 11:43:29 kai - * more compatility changes for 2.2.19 - * - * Revision 1.14.6.2 2001/02/10 14:41:20 kai - * Changes from kernel tree - * - * Revision 1.14.6.1 2000/11/28 12:02:45 kai - * MODULE_DEVICE_TABLE for 2.4 - * - * Revision 1.14.2.1 2000/11/26 17:47:53 kai - * added PCI_DEV_TABLE for 2.4 - * - * Revision 1.14 2000/11/23 20:45:14 kai - * fixed module_init/exit stuff - * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. - * - * Revision 1.13 2000/11/18 16:17:25 kai - * change from 2.4 tree - * - * Revision 1.12 2000/11/01 14:05:02 calle - * - use module_init/module_exit from linux/init.h. - * - all static struct variables are initialized with "membername:" now. - * - avm_cs.c, let it work with newer pcmcia-cs. - * - * Revision 1.11 2000/10/24 15:08:47 calle - * Too much includes. - * - * Revision 1.10 2000/10/12 10:12:35 calle - * Bugfix: second iput(inode) on umount, destroies a foreign inode. - * - * Revision 1.9 2000/08/20 07:30:13 keil - * changes for 2.4 - * - * Revision 1.8 2000/07/20 10:23:13 calle - * Include isdn_compat.h for people that don't use -p option of std2kern. - * - * Revision 1.7 2000/06/18 16:09:54 keil - * more changes for 2.4 - * - * Revision 1.6 2000/04/03 13:29:25 calle - * make Tim Waugh happy (module unload races in 2.3.99-pre3). - * no real problem there, but now it is much cleaner ... - * - * Revision 1.5 2000/03/13 17:49:52 calle - * make it running with 2.3.51. - * - * Revision 1.4 2000/03/08 17:06:33 calle - * - changes for devfs and 2.3.49 - * - capifs now configurable (no need with devfs) - * - New Middleware ioctl CAPI_NCCI_GETUNIT - * - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs) - * - * Revision 1.3 2000/03/06 18:00:23 calle - * - Middleware extention now working with 2.3.49 (capifs). - * - Fixed typos in debug section of capi.c - * - Bugfix: Makefile corrected for b1pcmcia.c - * - * Revision 1.2 2000/03/06 09:17:07 calle - * - capifs: fileoperations now in inode (change for 2.3.49) - * - Config.in: Middleware extention not a tristate, uups. - * - * Revision 1.1 2000/03/03 16:48:38 calle - * - Added CAPI2.0 Middleware support (CONFIG_ISDN_CAPI) - * It is now possible to create a connection with a CAPI2.0 applikation - * and than to handle the data connection from /dev/capi/ (capifs) and also - * using async or sync PPP on this connection. - * The two major device number 190 and 191 are not confirmed yet, - * but I want to save the code in cvs, before I go on. - * * */ @@ -105,7 +28,7 @@ MODULE_AUTHOR("Carsten Paeth <calle@calle.de>"); -static char *revision = "$Revision: 1.14.6.6 $"; +static char *revision = "$Revision: 1.14.6.7 $"; struct capifs_ncci { struct inode *inode; @@ -142,6 +65,7 @@ static inline struct capifs_sb_info *SBI(struct super_block *sb) static int capifs_root_readdir(struct file *,void *,filldir_t); static struct dentry *capifs_root_lookup(struct inode *,struct dentry *); static int capifs_revalidate(struct dentry *, int); +static struct inode *capifs_new_inode(struct super_block *sb); static struct file_operations capifs_root_operations = { read: generic_read_dir, @@ -285,9 +209,6 @@ static void capifs_put_super(struct super_block *sb) kfree(sbi->nccis); kfree(sbi); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51) - MOD_DEC_USE_COUNT; -#endif } static int capifs_statfs(struct super_block *sb, struct statfs *buf); @@ -363,10 +284,6 @@ struct super_block *capifs_read_super(struct super_block *s, void *data, struct dentry * root; struct capifs_sb_info *sbi; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51) - MOD_INC_USE_COUNT; - lock_super(s); -#endif /* Super block already completed? */ if (s->s_root) goto out; @@ -449,34 +366,11 @@ struct super_block *capifs_read_super(struct super_block *s, void *data, mounts = s; out: /* Success ... somebody else completed the super block for us. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51) - unlock_super(s); -#endif return s; fail: -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51) - unlock_super(s); - MOD_DEC_USE_COUNT; -#endif return NULL; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51) -static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) -{ - struct statfs tmp; - - tmp.f_type = CAPIFS_SUPER_MAGIC; - tmp.f_bsize = 1024; - tmp.f_blocks = 0; - tmp.f_bfree = 0; - tmp.f_bavail = 0; - tmp.f_files = 0; - tmp.f_ffree = 0; - tmp.f_namelen = NAME_MAX; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; -} -#else static int capifs_statfs(struct super_block *sb, struct statfs *buf) { buf->f_type = CAPIFS_SUPER_MAGIC; @@ -489,11 +383,10 @@ static int capifs_statfs(struct super_block *sb, struct statfs *buf) buf->f_namelen = NAME_MAX; return 0; } -#endif -static struct inode *capifs_new_inode(struct super_block *sb); +static struct inode *capifs_new_inode(struct super_block *sb) { - inode = new_inode(sb); + struct inode *inode = new_inode(sb); if (inode) { inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = 0; @@ -503,16 +396,7 @@ static struct inode *capifs_new_inode(struct super_block *sb); return inode; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51) -static struct file_system_type capifs_fs_type = { - "capifs", - 0, - capifs_read_super, - NULL -}; -#else static DECLARE_FSTYPE(capifs_fs_type, "capifs", capifs_read_super, 0); -#endif void capifs_new_ncci(char type, unsigned int num, kdev_t device) { @@ -594,11 +478,7 @@ static int __init capifs_init(void) MOD_DEC_USE_COUNT; return err; } -#ifdef MODULE - printk(KERN_NOTICE "capifs: Rev %s: loaded\n", rev); -#else - printk(KERN_NOTICE "capifs: Rev %s: started\n", rev); -#endif + printk(KERN_NOTICE "capifs: Rev %s\n", rev); MOD_DEC_USE_COUNT; return 0; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f93ffc1e8304..bb2ace28c8b6 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -298,7 +298,7 @@ static void raid1_shrink_buffers (raid1_conf_t *conf) md_spin_unlock_irq(&conf->device_lock); } -static int raid1_map (mddev_t *mddev, kdev_t *rdev, unsigned long size) +static int raid1_map (mddev_t *mddev, kdev_t *rdev) { raid1_conf_t *conf = mddev_to_conf(mddev); int i, disks = MD_SB_DISKS; @@ -602,7 +602,7 @@ static int raid1_make_request (mddev_t *mddev, int rw, bh_req = &r1_bh->bh_req; memcpy(bh_req, bh, sizeof(*bh)); - bh_req->b_blocknr = bh->b_rsector / sectors; + bh_req->b_blocknr = bh->b_rsector; bh_req->b_dev = mirror->dev; bh_req->b_rdev = mirror->dev; /* bh_req->b_rsector = bh->n_rsector; */ @@ -646,7 +646,7 @@ static int raid1_make_request (mddev_t *mddev, int rw, /* * prepare mirrored mbh (fields ordered for max mem throughput): */ - mbh->b_blocknr = bh->b_rsector / sectors; + mbh->b_blocknr = bh->b_rsector; mbh->b_dev = conf->mirrors[i].dev; mbh->b_rdev = conf->mirrors[i].dev; mbh->b_rsector = bh->b_rsector; @@ -1138,7 +1138,6 @@ static void raid1d (void *data) int disks = MD_SB_DISKS; struct buffer_head *bhl, *mbh; raid1_conf_t *conf; - int sectors = bh->b_size >> 9; conf = mddev_to_conf(mddev); bhl = raid1_alloc_bh(conf, conf->raid_disks); /* don't really need this many */ @@ -1168,7 +1167,7 @@ static void raid1d (void *data) mbh->b_blocknr = bh->b_blocknr; mbh->b_dev = conf->mirrors[i].dev; mbh->b_rdev = conf->mirrors[i].dev; - mbh->b_rsector = bh->b_blocknr * sectors; + mbh->b_rsector = bh->b_blocknr; mbh->b_state = (1<<BH_Req) | (1<<BH_Dirty) | (1<<BH_Mapped) | (1<<BH_Lock); atomic_set(&mbh->b_count, 1); @@ -1195,7 +1194,7 @@ static void raid1d (void *data) } } else { dev = bh->b_dev; - raid1_map (mddev, &bh->b_dev, bh->b_size >> 9); + raid1_map (mddev, &bh->b_dev); if (bh->b_dev == dev) { printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr); md_done_sync(mddev, bh->b_size>>9, 0); @@ -1203,6 +1202,7 @@ static void raid1d (void *data) printk (REDIRECT_SECTOR, partition_name(bh->b_dev), bh->b_blocknr); bh->b_rdev = bh->b_dev; + bh->b_rsector = bh->b_blocknr; generic_make_request(READ, bh); } } @@ -1211,8 +1211,7 @@ static void raid1d (void *data) case READ: case READA: dev = bh->b_dev; - - raid1_map (mddev, &bh->b_dev, bh->b_size >> 9); + raid1_map (mddev, &bh->b_dev); if (bh->b_dev == dev) { printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr); raid1_end_bh_io(r1_bh, 0); @@ -1220,6 +1219,7 @@ static void raid1d (void *data) printk (REDIRECT_SECTOR, partition_name(bh->b_dev), bh->b_blocknr); bh->b_rdev = bh->b_dev; + bh->b_rsector = bh->b_blocknr; generic_make_request (r1_bh->cmd, bh); } break; @@ -1313,6 +1313,7 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long sector_nr) struct buffer_head *bh; int bsize; int disk; + int block_nr; spin_lock_irq(&conf->segment_lock); if (!sector_nr) { @@ -1383,11 +1384,11 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long sector_nr) r1_bh->cmd = SPECIAL; bh = &r1_bh->bh_req; - bh->b_blocknr = sector_nr; + block_nr = sector_nr; bsize = 512; - while (!(bh->b_blocknr & 1) && bsize < PAGE_SIZE - && (bh->b_blocknr+2)*(bsize>>9) < (mddev->sb->size *2)) { - bh->b_blocknr >>= 1; + while (!(block_nr & 1) && bsize < PAGE_SIZE + && (block_nr+2)*(bsize>>9) < (mddev->sb->size *2)) { + block_nr >>= 1; bsize <<= 1; } bh->b_size = bsize; @@ -1403,6 +1404,7 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long sector_nr) BUG(); bh->b_end_io = end_sync_read; bh->b_private = r1_bh; + bh->b_blocknr = sector_nr; bh->b_rsector = sector_nr; init_waitqueue_head(&bh->b_wait); @@ -1440,7 +1442,7 @@ static void end_sync_write(struct buffer_head *bh, int uptodate) md_error (r1_bh->mddev, bh->b_dev); if (atomic_dec_and_test(&r1_bh->remaining)) { mddev_t *mddev = r1_bh->mddev; - unsigned long sect = bh->b_blocknr * (bh->b_size>>9); + unsigned long sect = bh->b_blocknr; int size = bh->b_size; raid1_free_buf(r1_bh); sync_request_done(sect, mddev_to_conf(mddev)); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f11fd8a24c1f..d1e190168405 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1051,8 +1051,8 @@ static void handle_stripe(struct stripe_head *sh) action[failed_num] = WRITE+1; locked++; set_bit(STRIPE_INSYNC, &sh->state); - if (conf->disks[i].operational) - md_sync_acct(conf->disks[i].dev, bh->b_size>>9); + if (conf->disks[failed_num].operational) + md_sync_acct(conf->disks[failed_num].dev, bh->b_size>>9); else if (conf->spare) md_sync_acct(conf->spare->dev, bh->b_size>>9); diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 342a889693f6..caab942d2a23 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -41,6 +41,7 @@ struct pms_device struct video_picture picture; int height; int width; + struct semaphore lock; }; struct i2c_info @@ -739,8 +740,10 @@ static int pms_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EFAULT; if(v<0 || v>3) return -EINVAL; + down(&pd->lock); pms_videosource(v&1); pms_vcrinput(v>>1); + up(&pd->lock); return 0; } case VIDIOCGTUNER: @@ -780,6 +783,7 @@ static int pms_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EFAULT; if(v.tuner) return -EINVAL; + down(&pd->lock); switch(v.mode) { case VIDEO_MODE_AUTO: @@ -803,8 +807,10 @@ static int pms_ioctl(struct video_device *dev, unsigned int cmd, void *arg) pms_format(2); break; default: + up(&pd->lock); return -EINVAL; } + up(&pd->lock); return 0; } case VIDIOCGPICT: @@ -828,10 +834,12 @@ static int pms_ioctl(struct video_device *dev, unsigned int cmd, void *arg) * Now load the card. */ + down(&pd->lock); pms_brightness(p.brightness>>8); pms_hue(p.hue>>8); pms_colour(p.colour>>8); pms_contrast(p.contrast>>8); + up(&pd->lock); return 0; } case VIDIOCSWIN: @@ -849,8 +857,9 @@ static int pms_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EINVAL; pd->width=vw.width; pd->height=vw.height; + down(&pd->lock); pms_resolution(pd->width, pd->height); - /* Ok we figured out what to use from our wide choice */ + up(&pd->lock); /* Ok we figured out what to use from our wide choice */ return 0; } case VIDIOCGWIN: @@ -893,8 +902,9 @@ static long pms_read(struct video_device *v, char *buf, unsigned long count, in struct pms_device *pd=(struct pms_device *)v; int len; - /* FIXME: semaphore this */ + down(&pd->lock); len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count); + up(&pd->lock); return len; } @@ -1037,6 +1047,7 @@ static int __init init_pms_cards(void) return -ENODEV; } memcpy(&pms_device, &pms_template, sizeof(pms_template)); + init_MUTEX(&pms_device.lock); pms_device.height=240; pms_device.width=320; pms_swsense(75); diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 8225524ffcc3..ce160c3851d3 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -760,7 +760,7 @@ static int w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *ar if(vtune.tuner != 0); return -EINVAL; - strcpy(vtune.name, "Foo-tuner"); + strcpy(vtune.name, "no tuner"); vtune.rangelow = 0; vtune.rangehigh = 0; vtune.flags = VIDEO_TUNER_NORM; diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 074f2709be96..f08ee0f9b242 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -849,13 +849,13 @@ static int netdev_open(struct net_device *dev) #if defined(__powerpc__) // 89/9/1 modify, // np->bcrvalue=0x04 | 0x0x38; /* big-endian, 256 burst length */ - np->bcrvalue = 0x04 | 0x0 x10; /* big-endian, tx 8 burst length */ - a np->cralue = 0xe00; /* rx 128 burst length */ + np->bcrvalue = 0x04 | 0x10; /* big-endian, tx 8 burst length */ + np->crvalue = 0xe00; /* rx 128 burst length */ #elif defined(__alpha__) // 89/9/1 modify, // np->bcrvalue=0x38; /* little-endian, 256 burst length */ np->bcrvalue = 0x10; /* little-endian, 8 burst length */ - np->cralue = 0xe00; /* rx 128 burst length */ + np->crvalue = 0xe00; /* rx 128 burst length */ #elif defined(__i386__) #if defined(MODULE) // 89/9/1 modify, diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog index 67d90c26a323..134a4ec3798f 100644 --- a/drivers/parport/ChangeLog +++ b/drivers/parport/ChangeLog @@ -1,4 +1,14 @@ - 2001-05-10 Fred Barnes <frmb2@ukc.ac.uk> +2001-05-22 Juan Quintela <quintela@mandrakesoft.com> + + * parport_amiga.c: Set printk levels. + * parport_gsc.c: Likewise. + * parport_mfc3.c: Likewise. + * parport_pc.c: Likewise. + * parport_sunbpp.c: Likewise. + * probe.c: Likewise. + * share.c: Likewise. + +2001-05-10 Fred Barnes <frmb2@ukc.ac.uk> * parport_pc.c (parport_pc_epp_read_data): added support for reading from a w91284pic peripheral, flag is PARPORT_W91284PIC. diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c index e5314cec9c71..ea26b4797f17 100644 --- a/drivers/parport/parport_amiga.c +++ b/drivers/parport/parport_amiga.c @@ -34,7 +34,7 @@ static struct parport *this_port = NULL; static void amiga_write_data(struct parport *p, unsigned char data) { - DPRINTK("write_data %c\n",data); + DPRINTK(KERN_DEBUG "write_data %c\n",data); /* Triggers also /STROBE. This behavior cannot be changed */ ciaa.prb = data; mb(); @@ -73,13 +73,13 @@ static unsigned char control_amiga_to_pc(unsigned char control) static void amiga_write_control(struct parport *p, unsigned char control) { - DPRINTK("write_control %02x\n",control); + DPRINTK(KERN_DEBUG "write_control %02x\n",control); /* No implementation possible */ } static unsigned char amiga_read_control( struct parport *p) { - DPRINTK("read_control \n"); + DPRINTK(KERN_DEBUG "read_control \n"); return control_amiga_to_pc(0); } @@ -87,7 +87,7 @@ static unsigned char amiga_frob_control( struct parport *p, unsigned char mask, { unsigned char old; - DPRINTK("frob_control mask %02x, value %02x\n",mask,val); + DPRINTK(KERN_DEBUG "frob_control mask %02x, value %02x\n",mask,val); old = amiga_read_control(p); amiga_write_control(p, (old & ~mask) ^ val); return old; @@ -132,7 +132,7 @@ static unsigned char amiga_read_status(struct parport *p) unsigned char status; status = status_amiga_to_pc(ciab.pra & 7); - DPRINTK("read_status %02x\n", status); + DPRINTK(KERN_DEBUG "read_status %02x\n", status); return status; } @@ -154,14 +154,14 @@ static void amiga_disable_irq(struct parport *p) static void amiga_data_forward(struct parport *p) { - DPRINTK("forward\n"); + DPRINTK(KERN_DEBUG "forward\n"); ciaa.ddrb = 0xff; /* all pins output */ mb(); } static void amiga_data_reverse(struct parport *p) { - DPRINTK("reverse\n"); + DPRINTK(KERN_DEBUG "reverse\n"); ciaa.ddrb = 0; /* all pins input */ mb(); } diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c index e44900e300df..6157aab400fc 100644 --- a/drivers/parport/parport_gsc.c +++ b/drivers/parport/parport_gsc.c @@ -473,7 +473,7 @@ static int __init parport_init_chip(struct hp_device *d, struct pa_iodc_driver * irq = busdevice_alloc_irq(d); if (!irq) { - printk("IRQ not found for parallel device at 0x%p\n", d->hpa); + printk(KERN_DEBUG "IRQ not found for parallel device at 0x%p\n", d->hpa); return -ENODEV; } @@ -484,10 +484,10 @@ static int __init parport_init_chip(struct hp_device *d, struct pa_iodc_driver * */ if (!pdc_add_valid( (void *)(port+4))) { /* Initialize bidirectional-mode (0x10) & data-tranfer-mode #1 (0x20) */ - printk("%s: initialize bidirectional-mode.\n", __FUNCTION__); + printk(KERN_DEBUG "%s: initialize bidirectional-mode.\n", __FUNCTION__); parport_writeb ( (0x10 + 0x20), port + 4); } else { - printk("%s: enhanced parport-modes not supported.\n", __FUNCTION__); + printk(KERN_DEBUG "%s: enhanced parport-modes not supported.\n", __FUNCTION__); } if (parport_gsc_probe_port(port, 0, diff --git a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c index 4e001494b9b4..41cc106ba7ef 100644 --- a/drivers/parport/parport_mfc3.c +++ b/drivers/parport/parport_mfc3.c @@ -82,7 +82,7 @@ static struct parport_operations pp_mfc3_ops; static void mfc3_write_data(struct parport *p, unsigned char data) { -DPRINTK("write_data %c\n",data); +DPRINTK(KERN_DEBUG "write_data %c\n",data); dummy = pia(p)->pprb; /* clears irq bit */ /* Triggers also /STROBE.*/ @@ -126,13 +126,13 @@ static unsigned char control_mfc3_to_pc(unsigned char control) static void mfc3_write_control(struct parport *p, unsigned char control) { -DPRINTK("write_control %02x\n",control); +DPRINTK(KERN_DEBUG "write_control %02x\n",control); pia(p)->ppra = (pia(p)->ppra & 0x1f) | control_pc_to_mfc3(control); } static unsigned char mfc3_read_control( struct parport *p) { -DPRINTK("read_control \n"); +DPRINTK(KERN_DEBUG "read_control \n"); return control_mfc3_to_pc(pia(p)->ppra & 0xe0); } @@ -140,7 +140,7 @@ static unsigned char mfc3_frob_control( struct parport *p, unsigned char mask, u { unsigned char old; -DPRINTK("frob_control mask %02x, value %02x\n",mask,val); +DPRINTK(KERN_DEBUG "frob_control mask %02x, value %02x\n",mask,val); old = mfc3_read_control(p); mfc3_write_control(p, (old & ~mask) ^ val); return old; @@ -186,7 +186,7 @@ static unsigned char status_mfc3_to_pc(unsigned char status) #if 0 /* currently unused */ static void mfc3_write_status( struct parport *p, unsigned char status) { -DPRINTK("write_status %02x\n",status); +DPRINTK(KERN_DEBUG "write_status %02x\n",status); pia(p)->ppra = (pia(p)->ppra & 0xe0) | status_pc_to_mfc3(status); } #endif @@ -196,7 +196,7 @@ static unsigned char mfc3_read_status(struct parport *p) unsigned char status; status = status_mfc3_to_pc(pia(p)->ppra & 0x1f); -DPRINTK("read_status %02x\n", status); +DPRINTK(KERN_DEBUG "read_status %02x\n", status); return status; } @@ -234,7 +234,7 @@ static void mfc3_disable_irq(struct parport *p) static void mfc3_data_forward(struct parport *p) { - DPRINTK("forward\n"); + DPRINTK(KERN_DEBUG "forward\n"); pia(p)->crb &= ~PIA_DDR; /* make data direction register visible */ pia(p)->pddrb = 255; /* all pins output */ pia(p)->crb |= PIA_DDR; /* make data register visible - default */ @@ -242,7 +242,7 @@ static void mfc3_data_forward(struct parport *p) static void mfc3_data_reverse(struct parport *p) { - DPRINTK("reverse\n"); + DPRINTK(KERN_DEBUG "reverse\n"); pia(p)->crb &= ~PIA_DDR; /* make data direction register visible */ pia(p)->pddrb = 0; /* all pins input */ pia(p)->crb |= PIA_DDR; /* make data register visible - default */ diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 0207d7e772b1..3cb7ffebfac3 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -118,7 +118,7 @@ static int change_mode(struct parport *p, int m) unsigned char oecr; int mode; - DPRINTK("parport change_mode ECP-ISA to mode 0x%02x\n",m); + DPRINTK(KERN_INFO "parport change_mode ECP-ISA to mode 0x%02x\n",m); if (!priv->ecr) { printk (KERN_DEBUG "change_mode: but there's no ECR!\n"); @@ -1265,20 +1265,20 @@ static void __devinit show_parconfig_smsc37c669(int io, int key) cr27=inb(io+1); outb(0xaa,io); - printk ("SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, " + printk (KERN_INFO "SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, " "A=0x%2x, 23=0x%02x, 26=0x%02x, 27=0x%02x\n", cr1,cr4,cra,cr23,cr26,cr27); /* The documentation calls DMA and IRQ-Lines by letters, so the board maker can/will wire them appropriately/randomly... G=reserved H=IDE-irq, */ - printk ("SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, " + printk (KERN_INFO "SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, " "fifo threshold=%d\n", cr23*4, (cr27 &0x0f) ? 'A'-1+(cr27 &0x0f): '-', (cr26 &0x0f) ? 'A'-1+(cr26 &0x0f): '-', cra & 0x0f); - printk("SMSC LPT Config: enabled=%s power=%s\n", + printk(KERN_INFO "SMSC LPT Config: enabled=%s power=%s\n", (cr23*4 >=0x100) ?"yes":"no", (cr1 & 4) ? "yes" : "no"); - printk("SMSC LPT Config: Port mode=%s, EPP version =%s\n", + printk(KERN_INFO "SMSC LPT Config: Port mode=%s, EPP version =%s\n", (cr1 & 0x08 ) ? "Standard mode only (SPP)" : modes[cr4 & 0x03], (cr4 & 0x40) ? "1.7" : "1.9"); @@ -1290,7 +1290,7 @@ static void __devinit show_parconfig_smsc37c669(int io, int key) while((superios[i].io!= 0) && (i<NR_SUPERIOS)) i++; if(i==NR_SUPERIOS) - printk("Super-IO: too many chips!\n"); + printk(KERN_INFO "Super-IO: too many chips!\n"); else { int d; switch (cr23*4) { @@ -1350,23 +1350,23 @@ static void __devinit show_parconfig_winbond(int io, int key) crf0=inb(io+1); outb(0xaa,io); - printk("Winbond LPT Config: cr_30=%02x 60,61=%02x%02x " + printk(KERN_INFO "Winbond LPT Config: cr_30=%02x 60,61=%02x%02x " "70=%02x 74=%02x, f0=%02x\n", cr30,cr60,cr61,cr70,cr74,crf0); - printk("Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ", + printk(KERN_INFO "Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ", (cr30 & 0x01) ? "yes":"no", cr60,cr61,cr70&0x0f ); if ((cr74 & 0x07) > 3) printk("dma=none\n"); else printk("dma=%d\n",cr74 & 0x07); - printk("Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n", + printk(KERN_INFO "Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n", irqtypes[crf0>>7], (crf0>>3)&0x0f); - printk("Winbond LPT Config: Port mode=%s\n", modes[crf0 & 0x07]); + printk(KERN_INFO "Winbond LPT Config: Port mode=%s\n", modes[crf0 & 0x07]); if(cr30 & 0x01) { /* the settings can be interrogated later ... */ while((superios[i].io!= 0) && (i<NR_SUPERIOS)) i++; if(i==NR_SUPERIOS) - printk("Super-IO: too many chips!\n"); + printk(KERN_INFO "Super-IO: too many chips!\n"); else { superios[i].io = (cr60<<8)|cr61; superios[i].irq = cr70&0x0f; @@ -1386,7 +1386,7 @@ static void __devinit decode_winbond(int efer, int key, int devid, int devrev, i non-winbond register */ return; - printk("Winbond chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x " + printk(KERN_INFO "Winbond chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x " "oldid=%02x\n", efer,key,devid,devrev,oldid); id=(devid<<8) | devrev; @@ -1406,9 +1406,9 @@ static void __devinit decode_winbond(int efer, int key, int devid, int devrev, i else progif=0; if(type==NULL) - printk("Winbond unknown chip type\n"); + printk(KERN_INFO "Winbond unknown chip type\n"); else - printk("Winbond chip type %s\n",type); + printk(KERN_INFO "Winbond chip type %s\n",type); if(progif==2) show_parconfig_winbond(efer,key); @@ -1427,7 +1427,7 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev) return; func=NULL; - printk("SMSC chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x\n", + printk(KERN_INFO "SMSC chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x\n", efer,key,devid,devrev); id=(devid<<8) | devrev; @@ -1437,9 +1437,9 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev) else if (devid==0x66) type="37c666GT"; if(type==NULL) - printk("SMSC unknown chip type\n"); + printk(KERN_INFO "SMSC unknown chip type\n"); else - printk("SMSC chip type %s\n",type); + printk(KERN_INFO "SMSC chip type %s\n",type); if(func) (func)(efer,key); return; @@ -1540,7 +1540,7 @@ static void __devinit smsc_check(int io, int key) static void __devinit detect_and_report_winbond (void) { - printk("Winbond Super-IO detection, now testing ports 3F0,370,250,4E,2E ...\n"); + printk(KERN_DEBUG "Winbond Super-IO detection, now testing ports 3F0,370,250,4E,2E ...\n"); winbond_check(0x3f0,0x87); winbond_check(0x370,0x87); @@ -1553,7 +1553,7 @@ static void __devinit detect_and_report_winbond (void) static void __devinit detect_and_report_smsc (void) { - printk("SMSC Super-IO detection, now testing Ports 2F0, 370 ...\n"); + printk(KERN_DEBUG "SMSC Super-IO detection, now testing Ports 2F0, 370 ...\n"); smsc_check(0x3f0,0x55); smsc_check(0x370,0x55); smsc_check(0x3f0,0x44); @@ -1863,7 +1863,7 @@ static int __devinit parport_ECP_supported(struct parport *pb) printk("%d",intrline[(configb >>3) & 0x07]); else printk("<none or set by other means>"); - printk ( " dma="); + printk (" dma="); if( (configb & 0x03 ) == 0x00) printk("<none or set by other means>\n"); else diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 6531cb1cb78c..63e8f3d1b695 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c @@ -74,7 +74,7 @@ static void parport_sunbpp_write_data(struct parport *p, unsigned char d) struct bpp_regs *regs = (struct bpp_regs *)p->base; sbus_writeb(d, ®s->p_dr); - dprintk(("wrote 0x%x\n", d)); + dprintk((KERN_DEBUG "wrote 0x%x\n", d)); } static unsigned char parport_sunbpp_read_data(struct parport *p) @@ -123,8 +123,8 @@ static unsigned char status_sunbpp_to_pc(struct parport *p) if (!(value_tcr & P_TCR_BUSY)) bits |= PARPORT_STATUS_BUSY; - dprintk(("tcr 0x%x ir 0x%x\n", regs->p_tcr, regs->p_ir)); - dprintk(("read status 0x%x\n", bits)); + dprintk((KERN_DEBUG "tcr 0x%x ir 0x%x\n", regs->p_tcr, regs->p_ir)); + dprintk((KERN_DEBUG "read status 0x%x\n", bits)); return bits; } @@ -144,8 +144,8 @@ static unsigned char control_sunbpp_to_pc(struct parport *p) if (value_or & P_OR_SLCT_IN) bits |= PARPORT_CONTROL_SELECT; - dprintk(("tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); - dprintk(("read control 0x%x\n", bits)); + dprintk((KERN_DEBUG "tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); + dprintk((KERN_DEBUG "read control 0x%x\n", bits)); return bits; } @@ -162,7 +162,7 @@ static unsigned char parport_sunbpp_frob_control(struct parport *p, unsigned char value_tcr = sbus_readb(®s->p_tcr); unsigned char value_or = sbus_readb(®s->p_or); - dprintk(("frob1: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); + dprintk((KERN_DEBUG "frob1: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); if (mask & PARPORT_CONTROL_STROBE) { if (val & PARPORT_CONTROL_STROBE) { value_tcr &= ~P_TCR_DS; @@ -194,7 +194,7 @@ static unsigned char parport_sunbpp_frob_control(struct parport *p, sbus_writeb(value_or, ®s->p_or); sbus_writeb(value_tcr, ®s->p_tcr); - dprintk(("frob2: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); + dprintk((KERN_DEBUG "frob2: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); return parport_sunbpp_read_control(p); } @@ -218,7 +218,7 @@ static void parport_sunbpp_data_forward (struct parport *p) struct bpp_regs *regs = (struct bpp_regs *)p->base; unsigned char value_tcr = sbus_readb(®s->p_tcr); - dprintk(("forward\n")); + dprintk((KERN_DEBUG "forward\n")); value_tcr &= ~P_TCR_DIR; sbus_writeb(value_tcr, ®s->p_tcr); } @@ -228,7 +228,7 @@ static void parport_sunbpp_data_reverse (struct parport *p) struct bpp_regs *regs = (struct bpp_regs *)p->base; u8 val = sbus_readb(®s->p_tcr); - dprintk(("reverse\n")); + dprintk((KERN_DEBUG "reverse\n")); val |= P_TCR_DIR; sbus_writeb(val, ®s->p_tcr); } @@ -311,7 +311,7 @@ static int __init init_one_port(struct sbus_dev *sdev) struct bpp_regs *regs; unsigned char value_tcr; - dprintk(("init_one_port(%p): ranges, alloc_io, ", sdev)); + dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev)); irq = sdev->irqs[0]; base = sbus_ioremap(&sdev->resource[0], 0, sdev->reg_addrs[0].reg_size, @@ -328,7 +328,7 @@ static int __init init_one_port(struct sbus_dev *sdev) memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); - dprintk(("register_port, ")); + dprintk(("register_port\n")); if (!(p = parport_register_port(base, irq, dma, ops))) { kfree(ops); sbus_iounmap(base, size); @@ -337,7 +337,7 @@ static int __init init_one_port(struct sbus_dev *sdev) p->size = size; - dprintk(("init_one_port: request_irq(%08x:%p:%x:%s:%p) ", + dprintk((KERN_DEBUG "init_one_port: request_irq(%08x:%p:%x:%s:%p) ", p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)); if ((err = request_irq(p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)) != 0) { @@ -352,7 +352,7 @@ static int __init init_one_port(struct sbus_dev *sdev) } regs = (struct bpp_regs *)p->base; - dprintk(("forward\n")); + dprintk((KERN_DEBUG "forward\n")); value_tcr = sbus_readb(®s->p_tcr); value_tcr &= ~P_TCR_DIR; sbus_writeb(value_tcr, ®s->p_tcr); diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c index e19771dfca9c..e2c8489826e0 100644 --- a/drivers/parport/probe.c +++ b/drivers/parport/probe.c @@ -62,7 +62,7 @@ static void parse_data(struct parport *port, int device, char *str) struct parport_device_info *info = &port->probe_info[device + 1]; if (!txt) { - printk("%s probe: memory squeeze\n", port->name); + printk(KERN_WARNING "%s probe: memory squeeze\n", port->name); return; } strcpy(txt, str); diff --git a/drivers/parport/share.c b/drivers/parport/share.c index d9a7d28a868e..12e29ee5ba17 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -1103,7 +1103,7 @@ static int parport_parse_params (int nports, const char *str[], int val[], if (ep != str[i]) val[i] = r; else { - printk("parport: bad specifier `%s'\n", str[i]); + printk(KERN_ERR "parport: bad specifier `%s'\n", str[i]); return -1; } } diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 9e50202f7beb..f47246a18a3a 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -843,7 +843,7 @@ void scsi_do_req(Scsi_Request * SRpnt, const void *cmnd, */ scsi_insert_special_req(SRpnt, 0); - SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_do_cmd()\n")); + SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_do_req()\n")); } /* @@ -929,7 +929,7 @@ void scsi_init_cmd_from_req(Scsi_Cmnd * SCpnt, Scsi_Request * SRpnt) SCpnt->abort_reason = 0; SCpnt->result = 0; - SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_do_cmd()\n")); + SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_init_cmd_from_req()\n")); } /* diff --git a/drivers/sound/cs46xx.c b/drivers/sound/cs46xx.c index 1eb0bfe0b880..36985308214f 100644 --- a/drivers/sound/cs46xx.c +++ b/drivers/sound/cs46xx.c @@ -49,6 +49,7 @@ * 20010228-dh patch from David Huggins - cs_update_ptr recursion. * 20010409-tw add hercules game theatre XP amp code. * 20010420-tw cleanup powerdown/up code. + * 20010521-tw eliminate pops, and fixes for powerdown. * * Status: * Playback/Capture supported from 8k-48k. @@ -198,7 +199,7 @@ struct cs_channel }; #define CS46XX_MAJOR_VERSION "1" -#define CS46XX_MINOR_VERSION "26" +#define CS46XX_MINOR_VERSION "27" #ifdef __ia64__ #define CS46XX_ARCH "64" //architecture key @@ -687,6 +688,9 @@ static void cs_mute(struct cs_card *card, int state) { struct ac97_codec *dev=card->ac97_codec[0]; + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mute()+ %s\n", + (state == CS_TRUE) ? "Muting" : "UnMuting") ); + if(state == CS_TRUE) { /* @@ -713,6 +717,7 @@ static void cs_mute(struct cs_card *card, int state) cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, card->pm.u32AC97_master_volume_mono); cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, card->pm.u32AC97_pcm_out_volume); } + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mute()-\n")); } /* set playback sample rate */ @@ -1485,8 +1490,6 @@ static int drain_dac(struct cs_state *state, int nonblock) /* * set to silence and let that clear the fifos. */ - memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, - dmabuf->dmasize); cs461x_clear_serial_FIFOs(card, CS_TYPE_DAC); return -ERESTARTSYS; } @@ -4370,6 +4373,12 @@ static int cs461x_powerdown(struct cs_card *card, unsigned int type) "cs46xx: cs461x_powerdown()- 0 unable to powerdown. tmp=0x%x\n",tmp)); return 0; } +/* +* for now, always keep power to the mixer block. +* not sure why it's a problem but it seems to be if we power off. +*/ + type &= ~CS_POWER_MIXVON; + type &= ~CS_POWER_MIXVOFF; cs_mute(card, CS_TRUE); diff --git a/drivers/sound/wavfront.c b/drivers/sound/wavfront.c index f0d9676b5835..9422781c992e 100644 --- a/drivers/sound/wavfront.c +++ b/drivers/sound/wavfront.c @@ -131,7 +131,7 @@ #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ static int (*midi_load_patch) (int devno, int format, const char *addr, int offs, int count, int pmgr_flag) = NULL; -#endif OSS_SUPPORT_SEQ +#endif /* OSS_SUPPORT_SEQ */ /* if WF_DEBUG not defined, no run-time debugging messages will be available via the debug flag setting. Given the current @@ -279,7 +279,7 @@ struct wf_config { int fx_mididev; /* devno for FX MIDI interface */ #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ int oss_dev; /* devno for OSS sequencer synth */ -#endif OSS_SUPPORT_SEQ +#endif /* OSS_SUPPORT_SEQ */ char fw_version[2]; /* major = [0], minor = [1] */ char hw_version[2]; /* major = [0], minor = [1] */ @@ -2139,7 +2139,7 @@ static struct synth_operations wavefront_operations = bender: midi_synth_bender, setup_voice: midi_synth_setup_voice }; -#endif OSS_SUPPORT_SEQ +#endif /* OSS_SUPPORT_SEQ */ #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_STATIC_INSTALL @@ -2158,7 +2158,7 @@ static void __exit unload_wavefront (struct address_info *hw_config) (void) uninstall_wavefront (); } -#endif OSS_SUPPORT_STATIC_INSTALL +#endif /* OSS_SUPPORT_STATIC_INSTALL */ /***********************************************************************/ /* WaveFront: Linux modular sound kernel installation interface */ @@ -2674,7 +2674,7 @@ static int __init wavefront_config_midi (void) &wavefront_oss_load_patch; } -#endif OSS_SUPPORT_SEQ +#endif /* OSS_SUPPORT_SEQ */ /* Turn on Virtual MIDI, but first *always* turn it off, since otherwise consectutive reloads of the driver will @@ -2852,14 +2852,14 @@ static int __init install_wavefront (void) } else { synth_devs[dev.oss_dev] = &wavefront_operations; } -#endif OSS_SUPPORT_SEQ +#endif /* OSS_SUPPORT_SEQ */ if (wavefront_init (1) < 0) { printk (KERN_WARNING LOGNAME "initialization failed.\n"); #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ sound_unload_synthdev (dev.oss_dev); -#endif OSS_SUPPORT_SEQ +#endif /* OSS_SUPPORT_SEQ */ return -1; } @@ -2890,7 +2890,7 @@ static void __exit uninstall_wavefront (void) #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ sound_unload_synthdev (dev.oss_dev); -#endif OSS_SUPPORT_SEQ +#endif /* OSS_SUPPORT_SEQ */ uninstall_wf_mpu (); } diff --git a/drivers/sound/yss225.h b/drivers/sound/yss225.h index 7e4cd65719fc..56d8b6b5e432 100644 --- a/drivers/sound/yss225.h +++ b/drivers/sound/yss225.h @@ -20,5 +20,5 @@ extern unsigned char coefficients2[56]; extern unsigned char coefficients3[404]; -#endif __ys225_h__ +#endif /* __ys225_h__ */ diff --git a/drivers/usb/dc2xx.c b/drivers/usb/dc2xx.c index ed4d67478141..1f34afbfa4c1 100644 --- a/drivers/usb/dc2xx.c +++ b/drivers/usb/dc2xx.c @@ -336,8 +336,9 @@ static int camera_release (struct inode *inode, struct file *file) if (!camera->dev) { minor_data [subminor] = NULL; kfree (camera); - } - up (&camera->sem); + } else + up (&camera->sem); + up (&state_table_mutex); dbg ("close #%d", subminor); @@ -397,7 +398,6 @@ camera_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_devic } if (i >= MAX_CAMERAS) { info ("Ignoring additional USB Camera"); - up (&state_table_mutex); goto bye; } @@ -405,7 +405,6 @@ camera_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_devic camera = minor_data [i] = kmalloc (sizeof *camera, GFP_KERNEL); if (!camera) { err ("no memory!"); - up (&state_table_mutex); goto bye; } @@ -472,13 +471,15 @@ static void camera_disconnect(struct usb_device *dev, void *ptr) if (!camera->buf) { minor_data [subminor] = NULL; kfree (camera); + camera = NULL; } else camera->dev = NULL; info ("USB Camera #%d disconnected", subminor); usb_dec_dev_use (dev); - up (&camera->sem); + if (camera != NULL) + up (&camera->sem); up (&state_table_mutex); } diff --git a/drivers/usb/ibmcam.c b/drivers/usb/ibmcam.c index 54bd6679e189..c2ebd0d6d1d8 100644 --- a/drivers/usb/ibmcam.c +++ b/drivers/usb/ibmcam.c @@ -47,7 +47,7 @@ * Version Information */ #define DRIVER_VERSION "v1.0.0" -#define DRIVER_AUTHOR "Johannes Erdfelt, Randy Dunlap" +#define DRIVER_AUTHOR "http://www.linux-usb.org/ibmcam/" #define DRIVER_DESC "IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000" #define ENABLE_HEXDUMP 0 /* Enable if you need it */ diff --git a/drivers/usb/pwc.h b/drivers/usb/pwc.h index fc0c7917500a..3802535961d6 100644 --- a/drivers/usb/pwc.h +++ b/drivers/usb/pwc.h @@ -19,10 +19,12 @@ #define PWC_H #ifdef __KERNEL__ +#include <linux/module.h> #include <asm/semaphore.h> #include <asm/errno.h> #include <linux/usb.h> #include <linux/spinlock.h> +#include <linux/slab.h> #else #include <errno.h> #include <sys/types.h> diff --git a/drivers/usb/scanner.h b/drivers/usb/scanner.h index d5183bb4926d..73b96eef3938 100644 --- a/drivers/usb/scanner.h +++ b/drivers/usb/scanner.h @@ -120,8 +120,9 @@ static struct usb_device_id scanner_device_ids [] = { { USB_DEVICE(0x04b8, 0x0104) }, /* Perfection 1200U and 1200Photo*/ { USB_DEVICE(0x04b8, 0x0106) }, /* Stylus Scan 2500 */ { USB_DEVICE(0x04b8, 0x0107) }, /* Expression 1600 */ - { USB_DEVICE(0x04b8, 0x010b) }, /* Perfection 1240U */ { USB_DEVICE(0x04b8, 0x010a) }, /* Perfection 1640SU and 1640SU Photo */ + { USB_DEVICE(0x04b8, 0x010b) }, /* Perfection 1240U */ + { USB_DEVICE(0x04b8, 0x010c) }, /* Perfection 640U */ /* Umax */ { USB_DEVICE(0x1606, 0x0010) }, /* Astra 1220U */ { USB_DEVICE(0x1606, 0x0030) }, /* Astra 2000U */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c605f1a165d3..881d2983ac77 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -15,9 +15,21 @@ * See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info * and extra documentation * + * (23/May/2001) Bill Ryder + * Added runtime debug patch (thanx Tyson D Sawyer). + * Cleaned up comments for 8U232 + * Added parity, framing and overrun error handling + * Added receive break handling. + * * (04/08/2001) gb * Identify version on module load. * + * (18/March/2001) Bill Ryder + * (Not released) + * Added send break handling. (requires kernel patch too) + * Fixed 8U232AM hardware RTS/CTS etc status reporting. + * Added flipbuf fix copied from generic device + * * (12/3/2000) Bill Ryder * Added support for 8U232AM device. * Moved PID and VIDs into header file only. @@ -96,7 +108,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.0.0" +#define DRIVER_VERSION "v1.1.0" #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>" #define DRIVER_DESC "USB FTDI RS232 Converters Driver" @@ -105,9 +117,12 @@ static __devinitdata struct usb_device_id id_table_sio [] = { { } /* Terminating entry */ }; -/* THe 8U232AM has the same API as the sio - but it can support MUCH - higher baudrates (921600 at 48MHz/230400 at 12MHz - so .. it's baudrate setting codes are different */ +/* THe 8U232AM has the same API as the sio except for: + - it can support MUCH higher baudrates (921600 at 48MHz/230400 + at 12MHz so .. it's baudrate setting codes are different + - it has a two byte status code. + - it returns characters very 16ms (the FTDI does it every 40ms) + */ static __devinitdata struct usb_device_id id_table_8U232AM [] = { @@ -127,9 +142,7 @@ MODULE_DEVICE_TABLE (usb, id_table_combined); struct ftdi_private { ftdi_type_t ftdi_type; - char last_status_byte; /* device sends this every 40ms when open */ - - + __u16 last_set_data_urb_value ; /* the last data state set - needed for doing a break */ }; /* function prototypes for a FTDI serial converter */ static int ftdi_sio_startup (struct usb_serial *serial); @@ -142,6 +155,7 @@ static void ftdi_sio_write_bulk_callback (struct urb *urb); static void ftdi_sio_read_bulk_callback (struct urb *urb); static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old); static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); +static void ftdi_sio_break_ctl (struct usb_serial_port *port, int break_state ); /* Should rename most ftdi_sio's to ftdi_ now since there are two devices which share common code */ @@ -163,6 +177,7 @@ struct usb_serial_device_type ftdi_sio_device = { write_bulk_callback: ftdi_sio_write_bulk_callback, ioctl: ftdi_sio_ioctl, set_termios: ftdi_sio_set_termios, + break_ctl: ftdi_sio_break_ctl, startup: ftdi_sio_startup, shutdown: ftdi_sio_shutdown, }; @@ -184,6 +199,7 @@ struct usb_serial_device_type ftdi_8U232AM_device = { write_bulk_callback: ftdi_sio_write_bulk_callback, ioctl: ftdi_sio_ioctl, set_termios: ftdi_sio_set_termios, + break_ctl: ftdi_sio_break_ctl, startup: ftdi_8U232AM_startup, shutdown: ftdi_sio_shutdown, }; @@ -237,7 +253,7 @@ static int ftdi_sio_startup (struct usb_serial *serial) priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); if (!priv){ - err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct ftdi_private)); + err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private)); return -ENOMEM; } @@ -255,7 +271,7 @@ static int ftdi_8U232AM_startup (struct usb_serial *serial) priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); if (!priv){ - err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct ftdi_private)); + err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private)); return -ENOMEM; } @@ -301,7 +317,8 @@ static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp) spin_unlock_irqrestore (&port->port_lock, flags); - /* do not allow a task to be queued to deliver received data */ + /* This will push the characters through immediately rather + than queue a task to deliver them */ port->tty->low_latency = 1; /* No error checking for this (will get errors later anyway) */ @@ -432,7 +449,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user, unsigned char *first_byte = port->write_urb->transfer_buffer; /* Was seeing a race here, got a read callback, then write callback before - hitting interruptible_sleep_on - so wrapping in a wait_queue */ + hitting interuptible_sleep_on - so wrapping in a wait_queue */ add_wait_queue(&port->write_wait, &wait); set_current_state (TASK_INTERRUPTIBLE); @@ -530,9 +547,9 @@ static void ftdi_sio_write_bulk_callback (struct urb *urb) static void ftdi_sio_read_bulk_callback (struct urb *urb) { /* ftdi_sio_serial_buld_callback */ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct ftdi_private *priv = (struct ftdi_private *)port->private; struct usb_serial *serial; struct tty_struct *tty = port->tty ; + char error_flag; unsigned char *data = urb->transfer_buffer; const int data_offset = 2; @@ -559,23 +576,76 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb) if (urb->actual_length > 2) { usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); } else { - dbg("Just status"); + dbg("Just status 0o%03o0o%03o",data[0],data[1]); } - priv->last_status_byte = data[0]; /* this has modem control lines */ /* TO DO -- check for hung up line and handle appropriately: */ /* send hangup */ /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */ /* if CD is dropped and the line is not CLOCAL then we should hangup */ - + /* Handle errors and break */ + error_flag = TTY_NORMAL; + /* Although the device uses a bitmask and hence can have multiple */ + /* errors on a packet - the order here sets the priority the */ + /* error is returned to the tty layer */ + + if ( data[1] & FTDI_RS_OE ) { + error_flag = TTY_OVERRUN; + dbg("OVERRRUN error"); + } + if ( data[1] & FTDI_RS_BI ) { + error_flag = TTY_BREAK; + dbg("BREAK received"); + } + if ( data[1] & FTDI_RS_PE ) { + error_flag = TTY_PARITY; + dbg("PARITY error"); + } + if ( data[1] & FTDI_RS_FE ) { + error_flag = TTY_FRAME; + dbg("FRAMING error"); + } if (urb->actual_length > data_offset) { + for (i = data_offset ; i < urb->actual_length ; ++i) { - tty_insert_flip_char(tty, data[i], 0); - } + /* have to make sure we don't overflow the buffer + with tty_insert_flip_char's */ + if(tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + /* Note that the error flag is duplicated for + every character received since we don't know + which character it applied to */ + tty_insert_flip_char(tty, data[i], error_flag); + } tty_flip_buffer_push(tty); + + + } + +#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW + /* if a parity error is detected you get status packets forever + until a character is sent without a parity error. + This doesn't work well since the application receives a never + ending stream of bad data - even though new data hasn't been sent. + Therefore I (bill) have taken this out. + However - this might make sense for framing errors and so on + so I am leaving the code in for now. + */ + else { + if (error_flag != TTY_NORMAL){ + dbg("error_flag is not normal"); + /* In this case it is just status - if that is an error send a bad character */ + if(tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + tty_insert_flip_char(tty, 0xff, error_flag); + tty_flip_buffer_push(tty); + } } +#endif /* Continue trying to always read */ FILL_BULK_URB(urb, serial->dev, @@ -637,6 +707,38 @@ __u16 translate_baudrate_to_ftdi(unsigned int cflag, ftdi_type_t ftdi_type) return(urb_value); } +static void ftdi_sio_break_ctl( struct usb_serial_port *port, int break_state ) +{ + struct usb_serial *serial = port->serial; + struct ftdi_private *priv = (struct ftdi_private *)port->private; + __u16 urb_value = 0; + char buf[1]; + + /* break_state = -1 to turn on break, and 0 to turn off break */ + /* see drivers/char/tty_io.c to see it used */ + /* last_set_data_urb_value NEVER has the break bit set in it */ + + if (break_state) { + urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK; + } else { + urb_value = priv->last_set_data_urb_value; + } + + + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_DATA_REQUEST, + FTDI_SIO_SET_DATA_REQUEST_TYPE, + urb_value , 0, + buf, 0, WDR_TIMEOUT) < 0) { + err(__FUNCTION__ " FAILED to enable/disable break state (state was %d)",break_state); + } + + dbg(__FUNCTION__ " break state is %d - urb is %d",break_state, urb_value); + +} + + + /* As I understand this - old_termios contains the original termios settings */ /* and tty->termios contains the new setting to be used */ /* */ @@ -680,6 +782,11 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * err("CSIZE was set but not CS5-CS8"); } } + + /* This is needed by the break command since it uses the same command - but is + * or'ed with this value */ + priv->last_set_data_urb_value = urb_value; + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, @@ -753,7 +860,7 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns struct usb_serial *serial = port->serial; struct ftdi_private *priv = (struct ftdi_private *)port->private; __u16 urb_value=0; /* Will hold the new flags */ - char buf[1]; + char buf[2]; int ret, mask; dbg(__FUNCTION__ " cmd 0x%04x", cmd); @@ -763,12 +870,7 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns case TIOCMGET: dbg(__FUNCTION__ " TIOCMGET"); - /* The MODEM_STATUS_REQUEST works for the sio but not the 232 */ if (priv->ftdi_type == sio){ - /* TO DECIDE - use the 40ms status packets or not? */ - /* PRO: No need to send urb */ - /* CON: Could be 40ms out of date */ - /* Request the status from the device */ if ((ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -781,8 +883,18 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns return(ret); } } else { - /* This gets updated every 40ms - so just copy it in */ - buf[0] = priv->last_status_byte; + /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same + format as the data returned from the in point */ + if ((ret = usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + FTDI_SIO_GET_MODEM_STATUS_REQUEST, + FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, + 0, 0, + buf, 2, WDR_TIMEOUT)) < 0 ) { + err(__FUNCTION__ " Could not get modem status of device - err: %d", + ret); + return(ret); + } } return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 626aeb677315..321ae1914799 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -146,7 +146,7 @@ typedef enum { #define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11 ) #define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11 ) #define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11 ) - +#define FTDI_SIO_SET_BREAK (0x1 << 14) /* FTDI_SIO_SET_DATA */ /* @@ -170,7 +170,10 @@ typedef enum { * 0 = 1 * 1 = 1.5 * 2 = 2 - * B14..15 Reserved + * B14 + * 1 = TX ON (break) + * 0 = TX OFF (normal state) + * B15 Reserved * */ @@ -434,6 +437,17 @@ typedef enum { * B6 Transmitter Empty (TEMT) * B7 Error in RCVR FIFO * + */ +#define FTDI_RS_DR 1 +#define FTDI_RS_OE (1<<1) +#define FTDI_RS_PE (1<<2) +#define FTDI_RS_FE (1<<3) +#define FTDI_RS_BI (1<<4) +#define FTDI_RS_THRE (1<<5) +#define FTDI_RS_TEMT (1<<6) +#define FTDI_RS_FIFO (1<<7) + +/* * OUT Endpoint * * This device reserves the first bytes of data on this endpoint contain the length diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 3ae32e5d7ebd..bb9863e9ae23 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -24,6 +24,14 @@ * Basic tests have been performed with minicom/zmodem transfers and * modem dialing under Linux 2.4.0-test10 (for me it works fine). * + * 04-May-2001 Stelian Pop + * - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes + * instead of the device reported 32 (using 32 bytes causes many data + * loss, Windows driver uses 16 too). + * + * 02-May-2001 Stelian Pop + * - Fixed the baud calculation for Sitecom U232-P25 model + * * 08-Apr-2001 gb * - Identify version on module load. * diff --git a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c index 63f7a5ed37de..7b1cd9fefd0a 100644 --- a/drivers/usb/usb-ohci.c +++ b/drivers/usb/usb-ohci.c @@ -605,12 +605,14 @@ static int sohci_submit_urb (urb_t * urb) urb_priv->length = size; urb_priv->ed = ed; - /* allocate the TDs */ + /* allocate the TDs (updating hash chains) */ + spin_lock_irqsave (&usb_ed_lock, flags); for (i = 0; i < size; i++) { - urb_priv->td[i] = td_alloc (ohci, mem_flags); + urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC); if (!urb_priv->td[i]) { urb_priv->length = i; urb_free_priv (ohci, urb_priv); + spin_unlock_irqrestore (&usb_ed_lock, flags); usb_dec_dev_use (urb->dev); return -ENOMEM; } @@ -618,6 +620,7 @@ static int sohci_submit_urb (urb_t * urb) if (ed->state == ED_NEW || (ed->state & ED_DEL)) { urb_free_priv (ohci, urb_priv); + spin_unlock_irqrestore (&usb_ed_lock, flags); usb_dec_dev_use (urb->dev); return -EINVAL; } @@ -639,6 +642,7 @@ static int sohci_submit_urb (urb_t * urb) } if (bustime < 0) { urb_free_priv (ohci, urb_priv); + spin_unlock_irqrestore (&usb_ed_lock, flags); usb_dec_dev_use (urb->dev); return bustime; } @@ -648,7 +652,6 @@ static int sohci_submit_urb (urb_t * urb) #endif } - spin_lock_irqsave (&usb_ed_lock, flags); urb->actual_length = 0; urb->hcpriv = urb_priv; urb->status = USB_ST_URB_PENDING; @@ -1190,7 +1193,7 @@ static ed_t * ep_add_ed ( if (ed->state == ED_NEW) { ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ /* dummy td; end of td list for ed */ - td = td_alloc (ohci, mem_flags); + td = td_alloc (ohci, SLAB_ATOMIC); /* hash the ed for later reverse mapping */ if (!td || !hash_add_ed (ohci, (ed_t *)ed)) { /* out of memory */ @@ -2256,6 +2259,7 @@ static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r) // Count and limit the retries though; either hardware or // software errors can go forever... #endif + hc_reset (ohci); } if (ints & OHCI_INTR_WDH) { @@ -2269,6 +2273,7 @@ static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r) writel (OHCI_INTR_SO, ®s->intrenable); } + // FIXME: this assumes SOF (1/ms) interrupts don't get lost... if (ints & OHCI_INTR_SF) { unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1; writel (OHCI_INTR_SF, ®s->intrdisable); @@ -2512,6 +2517,11 @@ ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) if (pci_enable_device(dev) < 0) return -ENODEV; + + if (!dev->irq) { + err("found OHCI device with no IRQ assigned. check BIOS settings!"); + return -ENODEV; + } /* we read its hardware registers as memory */ mem_resource = pci_resource_start(dev, 0); diff --git a/drivers/usb/vcvt.h b/drivers/usb/vcvt.h deleted file mode 100644 index f6e02a236720..000000000000 --- a/drivers/usb/vcvt.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - (C) 2001 Nemosoft Unv. nemosoft@smcc.demon.nl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - - -/* 'Viewport' conversion routines. These functions convert from one colour - space to another, taking into account that the source image has a smaller - size than the view, and is placed inside the view: - - +-------view.x------------+ - | | - | +---image.x---+ | - | | | | - | | | | - | +-------------+ | - | | - +-------------------------+ - - The image should always be smaller than the view. The offset (top-left - corner of the image) should be precomputed, so you can place the image - anywhere in the view. - - The functions take these parameters: - - width image width (in pixels) - - height image height (in pixels) - - plus view width (in pixels) - *src pointer at start of image - *dst pointer at offset (!) in view -*/ - - -#ifndef VCVT_H -#define VCVT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Functions in vcvt_i386.S/vcvt_c.c */ -/* 4:2:0 YUV interlaced to RGB/BGR */ -void vcvt_420i_bgr24(int width, int height, int plus, void *src, void *dst); -void vcvt_420i_rgb24(int width, int height, int plus, void *src, void *dst); -void vcvt_420i_bgr32(int width, int height, int plus, void *src, void *dst); -void vcvt_420i_rgb32(int width, int height, int plus, void *src, void *dst); - - -/* Go from 420i to other yuv formats */ -void vcvt_420i_420p(int width, int height, int plus, void *src, void *dsty, void *dstu, void *dstv); -void vcvt_420i_yuyv(int width, int height, int plus, void *src, void *dst); - -#if 0 -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/usb/vcvt_c.c b/drivers/usb/vcvt_c.c deleted file mode 100644 index 222cd7f83a52..000000000000 --- a/drivers/usb/vcvt_c.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - Colour conversion routines (RGB <-> YUV) in plain C, with viewport - extension. - (C) 2001 Nemosoft Unv. nemosoft@smcc.demon.nl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -/* Colour conversion routines that use a viewport. See the assembly code/.h - files for more information. - - If you are always converting images where the image- and viewport size - is the same, you can hack out the 'plus' variable and delete the - offset calculation at the bottom of every for(line) {} loop. Otherwise, - just call the functions with plus = width. - - NB: for these function, the YUV420 format is defined as: - even lines: YYYY UU YYYY UU YYYY .. - odd lines: YYYY VV YYYY VV YYYY .. -*/ - -#include "vcvt.h" - - -#define PUSH_RGB24 1 -#define PUSH_BGR24 2 -#define PUSH_RGB32 3 -#define PUSH_BGR32 4 - -/** - \brief convert YUV 4:2:0 data into RGB, BGR, RGBa or BGRa - \param width Width of yuv data, in pixels - \param height Height of yuv data, in pixels - \param plus Width of viewport, in pixels - \param src beginning of YUV data - \param dst beginning of RGB data, \b including the initial offset into the viewport - \param push The requested RGB format - - \e push can be any of PUSH_RGB24, PUSH_BGR24, PUSH_RGB32 or PUSH_BGR32 - - This is a really simplistic approach. Speedups are welcomed. -*/ -static void vcvt_420i(int width, int height, int plus, unsigned char *src, unsigned char *dst, int push) -{ - int line, col, linewidth; - int y, u, v, yy, vr = 0, ug = 0, vg = 0, ub = 0; - int r, g, b; - unsigned char *sy, *su, *sv; - - linewidth = width + (width >> 1); - sy = src; - su = sy + 4; - sv = su + linewidth; - - /* The biggest problem is the interlaced data, and the fact that odd - add even lines have V and U data, resp. - */ - for (line = 0; line < height; line++) { - for (col = 0; col < width; col++) { - y = *sy++; - yy = y << 8; - if ((col & 1) == 0) { - /* only at even colums we update the u/v data */ - u = *su - 128; - ug = 88 * u; - ub = 454 * u; - v = *sv - 128; - vg = 183 * v; - vr = 359 * v; - - su++; - sv++; - } - if ((col & 3) == 3) { - sy += 2; /* skip u/v */ - su += 4; /* skip y */ - sv += 4; /* skip y */ - } - - r = (yy + vr) >> 8; - g = (yy - ug - vg) >> 8; - b = (yy + ub ) >> 8; - /* At moments like this, you crave for MMX instructions with saturation */ - if (r < 0) r = 0; - if (r > 255) r = 255; - if (g < 0) g = 0; - if (g > 255) g = 255; - if (b < 0) b = 0; - if (b > 255) b = 255; - - switch(push) { - case PUSH_RGB24: - *dst++ = r; - *dst++ = g; - *dst++ = b; - break; - - case PUSH_BGR24: - *dst++ = b; - *dst++ = g; - *dst++ = r; - break; - - case PUSH_RGB32: - *dst++ = r; - *dst++ = g; - *dst++ = b; - *dst++ = 0; - break; - - case PUSH_BGR32: - *dst++ = b; - *dst++ = g; - *dst++ = r; - *dst++ = 0; - break; - } - } /* ..for col */ - if (line & 1) { // odd line: go to next band - su += linewidth; - sv += linewidth; - } - else { // rewind u/v pointers - su -= linewidth; - sv -= linewidth; - } - /* Adjust destination pointer, using viewport. We have just - filled one line worth of data, so only skip the difference - between the view width and the image width. - */ - if (push == PUSH_RGB24 || push == PUSH_BGR24) - dst += ((plus - width) * 3); - else - dst += ((plus - width) * 4); - } /* ..for line */ -} - -void vcvt_420i_rgb24(int width, int height, int plus, void *src, void *dst) -{ - vcvt_420i(width, height, plus, (unsigned char *)src, (unsigned char *)dst, PUSH_RGB24); -} - -void vcvt_420i_bgr24(int width, int height, int plus, void *src, void *dst) -{ - vcvt_420i(width, height, plus, (unsigned char *)src, (unsigned char *)dst, PUSH_BGR24); -} - -void vcvt_420i_rgb32(int width, int height, int plus, void *src, void *dst) -{ - vcvt_420i(width, height, plus, (unsigned char *)src, (unsigned char *)dst, PUSH_RGB32); -} - -void vcvt_420i_bgr32(int width, int height, int plus, void *src, void *dst) -{ - vcvt_420i(width, height, plus, (unsigned char *)src, (unsigned char *)dst, PUSH_BGR32); -} - - -/** \brief Convert from interlaces YUV 420 to planar format -*/ -void vcvt_420i_420p(int width, int height, int plus, void *src, void *dsty, void *dstu, void *dstv) -{ - short *s, *dy, *du, *dv; - int line, col; - - s = (short *)src; - dy = (short *)dsty; - du = (short *)dstu; - dv = (short *)dstv; - for (line = 0; line < height; line++) { - for (col = 0; col < width; col += 4) { - *dy++ = *s++; - *dy++ = *s++; - if (line & 1) - *dv++ = *s++; - else - *du++ = *s++; - } /* ..for col */ - dy += (plus - width); - dv += ((plus - width) >> 1); - du += ((plus - width) >> 1); - } /* ..for line */ -} - -void vcvt_420i_yuyv(int width, int height, int plus, void *src, void *dst) -{ - int line, col, linewidth; - unsigned char *sy, *su, *sv, *d; - - linewidth = width + (width >> 1); - sy = (unsigned char *)src; - su = sy + 4; - sv = su + linewidth; - d = (unsigned char *)dst; - - for (line = 0; line < height; line++) { - for (col = 0; col < width; col += 4) { - /* four pixels in one go */ - *d++ = *sy++; - *d++ = *su; - *d++ = *sy++; - *d++ = *sv; - - *d++ = *sy++; - *d++ = *su++; - *d++ = *sy++; - *d++ = *sv++; - - sy += 2; - su += 4; - sv += 4; - } /* ..for col */ - if (line & 1) { // odd line: go to next band - su += linewidth; - sv += linewidth; - } - else { // rewind u/v pointers - su -= linewidth; - sv -= linewidth; - } - /* Adjust for viewport width */ - d += ((plus - width) << 1); - } /* ..for line */ -} - diff --git a/drivers/usb/vcvt_i386.S b/drivers/usb/vcvt_i386.S deleted file mode 100644 index ea943c8740b1..000000000000 --- a/drivers/usb/vcvt_i386.S +++ /dev/null @@ -1,795 +0,0 @@ -/* - Colour conversion routines (RGB <-> YUV) in x86 assembly, with viewport - extension. - (C) 2001 Nemosoft Unv. nemosoft@smcc.demon.nl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -/* The vcvt_* functions always start with width and height and plus, so these - parameters are in 8(%ebp), 12(%ebp) and 16(%ebp). - The other parameters can be 2 to 4 pointers, in one of these combinations: - *src, *dst - *srcy, *srcu, *srv, *dst - *src, *dsty, *dstu, *dstv - */ - -#define __ASSEMBLY__ -#include <linux/linkage.h> - -.line 35 - -#define Width 8(%ebp) -#define Height 12(%ebp) -#define Plus 16(%ebp) - -/* 2 parameters, 1 in, 1 out */ -#define Src2 20(%ebp) -#define Dst2 24(%ebp) - -/* 4 parameters, 3 in, 1 out */ -#define SrcY 20(%ebp) -#define SrcU 24(%ebp) -#define SrcV 28(%ebp) -#define Dst4 32(%ebp) - -/* 4 parameters, 1 in, 3 out */ -#define Src4 20(%ebp) -#define DstY 24(%ebp) -#define DstU 28(%ebp) -#define DstV 32(%ebp) - -/* This buffer space used to be staticly allocted, but this is going to - give problems with multiple cams (though I have yet to see it). - Therefor, we reserve least 64 bytes (16 * 4) bytes on the stack, - plus some space for extra variables. - */ - -#define PixelBuffer -64(%ebp) -#define Uptr -68(%ebp) -#define Vptr -72(%ebp) -#define DstPlus -76(%ebp) - -#define StackSpace $76 - - .text - -/* This function will load the src and destination pointers, including - Uptr/Vptr when necessary, and test the width/height parameters. - - %esi will be set to Src or SrcY - - %edi will be set to Dst or DstY - the carry flag will be set if any of these tests fail. - It assumes %ebp has been set. - */ -/* 2 parameters, src & dst */ -test_param_2: - mov Src2, %esi - mov Dst2, %edi - - cmp $0, %esi # NULL pointers? - je param_fail - cmp $0, %edi - je param_fail - - jmp test_width_height - -/* 3 inputs, 1 output */ -test_param_31: - mov Dst4, %edi # NULL pointers - cmp $0, %edi - je param_fail - - mov SrcV, %esi - cmp $0, %esi - je param_fail - mov %esi, Vptr - - mov SrcU, %esi - cmp $0, %esi - je param_fail - mov %esi, Uptr - - mov SrcY, %esi - cmp $0, %esi - je param_fail - - jmp test_width_height - -/* 1 input, 3 output */ -test_param_13: - mov Src4, %esi # NULL pointers - cmp $0, %esi - je param_fail - - mov DstV, %edi - cmp $0, %edi - je param_fail - mov %edi, Vptr - - mov DstU, %edi - cmp $0, %edi - je param_fail - mov %edi, Uptr - - mov DstY, %edi - cmp $0, %edi - je param_fail - - jmp test_width_height - - nop - -test_width_height: - cmpl $0, Width - jbe param_fail - testl $3, Width # multiple of 4? - jnz param_fail # Nope... - - cmp $0, Height # check illegal height - jbe param_fail - testl $1, Height # Odd no. of lines? - jnz param_fail # Aye - - /* fall through */ - -/* exit points */ -param_ok: - clc # Success: clear carry - ret - -param_fail: - stc # Fail: set carry - ret - - - -# This will fill PixelBuffer with 4 grey scale pixels (Y) -# In: %eax = Value (Y3Y2Y1Y0) -# Out: -# Modifies: %ecx (-4) -# Destroys: %edx -expand_4_y: - mov %eax, %edx # Keep in edx (we need eax) - lea PixelBuffer, %edi - -0: # This code is executed 4 times - movzbl %dl, %eax # move, zero extending byte-to-long - shl $8, %eax # 8 digit precision - - stosl # Expand into PixelBuffer - stosl - stosl - add $4, %edi # Skip alpha - - shr $8, %edx # next Y - - dec %ecx - test $3, %ecx - jnz 0b - - ret # from expand_4_y - -# This will add the color factors to the (grey) values in PixelBuffer -# In: %ebx (U1U0V1V0) -# Out: -# Modifies: -# Destroys: %edi, %ebx, %eax, %edx -expand_4_uv: - lea PixelBuffer, %edi # reset pointer - - # V0 - sub $128, %bl - movsbl %bl, %eax - mov $359, %edx # Vr - mul %edx - add %eax, 0x00(%edi) - add %eax, 0x10(%edi) - - movsbl %bl, %eax - mov $183, %edx # Vg - mul %edx - sub %eax, 0x04(%edi) - sub %eax, 0x14(%edi) - - # V1 - sub $128, %bh - movsbl %bh, %eax - mov $359, %edx # Vr - mul %edx - add %eax, 0x20(%edi) - add %eax, 0x30(%edi) - - movsbl %bh, %eax - mov $183, %edx # Vg - mul %edx - sub %eax, 0x24(%edi) - sub %eax, 0x34(%edi) - - # U0 - bswap %ebx # Get U values in lower half - sub $128, %bh - movsbl %bh, %eax - mov $88, %edx # Ug - mul %edx - sub %eax, 0x04(%edi) - sub %eax, 0x14(%edi) - - movsbl %bh, %eax - mov $454, %edx # Ub - mul %edx - add %eax, 0x08(%edi) - add %eax, 0x18(%edi) - - # U1 - sub $128, %bl - movsbl %bl, %eax - mov $88, %edx # Ug - mul %edx - sub %eax, 0x24(%edi) - sub %eax, 0x34(%edi) - - movsbl %bl, %eax - mov $454, %edx # Ub - mul %edx - add %eax, 0x28(%edi) - add %eax, 0x38(%edi) - ret # expand_4_uv - - -/* This function expands 4 420i pixels into PixelBuffer */ -do_four_yuvi: - push %edi - - lodsl # 4 bytes at a time - - call expand_4_y - - # now do UV values. on even lines, Y is followed by U values; on - # odd lines V values follow. The U and V values are always pushed - # on the stack in this order: - # U V - - # First, calculate offset per line (1.5 * width) - mov Width, %ebx # width - shl %ebx # 2 * - add Width, %ebx # 3 * - shr %ebx # 1.5 * - - # even or odd lines - testl $1, Height - jz 2f - - # odd line; we are at V data, but do U data first - neg %ebx # make ebx offset negative - mov (%esi,%ebx),%ax # U - push %ax - lodsw # V - push %ax - jmp 3f - -2: # even line - lodsw # U - push %ax - sub $2, %ebx - mov (%esi,%ebx), %ax # V - push %ax - -3: # Okay, so we now have the U and V values... expand into PixelBuffer - - pop %ebx - call expand_4_uv - - pop %edi - ret # from do_four_yuvi - - -# Do four pixels, in planar format -do_four_yuvp: - push %edi - - # The first part is the same as for interlaced (4 bytes Y) - lodsl # 4 bytes at a time - call expand_4_y - - # now gather U and V values... - mov Uptr, %ebx # Use Uptr/Vptr - mov (%ebx), %ax - push %ax - add $2, %ebx - mov %ebx, Uptr - - mov Vptr, %ebx - mov (%ebx), %ax - push %ax - add $2, %ebx - mov %ebx, Vptr - - pop %ebx - call expand_4_uv - - pop %edi - ret - - -# Do four pixels, in yuyv interlaced format -do_four_yuyv: - push %edi - - lodsl # v0y1u0y0 - mov %eax, %ebx - bswap %ebx # y0u0y1v0 - mov %bh, %ah # v0y1y1y0 - and $0x00ff00ff, %ebx # __u0__v0 - push %ax # y1y0 - - lodsl # v1y3u1y2 # mix register instructions - mov %eax, %edx # so CPU pipeline doesnt stall - rol $16, %eax # u1y2v1y3 - mov %dl, %dh # v1y3y2y2 - and $0xff00ff00, %eax # u1__v1__ - mov $0, %dl # v1y3y2__ - or %eax, %ebx # u1u0v1v0 - shl $8, %edx # y3y2____ - pop %dx # y3y2y1y0 - mov %edx, %eax - call expand_4_y - call expand_4_uv - - pop %edi - ret - -limit_pixels: - # Limit all values in PixelBuffer - push %esi - push %edi - push %ecx - lea PixelBuffer, %esi - mov %esi, %edi - mov $16, %ecx -0: lodsl - cmp $0, %eax # this would have been a perfect spot for CMOVxx instructions... - jl 2f # except they only work on Pentium Pro processors, - cmp $0xff00, %eax # and not even all of them - jg 3f - add $4, %edi # no use for stosl here - loop 0b - jmp 9f -2: mov $0, %eax - stosl - loop 0b - jmp 9f -3: mov $0xff00, %eax - stosl - loop 0b - jmp 9f - -9: pop %ecx - pop %edi - pop %esi - ret # from limit_pixels - -/* Copy RGB values from PixelBuffer into destination buffer, 4 bytes - with alpha - */ - -/* Push 3 pixel (12 bytes), in correct order */ -push_rgb24: - push %ecx - push %esi - lea PixelBuffer, %esi - mov $4, %ecx -0: lodsl - shr $8, %eax - mov %al, (%edi) # Red - lodsl - shr $8, %eax - mov %al, 1(%edi) # Green - lodsl - shr $8, %eax - mov %al, 2(%edi) # Blue - add $3, %edi - lodsl # dummy - loop 0b - pop %esi - pop %ecx - ret - -/* Push 3 pixels (12 bytes), in wrong order */ -push_bgr24: - push %ecx - push %esi - lea PixelBuffer, %esi - mov $4, %ecx -0: lodsl - shr $8, %eax - mov %al, 2(%edi) # Red - lodsl - shr $8, %eax - mov %al, 1(%edi) # Green - lodsl - shr $8, %eax - mov %al, (%edi) # Blue - add $3, %edi - lodsl # dummy - loop 0b - pop %esi - pop %ecx - ret - -/* The simplest format: push 4 bytes, RGBa */ -push_rgb32: - push %ecx - push %esi - mov $16, %ecx - lea PixelBuffer, %esi -0: lodsl # red - shr $8, %eax # 8 bit precision - stosb - loop 0b - pop %esi - pop %ecx - ret - - -/* Gosh. Would you believe it. They even made this format... (Qt 2.*) */ -push_bgr32: - # copy all 4 values to output buffer - push %ecx - push %esi - mov $4, %ecx - lea PixelBuffer, %esi -0: lodsl # red - shr $8, %eax # 8 bit precision - mov %al, 2(%edi) - lodsl # green - shr $8, %eax - mov %al, 1(%edi) - lodsl # blue - shr $8, %eax - mov %al, (%edi) - add $4, %edi - lodsl # dummy - loop 0b - pop %esi - pop %ecx - ret - -/*************************************/ - -/* Functions to go from YUV interlaced formats to RGB */ - -/* Go from interlaced to RGB, red first */ - -ENTRY(vcvt_420i_rgb24) - enter StackSpace, $0 # no extra space, no stackframes - push %ebx - push %esi - push %edi - - call test_param_2 - jc 9f - - mov Plus, %eax # 3 bytes per pixel - shl $1, %eax - add Plus, %eax - mov %eax, DstPlus - -0: mov Width, %ecx # width - push %edi # Save dst pointer -1: call do_four_yuvi - call limit_pixels - call push_rgb24 - - cmp $0, %ecx - jnz 1b # end of line? - pop %edi # Get dst pointer - add DstPlus, %edi # Add offset - decl Height # yes; decrement line counter - jnz 0b - -9: pop %edi - pop %esi - pop %ebx - leave - ret - -/* Go from interlaced to BGR, blue first */ - -ENTRY(vcvt_420i_bgr24) - enter StackSpace, $0 # no extra space, no stackframes - push %ebx - push %esi - push %edi - - call test_param_2 - jc 9f - - mov Plus, %eax # 3 bytes per pixel - shl $1, %eax - add Plus, %eax - mov %eax, DstPlus - -0: mov Width, %ecx # width - push %edi -1: call do_four_yuvi - call limit_pixels - call push_bgr24 - - cmp $0, %ecx - jnz 1b # end of line? - pop %edi # Get dst pointer - add DstPlus, %edi # Add offset - decl Height # yes; decrement line counter - jnz 0b - -9: pop %edi - pop %esi - pop %ebx - leave - ret - - -/* From interlaced to RGBa */ - -ENTRY(vcvt_420i_rgb32) - enter StackSpace, $0 # no extra space, no stackframes - push %ebx - push %esi - push %edi - - call test_param_2 - jc 9f - - mov Plus, %eax # 4 bytes per pixel - shl $2, %eax - mov %eax, DstPlus - -0: mov Width, %ecx # width - push %edi -1: call do_four_yuvi - call limit_pixels - call push_rgb32 - - cmp $0, %ecx # end of line? - jnz 1b - pop %edi # Get dst pointer - add DstPlus, %edi # Add offset - decl Height # yes; decrement line counter - jnz 0b - -9: pop %edi - pop %esi - pop %ebx - leave - ret - -/* Guess what? Go from interlaced to BGRa */ - -ENTRY(vcvt_420i_bgr32) - enter StackSpace, $0 # no extra space, no stackframes - push %ebx - push %esi - push %edi - - call test_param_2 - jc 9f - - mov Plus, %eax # 4 bytes per pixel - shl $2, %eax - mov %eax, DstPlus - -0: mov Width, %ecx # width - push %edi -1: call do_four_yuvi - call limit_pixels - call push_bgr32 - - cmp $0, %ecx # end of line? - jnz 1b - pop %edi # Get dst pointer - add DstPlus, %edi # Add offset - decl Height # yes; decrement line counter - jnz 0b - -9: pop %edi - pop %esi - pop %ebx - leave - ret - - - - - - - -/**************************************************************************/ - - -/* Go from 'interlaced' (YYYY UU/VV) format to planar */ - -ENTRY(vcvt_420i_420p) - enter $80, $0 # 4 bytes extra space, no stackframes - push %ebx # -4: width / 4 - push %esi - push %edi - - call test_param_13 - jc 9f - - # Okay, this is fairly easy... we first grab the Y values (4 bytes - # at a time), then rewind and do the U values, and repeat for V. - # This leaves us with a nice planar format - - mov Width, %eax - shr %eax - shr %eax # width / 4 - mov %eax, -80(%ebp) # Store - - # Y - mov Height, %edx # line counter -0: mov -80(%ebp), %ecx - push %edi -1: lodsl # get 4 bytes... - stosl # ...push 4 bytes - add $2, %esi # Skip U or V - loop 1b - pop %edi - add Plus, %edi - dec %edx - jnz 0b - - shrl $1, Plus # divide increment by 2 - - # U - mov Src4, %esi # rewind source pointer - mov DstU, %edi - add $4, %esi # set to U - mov Height, %edx - shr %edx # height / 2 - mov Width, %ebx - shl %ebx - add Width, %ebx - shr %ebx # Width * 1.5 (line offset) - -2: mov -80(%ebp), %ecx # width / 4 - push %edi -3: lodsw # 2 bytes at a time - stosw - add $4, %esi # skip Y - loop 3b - add %ebx, %esi # Skip line (U is on even lines) - pop %edi - add Plus, %edi - dec %edx - jnz 2b - - # V - mov Src4, %esi # rewind, set to V in first odd line - add $4, %esi - add %ebx, %esi # register re-use; no compiler can beat that :) - mov DstV, %edi # V ptr - mov Height, %edx - shr %edx # height / 2 - -4: mov -80(%ebp), %ecx # Get width/4 - push %edi -5: lodsw - stosw - add $4, %esi # Skip Y - loop 5b - add %ebx, %esi # Skip line (V is on odd lines) - pop %edi - add Plus, %edi - dec %edx - jnz 4b - - /* That's it! */ - -9: pop %edi - pop %esi - pop %ebx - leave - ret - - -/* Go from 4:2:0 interlaced to 'normal' YUYV */ - -ENTRY(vcvt_420i_yuyv) - enter $84, $0 # 8 bytes extra space, no stackframes - push %ebx - push %esi - push %edi - - call test_param_2 - jc 9f - - mov Width, %ecx # -4: width / 4 = no. loops per line - shr %ecx - shr %ecx - mov %ecx, -80(%ebp) - - mov Width, %ebx # -8: width * 1.5 = line offset - shl %ebx - add Width, %ebx - shr %ebx - mov %ebx, -84(%ebp) - - # Okay, this requires a bit of byte shuffling... we go from - # YYYY UU - # YYYY VV - # to - # YUYV YUYV - # YUYV YUYV - # which indeed takes up more space - - # - shll Plus # Plus * 2 -0: mov -80(%ebp), %ecx - push %edi -1: lodsl # 4 Y in eax - testl $1, Height # even or odd line? - jnz 2f - - # Even - mov -84(%ebp), %ebx - mov (%ebx, %esi), %dx # 16 bits V - shl $16, %edx # store in high word - mov (%esi), %dx # 16 bits U - add $2, %esi - jmp 3f - -2: # Odd - mov -84(%ebp), %ebx - neg %ebx # negative offset - mov (%esi), %dx # 16 bits V - shl $16, %edx # store in high word - mov (%ebx, %esi), %dx # 16 bits U - add $2, %esi - -3: # eax = Y3Y2Y1Y0, edx = V1V0U1U0, ebx is free - push %eax - - movzbl %al, %ebx # ______y0 - and $0xFF00, %eax # ____y1__ - shl $8, %eax # __y1____ - or %ebx, %eax # __y1__y0 - mov %edx, %ebx # v1v0u1u0 - shl $8, %ebx # v0u1u0__ - and $0xff00ff00, %ebx # v0__u0__ - or %ebx, %eax # v0y1u0y0 - stosl - - pop %eax # y3y2y1y0 - # Second half - shr $8, %eax # __y3y2y1 - shr $8, %ax # __y3__y2 - and $0xff00ff00, %edx # v1__u1__ - or %edx, %eax # v1y3u1y2 - stosl - - loop 1b - pop %edi - add Plus, %edi - decl Height # height-- - jnz 0b - # Done - -9: pop %edi - pop %esi - pop %ebx - leave - ret diff --git a/fs/fat/buffer.c b/fs/fat/buffer.c index 373dcee839a9..bff1cc366a0c 100644 --- a/fs/fat/buffer.c +++ b/fs/fat/buffer.c @@ -8,6 +8,7 @@ #include <linux/slab.h> #include <linux/string.h> #include <linux/fs.h> +#include <linux/blkdev.h> #include <linux/msdos_fs.h> #include <linux/fat_cvf.h> @@ -58,22 +59,26 @@ void fat_ll_rw_block ( struct buffer_head *default_fat_bread(struct super_block *sb, int block) { - return bread (sb->s_dev,block,512); + return bread (sb->s_dev, block, sb->s_blocksize); } + struct buffer_head *default_fat_getblk(struct super_block *sb, int block) { - return getblk (sb->s_dev,block,512); + return getblk (sb->s_dev, block, sb->s_blocksize); } + void default_fat_brelse(struct super_block *sb, struct buffer_head *bh) { brelse (bh); } + void default_fat_mark_buffer_dirty ( struct super_block *sb, struct buffer_head *bh) { mark_buffer_dirty (bh); } + void default_fat_set_uptodate ( struct super_block *sb, struct buffer_head *bh, @@ -81,10 +86,12 @@ void default_fat_set_uptodate ( { mark_buffer_uptodate(bh, val); } + int default_fat_is_uptodate (struct super_block *sb, struct buffer_head *bh) { return buffer_uptodate(bh); } + void default_fat_ll_rw_block ( struct super_block *sb, int opr, @@ -94,109 +101,61 @@ void default_fat_ll_rw_block ( ll_rw_block(opr,nbreq,bh); } -struct buffer_head *bigblock_fat_bread ( - struct super_block *sb, - int block) -{ - struct buffer_head *ret = NULL; - struct buffer_head *real; - if (sb->s_blocksize == 1024){ - real = bread (sb->s_dev,block>>1,1024); - } else { - real = bread (sb->s_dev,block>>2,2048); - } +struct buffer_head *bigblock_fat_bread(struct super_block *sb, int block) +{ + unsigned int hardsect = get_hardsect_size(sb->s_dev); + int rblock, roffset; + struct buffer_head *real, *dummy; + + if (hardsect <= sb->s_blocksize) + BUG(); + dummy = NULL; + rblock = block / (hardsect / sb->s_blocksize); + roffset = (block % (hardsect / sb->s_blocksize)) * sb->s_blocksize; + real = bread(sb->s_dev, rblock, hardsect); if (real != NULL) { - ret = (struct buffer_head *) - kmalloc (sizeof(struct buffer_head), GFP_KERNEL); - if (ret != NULL) { - /* #Specification: msdos / strategy / special device / dummy blocks - * Many special device (Scsi optical disk for one) use - * larger hardware sector size. This allows for higher - * capacity. - - * Most of the time, the MS-DOS filesystem that sits - * on this device is totally unaligned. It use logically - * 512 bytes sector size, with logical sector starting - * in the middle of a hardware block. The bad news is - * that a hardware sector may hold data own by two - * different files. This means that the hardware sector - * must be read, patch and written almost all the time. - - * Needless to say that it kills write performance - * on all OS. - - * Internally the linux msdos fs is using 512 bytes - * logical sector. When accessing such a device, we - * allocate dummy buffer cache blocks, that we stuff - * with the information of a real one (1k large). - - * This strategy is used to hide this difference to - * the core of the msdos fs. The slowdown is not - * hidden though! - */ - /* - * The memset is there only to catch errors. The msdos - * fs is only using b_data - */ - memset (ret,0,sizeof(*ret)); - ret->b_data = real->b_data; - if (sb->s_blocksize == 2048) { - if (block & 3) ret->b_data += (block & 3) << 9; - }else{ - if (block & 1) ret->b_data += 512; - } - ret->b_next = real; - }else{ - brelse (real); - } + dummy = kmalloc(sizeof(struct buffer_head), GFP_KERNEL); + if (dummy != NULL) { + memset(dummy, 0, sizeof(*dummy)); + dummy->b_data = real->b_data + roffset; + dummy->b_next = real; + } else + brelse(real); } - return ret; + + return dummy; } -void bigblock_fat_brelse ( - struct super_block *sb, - struct buffer_head *bh) +void bigblock_fat_brelse(struct super_block *sb, struct buffer_head *bh) { - brelse (bh->b_next); - /* - * We can free the dummy because a new one is allocated at - * each fat_getblk() and fat_bread(). - */ - kfree (bh); + brelse(bh->b_next); + kfree(bh); } -void bigblock_fat_mark_buffer_dirty ( - struct super_block *sb, - struct buffer_head *bh) +void bigblock_fat_mark_buffer_dirty(struct super_block *sb, struct buffer_head *bh) { - mark_buffer_dirty (bh->b_next); + mark_buffer_dirty(bh->b_next); } -void bigblock_fat_set_uptodate ( - struct super_block *sb, - struct buffer_head *bh, - int val) +void bigblock_fat_set_uptodate(struct super_block *sb, struct buffer_head *bh, + int val) { mark_buffer_uptodate(bh->b_next, val); } -int bigblock_fat_is_uptodate ( - struct super_block *sb, - struct buffer_head *bh) +int bigblock_fat_is_uptodate(struct super_block *sb, struct buffer_head *bh) { return buffer_uptodate(bh->b_next); } -void bigblock_fat_ll_rw_block ( - struct super_block *sb, - int opr, - int nbreq, - struct buffer_head *bh[32]) +void bigblock_fat_ll_rw_block (struct super_block *sb, int opr, int nbreq, + struct buffer_head *bh[32]) { struct buffer_head *tmp[32]; int i; - for (i=0; i<nbreq; i++) + + for (i = 0; i < nbreq; i++) tmp[i] = bh[i]->b_next; - ll_rw_block(opr,nbreq,tmp); + ll_rw_block(opr, nbreq, tmp); } diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 35874bf50854..f5fea6704d6f 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -41,9 +41,9 @@ int fat_bmap(struct inode *inode,int sector) int default_fat_access(struct super_block *sb,int nr,int new_value) { - struct buffer_head *bh,*bh2,*c_bh,*c_bh2; - unsigned char *p_first,*p_last; - int copy,first,last,next,b; + struct buffer_head *bh, *bh2, *c_bh, *c_bh2; + unsigned char *p_first, *p_last; + int copy, first, last, next, b; if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters) return 0; @@ -55,12 +55,12 @@ int default_fat_access(struct super_block *sb,int nr,int new_value) first = nr*3/2; last = first+1; } - b = MSDOS_SB(sb)->fat_start + (first >> SECTOR_BITS); + b = MSDOS_SB(sb)->fat_start + (first >> sb->s_blocksize_bits); if (!(bh = fat_bread(sb, b))) { printk("bread in fat_access failed\n"); return 0; } - if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS)) { + if ((first >> sb->s_blocksize_bits) == (last >> sb->s_blocksize_bits)) { bh2 = bh; } else { if (!(bh2 = fat_bread(sb, b+1))) { @@ -72,7 +72,7 @@ int default_fat_access(struct super_block *sb,int nr,int new_value) if (MSDOS_SB(sb)->fat_bits == 32) { p_first = p_last = NULL; /* GCC needs that stuff */ next = CF_LE_L(((__u32 *) bh->b_data)[(first & - (SECTOR_SIZE-1)) >> 2]); + (sb->s_blocksize - 1)) >> 2]); /* Fscking Microsoft marketing department. Their "32" is 28. */ next &= 0xfffffff; if (next >= 0xffffff7) next = -1; @@ -81,23 +81,22 @@ int default_fat_access(struct super_block *sb,int nr,int new_value) } else if (MSDOS_SB(sb)->fat_bits == 16) { p_first = p_last = NULL; /* GCC needs that stuff */ next = CF_LE_W(((__u16 *) bh->b_data)[(first & - (SECTOR_SIZE-1)) >> 1]); + (sb->s_blocksize - 1)) >> 1]); if (next >= 0xfff7) next = -1; } else { - p_first = &((__u8 *) bh->b_data)[first & (SECTOR_SIZE-1)]; - p_last = &((__u8 *) bh2->b_data)[(first+1) & - (SECTOR_SIZE-1)]; + p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)]; + p_last = &((__u8 *)bh2->b_data)[(first + 1) & (sb->s_blocksize - 1)]; if (nr & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff; else next = (*p_first+(*p_last << 8)) & 0xfff; if (next >= 0xff7) next = -1; } if (new_value != -1) { if (MSDOS_SB(sb)->fat_bits == 32) { - ((__u32 *) bh->b_data)[(first & (SECTOR_SIZE-1)) >> - 2] = CT_LE_L(new_value); + ((__u32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2] + = CT_LE_L(new_value); } else if (MSDOS_SB(sb)->fat_bits == 16) { - ((__u16 *) bh->b_data)[(first & (SECTOR_SIZE-1)) >> - 1] = CT_LE_W(new_value); + ((__u16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1] + = CT_LE_W(new_value); } else { if (nr & 1) { *p_first = (*p_first & 0xf) | (new_value << 4); @@ -111,20 +110,21 @@ int default_fat_access(struct super_block *sb,int nr,int new_value) } fat_mark_buffer_dirty(sb, bh); for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) { - b = MSDOS_SB(sb)->fat_start + (first >> SECTOR_BITS) + - MSDOS_SB(sb)->fat_length * copy; + b = MSDOS_SB(sb)->fat_start + (first >> sb->s_blocksize_bits) + + MSDOS_SB(sb)->fat_length * copy; if (!(c_bh = fat_bread(sb, b))) break; - memcpy(c_bh->b_data,bh->b_data,SECTOR_SIZE); - fat_mark_buffer_dirty(sb, c_bh); if (bh != bh2) { if (!(c_bh2 = fat_bread(sb, b+1))) { fat_brelse(sb, c_bh); break; } - memcpy(c_bh2->b_data,bh2->b_data,SECTOR_SIZE); + memcpy(c_bh2->b_data, bh2->b_data, sb->s_blocksize); + fat_mark_buffer_dirty(sb, c_bh2); fat_brelse(sb, c_bh2); } + memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize); + fat_mark_buffer_dirty(sb, c_bh); fat_brelse(sb, c_bh); } } @@ -143,7 +143,7 @@ void fat_cache_init(void) if (initialized) { spin_unlock(&fat_cache_lock); return; - } + } fat_cache = &cache[0]; for (count = 0; count < FAT_CACHE; count++) { cache[count].device = 0; @@ -294,22 +294,28 @@ int fat_get_cluster(struct inode *inode,int cluster) int default_fat_bmap(struct inode *inode,int sector) { - struct msdos_sb_info *sb=MSDOS_SB(inode->i_sb); - int cluster,offset; + struct super_block *sb = inode->i_sb; + struct msdos_sb_info *sbi = MSDOS_SB(sb); + int cluster, offset, last_block; - if ((sb->fat_bits != 32) && + if ((sbi->fat_bits != 32) && (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) && !MSDOS_I(inode)->i_start))) { - if (sector >= sb->dir_entries >> MSDOS_DPS_BITS) + if (sector >= sbi->dir_entries >> sbi->dir_per_block_bits) return 0; - return sector+sb->dir_start; + return sector + sbi->dir_start; } - if (sector >= (MSDOS_I(inode)->mmu_private+511)>>9) + last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1)) + >> sb->s_blocksize_bits; + if (sector >= last_block) return 0; - cluster = sector/sb->cluster_size; - offset = sector % sb->cluster_size; - if (!(cluster = fat_get_cluster(inode,cluster))) return 0; - return (cluster-2)*sb->cluster_size+sb->data_start+offset; + + cluster = sector / sbi->cluster_size; + offset = sector % sbi->cluster_size; + if (!(cluster = fat_get_cluster(inode, cluster))) + return 0; + + return (cluster - 2) * sbi->cluster_size + sbi->data_start + offset; } @@ -351,7 +357,7 @@ int fat_free(struct inode *inode,int skip) fat_clusters_flush(inode->i_sb); } } - inode->i_blocks -= MSDOS_SB(inode->i_sb)->cluster_size; + inode->i_blocks -= (1 << MSDOS_SB(inode->i_sb)->cluster_bits) / 512; } unlock_fat(inode->i_sb); return 0; diff --git a/fs/fat/file.c b/fs/fat/file.c index f82741be845e..18df5b1ee112 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -54,8 +54,11 @@ ssize_t fat_file_read( } -int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) { +int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) +{ + struct super_block *sb = inode->i_sb; unsigned long phys; + phys = fat_bmap(inode, iblock); if (phys) { bh_result->b_dev = inode->i_dev; @@ -65,7 +68,7 @@ int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_resul } if (!create) return 0; - if (iblock<<9 != MSDOS_I(inode)->mmu_private) { + if (iblock << sb->s_blocksize_bits != MSDOS_I(inode)->mmu_private) { BUG(); return -EIO; } @@ -73,8 +76,8 @@ int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_resul if (fat_add_cluster(inode)) return -ENOSPC; } - MSDOS_I(inode)->mmu_private += 512; - phys=fat_bmap(inode, iblock); + MSDOS_I(inode)->mmu_private += sb->s_blocksize; + phys = fat_bmap(inode, iblock); if (!phys) BUG(); bh_result->b_dev = inode->i_dev; @@ -124,7 +127,7 @@ void fat_truncate(struct inode *inode) return /* -EPERM */; if (IS_IMMUTABLE(inode)) return /* -EPERM */; - cluster = SECTOR_SIZE*sbi->cluster_size; + cluster = 1 << sbi->cluster_bits; /* * This protects against truncating a file bigger than it was then * trying to write into the hole. @@ -132,7 +135,7 @@ void fat_truncate(struct inode *inode) if (MSDOS_I(inode)->mmu_private > inode->i_size) MSDOS_I(inode)->mmu_private = inode->i_size; - fat_free(inode,(inode->i_size+(cluster-1))>>sbi->cluster_bits); + fat_free(inode, (inode->i_size + (cluster - 1)) >> sbi->cluster_bits); MSDOS_I(inode)->i_attrs |= ATTR_ARCH; inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 1e02a2f727a6..f43ec9e614eb 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -201,7 +201,7 @@ void fat_put_super(struct super_block *sb) } -static int parse_options(char *options,int *fat, int *blksize, int *debug, +static int parse_options(char *options,int *fat, int *debug, struct fat_mount_options *opts, char *cvf_format, char *cvf_options) { @@ -310,13 +310,8 @@ static int parse_options(char *options,int *fat, int *blksize, int *debug, else opts->quiet = 1; } else if (!strcmp(this_char,"blocksize")) { - if (!value || !*value) ret = 0; - else { - *blksize = simple_strtoul(value,&value,0); - if (*value || (*blksize != 512 && - *blksize != 1024 && *blksize != 2048)) - ret = 0; - } + printk("FAT: blocksize option is obsolete, " + "not supported now\n"); } else if (!strcmp(this_char,"sys_immutable")) { if (value) ret = 0; @@ -383,8 +378,8 @@ static void fat_read_root(struct inode *inode) MSDOS_I(inode)->i_start = sbi->root_cluster; if ((nr = MSDOS_I(inode)->i_start) != 0) { while (nr != -1) { - inode->i_size += SECTOR_SIZE*sbi->cluster_size; - if (!(nr = fat_access(sb,nr,-1))) { + inode->i_size += 1 << sbi->cluster_bits; + if (!(nr = fat_access(sb, nr, -1))) { printk("Directory %ld: bad FAT\n", inode->i_ino); break; @@ -393,13 +388,11 @@ static void fat_read_root(struct inode *inode) } } else { MSDOS_I(inode)->i_start = 0; - inode->i_size = sbi->dir_entries* - sizeof(struct msdos_dir_entry); + inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry); } - inode->i_blksize = sbi->cluster_size* SECTOR_SIZE; - inode->i_blocks = - ((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) * - sbi->cluster_size; + inode->i_blksize = 1 << sbi->cluster_bits; + inode->i_blocks = ((inode->i_size + inode->i_blksize - 1) + & ~(inode->i_blksize - 1)) / 512; MSDOS_I(inode)->i_logstart = 0; MSDOS_I(inode)->mmu_private = inode->i_size; @@ -432,10 +425,9 @@ fat_read_super(struct super_block *sb, void *data, int silent, struct fat_boot_sector *b; struct msdos_sb_info *sbi = MSDOS_SB(sb); char *p; - int data_sectors,logical_sector_size,sector_mult,fat_clusters=0; - int debug,error,fat,cp; - int blksize; - int fat32; + int logical_sector_size, hard_blksize, fat_clusters = 0; + unsigned int total_sectors, rootdir_sectors; + int fat32, debug, error, fat, cp; struct fat_mount_options opts; char buf[50]; int i; @@ -451,35 +443,26 @@ fat_read_super(struct super_block *sb, void *data, int silent, sb->s_maxbytes = MAX_NON_LFS; sb->s_op = &fat_sops; - blksize = get_hardsect_size(sb->s_dev); - if (!blksize) - blksize = 512; - if (blksize != 512) - printk ("MSDOS: Hardware sector size is %d\n",blksize); + + hard_blksize = get_hardsect_size(sb->s_dev); + if (!hard_blksize) + hard_blksize = 512; + if (hard_blksize != 512) + printk("MSDOS: Hardware sector size is %d\n", hard_blksize); opts.isvfat = sbi->options.isvfat; - if (!parse_options((char *) data, &fat, &blksize, &debug, &opts, - cvf_format, cvf_options) - || (blksize != 512 && blksize != 1024 && blksize != 2048)) + if (!parse_options((char *) data, &fat, &debug, &opts, + cvf_format, cvf_options)) goto out_fail; /* N.B. we should parse directly into the sb structure */ memcpy(&(sbi->options), &opts, sizeof(struct fat_mount_options)); fat_cache_init(); - if( blksize > 1024 ) - { - /* Force the superblock to a larger size here. */ - sb->s_blocksize = blksize; - set_blocksize(sb->s_dev, blksize); - } - else - { - /* The first read is always 1024 bytes */ - sb->s_blocksize = 1024; - set_blocksize(sb->s_dev, 1024); - } + + sb->s_blocksize = hard_blksize; + set_blocksize(sb->s_dev, hard_blksize); bh = bread(sb->s_dev, 0, sb->s_blocksize); - if (bh == NULL || !buffer_uptodate(bh)) { + if (bh == NULL) { brelse (bh); goto out_no_bread; } @@ -499,110 +482,122 @@ fat_read_super(struct super_block *sb, void *data, int silent, * (by Drew Eckhardt) */ -#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) - /* don't divide by zero */ b = (struct fat_boot_sector *) bh->b_data; logical_sector_size = CF_LE_W(get_unaligned((unsigned short *) &b->sector_size)); - sector_mult = logical_sector_size >> SECTOR_BITS; - sbi->cluster_size = b->cluster_size*sector_mult; - if (!sbi->cluster_size || (sbi->cluster_size & (sbi->cluster_size-1))) { - printk("fatfs: bogus cluster size\n"); + if (!logical_sector_size + || (logical_sector_size & (logical_sector_size - 1))) { + printk("fatfs: bogus logical sector size %d\n", + logical_sector_size); brelse(bh); goto out_invalid; } - for (sbi->cluster_bits=0; - 1<<sbi->cluster_bits<sbi->cluster_size; - sbi->cluster_bits++) - ; - sbi->cluster_bits += SECTOR_BITS; + + sbi->cluster_size = b->cluster_size; + if (!sbi->cluster_size || (sbi->cluster_size & (sbi->cluster_size - 1))) { + printk("fatfs: bogus cluster size %d\n", sbi->cluster_size); + brelse(bh); + goto out_invalid; + } + + sbi->cluster_bits = ffs(logical_sector_size * sbi->cluster_size) - 1; sbi->fats = b->fats; - sbi->fat_start = CF_LE_W(b->reserved)*sector_mult; + sbi->fat_start = CF_LE_W(b->reserved); if (!b->fat_length && b->fat32_length) { struct fat_boot_fsinfo *fsinfo; + struct buffer_head *fsinfo_bh; + int fsinfo_block, fsinfo_offset; /* Must be FAT32 */ fat32 = 1; - sbi->fat_length= CF_LE_L(b->fat32_length)*sector_mult; + sbi->fat_length = CF_LE_L(b->fat32_length); sbi->root_cluster = CF_LE_L(b->root_cluster); + sbi->fsinfo_sector = CF_LE_W(b->info_sector); /* MC - if info_sector is 0, don't multiply by 0 */ - if(CF_LE_W(b->info_sector) == 0) { - sbi->fsinfo_offset = - logical_sector_size + 0x1e0; - } else { - sbi->fsinfo_offset = - (CF_LE_W(b->info_sector) * logical_sector_size) - + 0x1e0; - } - if (sbi->fsinfo_offset + sizeof(struct fat_boot_fsinfo) > sb->s_blocksize) { - printk("fat_read_super: Bad fsinfo_offset\n"); - brelse(bh); - goto out_invalid; + if (sbi->fsinfo_sector == 0) + sbi->fsinfo_sector = 1; + + fsinfo_block = + (sbi->fsinfo_sector * logical_sector_size) / hard_blksize; + fsinfo_offset = + (sbi->fsinfo_sector * logical_sector_size) % hard_blksize; + fsinfo_bh = bh; + if (bh->b_blocknr != fsinfo_block) { + fsinfo_bh = bread(sb->s_dev, fsinfo_block, hard_blksize); + if (fsinfo_bh == NULL) { + printk("FAT: bread failed, fsinfo block %d\n", + fsinfo_block); + brelse(bh); + goto out_invalid; + } } - fsinfo = (struct fat_boot_fsinfo *) - &bh->b_data[sbi->fsinfo_offset]; - if (CF_LE_L(fsinfo->signature) != 0x61417272) { - printk("fat_read_super: Did not find valid FSINFO " - "signature. Found 0x%x\n", - CF_LE_L(fsinfo->signature)); + fsinfo = (struct fat_boot_fsinfo *)&fsinfo_bh->b_data[fsinfo_offset]; + if (!IS_FSINFO(fsinfo)) { + printk("FAT: Did not find valid FSINFO signature.\n" + "Found signature1 0x%x signature2 0x%x sector=%ld.\n", + CF_LE_L(fsinfo->signature1), + CF_LE_L(fsinfo->signature2), + sbi->fsinfo_sector); } else { sbi->free_clusters = CF_LE_L(fsinfo->free_clusters); } + + if (bh->b_blocknr != fsinfo_block) + brelse(fsinfo_bh); } else { fat32 = 0; - sbi->fat_length = CF_LE_W(b->fat_length)*sector_mult; + sbi->fat_length = CF_LE_W(b->fat_length); sbi->root_cluster = 0; sbi->free_clusters = -1; /* Don't know yet */ } - sbi->dir_start= CF_LE_W(b->reserved)*sector_mult+ - b->fats*sbi->fat_length; + + sbi->dir_per_block = logical_sector_size / sizeof(struct msdos_dir_entry); + sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1; + + sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length; sbi->dir_entries = - CF_LE_W(get_unaligned((unsigned short *) &b->dir_entries)); - sbi->data_start = sbi->dir_start+ROUND_TO_MULTIPLE(( - sbi->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS, - sector_mult); - data_sectors = CF_LE_W(get_unaligned((unsigned short *) &b->sectors)); - if (!data_sectors) { - data_sectors = CF_LE_L(b->total_sect); - } - data_sectors = data_sectors * sector_mult - sbi->data_start; - error = !b->cluster_size || !sector_mult; + CF_LE_W(get_unaligned((unsigned short *)&b->dir_entries)); + rootdir_sectors = sbi->dir_entries + * sizeof(struct msdos_dir_entry) / logical_sector_size; + sbi->data_start = sbi->dir_start + rootdir_sectors; + total_sectors = CF_LE_W(get_unaligned((unsigned short *)&b->sectors)); + if (total_sectors == 0) + total_sectors = CF_LE_L(b->total_sect); + sbi->clusters = (total_sectors - sbi->data_start) / sbi->cluster_size; + + error = 0; if (!error) { - sbi->clusters = b->cluster_size ? data_sectors/ - b->cluster_size/sector_mult : 0; sbi->fat_bits = fat32 ? 32 : (fat ? fat : (sbi->clusters > MSDOS_FAT12 ? 16 : 12)); - fat_clusters = sbi->fat_length*SECTOR_SIZE*8/ - sbi->fat_bits; - error = !sbi->fats || (sbi->dir_entries & - (MSDOS_DPS-1)) || sbi->clusters+2 > fat_clusters+ - MSDOS_MAX_EXTRA || (logical_sector_size & (SECTOR_SIZE-1)) - || !b->secs_track || !b->heads; + fat_clusters = + sbi->fat_length * logical_sector_size * 8 / sbi->fat_bits; + error = !sbi->fats || (sbi->dir_entries & (sbi->dir_per_block - 1)) + || sbi->clusters + 2 > fat_clusters + MSDOS_MAX_EXTRA + || logical_sector_size < 512 + || PAGE_CACHE_SIZE < logical_sector_size + || !b->secs_track || !b->heads; } brelse(bh); - set_blocksize(sb->s_dev, blksize); - /* - This must be done after the brelse because the bh is a dummy - allocated by fat_bread (see buffer.c) - */ - sb->s_blocksize = blksize; /* Using this small block size solves */ - /* the misfit with buffer cache and cluster */ - /* because clusters (DOS) are often aligned */ - /* on odd sectors. */ - sb->s_blocksize_bits = blksize == 512 ? 9 : (blksize == 1024 ? 10 : 11); + + sb->s_blocksize = logical_sector_size; + sb->s_blocksize_bits = ffs(logical_sector_size) - 1; + if (sb->s_blocksize >= hard_blksize) { + set_blocksize(sb->s_dev, sb->s_blocksize); + sbi->cvf_format = &default_cvf; + } else { + set_blocksize(sb->s_dev, hard_blksize); + sbi->cvf_format = &bigblock_cvf; + } + if (!strcmp(cvf_format,"none")) i = -1; else i = detect_cvf(sb,cvf_format); if (i >= 0) error = cvf_formats[i]->mount_cvf(sb,cvf_options); - else if (sb->s_blocksize == 512) - sbi->cvf_format = &default_cvf; - else - sbi->cvf_format = &bigblock_cvf; if (error || debug) { /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */ printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c," @@ -612,18 +607,19 @@ fat_read_super(struct super_block *sb, void *data, int silent, MSDOS_CAN_BMAP(sbi) ? ",bmap" : ""); printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%ld,ds=%ld,de=%d,data=%ld," "se=%d,ts=%ld,ls=%d,rc=%ld,fc=%u]\n", - b->media,sbi->cluster_size, - sbi->fats,sbi->fat_start, - sbi->fat_length, + b->media,sbi->cluster_size, + sbi->fats,sbi->fat_start, + sbi->fat_length, sbi->dir_start,sbi->dir_entries, sbi->data_start, CF_LE_W(*(unsigned short *) &b->sectors), (unsigned long)b->total_sect,logical_sector_size, sbi->root_cluster,sbi->free_clusters); - printk ("Transaction block size = %d\n",blksize); + printk ("Transaction block size = %d\n", hard_blksize); } - if (i<0) if (sbi->clusters+2 > fat_clusters) - sbi->clusters = fat_clusters-2; + if (i < 0) + if (sbi->clusters + 2 > fat_clusters) + sbi->clusters = fat_clusters - 2; if (error) goto out_invalid; @@ -692,7 +688,7 @@ out_fail: } if(sbi->private_data) kfree(sbi->private_data); - sbi->private_data=NULL; + sbi->private_data = NULL; return NULL; } @@ -717,7 +713,7 @@ int fat_statfs(struct super_block *sb,struct statfs *buf) } unlock_fat(sb); buf->f_type = sb->s_magic; - buf->f_bsize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE; + buf->f_bsize = 1 << MSDOS_SB(sb)->cluster_bits; buf->f_blocks = MSDOS_SB(sb)->clusters; buf->f_bfree = free; buf->f_bavail = free; @@ -796,8 +792,8 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) #endif if ((nr = MSDOS_I(inode)->i_start) != 0) while (nr != -1) { - inode->i_size += SECTOR_SIZE*sbi->cluster_size; - if (!(nr = fat_access(sb,nr,-1))) { + inode->i_size += 1 << sbi->cluster_bits; + if (!(nr = fat_access(sb, nr, -1))) { printk("Directory %ld: bad FAT\n", inode->i_ino); break; @@ -828,12 +824,11 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) inode->i_flags |= S_IMMUTABLE; MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; /* this is as close to the truth as we can get ... */ - inode->i_blksize = sbi->cluster_size*SECTOR_SIZE; - inode->i_blocks = - ((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) * - sbi->cluster_size; + inode->i_blksize = 1 << sbi->cluster_bits; + inode->i_blocks = ((inode->i_size + inode->i_blksize - 1) + & ~(inode->i_blksize - 1)) / 512; inode->i_mtime = inode->i_atime = - date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date)); + date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date)); inode->i_ctime = MSDOS_SB(sb)->options.isvfat ? date_dos2unix(CF_LE_W(de->ctime),CF_LE_W(de->cdate)) @@ -854,7 +849,7 @@ retry: return; } lock_kernel(); - if (!(bh = fat_bread(sb, i_pos >> MSDOS_DPB_BITS))) { + if (!(bh = fat_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) { printk("dev = %s, ino = %d\n", kdevname(inode->i_dev), i_pos); fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block"); unlock_kernel(); @@ -869,7 +864,7 @@ retry: } raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) - [i_pos & (MSDOS_DPB-1)]; + [i_pos & (MSDOS_SB(sb)->dir_per_block - 1)]; if (S_ISDIR(inode->i_mode)) { raw_entry->attr = ATTR_DIR; raw_entry->size = 0; diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 2213a41fe34e..16b750ae9d23 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -108,24 +108,22 @@ void unlock_fat(struct super_block *sb) /* XXX: Need to write one per FSINFO block. Currently only writes 1 */ void fat_clusters_flush(struct super_block *sb) { - int offset; struct buffer_head *bh; struct fat_boot_fsinfo *fsinfo; - /* The fat32 boot fs info is at offset 0x3e0 by observation */ - offset = MSDOS_SB(sb)->fsinfo_offset; - bh = fat_bread(sb, (offset >> SECTOR_BITS)); + bh = fat_bread(sb, MSDOS_SB(sb)->fsinfo_sector); if (bh == NULL) { printk("FAT bread failed in fat_clusters_flush\n"); return; } - fsinfo = (struct fat_boot_fsinfo *) - &bh->b_data[offset & (SECTOR_SIZE-1)]; + fsinfo = (struct fat_boot_fsinfo *)bh->b_data; /* Sanity check */ - if (CF_LE_L(fsinfo->signature) != 0x61417272) { - printk("fat_clusters_flush: Did not find valid FSINFO signature. Found 0x%x. offset=0x%x\n", CF_LE_L(fsinfo->signature), offset); - fat_brelse(sb, bh); + if (!IS_FSINFO(fsinfo)) { + printk("FAT: Did not find valid FSINFO signature.\n" + "Found signature1 0x%x signature2 0x%x sector=%ld.\n", + CF_LE_L(fsinfo->signature1), CF_LE_L(fsinfo->signature2), + MSDOS_SB(sb)->fsinfo_sector); return; } fsinfo->free_clusters = CF_LE_L(MSDOS_SB(sb)->free_clusters); @@ -145,7 +143,6 @@ int fat_add_cluster(struct inode *inode) struct super_block *sb = inode->i_sb; int count,nr,limit,last,curr,file_cluster; int res = -ENOSPC; - int cluster_size = MSDOS_SB(sb)->cluster_size; if (!MSDOS_SB(sb)->free_clusters) return res; lock_fat(sb); @@ -167,7 +164,7 @@ int fat_add_cluster(struct inode *inode) if (MSDOS_SB(sb)->fat_bits == 32) fat_clusters_flush(sb); unlock_fat(sb); - last = 0; + /* We must locate the last cluster of the file to add this new one (nr) to the end of the link list (the FAT). @@ -178,7 +175,7 @@ int fat_add_cluster(struct inode *inode) use last to plug the nr cluster. We will use file_cluster to update the cache. */ - file_cluster = 0; + last = file_cluster = 0; if ((curr = MSDOS_I(inode)->i_start) != 0) { fat_cache_lookup(inode,INT_MAX,&last,&curr); file_cluster = last; @@ -190,14 +187,15 @@ int fat_add_cluster(struct inode *inode) } } } - if (last) fat_access(sb,last,nr); - else { + if (last) { + fat_access(sb, last, nr); + fat_cache_add(inode, file_cluster, nr); + } else { MSDOS_I(inode)->i_start = nr; MSDOS_I(inode)->i_logstart = nr; mark_inode_dirty(inode); } - fat_cache_add(inode,file_cluster,nr); - inode->i_blocks += cluster_size; + inode->i_blocks += (1 << MSDOS_SB(sb)->cluster_bits) / 512; return 0; } @@ -209,36 +207,44 @@ struct buffer_head *fat_extend_dir(struct inode *inode) int cluster_size = MSDOS_SB(sb)->cluster_size; if (MSDOS_SB(sb)->fat_bits != 32) { - if (inode->i_ino == MSDOS_ROOT_INO) return res; + if (inode->i_ino == MSDOS_ROOT_INO) + return res; } - if (!MSDOS_SB(sb)->free_clusters) return res; + if (!MSDOS_SB(sb)->free_clusters) + return res; + lock_fat(sb); + limit = MSDOS_SB(sb)->clusters; nr = limit; /* to keep GCC happy */ for (count = 0; count < limit; count++) { - nr = ((count+MSDOS_SB(sb)->prev_free) % limit)+2; - if (fat_access(sb,nr,-1) == 0) break; + nr = ((count + MSDOS_SB(sb)->prev_free) % limit) + 2; + if (fat_access(sb, nr, -1) == 0) + break; } - PRINTK (("cnt = %d --",count)); + PRINTK (("cnt = %d --", count)); #ifdef DEBUG -printk("free cluster: %d\n",nr); + printk("free cluster: %d\n", nr); #endif - MSDOS_SB(sb)->prev_free = (count+MSDOS_SB(sb)->prev_free+1) % limit; if (count >= limit) { MSDOS_SB(sb)->free_clusters = 0; unlock_fat(sb); return res; } - fat_access(sb,nr,EOF_FAT(sb)); + + MSDOS_SB(sb)->prev_free = (count + MSDOS_SB(sb)->prev_free + 1) % limit; + fat_access(sb, nr, EOF_FAT(sb)); if (MSDOS_SB(sb)->free_clusters != -1) MSDOS_SB(sb)->free_clusters--; if (MSDOS_SB(sb)->fat_bits == 32) fat_clusters_flush(sb); + unlock_fat(sb); + #ifdef DEBUG -printk("set to %x\n",fat_access(sb,nr,-1)); + printk("set to %x\n", fat_access(sb, nr, -1)); #endif - last = 0; + /* We must locate the last cluster of the file to add this new one (nr) to the end of the link list (the FAT). @@ -249,15 +255,14 @@ printk("set to %x\n",fat_access(sb,nr,-1)); use last to plug the nr cluster. We will use file_cluster to update the cache. */ - file_cluster = 0; + last = file_cluster = 0; if ((curr = MSDOS_I(inode)->i_start) != 0) { - fat_cache_lookup(inode,INT_MAX,&last,&curr); + fat_cache_lookup(inode, INT_MAX, &last, &curr); file_cluster = last; while (curr && curr != -1){ PRINTK ((".")); file_cluster++; - if (!(curr = fat_access(sb, - last = curr,-1))) { + if (!(curr = fat_access(sb, last = curr, -1))) { fat_fs_panic(sb,"File without EOF"); return res; } @@ -265,53 +270,57 @@ printk("set to %x\n",fat_access(sb,nr,-1)); PRINTK ((" -- ")); } #ifdef DEBUG -printk("last = %d\n",last); + printk("last = %d\n", last); #endif - if (last) fat_access(sb,last,nr); + if (last) + fat_access(sb, last, nr); else { MSDOS_I(inode)->i_start = nr; MSDOS_I(inode)->i_logstart = nr; mark_inode_dirty(inode); } #ifdef DEBUG -if (last) printk("next set to %d\n",fat_access(sb,last,-1)); + if (last) + printk("next set to %d\n",fat_access(sb, last, -1)); #endif - sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size; + sector = MSDOS_SB(sb)->data_start + (nr - 2) * cluster_size; last_sector = sector + cluster_size; - if (MSDOS_SB(sb)->cvf_format && - MSDOS_SB(sb)->cvf_format->zero_out_cluster) - MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr); - else - for ( ; sector < last_sector; sector++) { - #ifdef DEBUG - printk("zeroing sector %d\n",sector); - #endif - if (!(bh = fat_getblk(sb, sector))) - printk("getblk failed\n"); - else { - memset(bh->b_data,0,SECTOR_SIZE); - fat_set_uptodate(sb, bh, 1); - fat_mark_buffer_dirty(sb, bh); - if (!res) - res=bh; - else - fat_brelse(sb, bh); + if (MSDOS_SB(sb)->cvf_format && MSDOS_SB(sb)->cvf_format->zero_out_cluster) + MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode, nr); + else { + for ( ; sector < last_sector; sector++) { +#ifdef DEBUG + printk("zeroing sector %d\n", sector); +#endif + if (!(bh = fat_getblk(sb, sector))) + printk("getblk failed\n"); + else { + memset(bh->b_data, 0, sb->s_blocksize); + fat_set_uptodate(sb, bh, 1); + fat_mark_buffer_dirty(sb, bh); + if (!res) + res = bh; + else + fat_brelse(sb, bh); + } } } - if (file_cluster != inode->i_blocks/cluster_size){ - printk ("file_cluster badly computed!!! %d <> %ld\n" - ,file_cluster,inode->i_blocks/cluster_size); + if (file_cluster + != inode->i_blocks / cluster_size / (sb->s_blocksize / 512)) { + printk ("file_cluster badly computed!!! %d <> %ld\n", + file_cluster, + inode->i_blocks / cluster_size / (sb->s_blocksize / 512)); }else{ - fat_cache_add(inode,file_cluster,nr); + fat_cache_add(inode, file_cluster, nr); } - inode->i_blocks += cluster_size; - if (inode->i_size & (SECTOR_SIZE-1)) { - fat_fs_panic(sb,"Odd directory size"); - inode->i_size = (inode->i_size+SECTOR_SIZE) & - ~(SECTOR_SIZE-1); + inode->i_blocks += (1 << MSDOS_SB(sb)->cluster_bits) / 512; + if (inode->i_size & (sb->s_blocksize - 1)) { + fat_fs_panic(sb, "Odd directory size"); + inode->i_size = (inode->i_size + sb->s_blocksize) & + ~(sb->s_blocksize - 1); } - inode->i_size += SECTOR_SIZE*cluster_size; - MSDOS_I(inode)->mmu_private += SECTOR_SIZE*cluster_size; + inode->i_size += 1 << MSDOS_SB(sb)->cluster_bits; + MSDOS_I(inode)->mmu_private += 1 << MSDOS_SB(sb)->cluster_bits; mark_inode_dirty(inode); return res; } @@ -386,6 +395,7 @@ int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh, struct msdos_dir_entry **de, int *ino) { struct super_block *sb = dir->i_sb; + struct msdos_sb_info *sbi = MSDOS_SB(sb); int sector, offset; while (1) { @@ -394,7 +404,7 @@ int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh, if (*bh) fat_brelse(sb, *bh); *bh = NULL; - if ((sector = fat_bmap(dir,offset >> SECTOR_BITS)) == -1) + if ((sector = fat_bmap(dir,offset >> sb->s_blocksize_bits)) == -1) return -1; PRINTK (("get_entry sector %d %p\n",sector,*bh)); PRINTK (("get_entry sector apres brelse\n")); @@ -406,10 +416,11 @@ int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh, continue; } PRINTK (("get_entry apres sread\n")); - *de = (struct msdos_dir_entry *) ((*bh)->b_data+(offset & - (SECTOR_SIZE-1))); - *ino = (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >> - MSDOS_DIR_BITS); + + offset &= sb->s_blocksize - 1; + *de = (struct msdos_dir_entry *) ((*bh)->b_data + offset); + *ino = (sector << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS); + return 0; } } @@ -476,7 +487,7 @@ static int raw_scan_sector(struct super_block *sb,int sector,const char *name, if (!(bh = fat_bread(sb,sector))) return -EIO; data = (struct msdos_dir_entry *) bh->b_data; - for (entry = 0; entry < MSDOS_DPS; entry++) { + for (entry = 0; entry < MSDOS_SB(sb)->dir_per_block; entry++) { /* RSS_COUNT: if (data[entry].name == name) done=true else done=false. */ if (name) { RSS_NAME @@ -488,7 +499,8 @@ static int raw_scan_sector(struct super_block *sb,int sector,const char *name, } } if (done) { - if (ino) *ino = sector*MSDOS_DPS+entry; + if (ino) + *ino = sector * MSDOS_SB(sb)->dir_per_block + entry; start = CF_LE_W(data[entry].start); if (MSDOS_SB(sb)->fat_bits == 32) { start |= (CF_LE_W(data[entry].starthi) << 16); @@ -517,9 +529,12 @@ static int raw_scan_root(struct super_block *sb,const char *name,int *number,int { int count,cluster; - for (count = 0; count < MSDOS_SB(sb)->dir_entries/MSDOS_DPS; count++) { + for (count = 0; + count < MSDOS_SB(sb)->dir_entries / MSDOS_SB(sb)->dir_per_block; + count++) { if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count, - name,number,ino,res_bh,res_de)) >= 0) return cluster; + name,number,ino,res_bh,res_de)) >= 0) + return cluster; } return -ENOENT; } @@ -570,13 +585,12 @@ static int raw_scan(struct super_block *sb, int start, const char *name, int *number, int *ino, struct buffer_head **res_bh, struct msdos_dir_entry **res_de) { - if (start) return raw_scan_nonroot - (sb,start,name,number,ino,res_bh,res_de); - else return raw_scan_root - (sb,name,number,ino,res_bh,res_de); + if (start) + return raw_scan_nonroot(sb,start,name,number,ino,res_bh,res_de); + else + return raw_scan_root(sb,name,number,ino,res_bh,res_de); } - /* * fat_parent_ino returns the inode number of the parent directory of dir. * File creation has to be deferred while fat_parent_ino is running to @@ -628,7 +642,6 @@ int fat_parent_ino(struct inode *dir,int locked) return nr; } - /* * fat_subdirs counts the number of sub-directories of dir. It can be run * on directories being created. diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c index 12dafab5e305..e23ddbca3a82 100644 --- a/fs/freevxfs/vxfs_bmap.c +++ b/fs/freevxfs/vxfs_bmap.c @@ -169,7 +169,7 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) struct vxfs_typed_dev4 *typ4 = (struct vxfs_typed_dev4 *)typ; printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); printk(KERN_INFO "block: %Ld\tsize: %Ld\tdev: %d\n", - typ4->vd4_block, typ4->vd4_size, typ4->vd4_dev); + (long long)typ4->vd4_block, (long long)typ4->vd4_size, typ4->vd4_dev); goto fail; } default: @@ -228,7 +228,7 @@ vxfs_bmap_typed(struct inode *ip, long iblock) struct vxfs_typed_dev4 *typ4 = (struct vxfs_typed_dev4 *)typ; printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); printk(KERN_INFO "block: %Ld\tsize: %Ld\tdev: %d\n", - typ4->vd4_block, typ4->vd4_size, typ4->vd4_dev); + (long long)typ4->vd4_block, (long long)typ4->vd4_size, typ4->vd4_dev); return 0; } default: diff --git a/fs/proc/generic.c b/fs/proc/generic.c index e46ef0b25fc7..fe7ce7a43d57 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -428,6 +428,7 @@ struct proc_dir_entry *proc_symlink(const char *name, ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL); if (!ent->data) { kfree(ent); + ent = NULL; goto out; } strcpy((char*)ent->data,dest); diff --git a/fs/super.c b/fs/super.c index 0bd338e7affc..66212fdf2f46 100644 --- a/fs/super.c +++ b/fs/super.c @@ -282,6 +282,24 @@ struct file_system_type *get_fs_type(const char *name) static LIST_HEAD(vfsmntlist); +static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) +{ + old_nd->dentry = mnt->mnt_mountpoint; + old_nd->mnt = mnt->mnt_parent; + mnt->mnt_parent = mnt; + mnt->mnt_mountpoint = mnt->mnt_root; + list_del_init(&mnt->mnt_child); + list_del_init(&mnt->mnt_clash); +} + +static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) +{ + mnt->mnt_parent = mntget(nd->mnt); + mnt->mnt_mountpoint = dget(nd->dentry); + list_add(&mnt->mnt_clash, &nd->dentry->d_vfsmnt); + list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); +} + /** * add_vfsmnt - add a new mount node * @nd: location of mountpoint or %NULL if we want a root node @@ -337,13 +355,12 @@ static struct vfsmount *add_vfsmnt(struct nameidata *nd, if (nd && !IS_ROOT(nd->dentry) && d_unhashed(nd->dentry)) goto fail; mnt->mnt_root = dget(root); - mnt->mnt_mountpoint = nd ? dget(nd->dentry) : dget(root); - mnt->mnt_parent = nd ? mntget(nd->mnt) : mnt; if (nd) { - list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); - list_add(&mnt->mnt_clash, &nd->dentry->d_vfsmnt); + attach_mnt(mnt, nd); } else { + mnt->mnt_mountpoint = mnt->mnt_root; + mnt->mnt_parent = mnt; INIT_LIST_HEAD(&mnt->mnt_child); INIT_LIST_HEAD(&mnt->mnt_clash); } @@ -362,12 +379,10 @@ fail: } static void move_vfsmnt(struct vfsmount *mnt, - struct dentry *mountpoint, - struct vfsmount *parent, + struct nameidata *nd, const char *dev_name) { - struct dentry *old_mountpoint; - struct vfsmount *old_parent; + struct nameidata parent_nd; char *new_devname = NULL; if (dev_name) { @@ -377,56 +392,35 @@ static void move_vfsmnt(struct vfsmount *mnt, } spin_lock(&dcache_lock); - old_mountpoint = mnt->mnt_mountpoint; - old_parent = mnt->mnt_parent; + detach_mnt(mnt, &parent_nd); + attach_mnt(mnt, nd); - /* flip names */ if (new_devname) { if (mnt->mnt_devname) kfree(mnt->mnt_devname); mnt->mnt_devname = new_devname; } - - /* flip the linkage */ - mnt->mnt_mountpoint = dget(mountpoint); - mnt->mnt_parent = parent ? mntget(parent) : mnt; - list_del(&mnt->mnt_clash); - list_del(&mnt->mnt_child); - if (parent) { - list_add(&mnt->mnt_child, &parent->mnt_mounts); - list_add(&mnt->mnt_clash, &mountpoint->d_vfsmnt); - } else { - INIT_LIST_HEAD(&mnt->mnt_child); - INIT_LIST_HEAD(&mnt->mnt_clash); - } spin_unlock(&dcache_lock); /* put the old stuff */ - dput(old_mountpoint); - if (old_parent != mnt) - mntput(old_parent); + if (parent_nd.mnt != mnt) + path_release(&parent_nd); } -/* - * Called with spinlock held, releases it. - */ -static void remove_vfsmnt(struct vfsmount *mnt) +static void kill_super(struct super_block *); + +void __mntput(struct vfsmount *mnt) { - /* First of all, remove it from all lists */ - list_del(&mnt->mnt_instances); - list_del(&mnt->mnt_clash); - list_del(&mnt->mnt_list); - list_del(&mnt->mnt_child); - spin_unlock(&dcache_lock); - /* Now we can work safely */ - if (mnt->mnt_parent != mnt) - mntput(mnt->mnt_parent); + struct super_block *sb = mnt->mnt_sb; - dput(mnt->mnt_mountpoint); dput(mnt->mnt_root); + spin_lock(&dcache_lock); + list_del(&mnt->mnt_instances); + spin_unlock(&dcache_lock); if (mnt->mnt_devname) kfree(mnt->mnt_devname); kfree(mnt); + kill_super(sb); } @@ -874,6 +868,12 @@ static void kill_super(struct super_block *sb) struct file_system_type *fs = sb->s_type; struct super_operations *sop = sb->s_op; + spin_lock(&dcache_lock); + if (!list_empty(&sb->s_mounts)) { + spin_unlock(&dcache_lock); + return; + } + spin_unlock(&dcache_lock); down_write(&sb->s_umount); sb->s_root = NULL; /* Need to clean after the sucker */ @@ -966,16 +966,6 @@ struct vfsmount *kern_mount(struct file_system_type *type) return mnt; } -/* Call only after unregister_filesystem() - it's a final cleanup */ - -void kern_umount(struct vfsmount *mnt) -{ - struct super_block *sb = mnt->mnt_sb; - spin_lock(&dcache_lock); - remove_vfsmnt(mnt); - kill_super(sb); -} - /* * Doesn't take quota and stuff into account. IOW, in some cases it will * give false negatives. The main reason why it's here is that we need @@ -991,6 +981,7 @@ int may_umount(struct vfsmount *mnt) static int do_umount(struct vfsmount *mnt, int flags) { struct super_block * sb = mnt->mnt_sb; + struct nameidata parent_nd; /* * No sense to grab the lock for this test, but test itself looks @@ -1007,7 +998,6 @@ static int do_umount(struct vfsmount *mnt, int flags) * Special case for "unmounting" root ... * we just try to remount it readonly. */ - mntput(mnt); return do_remount("/", MS_RDONLY, NULL); } @@ -1016,14 +1006,16 @@ static int do_umount(struct vfsmount *mnt, int flags) if (mnt->mnt_instances.next != mnt->mnt_instances.prev) { if (atomic_read(&mnt->mnt_count) > 2) { spin_unlock(&dcache_lock); - mntput(mnt); return -EBUSY; } if (sb->s_type->fs_flags & FS_SINGLE) put_filesystem(sb->s_type); - /* We hold two references, so mntput() is safe */ + detach_mnt(mnt, &parent_nd); + list_del(&mnt->mnt_list); + spin_unlock(&dcache_lock); mntput(mnt); - remove_vfsmnt(mnt); + if (parent_nd.mnt != mnt) + path_release(&parent_nd); return 0; } spin_unlock(&dcache_lock); @@ -1055,15 +1047,16 @@ static int do_umount(struct vfsmount *mnt, int flags) spin_lock(&dcache_lock); if (atomic_read(&mnt->mnt_count) > 2) { spin_unlock(&dcache_lock); - mntput(mnt); return -EBUSY; } /* OK, that's the point of no return */ + detach_mnt(mnt, &parent_nd); + list_del(&mnt->mnt_list); + spin_unlock(&dcache_lock); mntput(mnt); - remove_vfsmnt(mnt); - - kill_super(sb); + if (parent_nd.mnt != mnt) + path_release(&parent_nd); return 0; } @@ -1081,7 +1074,6 @@ asmlinkage long sys_umount(char * name, int flags) char *kname; int retval; - lock_kernel(); kname = getname(name); retval = PTR_ERR(kname); if (IS_ERR(kname)) @@ -1100,16 +1092,16 @@ asmlinkage long sys_umount(char * name, int flags) if (!capable(CAP_SYS_ADMIN) && current->uid!=nd.mnt->mnt_owner) goto dput_and_out; - dput(nd.dentry); - /* puts nd.mnt */ down(&mount_sem); + lock_kernel(); retval = do_umount(nd.mnt, flags); + unlock_kernel(); + path_release(&nd); up(&mount_sem); goto out; dput_and_out: path_release(&nd); out: - unlock_kernel(); return retval; } @@ -1372,8 +1364,7 @@ fs_out: fail: if (fstype->fs_flags & FS_SINGLE) put_filesystem(fstype); - if (list_empty(&sb->s_mounts)) - kill_super(sb); + kill_super(sb); goto unlock_out; } @@ -1612,8 +1603,9 @@ static void chroot_fs_refs(struct dentry *old_root, * - we don't move root/cwd if they are not at the root (reason: if something * cared enough to change them, it's probably wrong to force them elsewhere) * - it's okay to pick a root that isn't the root of a file system, e.g. - * /nfs/my_root where /nfs is the mount point. Better avoid creating - * unreachable mount points this way, though. + * /nfs/my_root where /nfs is the mount point. It must be a mountpoint, + * though, so you may need to say mount --bind /nfs/my_root /nfs/my_root + * first. */ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old) @@ -1621,7 +1613,7 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old) struct dentry *root; struct vfsmount *root_mnt; struct vfsmount *tmp; - struct nameidata new_nd, old_nd; + struct nameidata new_nd, old_nd, parent_nd, root_parent; char *name; int error; @@ -1669,6 +1661,10 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old) if (new_nd.mnt == root_mnt || old_nd.mnt == root_mnt) goto out2; /* loop */ error = -EINVAL; + if (root_mnt->mnt_root != root) + goto out2; + if (new_nd.mnt->mnt_root != new_nd.dentry) + goto out2; /* not a mountpoint */ tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */ spin_lock(&dcache_lock); if (tmp != new_nd.mnt) { @@ -1683,12 +1679,18 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old) goto out3; } else if (!is_subdir(old_nd.dentry, new_nd.dentry)) goto out3; + detach_mnt(new_nd.mnt, &parent_nd); + detach_mnt(root_mnt, &root_parent); + attach_mnt(root_mnt, &old_nd); + if (root_parent.mnt != root_mnt) + attach_mnt(new_nd.mnt, &root_parent); spin_unlock(&dcache_lock); - - move_vfsmnt(new_nd.mnt, new_nd.dentry, NULL, NULL); - move_vfsmnt(root_mnt, old_nd.dentry, old_nd.mnt, NULL); chroot_fs_refs(root,root_mnt,new_nd.dentry,new_nd.mnt); error = 0; + if (root_parent.mnt != root_mnt) + path_release(&root_parent); + if (parent_nd.mnt != new_nd.mnt) + path_release(&parent_nd); out2: up(&old_nd.dentry->d_inode->i_zombie); up(&mount_sem); @@ -1723,10 +1725,9 @@ int __init change_root(kdev_t new_root_dev,const char *put_old) if (!error) { if (devfs_nd.mnt->mnt_sb->s_magic == DEVFS_SUPER_MAGIC && devfs_nd.dentry == devfs_nd.mnt->mnt_root) { - dput(devfs_nd.dentry); down(&mount_sem); - /* puts devfs_nd.mnt */ do_umount(devfs_nd.mnt, 0); + path_release(&devfs_nd); up(&mount_sem); } else path_release(&devfs_nd); @@ -1753,6 +1754,7 @@ int __init change_root(kdev_t new_root_dev,const char *put_old) printk(KERN_NOTICE "Trying to unmount old root ... "); if (!blivet) { blivet = do_umount(old_rootmnt, 0); + mntput(old_rootmnt); if (!blivet) { ioctl_by_bdev(ramdisk, BLKFLSBUF, 0); printk("okay\n"); @@ -1765,7 +1767,7 @@ int __init change_root(kdev_t new_root_dev,const char *put_old) return error; } /* FIXME: we should hold i_zombie on nd.dentry */ - move_vfsmnt(old_rootmnt, nd.dentry, nd.mnt, "/dev/root.old"); + move_vfsmnt(old_rootmnt, &nd, "/dev/root.old"); mntput(old_rootmnt); path_release(&nd); return 0; diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h index 78e0f58c39b2..11935eaddac2 100644 --- a/include/asm-alpha/bitops.h +++ b/include/asm-alpha/bitops.h @@ -46,7 +46,7 @@ __set_bit(unsigned long nr, volatile void * addr) { int *m = ((int *) addr) + (nr >> 5); - *m |= 1UL << (nr & 31); + *m |= 1 << (nr & 31); } #define smp_mb__before_clear_bit() smp_mb() @@ -70,6 +70,17 @@ clear_bit(unsigned long nr, volatile void * addr) :"Ir" (~(1UL << (nr & 31))), "m" (*m)); } +/* + * WARNING: non atomic version. + */ +static __inline__ void +__change_bit(unsigned long nr, volatile void * addr) +{ + int *m = ((int *) addr) + (nr >> 5); + + *m ^= 1 << (nr & 31); +} + extern __inline__ void change_bit(unsigned long nr, volatile void * addr) { @@ -170,6 +181,20 @@ __test_and_clear_bit(unsigned long nr, volatile void * addr) return (old & mask) != 0; } +/* + * WARNING: non atomic version. + */ +static __inline__ int +__test_and_change_bit(unsigned long nr, volatile void * addr) +{ + unsigned long mask = 1 << (nr & 0x1f); + int *m = ((int *) addr) + (nr >> 5); + int old = *m; + + *m = old ^ mask; + return (old & mask) != 0; +} + extern __inline__ int test_and_change_bit(unsigned long nr, volatile void * addr) { diff --git a/include/asm-alpha/core_tsunami.h b/include/asm-alpha/core_tsunami.h index 00d20922b46d..691d164b2b6d 100644 --- a/include/asm-alpha/core_tsunami.h +++ b/include/asm-alpha/core_tsunami.h @@ -275,6 +275,9 @@ union TPchipPERRMASK { /* The IO address space is larger than 0xffff */ #define TSUNAMI_IO_SPACE (TSUNAMI_CONF(0) - TSUNAMI_IO(0)) +/* Offset between ram physical addresses and pci64 DAC bus addresses */ +#define TSUNAMI_DAC_OFFSET (1UL << 40) + /* * Data structure for handling TSUNAMI machine checks: */ diff --git a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h new file mode 100644 index 000000000000..8abf68ea7080 --- /dev/null +++ b/include/asm-alpha/mmzone.h @@ -0,0 +1,127 @@ +/* + * Written by Kanoj Sarcar (kanoj@sgi.com) Aug 99 + * Adapted for the alpha wildfire architecture Jan 2001. + */ +#ifndef _ASM_MMZONE_H_ +#define _ASM_MMZONE_H_ + +#include <linux/config.h> +#ifdef CONFIG_NUMA_SCHED +#include <linux/numa_sched.h> +#endif +#ifdef NOTYET +#include <asm/sn/types.h> +#include <asm/sn/addrs.h> +#include <asm/sn/arch.h> +#include <asm/sn/klkernvars.h> +#endif /* NOTYET */ + +typedef struct plat_pglist_data { + pg_data_t gendata; +#ifdef NOTYET + kern_vars_t kern_vars; +#endif +#if defined(CONFIG_NUMA) && defined(CONFIG_NUMA_SCHED) + struct numa_schedule_data schedule_data; +#endif +} plat_pg_data_t; + +struct bootmem_data_t; /* stupid forward decl. */ + +/* + * Following are macros that are specific to this numa platform. + */ + +extern plat_pg_data_t *plat_node_data[]; + +#ifdef CONFIG_ALPHA_WILDFIRE +# define ALPHA_PA_TO_NID(pa) ((pa) >> 36) /* 16 nodes max due 43bit kseg */ +#define NODE_MAX_MEM_SIZE (64L * 1024L * 1024L * 1024L) /* 64 GB */ +#define MAX_NUMNODES WILDFIRE_MAX_QBB +#else +# define ALPHA_PA_TO_NID(pa) (0) +#define NODE_MAX_MEM_SIZE (~0UL) +#define MAX_NUMNODES 1 +#endif + +#define PHYSADDR_TO_NID(pa) ALPHA_PA_TO_NID(pa) +#define PLAT_NODE_DATA(n) (plat_node_data[(n)]) +#define PLAT_NODE_DATA_STARTNR(n) \ + (PLAT_NODE_DATA(n)->gendata.node_start_mapnr) +#define PLAT_NODE_DATA_SIZE(n) (PLAT_NODE_DATA(n)->gendata.node_size) + +#if 1 +#define PLAT_NODE_DATA_LOCALNR(p, n) \ + (((p) - PLAT_NODE_DATA(n)->gendata.node_start_paddr) >> PAGE_SHIFT) +#else +static inline unsigned long +PLAT_NODE_DATA_LOCALNR(unsigned long p, int n) +{ + unsigned long temp; + temp = p - PLAT_NODE_DATA(n)->gendata.node_start_paddr; + return (temp >> PAGE_SHIFT); +} +#endif + +#ifdef CONFIG_DISCONTIGMEM + +/* + * Following are macros that each numa implmentation must define. + */ + +/* + * Given a kernel address, find the home node of the underlying memory. + */ +#define KVADDR_TO_NID(kaddr) PHYSADDR_TO_NID(__pa(kaddr)) + +/* + * Return a pointer to the node data for node n. + */ +#define NODE_DATA(n) (&((PLAT_NODE_DATA(n))->gendata)) + +/* + * NODE_MEM_MAP gives the kaddr for the mem_map of the node. + */ +#define NODE_MEM_MAP(nid) (NODE_DATA(nid)->node_mem_map) + +/* + * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory + * and returns the the mem_map of that node. + */ +#define ADDR_TO_MAPBASE(kaddr) \ + NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr))) + +/* + * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory + * and returns the kaddr corresponding to first physical page in the + * node's mem_map. + */ +#define LOCAL_BASE_ADDR(kaddr) ((unsigned long)__va(NODE_DATA(KVADDR_TO_NID(kaddr))->node_start_paddr)) + +#define LOCAL_MAP_NR(kvaddr) \ + (((unsigned long)(kvaddr)-LOCAL_BASE_ADDR(kvaddr)) >> PAGE_SHIFT) + +#define kern_addr_valid(kaddr) test_bit(LOCAL_MAP_NR(kaddr), \ + NODE_DATA(KVADDR_TO_NID(kaddr))->valid_addr_bitmap) + +#define virt_to_page(kaddr) (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr)) +#define VALID_PAGE(page) (((page) - mem_map) < max_mapnr) + +#ifdef CONFIG_NUMA +#ifdef CONFIG_NUMA_SCHED +#define NODE_SCHEDULE_DATA(nid) (&((PLAT_NODE_DATA(nid))->schedule_data)) +#endif + +#ifdef CONFIG_ALPHA_WILDFIRE +/* With wildfire assume 4 CPUs per node */ +#define cputonode(cpu) ((cpu) >> 2) +#else +#define cputonode(cpu) 0 +#endif /* CONFIG_ALPHA_WILDFIRE */ + +#define numa_node_id() cputonode(smp_processor_id()) +#endif /* CONFIG_NUMA */ + +#endif /* CONFIG_DISCONTIGMEM */ + +#endif /* _ASM_MMZONE_H_ */ diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h index fbae9324fd6d..f403fa813f3f 100644 --- a/include/asm-alpha/page.h +++ b/include/asm-alpha/page.h @@ -1,6 +1,8 @@ #ifndef _ALPHA_PAGE_H #define _ALPHA_PAGE_H +#include <asm/pal.h> + /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 13 #define PAGE_SIZE (1UL << PAGE_SHIFT) @@ -33,6 +35,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define pgprot_val(x) ((x).pgprot) #define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) #define __pgd(x) ((pgd_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } ) @@ -56,7 +59,11 @@ typedef unsigned long pgprot_t; #endif /* STRICT_MM_TYPECHECKS */ -#define BUG() __asm__ __volatile__("call_pal 129 # bugchk") +#define BUG() \ +do { \ + printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + __asm__ __volatile__("call_pal %0 # bugchk" : : "i" (PAL_bugchk)); \ +} while (0) #define PAGE_BUG(page) BUG() /* Pure 2^n version of get_order */ @@ -86,8 +93,10 @@ extern __inline__ int get_order(unsigned long size) #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) +#ifndef CONFIG_DISCONTIGMEM #define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT)) -#define VALID_PAGE(page) ((page - mem_map) < max_mapnr) +#define VALID_PAGE(page) (((page) - mem_map) < max_mapnr) +#endif /* CONFIG_DISCONTIGMEM */ #endif /* __KERNEL__ */ diff --git a/include/asm-alpha/pgalloc.h b/include/asm-alpha/pgalloc.h index 5b26f301643e..af01b68cd4a3 100644 --- a/include/asm-alpha/pgalloc.h +++ b/include/asm-alpha/pgalloc.h @@ -229,6 +229,7 @@ extern void flush_tlb_range(struct mm_struct *, unsigned long, unsigned long); #ifndef CONFIG_SMP extern struct pgtable_cache_struct { unsigned long *pgd_cache; + unsigned long *pmd_cache; unsigned long *pte_cache; unsigned long pgtable_cache_sz; } quicklists; @@ -237,7 +238,7 @@ extern struct pgtable_cache_struct { #define quicklists cpu_data[smp_processor_id()] #endif #define pgd_quicklist (quicklists.pgd_cache) -#define pmd_quicklist ((unsigned long *)0) +#define pmd_quicklist (quicklists.pmd_cache) #define pte_quicklist (quicklists.pte_cache) #define pgtable_cache_size (quicklists.pgtable_cache_sz) @@ -252,7 +253,7 @@ static inline pgd_t *get_pgd_fast(void) if ((ret = pgd_quicklist) != NULL) { pgd_quicklist = (unsigned long *)(*ret); - ret[0] = ret[1]; + ret[0] = 0; pgtable_cache_size--; } else ret = (unsigned long *)get_pgd_slow(); @@ -285,7 +286,7 @@ static inline pmd_t *pmd_alloc_one_fast(struct mm_struct *mm, unsigned long addr if ((ret = (unsigned long *)pte_quicklist) != NULL) { pte_quicklist = (unsigned long *)(*ret); - ret[0] = ret[1]; + ret[0] = 0; pgtable_cache_size--; } return (pmd_t *)ret; @@ -317,7 +318,7 @@ static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long addr if ((ret = (unsigned long *)pte_quicklist) != NULL) { pte_quicklist = (unsigned long *)(*ret); - ret[0] = ret[1]; + ret[0] = 0; pgtable_cache_size--; } return (pte_t *)ret; diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index 54341fff11e9..259eaa77b0a9 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -9,6 +9,7 @@ * in <asm/page.h> (currently 8192). */ #include <linux/config.h> +#include <linux/mmzone.h> #include <asm/page.h> #include <asm/processor.h> /* For TASK_SIZE */ @@ -189,6 +190,15 @@ extern unsigned long __zero_page(void); * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. */ +#ifndef CONFIG_DISCONTIGMEM +#define PAGE_TO_PA(page) ((page - mem_map) << PAGE_SHIFT) +#else +#define PAGE_TO_PA(page) \ + ((((page)-(page)->zone->zone_mem_map) << PAGE_SHIFT) \ + + (page)->zone->zone_start_paddr) +#endif + +#ifndef CONFIG_DISCONTIGMEM #define mk_pte(page, pgprot) \ ({ \ pte_t pte; \ @@ -197,6 +207,19 @@ extern unsigned long __zero_page(void); pgprot_val(pgprot); \ pte; \ }) +#else +#define mk_pte(page, pgprot) \ +({ \ + pte_t pte; \ + unsigned long pfn; \ + \ + pfn = ((unsigned long)((page)-(page)->zone->zone_mem_map)) << 32; \ + pfn += (page)->zone->zone_start_paddr << (32-PAGE_SHIFT); \ + pte_val(pte) = pfn | pgprot_val(pgprot); \ + \ + pte; \ +}) +#endif extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) { pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpage) << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; } @@ -210,7 +233,20 @@ extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep) extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp) { pgd_val(*pgdp) = _PAGE_TABLE | ((((unsigned long) pmdp) - PAGE_OFFSET) << (32-PAGE_SHIFT)); } +#ifndef CONFIG_DISCONTIGMEM #define pte_page(x) (mem_map+(unsigned long)((pte_val(x) >> 32))) +#else +#define pte_page(x) \ +({ \ + unsigned long kvirt; \ + struct page * __xx; \ + \ + kvirt = (unsigned long)__va(pte_val(x) >> (32-PAGE_SHIFT)); \ + __xx = virt_to_page(kvirt); \ + \ + __xx; \ +}) +#endif extern inline unsigned long pmd_page(pmd_t pmd) { return PAGE_OFFSET + ((pmd_val(pmd) & _PFN_MASK) >> (32-PAGE_SHIFT)); } @@ -303,7 +339,10 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ #define PageSkip(page) (0) + +#ifndef CONFIG_DISCONTIGMEM #define kern_addr_valid(addr) (1) +#endif #define io_remap_page_range(start, busaddr, size, prot) \ remap_page_range(start, virt_to_phys(__ioremap(busaddr)), size, prot) diff --git a/include/asm-alpha/smp.h b/include/asm-alpha/smp.h index 2cc52a7e0578..6c9edc2f61f3 100644 --- a/include/asm-alpha/smp.h +++ b/include/asm-alpha/smp.h @@ -29,6 +29,7 @@ struct cpuinfo_alpha { int need_new_asn; int asn_lock; unsigned long *pgd_cache; + unsigned long *pmd_cache; unsigned long *pte_cache; unsigned long pgtable_cache_sz; unsigned long ipi_count; diff --git a/include/asm-alpha/spinlock.h b/include/asm-alpha/spinlock.h index e1d809880901..bf560fde0a35 100644 --- a/include/asm-alpha/spinlock.h +++ b/include/asm-alpha/spinlock.h @@ -96,6 +96,8 @@ typedef struct { #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 } +#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) + #if DEBUG_RWLOCK extern void write_lock(rwlock_t * lock); extern void read_lock(rwlock_t * lock); diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h index 3a8c9385dd49..6de660cabfe1 100644 --- a/include/asm-alpha/system.h +++ b/include/asm-alpha/system.h @@ -35,6 +35,18 @@ #define START_ADDR (PAGE_OFFSET+KERNEL_START_PHYS+0x10000) +/* + * This is setup by the secondary bootstrap loader. Because + * the zero page is zeroed out as soon as the vm system is + * initialized, we need to copy things out into a more permanent + * place. + */ +#define PARAM ZERO_PGE +#define COMMAND_LINE ((char*)(PARAM + 0x0000)) +#define COMMAND_LINE_SIZE 256 +#define INITRD_START (*(unsigned long *) (PARAM+0x100)) +#define INITRD_SIZE (*(unsigned long *) (PARAM+0x108)) + #ifndef __ASSEMBLY__ #include <linux/kernel.h> diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h index 00716e836964..a3063cacc919 100644 --- a/include/asm-i386/bitops.h +++ b/include/asm-i386/bitops.h @@ -79,6 +79,23 @@ static __inline__ void clear_bit(int nr, volatile void * addr) #define smp_mb__after_clear_bit() barrier() /** + * __change_bit - Toggle a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +static __inline__ void __change_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( + "btcl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** * change_bit - Toggle a bit in memory * @nr: Bit to clear * @addr: Address to start counting from @@ -173,6 +190,18 @@ static __inline__ int __test_and_clear_bit(int nr, volatile void * addr) return oldbit; } +/* WARNING: non atomic and it can be reordered! */ +static __inline__ int __test_and_change_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( + "btcl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + /** * test_and_change_bit - Change a bit and return its new value * @nr: Bit to set diff --git a/include/asm-ppc/bootinfo.h b/include/asm-ppc/bootinfo.h index 2ce574d0b228..ce7650611398 100644 --- a/include/asm-ppc/bootinfo.h +++ b/include/asm-ppc/bootinfo.h @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.bootinfo.h 1.5 05/17/01 18:14:24 cort + * BK Id: SCCS/s.bootinfo.h 1.7 05/23/01 00:38:42 cort */ /* * Non-machine dependent bootinfo structure. Basic idea @@ -8,7 +8,6 @@ * Copyright (C) 1999 Cort Dougan <cort@ppc.kernel.org> */ - #ifdef __KERNEL__ #ifndef _PPC_BOOTINFO_H #define _PPC_BOOTINFO_H @@ -35,6 +34,27 @@ struct bi_record { #endif /* CONFIG_APUS */ -#endif /* _PPC_BOOTINFO_H */ +/* + * prom_init() is called very early on, before the kernel text + * and data have been mapped to KERNELBASE. At this point the code + * is running at whatever address it has been loaded at, so + * references to extern and static variables must be relocated + * explicitly. The procedure reloc_offset() returns the address + * we're currently running at minus the address we were linked at. + * (Note that strings count as static variables.) + * + * Because OF may have mapped I/O devices into the area starting at + * KERNELBASE, particularly on CHRP machines, we can't safely call + * OF once the kernel has been mapped to KERNELBASE. Therefore all + * OF calls should be done within prom_init(), and prom_init() + * and all routines called within it must be careful to relocate + * references as necessary. + */ +#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) +#define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) - offset)) +#define RELOC(x) (*PTRRELOC(&(x))) +#endif /* _PPC_BOOTINFO_H */ #endif /* __KERNEL__ */ + + diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index fdc154d70687..3bd0b2a7e345 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -554,10 +554,10 @@ n: #define SR15 15 #ifndef __ASSEMBLY__ -#ifndef CONFIG_MACH_SPECIFIC +#if defined(CONFIG_ALL_PPC) extern int _machine; extern int have_of; -#endif /* CONFIG_MACH_SPECIFIC */ +#endif /* CONFIG_ALL_PPC */ /* what kind of prep workstation we are */ extern int _prep_type; @@ -681,29 +681,24 @@ void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); #endif /* ndef ASSEMBLY*/ -#ifdef CONFIG_MACH_SPECIFIC -#if defined(CONFIG_8xx) -#define _machine _MACH_8xx -#define have_of 0 +#ifndef CONFIG_ALL_PPC +#if defined(CONFIG_APUS) +#define _machine _MACH_apus +#elif defined(CONFIG_GEMINI) +#define _machine _MACH_gemini #elif defined(CONFIG_OAK) #define _machine _MACH_oak -#define have_of 0 #elif defined(CONFIG_WALNUT) #define _machine _MACH_walnut -#define have_of 0 -#elif defined(CONFIG_APUS) -#define _machine _MACH_apus -#define have_of 0 -#elif defined(CONFIG_GEMINI) -#define _machine _MACH_gemini -#define have_of 0 +#elif defined(CONFIG_8xx) +#define _machine _MACH_8xx #elif defined(CONFIG_8260) #define _machine _MACH_8260 -#define have_of 0 #else #error "Machine not defined correctly" #endif -#endif /* CONFIG_MACH_SPECIFIC */ +#define have_of 0 +#endif /* !CONFIG_ALL_PPC */ #endif /* __ASM_PPC_PROCESSOR_H */ #endif /* __KERNEL__ */ diff --git a/include/linux/fs.h b/include/linux/fs.h index e2ce4ab43241..8db1b9fd31d8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -908,10 +908,10 @@ do { \ extern int register_filesystem(struct file_system_type *); extern int unregister_filesystem(struct file_system_type *); extern struct vfsmount *kern_mount(struct file_system_type *); -extern void kern_umount(struct vfsmount *); extern int may_umount(struct vfsmount *); extern long do_mount(char *, char *, char *, unsigned long, void *); +#define kern_umount mntput extern int vfs_statfs(struct super_block *, struct statfs *); diff --git a/include/linux/mm.h b/include/linux/mm.h index 26c72c982809..12edcb46cc8f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -480,7 +480,6 @@ extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int); #else #define __GFP_HIGHMEM 0x0 /* noop */ #endif -#define __GFP_VM 0x20 #define GFP_BUFFER (__GFP_HIGH | __GFP_WAIT) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 7e4e9f98e85f..0f65115f4500 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -16,7 +16,7 @@ typedef struct free_area_struct { struct list_head free_list; - unsigned int *map; + unsigned long *map; } free_area_t; struct pglist_data; @@ -34,7 +34,6 @@ typedef struct zone_struct { * Commonly accessed fields: */ spinlock_t lock; - unsigned long offset; unsigned long free_pages; unsigned long inactive_clean_pages; unsigned long inactive_dirty_pages; @@ -47,17 +46,18 @@ typedef struct zone_struct { free_area_t free_area[MAX_ORDER]; /* - * rarely used fields: - */ - char *name; - unsigned long size; - /* * Discontig memory support fields. */ struct pglist_data *zone_pgdat; + struct page *zone_mem_map; unsigned long zone_start_paddr; unsigned long zone_start_mapnr; - struct page *zone_mem_map; + + /* + * rarely used fields: + */ + char *name; + unsigned long size; } zone_t; #define ZONE_DMA 0 @@ -81,7 +81,7 @@ typedef struct zonelist_struct { int gfp_mask; } zonelist_t; -#define NR_GFPINDEX 0x100 +#define NR_GFPINDEX 0x20 /* * The pg_data_t structure is used in machines with CONFIG_DISCONTIGMEM @@ -112,8 +112,7 @@ extern int numnodes; extern pg_data_t *pgdat_list; #define memclass(pgzone, tzone) (((pgzone)->zone_pgdat == (tzone)->zone_pgdat) \ - && (((pgzone) - (pgzone)->zone_pgdat->node_zones) <= \ - ((tzone) - (pgzone)->zone_pgdat->node_zones))) + && ((pgzone) <= (tzone))) /* * The following two are not meant for general usage. They are here as diff --git a/include/linux/mount.h b/include/linux/mount.h index a4fc9a05c484..3b41b99cf1aa 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -39,11 +39,13 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt) return mnt; } +extern void __mntput(struct vfsmount *mnt); + static inline void mntput(struct vfsmount *mnt) { if (mnt) { if (atomic_dec_and_test(&mnt->mnt_count)) - BUG(); + __mntput(mnt); } } diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index 855c4d20c12a..e93201f56b10 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -76,6 +76,11 @@ #define EOF_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? EOF_FAT32 : \ MSDOS_SB(s)->fat_bits == 16 ? EOF_FAT16 : EOF_FAT12) +#define FAT_FSINFO_SIG1 0x41615252 +#define FAT_FSINFO_SIG2 0x61417272 +#define IS_FSINFO(x) (CF_LE_L((x)->signature1) == FAT_FSINFO_SIG1 \ + && CF_LE_L((x)->signature2) == FAT_FSINFO_SIG2) + /* * Inode flags */ @@ -127,8 +132,9 @@ struct fat_boot_sector { }; struct fat_boot_fsinfo { - __u32 reserved1; /* Nothing as far as I can tell */ - __u32 signature; /* 0x61417272L */ + __u32 signature1; /* 0x61417272L */ + __u32 reserved1[120]; /* Nothing as far as I can tell */ + __u32 signature2; /* 0x61417272L */ __u32 free_clusters; /* Free cluster count. -1 if unknown */ __u32 next_cluster; /* Most recently allocated cluster. * Unused under Linux. */ @@ -208,7 +214,7 @@ static __inline__ int fat_get_entry(struct inode *dir,loff_t *pos, { /* Fast stuff first */ if (*bh && *de && - (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_DPB-1) { + (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) { *pos += sizeof(struct msdos_dir_entry); (*de)++; (*ino)++; diff --git a/include/linux/msdos_fs_sb.h b/include/linux/msdos_fs_sb.h index 6c86a6a2e204..0421836a2059 100644 --- a/include/linux/msdos_fs_sb.h +++ b/include/linux/msdos_fs_sb.h @@ -44,7 +44,7 @@ struct msdos_sb_info { unsigned long data_start; /* first data sector */ unsigned long clusters; /* number of clusters */ unsigned long root_cluster; /* first cluster of the root directory */ - unsigned long fsinfo_offset; /* FAT32 fsinfo offset from start of disk */ + unsigned long fsinfo_sector; /* FAT32 fsinfo offset from start of disk */ wait_queue_head_t fat_wait; struct semaphore fat_lock; int prev_free; /* previously returned free cluster number */ @@ -54,7 +54,9 @@ struct msdos_sb_info { struct nls_table *nls_io; /* Charset used for input and display */ struct cvf_format* cvf_format; void *dir_ops; /* Opaque; default directory operations */ - void *private_data; + void *private_data; + int dir_per_block; /* dir entries per block */ + int dir_per_block_bits; /* log2(dir_per_block) */ }; #endif diff --git a/include/linux/swap.h b/include/linux/swap.h index 1ad8d5a72794..912586ea18dc 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -64,9 +64,9 @@ struct swap_info_struct { }; extern int nr_swap_pages; -FASTCALL(unsigned int nr_free_pages(void)); -FASTCALL(unsigned int nr_inactive_clean_pages(void)); -FASTCALL(unsigned int nr_free_buffer_pages(void)); +extern unsigned int nr_free_pages(void); +extern unsigned int nr_inactive_clean_pages(void); +extern unsigned int nr_free_buffer_pages(void); extern int nr_active_pages; extern int nr_inactive_dirty_pages; extern atomic_t nr_async_pages; diff --git a/include/net/syncppp.h b/include/net/syncppp.h index 350597961d5f..df5b0aa30010 100644 --- a/include/net/syncppp.h +++ b/include/net/syncppp.h @@ -94,5 +94,7 @@ int sppp_close (struct net_device *dev); #define SPPPIOCCISCO (SIOCDEVPRIVATE) #define SPPPIOCPPP (SIOCDEVPRIVATE+1) #define SPPPIOCDEBUG (SIOCDEVPRIVATE+2) +#define SPPPIOCSFLAGS (SIOCDEVPRIVATE+3) +#define SPPPIOCGFLAGS (SIOCDEVPRIVATE+4) #endif /* _SYNCPPP_H_ */ diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 22a048e6ada9..d1602d8d16f9 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -98,6 +98,8 @@ EXPORT_SYMBOL(__free_pages); EXPORT_SYMBOL(free_pages); #ifndef CONFIG_DISCONTIGMEM EXPORT_SYMBOL(contig_page_data); +#else +EXPORT_SYMBOL(alloc_pages); #endif EXPORT_SYMBOL(num_physpages); EXPORT_SYMBOL(kmem_find_general_cachep); @@ -320,7 +322,7 @@ EXPORT_SYMBOL(console_loglevel); EXPORT_SYMBOL(register_filesystem); EXPORT_SYMBOL(unregister_filesystem); EXPORT_SYMBOL(kern_mount); -EXPORT_SYMBOL(kern_umount); +EXPORT_SYMBOL(__mntput); EXPORT_SYMBOL(may_umount); /* executable format registration */ diff --git a/mm/bootmem.c b/mm/bootmem.c index 0870a25015ea..fc0fd30f2067 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -83,6 +83,14 @@ static void __init reserve_bootmem_core(bootmem_data_t *bdata, unsigned long add if (!size) BUG(); + if (sidx < 0) + BUG(); + if (eidx < 0) + BUG(); + if (sidx >= eidx) + BUG(); + if ((addr >> PAGE_SHIFT) >= bdata->node_low_pfn) + BUG(); if (end > bdata->node_low_pfn) BUG(); for (i = sidx; i < eidx; i++) @@ -143,6 +151,9 @@ static void * __init __alloc_bootmem_core (bootmem_data_t *bdata, if (!size) BUG(); + if (align & (align-1)) + BUG(); + /* * We try to allocate bootmem pages above 'goal' * first, then we try to allocate lower pages. diff --git a/mm/mmap.c b/mm/mmap.c index bc5c71b45dfe..6f539de6dce2 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -54,7 +54,7 @@ int vm_enough_memory(long pages) * of num_physpages for safety margin. */ - long free; + unsigned long free; /* Sometimes we want to use more memory than we have. */ if (sysctl_overcommit_memory) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 822f5fc3f7e6..7f02c56e75ec 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -53,7 +53,7 @@ struct list_head inactive_dirty_list; /* * Temporary debugging check. */ -#define BAD_RANGE(zone,x) (((zone) != (x)->zone) || (((x)-mem_map) < (zone)->offset) || (((x)-mem_map) >= (zone)->offset+(zone)->size)) +#define BAD_RANGE(zone,x) (((zone) != (x)->zone) || (((x)-mem_map) < (zone)->zone_start_mapnr) || (((x)-mem_map) >= (zone)->zone_start_mapnr+(zone)->size)) /* * Buddy system. Hairy. You really aren't expected to understand this @@ -94,7 +94,7 @@ static void __free_pages_ok (struct page *page, unsigned long order) zone = page->zone; mask = (~0UL) << order; - base = mem_map + zone->offset; + base = zone->zone_mem_map; page_idx = page - base; if (page_idx & ~mask) BUG(); @@ -111,7 +111,7 @@ static void __free_pages_ok (struct page *page, unsigned long order) if (area >= zone->free_area + MAX_ORDER) BUG(); - if (!test_and_change_bit(index, area->map)) + if (!__test_and_change_bit(index, area->map)) /* * the buddy page is still allocated. */ @@ -146,7 +146,7 @@ static void __free_pages_ok (struct page *page, unsigned long order) } #define MARK_USED(index, order, area) \ - change_bit((index) >> (1+(order)), (area)->map) + __change_bit((index) >> (1+(order)), (area)->map) static inline struct page * expand (zone_t *zone, struct page *page, unsigned long index, int low, int high, free_area_t * area) @@ -190,8 +190,9 @@ static struct page * rmqueue(zone_t *zone, unsigned long order) if (BAD_RANGE(zone,page)) BUG(); memlist_del(curr); - index = (page - mem_map) - zone->offset; - MARK_USED(index, curr_order, area); + index = page - zone->zone_mem_map; + if (curr_order != MAX_ORDER-1) + MARK_USED(index, curr_order, area); zone->free_pages -= 1 << order; page = expand(zone, page, index, order, curr_order, area); @@ -743,7 +744,10 @@ void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap, unsigned long i, j; unsigned long map_size; unsigned long totalpages, offset, realtotalpages; - unsigned int cumulative = 0; + const unsigned long zone_required_alignment = 1UL << (MAX_ORDER-1); + + if (zone_start_paddr & ~PAGE_MASK) + BUG(); totalpages = 0; for (i = 0; i < MAX_NR_ZONES; i++) { @@ -812,8 +816,6 @@ void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap, if (!size) continue; - zone->offset = offset; - cumulative += size; mask = (realsize / zone_balance_ratio[j]); if (mask < zone_balance_min[j]) mask = zone_balance_min[j]; @@ -840,28 +842,34 @@ void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap, zone->zone_start_mapnr = offset; zone->zone_start_paddr = zone_start_paddr; + if ((zone_start_paddr >> PAGE_SHIFT) & (zone_required_alignment-1)) + printk("BUG: wrong zone alignment, it will crash\n"); + for (i = 0; i < size; i++) { struct page *page = mem_map + offset + i; page->zone = zone; - if (j != ZONE_HIGHMEM) { + if (j != ZONE_HIGHMEM) page->virtual = __va(zone_start_paddr); - zone_start_paddr += PAGE_SIZE; - } + zone_start_paddr += PAGE_SIZE; } offset += size; mask = -1; - for (i = 0; i < MAX_ORDER; i++) { + for (i = 0; ; i++) { unsigned long bitmap_size; memlist_init(&zone->free_area[i].free_list); + if (i == MAX_ORDER-1) { + zone->free_area[i].map = NULL; + break; + } mask += mask; size = (size + ~mask) & mask; - bitmap_size = size >> i; + bitmap_size = size >> (i+1); bitmap_size = (bitmap_size + 7) >> 3; bitmap_size = LONG_ALIGN(bitmap_size); zone->free_area[i].map = - (unsigned int *) alloc_bootmem_node(pgdat, bitmap_size); + (unsigned long *) alloc_bootmem_node(pgdat, bitmap_size); } } build_zonelists(pgdat); diff --git a/mm/swap_state.c b/mm/swap_state.c index bb786975a909..c0adb051bd4f 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -189,7 +189,6 @@ struct page * lookup_swap_cache(swp_entry_t entry) struct page * read_swap_cache_async(swp_entry_t entry) { struct page *found_page = 0, *new_page; - unsigned long new_page_addr; /* * Make sure the swap entry is still in use. @@ -203,10 +202,9 @@ struct page * read_swap_cache_async(swp_entry_t entry) if (found_page) goto out_free_swap; - new_page_addr = __get_free_page(GFP_USER); - if (!new_page_addr) + new_page = alloc_page(GFP_USER); + if (!new_page) goto out_free_swap; /* Out of memory */ - new_page = virt_to_page(new_page_addr); /* * Check the swap cache again, in case we stalled above. @@ -217,7 +215,8 @@ struct page * read_swap_cache_async(swp_entry_t entry) /* * Add it to the swap cache and read its contents. */ - lock_page(new_page); + if (TryLockPage(new_page)) + BUG(); add_to_swap_cache(new_page, entry); rw_swap_page(READ, new_page); return new_page; diff --git a/mm/vmalloc.c b/mm/vmalloc.c index dbb3f6fd8a85..b9ad759fa27c 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -182,7 +182,7 @@ struct vm_struct * get_vm_area(unsigned long size, unsigned long flags) for (p = &vmlist; (tmp = *p) ; p = &tmp->next) { if ((size + addr) < addr) goto out; - if (size + addr < (unsigned long) tmp->addr) + if (size + addr <= (unsigned long) tmp->addr) break; addr = tmp->size + (unsigned long) tmp->addr; if (addr > VMALLOC_END-size) diff --git a/mm/vmscan.c b/mm/vmscan.c index 73f7dc4108bd..158218798dd3 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -923,8 +923,7 @@ int kswapd(void *unused) { struct task_struct *tsk = current; - tsk->session = 1; - tsk->pgrp = 1; + daemonize(); strcpy(tsk->comm, "kswapd"); sigfillset(&tsk->blocked); @@ -1028,8 +1027,7 @@ int kreclaimd(void *unused) struct task_struct *tsk = current; pg_data_t *pgdat; - tsk->session = 1; - tsk->pgrp = 1; + daemonize(); strcpy(tsk->comm, "kreclaimd"); sigfillset(&tsk->blocked); current->flags |= PF_MEMALLOC; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index cf01c76e7d15..a6ea0387de07 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -1,7 +1,7 @@ /* * Linux NET3: IP/IP protocol decoder. * - * Version: $Id: ipip.c,v 1.45 2001/04/19 22:32:55 davem Exp $ + * Version: $Id: ipip.c,v 1.46 2001/05/17 04:12:18 davem Exp $ * * Authors: * Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index c6423f024056..7277b0ac7477 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.229 2001/05/13 18:14:46 davem Exp $ + * Version: $Id: tcp_input.c,v 1.231 2001/05/22 05:15:16 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -3711,8 +3711,12 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, queued = tcp_rcv_synsent_state_process(sk, skb, th, len); if (queued >= 0) return queued; - queued = 0; - goto step6; + + /* Do step6 onward by hand. */ + tcp_urg(sk, skb, th); + __kfree_skb(skb); + tcp_data_snd_check(sk); + return 0; } if (tcp_fast_parse_options(skb, th, tp) && tp->saw_tstamp && @@ -3853,7 +3857,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } else goto discard; -step6: /* step 6: check the URG bit */ tcp_urg(sk, skb, th); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index a77d9b8d12dd..d8fc9bfabf2d 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -6,7 +6,7 @@ * Pedro Roque <roque@di.fc.ul.pt> * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> * - * $Id: sit.c,v 1.50 2001/04/19 22:32:55 davem Exp $ + * $Id: sit.c,v 1.51 2001/05/17 04:12:18 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index 5d0bd0ded202..82f1efc2d1c8 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -267,8 +267,10 @@ typedef struct wan_stat_entry offs = file->f_pos; if (offs < pos) { len = min(pos - offs, count); - if(copy_to_user(buf, (page + offs), len)) + if (copy_to_user(buf, (page + offs), len)) { + kfree(page); return -EFAULT; + } file->f_pos += len; } else |
