From 519cb0c651b1b249fe688d5d0501c6860d9950c9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:16:34 -0500 Subject: [PATCH] Import 2.1.120 --- CREDITS | 10 +- Documentation/Configure.help | 18 + Documentation/filesystems/umsdos.txt | 18 +- arch/alpha/kernel/core_lca.c | 2 +- arch/alpha/kernel/smc37c669.c | 2 +- arch/i386/boot/setup.S | 2 +- arch/i386/kernel/entry.S | 20 +- arch/i386/kernel/io_apic.c | 27 +- arch/i386/kernel/irq.c | 59 +- arch/i386/kernel/irq.h | 1 + arch/i386/kernel/process.c | 33 +- arch/i386/kernel/setup.c | 83 +- arch/i386/kernel/signal.c | 11 + arch/m68k/amiga/config.c | 13 +- arch/m68k/atari/atasound.c | 16 +- arch/m68k/atari/config.c | 3 +- arch/m68k/atari/joystick.c | 1 + arch/m68k/atari/stram.c | 81 +- arch/m68k/config.in | 43 +- arch/m68k/defconfig | 4 +- arch/m68k/hp300/Makefile | 6 +- arch/m68k/hp300/config.c | 33 +- arch/m68k/hp300/hil.c | 205 +++- arch/m68k/hp300/hp300map.map | 252 +++++ arch/m68k/hp300/ints.c | 140 ++- arch/m68k/hp300/ints.h | 3 + arch/m68k/hp300/time.c | 29 +- arch/m68k/kernel/entry.S | 4 +- arch/m68k/kernel/m68k_defs.h | 6 +- arch/m68k/kernel/process.c | 15 +- arch/m68k/kernel/setup.c | 13 +- arch/m68k/kernel/signal.c | 34 +- arch/m68k/lib/checksum.c | 88 +- arch/m68k/mac/mac_ksyms.c | 4 +- arch/m68k/mac/mackeyb.c | 33 +- arch/m68k/mm/init.c | 11 +- arch/m68k/mm/kmap.c | 7 +- arch/m68k/mm/memory.c | 26 +- drivers/char/ChangeLog | 5 + drivers/char/apm_bios.c | 374 +++---- drivers/char/bttv.c | 31 +- drivers/char/bttv.h | 1 + drivers/char/cyclades.c | 33 +- drivers/char/psaux.c | 11 +- drivers/char/rocket.c | 9 +- drivers/char/serial.c | 22 +- drivers/net/arcnet.c | 18 +- drivers/net/pcnet32.c | 37 +- drivers/net/sdla_fr.c | 9 +- drivers/net/sdla_ppp.c | 11 +- drivers/net/sdla_x25.c | 4 +- drivers/net/sdladrv.c | 20 +- drivers/net/sdlamain.c | 74 +- drivers/scsi/NCR5380.c | 20 +- drivers/sound/Config.in | 12 + drivers/sound/README.FIRST | 2 +- drivers/sound/audio.c | 13 +- drivers/sound/dev_table.h | 2 - drivers/sound/dmabuf.c | 1 + drivers/sound/es1370.c | 58 +- drivers/sound/es1371.c | 29 +- drivers/sound/msnd.c | 23 +- drivers/sound/msnd.h | 85 +- drivers/sound/msnd_classic.h | 236 ++--- drivers/sound/msnd_pinnacle.c | 768 +++++++++----- drivers/sound/msnd_pinnacle.h | 375 +++---- drivers/sound/sonicvibes.c | 21 +- drivers/sound/sound_core.c | 15 +- fs/binfmt_aout.c | 5 + fs/coda/cnode.c | 23 +- fs/coda/dir.c | 2 +- fs/coda/file.c | 2 +- fs/coda/pioctl.c | 2 +- fs/coda/psdev.c | 16 +- fs/coda/upcall.c | 26 +- fs/isofs/inode.c | 30 +- fs/lockd/svc.c | 19 +- fs/nfs/dir.c | 142 ++- fs/nfs/write.c | 11 +- fs/proc/array.c | 8 +- fs/qnx4/bitmap.c | 1 + fs/qnx4/dir.c | 1 + fs/qnx4/file.c | 1 + fs/qnx4/fsync.c | 1 + fs/qnx4/inode.c | 1 + fs/qnx4/namei.c | 1 + fs/qnx4/symlinks.c | 1 + fs/qnx4/truncate.c | 1 + fs/ufs/acl.c | 11 +- fs/ufs/balloc.c | 20 +- fs/ufs/dir.c | 40 +- fs/ufs/inode.c | 16 +- fs/ufs/namei.c | 24 +- fs/ufs/super.c | 157 +-- fs/ufs/swab.h | 67 +- fs/ufs/symlink.c | 2 +- fs/ufs/truncate.c | 4 +- fs/ufs/util.c | 3 +- fs/ufs/util.h | 55 +- fs/umsdos/Makefile | 6 +- fs/umsdos/README-WIP.txt | 159 +-- fs/umsdos/check.c | 4 +- fs/umsdos/dir.c | 508 ++++----- fs/umsdos/emd.c | 386 +++---- fs/umsdos/file.c | 4 - fs/umsdos/inode.c | 378 ++++--- fs/umsdos/ioctl.c | 56 +- fs/umsdos/mangle.c | 111 +- fs/umsdos/namei.c | 167 +-- fs/umsdos/rdir.c | 37 +- fs/umsdos/symlink.c | 21 +- include/asm-i386/processor.h | 2 + include/asm-m68k/adb_mouse.h | 23 + include/asm-m68k/amigahw.h | 270 ++--- include/asm-m68k/bitops.h | 4 +- include/asm-m68k/checksum.h | 10 +- include/asm-m68k/hardirq.h | 6 +- include/asm-m68k/io.h | 33 +- include/asm-m68k/linux_logo.h | 1417 +++++++++++++++++++++++++- include/asm-m68k/pgtable.h | 40 +- include/asm-m68k/setup.h | 24 +- include/asm-m68k/softirq.h | 2 +- include/asm-m68k/spinlock.h | 14 +- include/asm-m68k/uaccess.h | 53 +- include/asm-m68k/unistd.h | 6 +- include/asm-m68k/virtconvert.h | 76 ++ include/linux/byteorder/generic.h | 11 +- include/linux/byteorder/swab.h | 9 +- include/linux/byteorder/swabb.h | 4 +- include/linux/coda.h | 6 +- include/linux/coda_fs_i.h | 2 +- include/linux/coda_linux.h | 6 +- include/linux/cyclades.h | 7 + include/linux/sched.h | 2 + include/linux/ufs_fs.h | 13 +- include/linux/umsdos_fs.h | 25 +- include/linux/umsdos_fs.p | 49 +- init/main.c | 32 +- ipc/sem.c | 8 +- kernel/fork.c | 46 +- kernel/sched.c | 3 +- net/ax25/ax25_ip.c | 22 +- net/ipv4/ip_fw.c | 18 +- net/sunrpc/clnt.c | 1 + net/sunrpc/sched.c | 11 +- net/sunrpc/svcsock.c | 2 + net/wanrouter/wanmain.c | 15 +- net/wanrouter/wanproc.c | 9 +- 148 files changed, 5682 insertions(+), 2804 deletions(-) create mode 100644 arch/m68k/hp300/hp300map.map create mode 100644 include/asm-m68k/adb_mouse.h create mode 100644 include/asm-m68k/virtconvert.h diff --git a/CREDITS b/CREDITS index 412817b262a4..f651c17cc1e9 100644 --- a/CREDITS +++ b/CREDITS @@ -1472,8 +1472,8 @@ D: Generic Z8530 driver, AX.25 DAMA slave implementation D: Several AX.25 hacks N: Francois-Rene Rideau -E: rideau@ens.fr -W: http://www.eleves.ens.fr:8080/home/rideau/ +E: fare@tunes.org +W: http://www.tunes.org/~fare D: petty kernel janitor (byteorder, ufs) S: 6, rue Augustin Thierry S: 75019 Paris @@ -1511,10 +1511,12 @@ S: Germany N: Stephen Rothwell E: Stephen.Rothwell@canb.auug.org.au +W: http://www.canb.auug.org.au/~sfr +P: 1024/BD8C7805 CD A4 9D 01 10 6E 7E 3B 91 88 FA D9 C8 40 AA 02 D: Boot/setup/build work for setup > 2K D: Author, APM driver -S: 59 Bugden Avenue -S: Gowrie ACT 2904 +S: 66 Maltby Circuit +S: Wanniassa ACT 2903 S: Australia N: Gerard Roudier diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 28f0b0bf1907..9b1a00fa9d09 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -8272,6 +8272,24 @@ CONFIG_MSNDPIN_PERM_FILE obtained from Turtle Beach. See Documentation/sound/MultiSound for information on how to obtain this. +MSND Pinnacle Non-PnP Mode +CONFIG_MSNDPIN_NONPNP + The Pinnacle and Fiji card resources can be configured either with + PnP, or through a configuration port. For the Pinnacle, + configuration in non-PnP mode allows use of the IDE and joystick + peripherals on the card as well, since they do not show up when the + card is in PnP mode. Specifying zero for any resource of a device + will disable the device. If you are running the card in PnP mode, + you must say N here and use isapnptools to configure the card's + resources. + +MSND Pinnacle Config Port +CONFIG_MSNDPIN_CFG + This is the port which the Pinnacle and Fiji uses to configure + the card's resources when not in PnP mode. If your card is in + PnP mode, then be sure to say N to the previous option, + CONFIG_MSNDPIN_NONPNP. + /dev/dsp and /dev/audio support CONFIG_SOUND_AUDIO Answering N disables /dev/dsp and /dev/audio, the A/D and D/A diff --git a/Documentation/filesystems/umsdos.txt b/Documentation/filesystems/umsdos.txt index 9dda08913e62..c253708f3466 100644 --- a/Documentation/filesystems/umsdos.txt +++ b/Documentation/filesystems/umsdos.txt @@ -3,7 +3,7 @@ and has some KNOWN BUGS (and quite a few unknown :-). Please read fs/umsdos/README-WIP.txt for more information on current status. Thanks. ---------------------------------------------------------------------------- -Very short explanation for the impatient!!! +Very short explanation for the impatient! Umsdos is a file system driver that run on top the MSDOS fs driver. It is written by Jacques Gelinas (jacques@solucorp.qc.ca) @@ -24,9 +24,7 @@ There is plenty of documentation on it in the source. A formatted document made from those comments is available from sunsite.unc.edu:/pub/Linux/system/Filesystems/umsdos. -Mostly... - -You mount a DOS partition like this +You mount a DOS partition like this: mount -t umsdos /dev/hda3 /mnt ^ @@ -41,7 +39,7 @@ the default. After doing the mount on a DOS partition, nothing special happens. This is why all mount options are passed to the msdos fs driver. Umsdos uses a special DOS file --linux-.--- to store the information -which can't be handle by the normal MsDOS file system. This is the trick. +which can't be handled by the normal MS-DOS filesystem. This is the trick. --linux-.--- is optional. There is one per directory. @@ -65,12 +63,12 @@ A compiled version is available in umsdos_progs-0.7.bin.tar.gz. So in our example, after mounting mnt, we do -umssync . + umssync . This will promote this directory (a recursive option is available) to full -umsdos capabilities (long name ...). A ls -l before and after won't show -much difference however. The files which were there are still there. But now -you can do all this: +umsdos capabilities (long name, etc.). However, an "ls -l" before and after +won't show much difference. The files which were there are still there, but +now you can do all this: chmod 644 * chown you.your_group * @@ -94,7 +92,7 @@ after the "mount -a": (You put one for each umsdos mount point in the fstab) -This will insure nice operation. A umsdos.fsck is in the making, +This will ensure nice operation. A umsdos.fsck is in the making, so you will be allowed to manage umsdos partitions in the same way other filesystems are, using the generic fsck front end. diff --git a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c index fe1e7795229b..950e6c0b0f82 100644 --- a/arch/alpha/kernel/core_lca.c +++ b/arch/alpha/kernel/core_lca.c @@ -470,7 +470,7 @@ lca_machine_check (unsigned long vector, unsigned long la, case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break; case MCHK_K_DCPERR: reason = "d-cache parity error"; break; case MCHK_K_ICPERR: reason = "i-cache parity error"; break; - case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on on PCI bus"; break; + case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on PCI bus"; break; case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break; case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break; case MCHK_K_UNKNOWN: diff --git a/arch/alpha/kernel/smc37c669.c b/arch/alpha/kernel/smc37c669.c index 3d7cd05f8077..d92fc281e984 100644 --- a/arch/alpha/kernel/smc37c669.c +++ b/arch/alpha/kernel/smc37c669.c @@ -1709,7 +1709,7 @@ unsigned int __init SMC37c669_disable_device ( unsigned int func ) ** the configuration is also updated. If the device function ** is currently disabled, only the local shadow copy is ** updated and the actual device function will be updated -** if/when is is enabled. +** if/when it is enabled. ** **-- */ diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S index 0959487c1d4f..22fca192c4c2 100644 --- a/arch/i386/boot/setup.S +++ b/arch/i386/boot/setup.S @@ -18,7 +18,7 @@ ! March 1993/June 1994 (Christoph.Niemann@linux.org) ! ! add APM BIOS checking by Stephen Rothwell, May 1994 -! (Stephen.Rothwell@pd.necisa.oz.au) +! (Stephen.Rothwell@canb.auug.org.au) ! ! High load stuff, initrd support and position independency ! by Hans Lermen & Werner Almesberger, February 1996 diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index dd9bf9853003..260021f01d6f 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -105,23 +105,21 @@ ENOSYS = 38 popl %eax; \ 1: popl %ds; \ 2: popl %es; \ -3: addl $4,%esp; \ -4: iret; \ + addl $4,%esp; \ +3: iret; \ .section fixup,"ax"; \ -5: pushl $0; \ - popl %ds; \ +4: movl $0,(%esp); \ + jmp 1b; \ +5: movl $0,(%esp); \ jmp 2b; \ -6: pushl $0; \ - popl %es; \ - jmp 3b; \ -7: pushl $11; \ +6: pushl $11; \ call do_exit; \ .previous; \ .section __ex_table,"a";\ .align 4; \ - .long 1b,5b; \ - .long 2b,6b; \ - .long 4b,7b; \ + .long 1b,4b; \ + .long 2b,5b; \ + .long 3b,6b; \ .previous #define GET_CURRENT(reg) \ diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 044ffdc3c003..fe956cf68df8 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -1159,6 +1159,31 @@ static inline void check_timer(void) } } +/* + * + * IRQ's that are handled by the old PIC in all cases: + * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ. + * Linux doesn't really care, as it's not actually used + * for any interrupt handling anyway. + * - IRQ13 is the FPU error IRQ, and may be connected + * directly from the FPU to the old PIC. Linux doesn't + * really care, because Linux doesn't want to use IRQ13 + * anyway (exception 16 is the proper FPU error signal) + * - IRQ9 is broken on PIIX4 motherboards: + * + * "IRQ9 cannot be re-assigned" + * + * IRQ9 is not available to assign to + * ISA add-in cards because it is + * dedicated to the power + * management function of the PIIX4 + * controller on the motherboard. + * This is true for other motherboards + * which use the 82371AB PIIX4 + * component. + */ +#define PIC_IRQS ((1<<2)|(1<<9)|(1<<13)) + void __init setup_IO_APIC(void) { init_sym_mode(); @@ -1176,7 +1201,7 @@ void __init setup_IO_APIC(void) pirqs_enabled) { printk("ENABLING IO-APIC IRQs\n"); - io_apic_irqs = ~((1<<2)|(1<<9)|(1<<13)); + io_apic_irqs = ~PIC_IRQS; } else { if (ioapic_blacklisted()) printk(" blacklisted board, DISABLING IO-APIC IRQs\n"); diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index f4a41e310b69..c2b00615912f 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -879,9 +879,9 @@ out: * with "IRQ_INPROGRESS" asserted and the interrupt * disabled. */ -unsigned long probe_irq_on (void) +unsigned long probe_irq_on(void) { - unsigned int i, irqs = 0; + unsigned int i; unsigned long delay; /* @@ -890,51 +890,68 @@ unsigned long probe_irq_on (void) spin_lock_irq(&irq_controller_lock); for (i = NR_IRQS-1; i > 0; i--) { if (!irq_desc[i].action) { - irq_desc[i].status &= ~IRQ_INPROGRESS; + unsigned int status = irq_desc[i].status | IRQ_AUTODETECT; + irq_desc[i].status = status & ~(IRQ_INPROGRESS | IRQ_PENDING); irq_desc[i].handler->enable(i); - irqs |= (1 << i); } } spin_unlock_irq(&irq_controller_lock); /* - * wait for spurious interrupts to increase counters + * Wait for spurious interrupts to trigger */ for (delay = jiffies + HZ/10; delay > jiffies; ) /* about 100ms delay */ synchronize_irq(); /* - * now filter out any obviously spurious interrupts + * Now filter out any obviously spurious interrupts */ spin_lock_irq(&irq_controller_lock); for (i=0; idisable(i); + } } spin_unlock_irq(&irq_controller_lock); - return irqs; + return 0x12345678; } -int probe_irq_off (unsigned long irqs) +int probe_irq_off(unsigned long unused) { - int i, irq_found = -1; + int i, irq_found, nr_irqs; + + if (unused != 0x12345678) + printk("Bad IRQ probe from %lx\n", (&unused)[-1]); + nr_irqs = 0; + irq_found = 0; spin_lock_irq(&irq_controller_lock); for (i=0; i>= 1; + irq_desc[i].status = status & ~IRQ_AUTODETECT; + irq_desc[i].handler->disable(i); } - if (irq_found == -1) - irq_found = 0; -out: spin_unlock_irq(&irq_controller_lock); + + if (nr_irqs > 1) + irq_found = -irq_found; return irq_found; } diff --git a/arch/i386/kernel/irq.h b/arch/i386/kernel/irq.h index 85f7710e0cf0..6812b8f0e7de 100644 --- a/arch/i386/kernel/irq.h +++ b/arch/i386/kernel/irq.h @@ -22,6 +22,7 @@ struct hw_interrupt_type { #define IRQ_DISABLED 2 /* IRQ disabled - do not enter! */ #define IRQ_PENDING 4 /* IRQ pending - replay on enable */ #define IRQ_REPLAY 8 /* IRQ has been replayed but not acked yet */ +#define IRQ_AUTODETECT 16 /* IRQ is being autodetected */ /* * This is the "IRQ descriptor", which contains various information diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 731797f6b50d..69dcd7b0b35c 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -488,21 +488,19 @@ void free_task_struct(struct task_struct *p) void release_segments(struct mm_struct *mm) { - void * ldt = mm->segments; - int nr; - /* forget local segments */ - __asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs ; lldt %w0" + __asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs" : /* no outputs */ : "r" (0)); - current->tss.ldt = 0; - /* - * Set the GDT entry back to the default. - */ - nr = current->tarray_ptr - &task[0]; - set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY, &default_ldt, 1); + if (mm->segments) { + void * ldt = mm->segments; + + /* + * Get the LDT entry from init_task. + */ + current->tss.ldt = _LDT(0); + load_ldt(0); - if (ldt) { mm->segments = NULL; vfree(ldt); } @@ -557,23 +555,22 @@ void copy_segments(int nr, struct task_struct *p, struct mm_struct *new_mm) void * old_ldt = old_mm->segments, * ldt = old_ldt; int ldt_size = LDT_ENTRIES; - p->tss.ldt = _LDT(nr); + /* "default_ldt" - use the one from init_task */ + p->tss.ldt = _LDT(0); if (old_ldt) { if (new_mm) { ldt = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE); new_mm->segments = ldt; if (!ldt) { printk(KERN_WARNING "ldt allocation failed\n"); - goto no_ldt; + return; } memcpy(ldt, old_ldt, LDT_ENTRIES*LDT_ENTRY_SIZE); } - } else { - no_ldt: - ldt = &default_ldt; - ldt_size = 1; + p->tss.ldt = _LDT(nr); + set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY, ldt, ldt_size); + return; } - set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY, ldt, ldt_size); } /* diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index b2bb692435e3..498820ec8caa 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -439,8 +439,8 @@ static struct cpu_model_info cpu_models[] __initdata = { NULL, NULL, NULL, NULL }}, { X86_VENDOR_INTEL, 6, { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)", - NULL, "Pentium II (Deschutes)", NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL }}, + NULL, "Pentium II (Deschutes)", "Celeron (Mendocino)", NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_AMD, 4, { NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT", @@ -467,6 +467,7 @@ __initfunc(void identify_cpu(struct cpuinfo_x86 *c)) char *p = NULL; c->loops_per_sec = loops_per_sec; + c->x86_cache_size = -1; get_cpu_vendor(c); @@ -479,13 +480,64 @@ __initfunc(void identify_cpu(struct cpuinfo_x86 *c)) return; } - if (c->x86_model < 16) - for (i=0; ix86_vendor && - cpu_models[i].x86 == c->x86) { + for (i = 0; i < sizeof(cpu_models)/sizeof(struct cpu_model_info); i++) { + if (c->cpuid_level > 1) { + /* supports eax=2 call */ + int edx, cache_size, dummy; + + cpuid(2, &dummy, &dummy, &dummy, &edx); + + /* We need only the LSB */ + edx &= 0xff; + + switch (edx) { + case 0x40: + cache_size = 0; + + case 0x41: + cache_size = 128; + break; + + case 0x42: + cache_size = 256; + break; + + case 0x43: + cache_size = 512; + break; + + case 0x44: + cache_size = 1024; + break; + + case 0x45: + cache_size = 2048; + break; + + default: + cache_size = 0; + break; + } + + c->x86_cache_size = cache_size; + } + + if (cpu_models[i].vendor == c->x86_vendor && + cpu_models[i].x86 == c->x86) { + if (c->x86_model <= 16) p = cpu_models[i].model_names[c->x86_model]; - break; + + /* Names for the Pentium II processors */ + if ((cpu_models[i].vendor == X86_VENDOR_INTEL) + && (cpu_models[i].x86 == 6) + && (c->x86_model == 5) + && (c->x86_cache_size == 0)) { + p = "Celeron"; } + } + + } + if (p) { strcpy(c->x86_model_id, p); return; @@ -548,14 +600,17 @@ int get_cpuinfo(char * buffer) if (!(cpu_present_map & (1<x86_vendor_id[0] ? c->x86_vendor_id : "unknown", c->x86 + '0', - c->x86_model_id[0] ? c->x86_model_id : "unknown", - c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown"); + c->x86_model, + c->x86_model_id[0] ? c->x86_model_id : "unknown"); + if (c->x86_mask) { if (c->x86_vendor == X86_VENDOR_CYRIX) p += sprintf(p, "stepping\t: %s\n", Cx86_step); @@ -564,6 +619,10 @@ int get_cpuinfo(char * buffer) } else p += sprintf(p, "stepping\t: unknown\n"); + /* Cache size */ + if (c->x86_cache_size >= 0) + p += sprintf(p, "cache size\t: %d KB\n", c->x86_cache_size); + /* Modify the capabilities according to chip type */ if (c->x86_mask) { if (c->x86_vendor == X86_VENDOR_CYRIX) { diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index 231356d909cd..c9332a780934 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -22,6 +22,17 @@ #include #include +void checksignals(void) +{ + sigset_t *blocked = ¤t->blocked; + unsigned long mask = blocked->sig[0] | sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT); + mask &= blocked->sig[1]; + if (~mask) { + printk("Bad signal mask\n"); + *(int *) 0 = 0; + } +} + #define DEBUG_SIG 0 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index 3c5dff56dfd0..9483c97b3835 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,7 @@ #include #include #include -#include +#include unsigned long amiga_model; unsigned long amiga_eclock; @@ -421,10 +422,6 @@ __initfunc(void config_amiga(void)) */ if (AMIGAHW_PRESENT(MAGIC_REKICK)) *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80; - -#ifdef CONFIG_ZORRO - zorro_init(); -#endif } static unsigned short jiffy_ticks; @@ -689,8 +686,8 @@ static NORET_TYPE void amiga_reset( void ) static void amiga_reset (void) { - unsigned long jmp_addr040 = VTOP(&&jmp_addr_label040); - unsigned long jmp_addr = VTOP(&&jmp_addr_label); + unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040); + unsigned long jmp_addr = virt_to_phys(&&jmp_addr_label); cli(); if (CPU_IS_040_OR_060) @@ -785,7 +782,7 @@ static void amiga_savekmsg_init(void) savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM); savekmsg->magic1 = SAVEKMSG_MAGIC1; savekmsg->magic2 = SAVEKMSG_MAGIC2; - savekmsg->magicptr = VTOP(savekmsg); + savekmsg->magicptr = virt_to_phys(savekmsg); savekmsg->size = 0; } diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c index 8223ce95ce21..7b401d17fef9 100644 --- a/arch/m68k/atari/atasound.c +++ b/arch/m68k/atari/atasound.c @@ -61,17 +61,21 @@ void atari_mksound (unsigned int hz, unsigned int ticks) save_flags(flags); cli(); - /* Convert from frequency value to PSG period value (base - frequency 125 kHz). */ - period = PSG_FREQ / hz; - - if (period > 0xfff) period = 0xfff; /* Disable generator A in mixer control. */ sound_ym.rd_data_reg_sel = 7; tmp = sound_ym.rd_data_reg_sel; tmp |= 011; sound_ym.wd_data = tmp; + + if (hz) { + /* Convert from frequency value to PSG period value (base + frequency 125 kHz). */ + + period = PSG_FREQ / hz; + + if (period > 0xfff) period = 0xfff; + /* Set generator A frequency to hz. */ sound_ym.rd_data_reg_sel = 0; sound_ym.wd_data = period & 0xff; @@ -101,6 +105,6 @@ void atari_mksound (unsigned int hz, unsigned int ticks) sound_ym.rd_data_reg_sel = 7; tmp &= ~1; sound_ym.wd_data = tmp; - + } restore_flags(flags); } diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c index a63e71e08eb1..8db027ab47d6 100644 --- a/arch/m68k/atari/config.c +++ b/arch/m68k/atari/config.c @@ -39,6 +39,7 @@ #include #include #include +#include u_long atari_mch_cookie; u_long atari_mch_type = 0; @@ -616,7 +617,7 @@ static void atari_reset (void) : : : "d0" ); if (CPU_IS_040_OR_060) { - unsigned long jmp_addr040 = VTOP(&&jmp_addr_label040); + unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040); if (CPU_IS_060) { /* 68060: clear PCR to turn off superscalar operation */ __asm__ __volatile__ diff --git a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c index 1deec96538aa..ba5dbcd98b8e 100644 --- a/arch/m68k/atari/joystick.c +++ b/arch/m68k/atari/joystick.c @@ -126,6 +126,7 @@ struct file_operations atari_joystick_fops = { NULL, /* joystick_ioctl */ NULL, /* joystick_mmap */ open_joystick, + NULL, /* flush */ release_joystick }; diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c index d11011c5efee..b3741ed96f21 100644 --- a/arch/m68k/atari/stram.c +++ b/arch/m68k/atari/stram.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef CONFIG_STRAM_SWAP @@ -121,9 +122,6 @@ #define ALIGN_IF_SWAP(x) (x) #endif -/* map entry for reserved swap page (used as buffer) */ -#define SWP_RSVD 0x80 - /* get index of swap page at address 'addr' */ #define SWAP_NR(addr) (((unsigned long)(addr)-swap_start) >> PAGE_SHIFT) @@ -232,10 +230,10 @@ static int unswap_vma( struct vm_area_struct * vma, pgd_t *pgdir, unsigned long entry, unsigned long page, int isswap ); static int unswap_process( struct mm_struct * mm, unsigned long entry, unsigned long page, int isswap ); -static int unswap_by_move( unsigned char *map, unsigned long max, unsigned - long start, unsigned long n_pages ); -static int unswap_by_read( unsigned char *map, unsigned long max, unsigned - long start, unsigned long n_pages ); +static int unswap_by_move(unsigned short *, unsigned long, unsigned long, + unsigned long); +static int unswap_by_read(unsigned short *, unsigned long, unsigned long, + unsigned long); static void *get_stram_region( unsigned long n_pages ); static void free_stram_region( unsigned long offset, unsigned long n_pages ); @@ -275,7 +273,7 @@ __initfunc(void atari_stram_init( void )) /* determine whether kernel code resides in ST-RAM (then ST-RAM is the * first memory block at virtual 0x0) */ - stram_start = PTOV( 0 ); + stram_start = phys_to_virt( 0 ); kernel_in_stram = (stram_start == 0); for( i = 0; i < m68k_num_memory; ++i ) { @@ -356,11 +354,13 @@ __initfunc(void atari_stram_reserve_pages( unsigned long start_mem )) DPRINTK( "atari_stram_reserve_pages: swapping enabled; " "swap=%08lx-%08lx\n", swap_start, swap_end ); - /* reserve some amount of memory for maintainance of swapping itself: - * 1 page for the lockmap, and one page for each 4096 (PAGE_SIZE) swap - * pages. (1 byte for each page) */ + /* reserve some amount of memory for maintainance of + * swapping itself: 1 page for the lockmap, and one page + * for each 2048 (PAGE_SIZE/2) swap pages. (2 bytes for + * each page) */ swap_data = start_mem; - start_mem += PAGE_ALIGN(SWAP_NR(swap_end)) + PAGE_SIZE; + start_mem += (((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1) + >> (PAGE_SHIFT-1)) + 1) << PAGE_SHIFT; /* correct swap_start if necessary */ if (swap_start == swap_data) swap_start = start_mem; @@ -621,7 +621,7 @@ __initfunc(static int swap_init( unsigned long start_mem, p->swap_file = &fake_dentry[0]; p->swap_device = 0; p->swap_lockmap = (unsigned char *)(swap_data); - p->swap_map = (unsigned char *)(swap_data + PAGE_SIZE); + p->swap_map = (unsigned short *)(swap_data + PAGE_SIZE); p->cluster_nr = 0; p->next = -1; p->prio = 0x7ff0; /* a rather high priority, but not the higest @@ -638,7 +638,7 @@ __initfunc(static int swap_init( unsigned long start_mem, memset( p->swap_lockmap, 0, PAGE_SIZE ); /* initialize swap_map: set regions that are already allocated or belong - * to kernel data space to SWP_RSVD, otherwise to free */ + * to kernel data space to SWAP_MAP_BAD, otherwise to free */ j = 0; /* # of free pages */ k = 0; /* # of already allocated pages (from pre-mem_init stram_alloc()) */ p->lowest_bit = 0; @@ -646,11 +646,11 @@ __initfunc(static int swap_init( unsigned long start_mem, for( i = 1, addr = (unsigned long)SWAP_ADDR(1); i < p->max; i++, addr += PAGE_SIZE ) { if (in_some_region( addr )) { - p->swap_map[i] = SWP_RSVD; + p->swap_map[i] = SWAP_MAP_BAD; ++k; } else if (kernel_in_stram && addr < start_mem ) { - p->swap_map[i] = SWP_RSVD; + p->swap_map[i] = SWAP_MAP_BAD; } else { p->swap_map[i] = 0; @@ -660,7 +660,7 @@ __initfunc(static int swap_init( unsigned long start_mem, } } /* first page always reserved (and doesn't really belong to swap space) */ - p->swap_map[0] = SWP_RSVD; + p->swap_map[0] = SWAP_MAP_BAD; /* now swapping to this device ok */ p->pages = j + k; @@ -846,8 +846,8 @@ static int unswap_process( struct mm_struct * mm, unsigned long entry, } -static int unswap_by_move( unsigned char *map, unsigned long max, - unsigned long start, unsigned long n_pages ) +static int unswap_by_move(unsigned short *map, unsigned long max, + unsigned long start, unsigned long n_pages) { struct task_struct *p; unsigned long entry, rover = (start == 1) ? n_pages+1 : 1; @@ -859,11 +859,11 @@ static int unswap_by_move( unsigned char *map, unsigned long max, /* can free the allocated pages by moving them to other swap pages */ for( i = start; i < start+n_pages; ++i ) { if (!map[i]) { - map[i] = SWP_RSVD; + map[i] = SWAP_MAP_BAD; DPRINTK( "unswap: page %lu was free\n", i ); continue; } - else if (map[i] == SWP_RSVD) { + else if (map[i] == SWAP_MAP_BAD) { printk( KERN_ERR "get_stram_region: page %lu already " "reserved??\n", i ); } @@ -923,7 +923,7 @@ static int unswap_by_move( unsigned char *map, unsigned long max, DPRINTK( "unswap: map[i=%lu]=%u map[j=%lu]=%u nr_swap=%u\n", i, map[i], j, map[j], nr_swap_pages ); - map[i] = SWP_RSVD; + map[i] = SWAP_MAP_BAD; if (stram_swap_info->lowest_bit == i) stram_swap_info->lowest_bit++; if (stram_swap_info->highest_bit == i) @@ -933,8 +933,8 @@ static int unswap_by_move( unsigned char *map, unsigned long max, return( 0 ); } -static int unswap_by_read( unsigned char *map, unsigned long max, - unsigned long start, unsigned long n_pages ) +static int unswap_by_read(unsigned short *map, unsigned long max, + unsigned long start, unsigned long n_pages) { struct task_struct *p; unsigned long entry, page = 0; @@ -944,7 +944,7 @@ static int unswap_by_read( unsigned char *map, unsigned long max, start, start+n_pages-1 ); for( i = start; i < start+n_pages; ++i ) { - if (map[i] == SWP_RSVD) { + if (map[i] == SWAP_MAP_BAD) { printk( KERN_ERR "get_stram_region: page %lu already " "reserved??\n", i ); continue; @@ -977,7 +977,7 @@ static int unswap_by_read( unsigned char *map, unsigned long max, * we freed the last reference to an overflowed entry, * or the system has lost track of the use counts. */ - if (map[i] && map[i] != SWP_RSVD-1) + if (map[i] && map[i] != SWAP_MAP_MAX) printk( KERN_ERR "get_stram_region: swap entry %08lx " "not used by any process\n", entry ); /* quit while loop and overwrite bad map entry */ @@ -990,7 +990,7 @@ static int unswap_by_read( unsigned char *map, unsigned long max, DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n", i, map[i], nr_swap_pages ); - map[i] = SWP_RSVD; + map[i] = SWAP_MAP_BAD; if (stram_swap_info->lowest_bit == i) stram_swap_info->lowest_bit++; if (stram_swap_info->highest_bit == i) @@ -1008,7 +1008,7 @@ static int unswap_by_read( unsigned char *map, unsigned long max, */ static void *get_stram_region( unsigned long n_pages ) { - unsigned char *map = stram_swap_info->swap_map; + unsigned short *map = stram_swap_info->swap_map; unsigned long max = stram_swap_info->max; unsigned long start, total_free, region_free; int err; @@ -1046,7 +1046,7 @@ static void *get_stram_region( unsigned long n_pages ) */ static void free_stram_region( unsigned long offset, unsigned long n_pages ) { - unsigned char *map = stram_swap_info->swap_map; + unsigned short *map = stram_swap_info->swap_map; DPRINTK( "free_stram_region(offset=%lu,n_pages=%lu)\n", offset, n_pages ); @@ -1057,7 +1057,7 @@ static void free_stram_region( unsigned long offset, unsigned long n_pages ) /* un-reserve the freed pages */ for( ; n_pages > 0; ++offset, --n_pages ) { - if (map[offset] != SWP_RSVD) + if (map[offset] != SWAP_MAP_BAD) printk( KERN_ERR "free_stram_region: Swap page %lu was not " "reserved\n", offset ); map[offset] = 0; @@ -1092,11 +1092,11 @@ static int in_some_region( unsigned long addr ) } -static unsigned long find_free_region( unsigned long n_pages, - unsigned long *total_free, - unsigned long *region_free ) +static unsigned long find_free_region(unsigned long n_pages, + unsigned long *total_free, + unsigned long *region_free) { - unsigned char *map = stram_swap_info->swap_map; + unsigned short *map = stram_swap_info->swap_map; unsigned long max = stram_swap_info->max; unsigned long head, tail, max_start; long nfree, max_free; @@ -1111,7 +1111,7 @@ static unsigned long find_free_region( unsigned long n_pages, /* increment tail until final window size reached, and count free pages */ nfree = 0; for( tail = head; tail-head < n_pages && tail < max-n_pages; ++tail ) { - if (map[tail] == SWP_RSVD) { + if (map[tail] == SWAP_MAP_BAD) { head = tail+1; goto start_over; } @@ -1134,7 +1134,7 @@ static unsigned long find_free_region( unsigned long n_pages, * possible are free */ while( tail < max ) { nfree -= (map[head++] == 0); - if (map[tail] == SWP_RSVD) { + if (map[tail] == SWAP_MAP_BAD) { head = tail+1; goto start_over; } @@ -1413,8 +1413,8 @@ int get_stram_list( char *buf ) int len = 0; BLOCK *p; #ifdef CONFIG_STRAM_SWAP - int i; - unsigned char *map = stram_swap_info->swap_map; + int i; + unsigned short *map = stram_swap_info->swap_map; unsigned long max = stram_swap_info->max; unsigned free = 0, used = 0, rsvd = 0; #endif @@ -1424,7 +1424,7 @@ int get_stram_list( char *buf ) for( i = 1; i < max; ++i ) { if (!map[i]) ++free; - else if (map[i] == SWP_RSVD) + else if (map[i] == SWAP_MAP_BAD) ++rsvd; else ++used; @@ -1466,7 +1466,8 @@ int get_stram_list( char *buf ) if (len + 50 >= PAGE_SIZE) break; PRINT_PROC( "0x%08lx-0x%08lx: %s (", - VTOP(p->start), VTOP(p->start+p->size-1), p->owner ); + virt_to_phys(p->start), + virt_to_phys(p->start+p->size-1), p->owner ); if (p->flags & BLOCK_STATIC) PRINT_PROC( "static)\n" ); else if (p->flags & BLOCK_GFP) diff --git a/arch/m68k/config.in b/arch/m68k/config.in index 33164f7bc98f..21ac9badc191 100644 --- a/arch/m68k/config.in +++ b/arch/m68k/config.in @@ -63,9 +63,10 @@ fi if [ "$CONFIG_VME" = "y" -a "$CONFIG_M68060" = "y" ]; then define_bool CONFIG_060_WRITETHROUGH y fi -bool 'Advanced processor options' CONFIG_ADVANCED_CPU -if [ "$CONFIG_ADVANCED_CPU" = "y" ]; then +bool 'Advanced configuration options' CONFIG_ADVANCED +if [ "$CONFIG_ADVANCED" = "y" ]; then bool 'Use read-modify-write instructions' CONFIG_RMW_INSNS + bool 'Use one physical chunk of memory only' CONFIG_SINGLE_MEMORY_CHUNK if [ "$CONFIG_M68060" = "y" -a "$CONFIG_VME" = "n" ]; then bool 'Use write-through caching for 68060 supervisor accesses' CONFIG_060_WRITETHROUGH fi @@ -235,23 +236,14 @@ if [ "$CONFIG_ATARI" = "y" ]; then tristate 'PAMsNet support' CONFIG_ATARI_PAMSNET fi fi +if [ "$CONFIG_HP300" = "y" ]; then + bool 'HP on-board LANCE support' CONFIG_HPLANCE fi -endmenu - fi +endmenu -source fs/Config.in - -if [ "$CONFIG_VME" = "n" ]; then - define_bool CONFIG_FB y - mainmenu_option next_comment - comment 'Console drivers' - source drivers/video/Config.in - endmenu fi -source fs/nls/Config.in - mainmenu_option next_comment comment 'Character devices' @@ -277,7 +269,7 @@ if [ "$CONFIG_ATARI" = "y" ]; then tristate 'Atari mouse support' CONFIG_ATARIMOUSE fi if [ "$CONFIG_MAC" = "y" ]; then - bool 'Mac ADB mouse support' CONFIG_MACMOUSE + bool 'Mac ADB mouse support' CONFIG_ADBMOUSE fi if [ "$CONFIG_ATARI" = "y" ]; then tristate 'Atari MFP serial support' CONFIG_ATARI_MFPSER @@ -344,6 +336,11 @@ fi if [ "$CONFIG_ATARI" = "y" ]; then bool 'Enhanced Real Time Clock Support' CONFIG_RTC fi +bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS +if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then + int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 +fi + endmenu mainmenu_option next_comment @@ -355,6 +352,22 @@ if [ "$CONFIG_SOUND" != "n" ]; then fi endmenu +source fs/Config.in + +if [ "$CONFIG_VME" = "n" ]; then + if [ "$CONFIG_HP300" = "y" ]; then + bool 'Frame buffer support' CONFIG_FB + else + define_bool CONFIG_FB y + fi + mainmenu_option next_comment + comment 'Console drivers' + source drivers/video/Config.in + endmenu +fi + +source fs/nls/Config.in + mainmenu_option next_comment comment 'Kernel hacking' diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig index e866b5dd3712..5a9f39e52382 100644 --- a/arch/m68k/defconfig +++ b/arch/m68k/defconfig @@ -30,7 +30,8 @@ CONFIG_M68040=y # CONFIG_M68060 is not set # CONFIG_OPTIMIZE_040 is not set # CONFIG_OPTIMIZE_060 is not set -# CONFIG_ADVANCED_CPU is not set +# CONFIG_ADVANCED is not set +# CONFIG_SINGLE_MEMORY_CHUNK is not set # CONFIG_RMW_INSNS is not set # @@ -135,6 +136,7 @@ CONFIG_GVP11_SCSI=y # CONFIG_A4000T_SCSI is not set # CONFIG_A4091_SCSI is not set # CONFIG_WARPENGINE_SCSI is not set +# CONFIG_BLZ603EPLUS_SCSI is not set CONFIG_ATARI_SCSI=y # CONFIG_ATARI_SCSI_TOSHIBA_DELAY is not set # CONFIG_ATARI_SCSI_RESET_BOOT is not set diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile index a59cede945bd..b0252c40cd2a 100644 --- a/arch/m68k/hp300/Makefile +++ b/arch/m68k/hp300/Makefile @@ -8,6 +8,10 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := hp300.o -O_OBJS := ksyms.o config.o ints.o time.o reboot.o hil.o +O_OBJS := ksyms.o config.o ints.o time.o reboot.o + +ifdef CONFIG_VT +O_OBJS += hil.o +endif include $(TOPDIR)/Rules.make diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c index 065430ca5d2b..97fb6e480800 100644 --- a/arch/m68k/hp300/config.c +++ b/arch/m68k/hp300/config.c @@ -24,7 +24,17 @@ #include "time.h" extern void hp300_reset(void); -extern void hp300_hil_init(void); +extern void (*hp300_default_handler[])(int, void *, struct pt_regs *); +extern int hp300_get_irq_list(char *buf); + +#ifdef CONFIG_VT +extern int hp300_keyb_init(void); +#else +/* Dummy function for when there is no keyboard. */ +__initfunc(int hp300_keyb_init(void)) +{ +} +#endif #ifdef CONFIG_HEARTBEAT static void hp300_pulse(int x) @@ -45,20 +55,30 @@ static void hp300_kbd_leds(unsigned int leds) { } +/* for "kbd-reset" cmdline param */ +__initfunc(void hp300_kbd_reset_setup(char *str, int i)) +{ +} + +static void hp300_get_model(char *model) +{ + strcpy(model, "HP9000/300"); +} + __initfunc(void config_hp300(void)) { mach_sched_init = hp300_sched_init; - mach_keyb_init = hp300_hil_init; + mach_keyb_init = hp300_keyb_init; mach_kbdrate = hp300_kbdrate; mach_kbd_leds = hp300_kbd_leds; mach_init_IRQ = hp300_init_IRQ; mach_request_irq = hp300_request_irq; mach_free_irq = hp300_free_irq; -#if 0 + kbd_reset_setup = hp300_kbd_reset_setup; mach_get_model = hp300_get_model; mach_get_irq_list = hp300_get_irq_list; -#endif mach_gettimeoffset = hp300_gettimeoffset; + mach_default_handler = &hp300_default_handler; #if 0 mach_gettod = hp300_gettod; #endif @@ -71,8 +91,3 @@ __initfunc(void config_hp300(void)) #endif mach_max_dma_address = 0xffffffff; } - -/* for "kbd-reset" cmdline param */ -__initfunc(void kbd_reset_setup(char *str, int *ints)) -{ -} diff --git a/arch/m68k/hp300/hil.c b/arch/m68k/hp300/hil.c index 76d45b4d1081..3be0d488a68b 100644 --- a/arch/m68k/hp300/hil.c +++ b/arch/m68k/hp300/hil.c @@ -54,63 +54,155 @@ #define HIL_IRQ 1 -static u_short hp_plain_map[NR_KEYS] __initdata = { - 0xf200, 0xf01b, 0xf20e, 0xf700, 0xf700, 0xf700, 0xf702, 0xf036, - 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009, - 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, - 0xfb62, 0xfb76, 0xf063, 0xfb78, 0xfb7a, 0xf702, 0xfb61, 0xfb73, - 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, - 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xfb63, 0xfb76, - 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200, - 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf104, - 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, - 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, - 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf038, 0xf039, 0xf030, 0xf200, 0xf200, 0xf008, 0xf200, 0xf200, - 0xfb69, 0xfb6f, 0xfb70, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, - 0xfb6a, 0xfb6b, 0xfb6c, 0xf305, 0xf306, 0xf00d, 0xf302, 0xf303, - 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200, - 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 +#define plain_map hp_plain_map +#define shift_map hp_shift_map +#define altgr_map hp_altgr_map +#define ctrl_map hp_ctrl_map +#define shift_ctrl_map hp_shift_ctrl_map +#define alt_map hp_alt_map +#define ctrl_alt_map hp_ctrl_alt_map + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb62, 0xfb76, 0xfb63, 0xfb78, 0xfb7a, 0xf200, 0xf200, 0xf01b, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xf200, 0xf207, + 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf009, + 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf060, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200, + 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf200, 0xf200, + 0xfb69, 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf05c, 0xf200, 0xf200, + 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, 0xf027, 0xf201, 0xf200, 0xf200, + 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602, +}; + +u_short shift_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb42, 0xfb56, 0xfb43, 0xfb58, 0xfb5a, 0xf200, 0xf200, 0xf07f, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb48, 0xfb47, 0xfb46, 0xfb44, 0xfb53, 0xfb41, 0xf200, 0xf207, + 0xfb55, 0xfb59, 0xfb54, 0xfb52, 0xfb45, 0xfb57, 0xfb51, 0xf009, + 0xf026, 0xf05e, 0xf025, 0xf024, 0xf023, 0xf040, 0xf021, 0xf07e, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200, + 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf200, 0xf200, 0xf200, + 0xfb49, 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf07c, 0xf200, 0xf200, + 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a, 0xf022, 0xf201, 0xf200, 0xf200, + 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb4e, 0xf020, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb62, 0xfb76, 0xfb63, 0xfb78, 0xfb7a, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xf200, 0xf207, + 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf040, 0xf021, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200, + 0xf02a, 0xf05b, 0xf05d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb69, 0xfb6f, 0xfb70, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb6a, 0xfb6b, 0xfb6c, 0xf200, 0xf200, 0xf201, 0xf200, 0xf200, + 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb6e, 0xf200, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602, }; -static u_short hp_shift_map[NR_KEYS] __initdata = { - 0xf200, 0xf01b, 0xf20e, 0xf700, 0xf700, 0xf700, 0xf002, 0xf036, - 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009, - 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, - 0xfb62, 0xfb76, 0xf063, 0xfb78, 0xfb7a, 0xf702, 0xfb61, 0xfb73, - 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, - 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xfb63, 0xfb76, - 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200, - 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf104, - 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, - 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, - 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf038, 0xf039, 0xf030, 0xf200, 0xf200, 0xf008, 0xf200, 0xf200, - 0xfb69, 0xfb6f, 0xfb70, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, - 0xfb6a, 0xfb6b, 0xfb6c, 0xf305, 0xf306, 0xf00d, 0xf302, 0xf303, - 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200, - 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf002, 0xf016, 0xf003, 0xf018, 0xf01a, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf008, 0xf007, 0xf006, 0xf004, 0xf013, 0xf001, 0xf200, 0xf207, + 0xf015, 0xf019, 0xf014, 0xf012, 0xf005, 0xf017, 0xf011, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf000, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf503, 0xf502, 0xf501, 0xf500, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf504, 0xf505, 0xf506, 0xf507, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf009, 0xf00f, 0xf010, 0xf200, 0xf200, 0xf01c, 0xf200, 0xf200, + 0xf00a, 0xf00b, 0xf00c, 0xf200, 0xf007, 0xf201, 0xf200, 0xf200, + 0xf00d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf00e, 0xf200, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602, }; -static u_short hp_ctrl_map[NR_KEYS] __initdata = { - 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, - 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200, - 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, - 0xf00f, 0xf010, 0xf003, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013, - 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, - 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016, - 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf07f, 0xf700, 0xf200, - 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, - 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, - 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, - 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf1ff, 0xf202, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, - 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303, - 0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf002, 0xf016, 0xf003, 0xf018, 0xf01a, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf008, 0xf007, 0xf006, 0xf004, 0xf013, 0xf001, 0xf200, 0xf207, + 0xf015, 0xf019, 0xf014, 0xf012, 0xf005, 0xf017, 0xf011, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf009, 0xf00f, 0xf010, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf00a, 0xf00b, 0xf00c, 0xf200, 0xf200, 0xf201, 0xf200, 0xf200, + 0xf00d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf00e, 0xf200, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602, }; +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf862, 0xf876, 0xf863, 0xf878, 0xf87a, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf868, 0xf867, 0xf866, 0xf864, 0xf873, 0xf861, 0xf200, 0xf207, + 0xf875, 0xf879, 0xf874, 0xf872, 0xf865, 0xf877, 0xf871, 0xf809, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf860, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf869, 0xf86f, 0xf870, 0xf200, 0xf200, 0xf85c, 0xf200, 0xf200, + 0xf86a, 0xf86b, 0xf86c, 0xf83b, 0xf827, 0xf201, 0xf200, 0xf200, + 0xf86d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf86e, 0xf200, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf802, 0xf816, 0xf803, 0xf818, 0xf81a, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf808, 0xf807, 0xf806, 0xf804, 0xf813, 0xf801, 0xf200, 0xf207, + 0xf815, 0xf819, 0xf814, 0xf812, 0xf805, 0xf817, 0xf811, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf809, 0xf80f, 0xf810, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf80a, 0xf80b, 0xf80c, 0xf200, 0xf200, 0xf201, 0xf200, 0xf200, + 0xf80d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf80e, 0xf200, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602, +}; + +#undef plain_map +#undef ctrl_alt_map +#undef shift_map +#undef altgr_map +#undef ctrl_map +#undef shift_ctrl_map +#undef alt_map + struct { unsigned char s, c; int valid; @@ -211,7 +303,7 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) * Initialise HIL. */ -__initfunc(void hp300_hil_init(void)) +__initfunc(int hp300_keyb_init(void)) { unsigned char s, c, kbid; unsigned int n = 0; @@ -221,7 +313,7 @@ __initfunc(void hp300_hil_init(void)) memcpy(key_maps[4], hp_ctrl_map, sizeof(plain_map)); if (!hwreg_present((void *)(HILBASE + HIL_DATA))) - return; /* maybe this can happen */ + return 1; /* maybe this can happen */ request_irq(HIL_IRQ, hil_interrupt, 0, "HIL", NULL); @@ -231,20 +323,21 @@ __initfunc(void hp300_hil_init(void)) /* Look for keyboards */ hil_do(HIL_READKBDSADR, NULL, 0); while (!hil_last.valid) { - if (n++ > 1000) { + if (n++ > 100000) { printk("HIL: timed out, assuming no keyboard present.\n"); - return; + return 1; } mb(); } hil_getlast(s, c); if (c == 0) { printk("HIL: no keyboard present.\n"); - return; + return 1; } for (kbid = 0; (kbid < 8) && ((c & (1< * - * This file contains the HP300-specific interrupt handling. There - * isn't much here -- we only use the autovector interrupts and at the - * moment everything difficult is handled by the generic code. + * This file contains the HP300-specific interrupt handling. + * We only use the autovector interrupts, and therefore we need to + * maintain lists of devices sharing each ipl. + * [ipl list code added by Peter Maydell 06/1998] */ -#include +#include #include #include #include @@ -19,29 +20,140 @@ #include #include #include +#include +#include #include "ints.h" -static void hp300_nmi_handler(int irq, void *dev_id, struct pt_regs *fp) +/* Each ipl has a linked list of interrupt service routines. + * Service routines are added via hp300_request_irq() and removed + * via hp300_free_irq(). The device driver should set IRQ_FLG_FAST + * if it needs to be serviced early (eg FIFOless UARTs); this will + * cause it to be added at the front of the queue rather than + * the back. + * Currently IRQ_FLG_SLOW and flags=0 are treated identically; if + * we needed three levels of priority we could distinguish them + * but this strikes me as mildly ugly... + */ + +/* we start with no entries in any list */ +static irq_node_t *hp300_irq_list[HP300_NUM_IRQS] = { [0 ... HP300_NUM_IRQS-1] = NULL }; + +static spinlock_t irqlist_lock; + +/* This handler receives all interrupts, dispatching them to the registered handlers */ +static void hp300_int_handler(int irq, void *dev_id, struct pt_regs *fp) { - extern void hp300_reset(void); - printk("RESET pressed - self destruct sequence initiated.\n"); - hp300_reset(); + irq_node_t *t; + /* We just give every handler on the chain an opportunity to handle + * the interrupt, in priority order. + */ + for(t = hp300_irq_list[irq]; t; t=t->next) + t->handler(irq, t->dev_id, fp); + /* We could put in some accounting routines, checks for stray interrupts, + * etc, in here. Note that currently we can't tell whether or not + * a handler handles the interrupt, though. + */ } +void (*hp300_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { + hp300_int_handler, hp300_int_handler, hp300_int_handler, hp300_int_handler, + hp300_int_handler, hp300_int_handler, hp300_int_handler, NULL +}; + +/* dev_id had better be unique to each handler because it's the only way we have + * to distinguish handlers when removing them... + * + * It would be pretty easy to support IRQ_FLG_LOCK (handler is not replacable) + * and IRQ_FLG_REPLACE (handler replaces existing one with this dev_id) + * if we wanted to. IRQ_FLG_FAST is needed for devices where interrupt latency + * matters (eg the dreaded FIFOless UART...) + */ int hp300_request_irq(unsigned int irq, - void (*handler) (int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) + void (*handler) (int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) { - return sys_request_irq(irq, handler, flags, devname, dev_id); + irq_node_t *t, *n = new_irq_node(); + + if (!n) /* oops, no free nodes */ + return -ENOMEM; + + spin_lock_irqsave(&irqlist_lock, flags); + + if (!hp300_irq_list[irq]) { + /* no list yet */ + hp300_irq_list[irq] = n; + n->next = NULL; + } else if (flags & IRQ_FLG_FAST) { + /* insert at head of list */ + n->next = hp300_irq_list[irq]; + hp300_irq_list[irq] = n; + } else { + /* insert at end of list */ + for(t = hp300_irq_list[irq]; t->next; t = t->next) + /* do nothing */; + n->next = NULL; + t->next = n; + } + + /* Fill in n appropriately */ + n->handler = handler; + n->flags = flags; + n->dev_id = dev_id; + n->devname = devname; + spin_unlock_irqrestore(&irqlist_lock, flags); + return 0; } void hp300_free_irq(unsigned int irq, void *dev_id) { - sys_free_irq(irq, dev_id); + irq_node_t *t; + unsigned long flags; + + spin_lock_irqsave(&irqlist_lock, flags); + + t = hp300_irq_list[irq]; + if (!t) /* no handlers at all for that IRQ */ + { + printk(KERN_ERR "hp300_free_irq: attempt to remove nonexistent handler for IRQ %d\n", irq); + spin_unlock_irqrestore(&irqlist_lock, flags); + return; + } + + if (t->dev_id == dev_id) + { /* removing first handler on chain */ + t->flags = IRQ_FLG_STD; /* we probably don't really need these */ + t->dev_id = NULL; + t->devname = NULL; + t->handler = NULL; /* frees this irq_node_t */ + hp300_irq_list[irq] = t->next; + spin_unlock_irqrestore(&irqlist_lock, flags); + return; + } + + /* OK, must be removing from middle of the chain */ + + for (t = hp300_irq_list[irq]; t->next && t->next->dev_id != dev_id; t = t->next) + /* do nothing */; + if (!t->next) + { + printk(KERN_ERR "hp300_free_irq: attempt to remove nonexistent handler for IRQ %d\n", irq); + spin_unlock_irqrestore(&irqlist_lock, flags); + return; + } + /* remove the entry after t: */ + t->next->flags = IRQ_FLG_STD; + t->next->dev_id = t->next->devname = t->next->handler = NULL; + t->next = t->next->next; + + spin_unlock_irqrestore(&irqlist_lock, flags); +} + +int hp300_get_irq_list(char *buf) +{ + return 0; } __initfunc(void hp300_init_IRQ(void)) { - /* IPL6 - NMI (keyboard reset) */ - sys_request_irq(7, hp300_nmi_handler, IRQ_FLG_STD, "NMI", hp300_nmi_handler); + spin_lock_init(&irqlist_lock); } diff --git a/arch/m68k/hp300/ints.h b/arch/m68k/hp300/ints.h index 38b62b61becc..26cb8d07784a 100644 --- a/arch/m68k/hp300/ints.h +++ b/arch/m68k/hp300/ints.h @@ -4,3 +4,6 @@ extern void hp300_free_irq(unsigned int irq, void *dev_id); extern int hp300_request_irq(unsigned int irq, void (*handler) (int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); + +/* number of interrupts, includes 0 (what's that?) */ +#define HP300_NUM_IRQS 8 diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c index 2a60c5621a84..d29c3c5f4365 100644 --- a/arch/m68k/hp300/time.c +++ b/arch/m68k/hp300/time.c @@ -31,10 +31,10 @@ #define CLKMSB2 0x9 #define CLKMSB3 0xD -unsigned long hp300_gettimeoffset (void) -{ - return 0L; -} +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) + +#define INTVAL ((10000 / 4) - 1) static void hp300_tick(int irq, void *dev_id, struct pt_regs *regs) { @@ -45,18 +45,31 @@ static void hp300_tick(int irq, void *dev_id, struct pt_regs *regs) vector(irq, NULL, regs); } -__initfunc(void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *))) +unsigned long hp300_gettimeoffset(void) { - unsigned int intval = (10000 / 4) - 1; + /* Read current timer 1 value */ + unsigned char lsb, msb1, msb2; + unsigned short ticks; + msb1 = readb(CLOCKBASE + 5); + lsb = readb(CLOCKBASE + 7); + msb2 = readb(CLOCKBASE + 5); + if (msb1 != msb2) + /* A carry happened while we were reading. Read it again */ + lsb = readb(CLOCKBASE + 7); + ticks = INTVAL - ((msb2 << 8) | lsb); + return (USECS_PER_JIFFY * ticks) / INTVAL; +} + +__initfunc(void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *))) +{ writeb(0x1, CLOCKBASE + CLKCR2); /* select CR1 */ writeb(0x1, CLOCKBASE + CLKCR1); /* reset */ - asm volatile(" movpw %0,%1@(5)" : : "d" (intval), "a" (CLOCKBASE)); + asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE)); sys_request_irq(6, hp300_tick, IRQ_FLG_STD, "timer tick", vector); writeb(0x1, CLOCKBASE + CLKCR2); /* select CR1 */ writeb(0x40, CLOCKBASE + CLKCR1); /* enable irq */ } - diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index eba9842cf29d..f4c1343cae85 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -418,7 +418,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_lseek) .long SYMBOL_NAME(sys_getpid) /* 20 */ .long SYMBOL_NAME(sys_mount) - .long SYMBOL_NAME(sys_umount) + .long SYMBOL_NAME(sys_oldumount) .long SYMBOL_NAME(sys_setuid) .long SYMBOL_NAME(sys_getuid) .long SYMBOL_NAME(sys_stime) /* 25 */ @@ -448,7 +448,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_geteuid) .long SYMBOL_NAME(sys_getegid) /* 50 */ .long SYMBOL_NAME(sys_acct) - .long SYMBOL_NAME(sys_ni_syscall) /* old phys syscall holder */ + .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ .long SYMBOL_NAME(sys_ioctl) .long SYMBOL_NAME(sys_fcntl) /* 55 */ diff --git a/arch/m68k/kernel/m68k_defs.h b/arch/m68k/kernel/m68k_defs.h index 992d390c75f9..b32e6a1c9941 100644 --- a/arch/m68k/kernel/m68k_defs.h +++ b/arch/m68k/kernel/m68k_defs.h @@ -3,6 +3,6 @@ */ #define TS_MAGICKEY 0x5a5a5a5a -#define TS_TSS 478 -#define TS_ESP0 498 -#define TS_FPU 502 +#define TS_TSS 482 +#define TS_ESP0 502 +#define TS_FPU 506 diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index dac2bfcc8929..fb9bac4000e4 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -134,29 +134,20 @@ void flush_thread(void) asmlinkage int m68k_fork(struct pt_regs *regs) { - int ret; - - lock_kernel(); - ret = do_fork(SIGCHLD, rdusp(), regs); - unlock_kernel(); - return ret; + return do_fork(SIGCHLD, rdusp(), regs); } asmlinkage int m68k_clone(struct pt_regs *regs) { unsigned long clone_flags; unsigned long newsp; - int ret; - lock_kernel(); /* syscall2 puts clone_flags in d1 and usp in d2 */ clone_flags = regs->d1; newsp = regs->d2; if (!newsp) - newsp = rdusp(); - ret = do_fork(clone_flags, newsp, regs); - unlock_kernel(); - return ret; + newsp = rdusp(); + return do_fork(clone_flags, newsp, regs); } int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index 6df005fb4865..e12786344c8c 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #ifdef CONFIG_AMIGA #include @@ -123,7 +124,7 @@ __initfunc(static void m68k_parse_bootinfo(const struct bi_record *record)) /* Already set up by head.S */ break; - case BI_MEMCHUNK: + case BI_MEMCHUNK: if (m68k_num_memory < NUM_MEMINFO) { m68k_memory[m68k_num_memory].addr = data[0]; m68k_memory[m68k_num_memory].size = data[1]; @@ -157,6 +158,14 @@ __initfunc(static void m68k_parse_bootinfo(const struct bi_record *record)) record->tag); record = (struct bi_record *)((u_long)record+record->size); } + +#ifdef CONFIG_SINGLE_MEMORY_CHUNK + if (m68k_num_memory > 1) { + printk("Ignoring last %i chunks of physical memory\n", + (m68k_num_memory - 1)); + m68k_num_memory = 1; + } +#endif } __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, @@ -270,7 +279,7 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, #ifdef CONFIG_BLK_DEV_INITRD if (m68k_ramdisk.size) { - initrd_start = PTOV (m68k_ramdisk.addr); + initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr); initrd_end = initrd_start + m68k_ramdisk.size; } #endif diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 03214a42f712..af5af69b62f4 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -808,16 +808,11 @@ static void setup_frame (int sig, struct k_sigaction *ka, push_cache ((unsigned long) &frame->retcode); - /* - * no matter what frame format we were using before, we - * will do the "RTE" using a normal 4 word frame. - */ - regs->format = 0; - /* Set up registers for signal handler */ wrusp ((unsigned long) frame); regs->pc = (unsigned long) ka->sa.sa_handler; +adjust_stack: /* Prepare to skip over the extra stuff in the exception frame. */ if (regs->stkadj) { struct pt_regs *tregs = @@ -827,8 +822,8 @@ static void setup_frame (int sig, struct k_sigaction *ka, #endif /* This must be copied with decreasing addresses to handle overlaps. */ - tregs->vector = regs->vector; - tregs->format = regs->format; + tregs->vector = 0; + tregs->format = 0; tregs->pc = regs->pc; tregs->sr = regs->sr; } @@ -838,6 +833,7 @@ give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); + goto adjust_stack; } static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, @@ -895,16 +891,11 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, push_cache ((unsigned long) &frame->retcode); - /* - * no matter what frame format we were using before, we - * will do the "RTE" using a normal 4 word frame. - */ - regs->format = 0; - /* Set up registers for signal handler */ wrusp ((unsigned long) frame); regs->pc = (unsigned long) ka->sa.sa_handler; +adjust_stack: /* Prepare to skip over the extra stuff in the exception frame. */ if (regs->stkadj) { struct pt_regs *tregs = @@ -914,8 +905,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, #endif /* This must be copied with decreasing addresses to handle overlaps. */ - tregs->vector = regs->vector; - tregs->format = regs->format; + tregs->vector = 0; + tregs->format = 0; tregs->pc = regs->pc; tregs->sr = regs->sr; } @@ -925,6 +916,7 @@ give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); + goto adjust_stack; } static inline void @@ -970,7 +962,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, setup_frame(sig, ka, oldset, regs); if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = NULL; + ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NODEFER)) { sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -1030,10 +1022,8 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) discard_frame: /* Make sure that a faulted bus cycle isn't restarted (only needed on the 680[23]0). */ - if (regs->format == 10 || regs->format == 11) { + if (regs->format == 10 || regs->format == 11) regs->stkadj = frame_extra_sizes[regs->format]; - regs->format = 0; - } continue; } current->exit_code = 0; @@ -1126,8 +1116,8 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) /* This must be copied with decreasing addresses to handle overlaps. */ - tregs->vector = regs->vector; - tregs->format = regs->format; + tregs->vector = 0; + tregs->format = 0; tregs->pc = regs->pc; tregs->sr = regs->sr; } diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c index 35bf38d1ed73..5110cac4ab33 100644 --- a/arch/m68k/lib/checksum.c +++ b/arch/m68k/lib/checksum.c @@ -26,6 +26,10 @@ * 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. + * + * 1998/8/31 Andreas Schwab: + * Zero out rest of buffer on exception in + * csum_partial_copy_from_user. */ #include @@ -239,23 +243,71 @@ csum_partial_copy_from_user(const char *src, char *dst, int len, "8:\n" ".section .fixup,\"ax\"\n" ".even\n" + /* If any execption occurs zero out the rest. + Similarities with the code above are intentional :-) */ + "90:\t" + "clrw %3@+\n\t" + "movel %1,%4\n\t" + "lsrl #5,%1\n\t" + "jeq 1f\n\t" + "subql #1,%1\n" + "91:\t" + "clrl %3@+\n" + "92:\t" + "clrl %3@+\n" + "93:\t" + "clrl %3@+\n" + "94:\t" + "clrl %3@+\n" + "95:\t" + "clrl %3@+\n" + "96:\t" + "clrl %3@+\n" + "97:\t" + "clrl %3@+\n" + "98:\t" + "clrl %3@+\n\t" + "dbra %1,91b\n\t" + "clrw %1\n\t" + "subql #1,%1\n\t" + "jcc 91b\n" + "1:\t" + "movel %4,%1\n\t" + "andw #0x1c,%4\n\t" + "jeq 1f\n\t" + "lsrw #2,%4\n\t" + "subqw #1,%4\n" + "99:\t" + "clrl %3@+\n\t" + "dbra %4,99b\n\t" + "1:\t" + "andw #3,%1\n\t" + "jeq 9f\n" + "100:\t" + "clrw %3@+\n\t" + "tstw %1\n\t" + "jeq 9f\n" + "101:\t" + "clrb %3@+\n" "9:\t" - "moveq #-14,%5\n\t" /* -EFAULT, out of inputs to asm ;( */ +#define STR(X) STR1(X) +#define STR1(X) #X + "moveq #-" STR(EFAULT) ",%5\n\t" "jra 8b\n" ".previous\n" ".section __ex_table,\"a\"\n" - ".long 10b,9b\n" - ".long 11b,9b\n" - ".long 12b,9b\n" - ".long 13b,9b\n" - ".long 14b,9b\n" - ".long 15b,9b\n" - ".long 16b,9b\n" - ".long 17b,9b\n" - ".long 18b,9b\n" - ".long 19b,9b\n" - ".long 20b,9b\n" - ".long 21b,9b\n" + ".long 10b,90b\n" + ".long 11b,91b\n" + ".long 12b,92b\n" + ".long 13b,93b\n" + ".long 14b,94b\n" + ".long 15b,95b\n" + ".long 16b,96b\n" + ".long 17b,97b\n" + ".long 18b,98b\n" + ".long 19b,99b\n" + ".long 20b,100b\n" + ".long 21b,101b\n" ".previous" : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), "=&d" (tmp1), "=d" (tmp2) @@ -267,16 +319,6 @@ csum_partial_copy_from_user(const char *src, char *dst, int len, return(sum); } -/* - * This one will go away soon. - */ -unsigned int -csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum) -{ - int dummy; - - return csum_partial_copy_from_user(src, dst, len, sum, &dummy); -} /* * copy from kernel space while checksumming, otherwise like csum_partial */ diff --git a/arch/m68k/mac/mac_ksyms.c b/arch/m68k/mac/mac_ksyms.c index 05373b04e092..a558d16844fa 100644 --- a/arch/m68k/mac/mac_ksyms.c +++ b/arch/m68k/mac/mac_ksyms.c @@ -2,6 +2,6 @@ #include #include /* Hook for mouse driver */ -extern void (*mac_mouse_interrupt_hook) (char *); +extern void (*adb_mouse_interrupt_hook) (char *); -EXPORT_SYMBOL(mac_mouse_interrupt_hook); +EXPORT_SYMBOL(adb_mouse_interrupt_hook); diff --git a/arch/m68k/mac/mackeyb.c b/arch/m68k/mac/mackeyb.c index 5946a9e8b178..fa529e29e862 100644 --- a/arch/m68k/mac/mackeyb.c +++ b/arch/m68k/mac/mackeyb.c @@ -59,9 +59,7 @@ static void mac_leds_done(struct adb_request *); static void keyboard_input(unsigned char *, int, struct pt_regs *); static void mouse_input(unsigned char *, int, struct pt_regs *); /* Hook for mouse driver */ -void (*mac_mouse_interrupt_hook) (char *); -int mac_emulate_button2; -int mac_emulate_button3; +void (*adb_mouse_interrupt_hook) (unsigned char *, int); /* The mouse driver - for debugging */ extern void mac_mouse_interrupt(char *); /* end keyb */ @@ -290,11 +288,11 @@ input_keycode(int keycode, int repeat) * (wanted: command and alt/option, or KP= and KP( ...) * Debug version; might be rewritten to be faster on normal keys. */ - if (mac_mouse_interrupt_hook || console_loglevel >= 8) { + if (adb_mouse_interrupt_hook || console_loglevel >= 8) { unsigned char button, button2, button3, fake_event; static unsigned char button2state=0, button3state=0; /* up */ - /* faked ADB packet: device type ff, handler 4 ! */ - static char data[6] = { 0xff, 0x40, 0x3c, 0x80, 0x80, 0x80 }; + /* faked ADB packet */ + static unsigned char data[4] = { 0, 0x80, 0x80, 0x80 }; button = 0; fake_event = 0; @@ -321,16 +319,16 @@ input_keycode(int keycode, int repeat) #endif if (button) { /* there's been a button state change */ /* fake a mouse packet : send all bytes, change one! */ - data[button+2] = (up_flag ? 0x80 : 0); - if (mac_mouse_interrupt_hook) - mac_mouse_interrupt_hook(data); + data[button] = (up_flag ? 0x80 : 0); + if (adb_mouse_interrupt_hook) + adb_mouse_interrupt_hook(data, 4); #ifdef DEBUG_ADBMOUSE else printk("mouse_fake: data %2x %2x %2x buttons %2x \n", - data[3], data[4], data[5], - ~( (data[3] & 0x80 ? 0 : 4) - | (data[4] & 0x80 ? 0 : 1) - | (data[5] & 0x80 ? 0 : 2) )&7 ); + data[1], data[2], data[3], + ~( (data[1] & 0x80 ? 0 : 4) + | (data[2] & 0x80 ? 0 : 1) + | (data[3] & 0x80 ? 0 : 2) )&7 ); #endif } /* @@ -485,8 +483,8 @@ mouse_input(unsigned char *data, int nb, struct pt_regs *regs) return; } - if (mac_mouse_interrupt_hook) { - mac_mouse_interrupt_hook(data); + if (adb_mouse_interrupt_hook) { + adb_mouse_interrupt_hook(data+2, nb-2); /* * passing the mouse data to i.e. the X server as done for * Xpmac will confuse applications on a sane X server :-) @@ -609,10 +607,7 @@ __initfunc(int mac_keyb_init(void)) memcpy(key_maps[12], mac_ctrl_alt_map, sizeof(plain_map)); /* initialize mouse interrupt hook */ - mac_mouse_interrupt_hook = NULL; - /* assume broken mouse :-) */ - mac_emulate_button2 = 1; - mac_emulate_button3 = 1; + adb_mouse_interrupt_hook = NULL; /* * Might put that someplace else, possibly .... diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c index 7ea05b3dd47e..395fb41b6f23 100644 --- a/arch/m68k/mm/init.c +++ b/arch/m68k/mm/init.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef CONFIG_ATARI #include #endif @@ -238,7 +239,7 @@ map_chunk (unsigned long addr, unsigned long size, unsigned long *memavailp)) ktablep = kernel_page_table (memavailp); } - ktable = VTOP(ktablep); + ktable = virt_to_phys(ktablep); /* * initialize section of the page table mapping @@ -278,7 +279,7 @@ map_chunk (unsigned long addr, unsigned long size, unsigned long *memavailp)) tbl = (unsigned long *)get_kpointer_table(); - kpointerp[pindex++] = VTOP(tbl) | _PAGE_TABLE |_PAGE_ACCESSED; + kpointerp[pindex++] = virt_to_phys(tbl) | _PAGE_TABLE |_PAGE_ACCESSED; for (i = 0; i < 64; i++, physaddr += PAGE_SIZE) tbl[i] = physaddr | _PAGE_PRESENT | _PAGE_ACCESSED; @@ -289,7 +290,7 @@ map_chunk (unsigned long addr, unsigned long size, unsigned long *memavailp)) /* not the first 256K */ kpointerp[pindex++] = physaddr | _PAGE_PRESENT | _PAGE_ACCESSED; #ifdef DEBUG - printk ("%lx=%lx ", VTOP(&kpointerp[pindex-1]), + printk ("%lx=%lx ", virt_to_phys(&kpointerp[pindex-1]), kpointerp[pindex-1]); #endif physaddr += 64 * PAGE_SIZE; @@ -398,7 +399,7 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, /* setup CPU root pointer for swapper task */ task[0]->tss.crp[0] = 0x80000000 | _PAGE_TABLE; - task[0]->tss.crp[1] = VTOP (swapper_pg_dir); + task[0]->tss.crp[1] = virt_to_phys (swapper_pg_dir); #ifdef DEBUG printk ("task 0 pagedir at %p virt, %#lx phys\n", @@ -456,7 +457,7 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) #endif for (tmp = 0 ; tmp < end_mem ; tmp += PAGE_SIZE) { - if (VTOP (tmp) >= mach_max_dma_address) + if (virt_to_phys ((void *)tmp) >= mach_max_dma_address) clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags); if (PageReserved(mem_map+MAP_NR(tmp))) { if (tmp >= (unsigned long)&_text diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c index be716a5b24a4..802771ab477a 100644 --- a/arch/m68k/mm/kmap.c +++ b/arch/m68k/mm/kmap.c @@ -277,8 +277,11 @@ unsigned long kernel_map(unsigned long phys_addr, unsigned long size, size = (size + KMAP_STEP - 1) & ~(KMAP_STEP-1); down( &kmap_sem ); - if (!(kmap = kmap_get_region( size, memavailp == NULL ))) - return( 0 ); + kmap = kmap_get_region(size, memavailp == NULL); + if (!kmap) { + up(&kmap_sem); + return 0; + } from = kmap->addr; retaddr += from; kmap->mapaddr = retaddr; diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c index ad7c8141a61f..fb13d8257f9b 100644 --- a/arch/m68k/mm/memory.c +++ b/arch/m68k/mm/memory.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef CONFIG_AMIGA #include #endif @@ -299,14 +300,14 @@ static unsigned long transp_transl_matches( unsigned long regval, return( (vaddr & mask) == (base & mask) ); } -static unsigned long mm_vtop_fallback (unsigned long); - +#ifndef CONFIG_SINGLE_MEMORY_CHUNK /* * The following two routines map from a physical address to a kernel * virtual address and vice versa. */ unsigned long mm_vtop (unsigned long vaddr) { +#ifndef CONFIG_SINGLE_MEMORY_CHUNK int i=0; unsigned long voff = vaddr; unsigned long offset = 0; @@ -322,12 +323,18 @@ unsigned long mm_vtop (unsigned long vaddr) offset += m68k_memory[i].size; i++; }while (i < m68k_num_memory); +#else + if (vaddr < m68k_memory[0].size) + return m68k_memory[0].addr + vaddr; +#endif + return mm_vtop_fallback(vaddr); } +#endif /* Separate function to make the common case faster (needs to save less registers) */ -static unsigned long mm_vtop_fallback (unsigned long vaddr) +unsigned long mm_vtop_fallback (unsigned long vaddr) { /* not in one of the memory chunks; test for applying transparent * translation */ @@ -420,7 +427,7 @@ static unsigned long mm_vtop_fallback (unsigned long vaddr) if (mmusr & (MMU_I|MMU_B|MMU_L)) panic ("VTOP030: bad virtual address %08lx (%x)", vaddr, mmusr); - descaddr = (unsigned long *)PTOV(descaddr); + descaddr = phys_to_virt((unsigned long)descaddr); switch (mmusr & MMU_NUM) { case 1: @@ -438,8 +445,10 @@ static unsigned long mm_vtop_fallback (unsigned long vaddr) panic ("VTOP: bad virtual address %08lx", vaddr); } +#ifndef CONFIG_SINGLE_MEMORY_CHUNK unsigned long mm_ptov (unsigned long paddr) { +#ifndef CONFIG_SINGLE_MEMORY_CHUNK int i = 0; unsigned long offset = 0; @@ -456,6 +465,11 @@ unsigned long mm_ptov (unsigned long paddr) offset += m68k_memory[i].size; i++; }while (i < m68k_num_memory); +#else + unsigned long base = m68k_memory[0].addr; + if (paddr >= base && paddr < (base + m68k_memory[0].size)) + return (paddr - base); +#endif /* * assume that the kernel virtual address is the same as the @@ -482,6 +496,7 @@ unsigned long mm_ptov (unsigned long paddr) #endif return paddr; } +#endif /* invalidate page in both caches */ #define clear040(paddr) \ @@ -635,6 +650,7 @@ void cache_push (unsigned long paddr, int len) #undef pushcl040 #undef pushcli040 +#ifndef CONFIG_SINGLE_MEMORY_CHUNK int mm_end_of_chunk (unsigned long addr, int len) { int i; @@ -644,4 +660,4 @@ int mm_end_of_chunk (unsigned long addr, int len) return 1; return 0; } - +#endif diff --git a/drivers/char/ChangeLog b/drivers/char/ChangeLog index eddd9e674639..7e055801344c 100644 --- a/drivers/char/ChangeLog +++ b/drivers/char/ChangeLog @@ -1,3 +1,8 @@ +1998-08-26 Theodore Ts'o + + * serial.c (rs_open): Correctly decrement the module in-use count + on errors. + Thu Feb 19 14:24:08 1998 Theodore Ts'o * tty_io.c (tty_name): Remove the non-reentrant (and non-SMP safe) diff --git a/drivers/char/apm_bios.c b/drivers/char/apm_bios.c index 32f109be32f5..08b3a78a2135 100644 --- a/drivers/char/apm_bios.c +++ b/drivers/char/apm_bios.c @@ -1,7 +1,7 @@ /* -*- linux-c -*- * APM BIOS driver for Linux - * Copyright 1994, 1995, 1996 Stephen Rothwell - * (Stephen.Rothwell@canb.auug.org.au) + * Copyright 1994-1998 Stephen Rothwell + * (Stephen.Rothwell@canb.auug.org.au) * * 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 @@ -13,8 +13,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * $Id: apm_bios.c,v 0.22 1995/03/09 14:12:02 sfr Exp $ - * * October 1995, Rik Faith (faith@cs.unc.edu): * Minor enhancements and updates (to the patch set) for 1.3.x * Documentation @@ -28,6 +26,7 @@ * May 1996, Version 1.2 * Feb 1998, Version 1.3 * Feb 1998, Version 1.4 + * Aug 1998, Version 1.5 * * History: * 0.6b: first version in official kernel, Linux 1.3.46 @@ -50,6 +49,9 @@ * 1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by * Dean Gaudet . * C. Scott Ananian Linux 2.1.87 + * 1.5: Fix segment register reloading (in case of bad segments saved + * across BIOS call). + * Stephen ROthwell * * APM 1.1 Reference: * @@ -158,6 +160,7 @@ extern unsigned long get_cmos_time(void); * [Confirmed by TI representative] * U: ACER 486DX4/75: uses dseg 0040, in violation of APM specification * [Confirmed by BIOS disassembly] + * [This may work now ...] * P: Toshiba 1950S: battery life information only gets updated after resume * P: Midwest Micro Soundbook Elite DX2/66 monochrome: screen blanking * broken in BIOS [Reported by Garst R. Reese ] @@ -180,6 +183,7 @@ extern unsigned long get_cmos_time(void); /* * Define to disable interrupts in APM BIOS calls (the CPU Idle BIOS call * should turn interrupts on before it does a 'hlt'). + * This reportedly needs undefining for the ThinkPad 600. */ #define APM_NOINTS @@ -207,121 +211,9 @@ extern unsigned long get_cmos_time(void); #define APM_CHECK_TIMEOUT (HZ) /* - * These are the actual BIOS calls in assembler. Depending on - * APM_ZERO_SEGS and APM_NOINTS, we are being really paranoid here! Not - * only are interrupts disabled, but all the segment registers (except SS) - * are saved and zeroed this means that if the BIOS tries to reference any - * data without explicitly loading the segment registers, the kernel will - * fault immediately rather than have some unforeseen circumstances for the - * rest of the kernel. And it will be very obvious! :-) Doing this - * depends on CS referring to the same physical memory as DS so that DS can - * be zeroed before the call. Unfortunately, we can't do anything about the - * stack segment/pointer. Also, we tell the compiler that everything could - * change. + * Save a segment register away */ -#ifdef APM_NOINTS -# define APM_DO_CLI "cli\n\t" -#else -# define APM_DO_CLI -#endif -#ifdef APM_ZERO_SEGS -# define APM_DO_ZERO_SEGS \ - "pushl %%ds\n\t" \ - "pushl %%es\n\t" \ - "pushl %%fs\n\t" \ - "pushl %%gs\n\t" \ - "xorl %%edx, %%edx\n\t" \ - "movl %%dx, %%ds\n\t" \ - "movl %%dx, %%es\n\t" \ - "movl %%dx, %%fs\n\t" \ - "movl %%dx, %%gs\n\t" -# define APM_DO_RESTORE_SEGS \ - "popl %%gs\n\t" \ - "popl %%fs\n\t" \ - "popl %%es\n\t" \ - "popl %%ds\n\t" -#else -# define APM_DO_ZERO_SEGS -# define APM_DO_RESTORE_SEGS -#endif - -#define APM_BIOS_CALL(error_reg) \ - __asm__ __volatile__( \ - APM_DO_ZERO_SEGS \ - "pushfl\n\t" \ - APM_DO_CLI \ - "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t" \ - "setc %%" # error_reg "\n\t" \ - "popfl\n\t" \ - APM_DO_RESTORE_SEGS -#define APM_BIOS_CALL_END \ - : "ax", "bx", "cx", "dx", "si", "di", "bp", "memory") - -#ifdef CONFIG_APM_CPU_IDLE -#define APM_SET_CPU_IDLE(error) \ - APM_BIOS_CALL(al) \ - : "=a" (error) \ - : "a" (0x5305) \ - APM_BIOS_CALL_END -#endif - -#define APM_SET_CPU_BUSY(error) \ - APM_BIOS_CALL(al) \ - : "=a" (error) \ - : "a" (0x5306) \ - APM_BIOS_CALL_END - -#define APM_SET_POWER_STATE(state, error) \ - APM_BIOS_CALL(al) \ - : "=a" (error) \ - : "a" (0x5307), "b" (0x0001), "c" (state) \ - APM_BIOS_CALL_END - -#ifdef CONFIG_APM_DISPLAY_BLANK -#define APM_SET_DISPLAY_POWER_STATE(state, error) \ - APM_BIOS_CALL(al) \ - : "=a" (error) \ - : "a" (0x5307), "b" (0x01ff), "c" (state) \ - APM_BIOS_CALL_END -#endif - -#ifdef CONFIG_APM_DO_ENABLE -#define APM_ENABLE_POWER_MANAGEMENT(device, error) \ - APM_BIOS_CALL(al) \ - : "=a" (error) \ - : "a" (0x5308), "b" (device), "c" (1) \ - APM_BIOS_CALL_END -#endif - -#define APM_GET_POWER_STATUS(bx, cx, dx, error) \ - APM_BIOS_CALL(al) \ - : "=a" (error), "=b" (bx), "=c" (cx), "=d" (dx) \ - : "a" (0x530a), "b" (1) \ - APM_BIOS_CALL_END - -#define APM_GET_BATTERY_STATUS(which, bx, cx, dx, si, error) \ - APM_BIOS_CALL(al) \ - : "=a" (error), "=b" (bx), "=c" (cx), "=d" (dx), "=S" (si) \ - : "a" (0x530a), "b" (0x8000 | (which)) \ - APM_BIOS_CALL_END - -#define APM_GET_EVENT(event, info, error) \ - APM_BIOS_CALL(al) \ - : "=a" (error), "=b" (event), "=c" (info) \ - : "a" (0x530b) \ - APM_BIOS_CALL_END - -#define APM_DRIVER_VERSION(ver, ax, error) \ - APM_BIOS_CALL(bl) \ - : "=a" (ax), "=b" (error) \ - : "a" (0x530e), "b" (0), "c" (ver) \ - APM_BIOS_CALL_END - -#define APM_ENGAGE_POWER_MANAGEMENT(device, error) \ - APM_BIOS_CALL(al) \ - : "=a" (error) \ - : "a" (0x530f), "b" (device), "c" (1) \ - APM_BIOS_CALL_END +#define savesegment(seg, where) __asm__ __volatile__("movw %%" #seg ", %0\n" : "=m" (where)) /* * Forward declarations @@ -371,7 +263,7 @@ static struct apm_bios_struct * user_list = NULL; static struct timer_list apm_timer; -static char driver_version[] = "1.4"; /* no spaces */ +static char driver_version[] = "1.5"; /* no spaces */ #ifdef APM_DEBUG static char * apm_event_name[] = { @@ -445,74 +337,197 @@ static const lookup_t error_table[] = { }; #define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t)) -static int apm_driver_version(u_short *val) +/* + * These are the actual BIOS calls. Depending on APM_ZERO_SEGS + * and APM_NOINTS, we are being really paranoid here! Not only are + * interrupts disabled, but all the segment registers (except SS) are + * saved and zeroed this means that if the BIOS tries to reference any + * data without explicitly loading the segment registers, the kernel will + * fault immediately rather than have some unforeseen circumstances for + * the rest of the kernel. And it will be very obvious! :-) Doing this + * depends on CS referring to the same physical memory as DS so that DS + * can be zeroed before the call. Unfortunately, we can't do anything + * about the stack segment/pointer. Also, we tell the compiler that + * everything could change. + */ + +static inline int apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in, + u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi) { - u_short error; + u16 old_fs; + u16 old_gs; + int error; + +#ifdef APM_ZERO_SEGS + savesegment(fs, old_fs); + savesegment(gs, old_gs); +#endif + __asm__ __volatile__( + "pushfl\n\t" +#ifdef APM_NOINTS + "cli\n\t" +#endif +#ifdef APM_ZERO_SEGS + "pushl %%ds\n\t" + "pushl %%es\n\t" + "movw %9, %%ds\n\t" + "movw %9, %%es\n\t" + "movw %9, %%fs\n\t" + "movw %9, %%gs\n\t" +#endif + "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t" + "movl $0, %%edi\n\t" + "jnc 1f\n\t" + "movl $1, %%edi\n" + "1:\tpopl %%es\n\t" + "popl %%ds\n\t" + "popfl\n\t" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx), + "=S" (*esi), "=D" (error) + : "a" (eax_in), "b" (ebx_in), "c" (ecx_in) +#ifdef APM_ZERO_SEGS + , "r" (0) +#endif + : "ax", "bx", "cx", "dx", "si", "di", "bp", "memory"); +#ifdef APM_ZERO_SEGS + loadsegment(fs, old_fs); + loadsegment(gs, old_gs); +#endif + return error; +} + +/* + * This version only returns one value (usually an error code) + */ - APM_DRIVER_VERSION(*val, *val, error); +static inline int apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in, u32 *eax) +{ + u16 old_fs; + u16 old_gs; + int error; - if (error & 0xff) - return (*val >> 8); +#ifdef APM_ZERO_SEGS + savesegment(fs, old_fs); + savesegment(gs, old_gs); +#endif + __asm__ __volatile__( + "pushfl\n\t" +#ifdef APM_NOINTS + "cli\n\t" +#endif +#ifdef APM_ZERO_SEGS + "pushl %%ds\n\t" + "pushl %%es\n\t" + "movw %5, %%ds\n\t" + "movw %5, %%es\n\t" + "movw %5, %%fs\n\t" + "movw %5, %%gs\n\t" +#endif + "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t" + "movl $0, %%edi\n\t" + "jnc 1f\n\t" + "movl $1, %%edi\n" + "1:\tpopl %%es\n\t" + "popl %%ds\n\t" + "popfl\n\t" + : "=a" (*eax), "=D" (error) + : "a" (eax_in), "b" (ebx_in), "c" (ecx_in) +#ifdef APM_ZERO_SEGS + , "r" (0) +#endif + : "ax", "bx", "cx", "dx", "si", "di", "bp", "memory"); +#ifdef APM_ZERO_SEGS + loadsegment(fs, old_fs); + loadsegment(gs, old_gs); +#endif + return error; +} + +static int apm_driver_version(u_short *val) +{ + int error; + u32 eax; + + error = apm_bios_call_simple(0x530e, 0, *val, &eax); + if (error) + return (eax >> 8) & 0xff; + *val = eax; return APM_SUCCESS; } static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info) { - u_short error; + int error; + u32 eax; + u32 ebx; + u32 ecx; + u32 dummy; - APM_GET_EVENT(*event, *info, error); - if (error & 0xff) - return (error >> 8); + error = apm_bios_call(0x530b, 0, 0, &eax, &ebx, &ecx, &dummy, &dummy); + if (error) + return (eax >> 8) & 0xff; + *event = ebx; if (apm_bios_info.version < 0x0102) *info = ~0; /* indicate info not valid */ + else + *info = ecx; return APM_SUCCESS; } -int apm_set_power_state(u_short state) +static int set_power_state(u_short what, u_short state) { - u_short error; + int error; + u32 eax; - APM_SET_POWER_STATE(state, error); - if (error & 0xff) - return (error >> 8); + error = apm_bios_call_simple(0x5307, what, state, &eax); + if (error) + return (eax >> 8) & 0xff; return APM_SUCCESS; } +int apm_set_power_state(u_short state) +{ + return set_power_state(0x0001, state); +} + #ifdef CONFIG_APM_DISPLAY_BLANK /* Called by apm_display_blank and apm_display_unblank when apm_enabled. */ static int apm_set_display_power_state(u_short state) { - u_short error; - - APM_SET_DISPLAY_POWER_STATE(state, error); - if (error & 0xff) - return (error >> 8); - return APM_SUCCESS; + return set_power_state(0x01ff, state); } #endif #ifdef CONFIG_APM_DO_ENABLE /* Called by apm_setup if apm_enabled will be true. */ -static inline int apm_enable_power_management(void) +static int apm_enable_power_management(void) { - u_short error; + int error; + u32 eax; - APM_ENABLE_POWER_MANAGEMENT((apm_bios_info.version > 0x100) - ? 0x0001 : 0xffff, - error); - if (error & 0xff) - return (error >> 8); + error = apm_bios_call_simple(0x5308, + (apm_bios_info.version > 0x100) ? 0x0001 : 0xffff, 1, &eax); + if (error) + return (eax >> 8) & 0xff; return APM_SUCCESS; } #endif static int apm_get_power_status(u_short *status, u_short *bat, u_short *life) { - u_short error; + int error; + u32 eax; + u32 ebx; + u32 ecx; + u32 edx; + u32 dummy; - APM_GET_POWER_STATUS(*status, *bat, *life, error); - if (error & 0xff) - return (error >> 8); + error = apm_bios_call(0x530a, 1, 0, &eax, &ebx, &ecx, &edx, &dummy); + if (error) + return (eax >> 8) & 0xff; + *status = ebx; + *bat = ecx; + *life = edx; return APM_SUCCESS; } @@ -521,29 +536,40 @@ static int apm_get_power_status(u_short *status, u_short *bat, u_short *life) static int apm_get_battery_status(u_short which, u_short *bat, u_short *life, u_short *nbat) { - u_short status, error; + u_short status; + int error; + u32 eax; + u32 ebx; + u32 ecx; + u32 edx; + u32 esi; if (apm_bios_info.version < 0x0102) { /* pretend we only have one battery. */ - if (which!=1) return APM_BAD_DEVICE; + if (which != 1) + return APM_BAD_DEVICE; *nbat = 1; return apm_get_power_status(&status, bat, life); } - APM_GET_BATTERY_STATUS(which, status, *bat, *life, *nbat, error); - if (error & 0xff) - return (error >> 8); + error = apm_bios_call(0x530a, (0x8000 | (which)), 0, &eax, &ebx, &ecx, &edx, &esi); + if (error) + return (eax >> 8) & 0xff; + *bat = ecx; + *life = edx; + *nbat = esi; return APM_SUCCESS; } #endif -static inline int apm_engage_power_management(u_short device) +static int apm_engage_power_management(u_short device) { - u_short error; + int error; + u32 eax; - APM_ENGAGE_POWER_MANAGEMENT(device, error); - if (error & 0xff) - return (error >> 8); + error = apm_bios_call_simple(0x530f, device, 1, &eax); + if (error) + return (eax >> 8) & 0xff; return APM_SUCCESS; } @@ -850,13 +876,14 @@ static void do_apm_timer(unsigned long unused) int apm_do_idle(void) { #ifdef CONFIG_APM_CPU_IDLE - unsigned short error; + int error; + u32 dummy; if (!apm_enabled) return 0; - APM_SET_CPU_IDLE(error); - if (error & 0xff) + error = apm_bios_call_simple(0x5305, 0, 0, &dummy); + if (error) return 0; clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0; @@ -870,19 +897,16 @@ int apm_do_idle(void) void apm_do_busy(void) { #ifdef CONFIG_APM_CPU_IDLE - unsigned short error; - - if (!apm_enabled) - return; + u32 dummy; + if (apm_enabled #ifndef ALWAYS_CALL_BUSY - if (!clock_slowed) - return; + && clock_slowed #endif - - APM_SET_CPU_BUSY(error); - - clock_slowed = 0; + ) { + (void) apm_bios_call_simple(0x5306, 0, 0, &dummy); + clock_slowed = 0; + } #endif } @@ -1242,11 +1266,11 @@ __initfunc(void apm_bios_init(void)) */ apm_bios_info.version = 0x0102; error = apm_driver_version(&apm_bios_info.version); - if (error != 0) { /* Fall back to an APM 1.1 connection. */ + if (error != APM_SUCCESS) { /* Fall back to an APM 1.1 connection. */ apm_bios_info.version = 0x0101; error = apm_driver_version(&apm_bios_info.version); } - if (error != 0) /* Fall back to an APM 1.0 connection. */ + if (error != APM_SUCCESS) /* Fall back to an APM 1.0 connection. */ apm_bios_info.version = 0x100; else { apm_engage_power_management(0x0001); diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index 5dc51998a10a..227dc40a201d 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -433,6 +433,9 @@ static struct tvcard tvcards[] = {0, 0xc00, 0x800, 0x400, 0xc00, 0}}, /* TurboTV */ { 3, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}}, + /* Newer Hauppauge */ + { 2, 0, 2, 1, { 2, 0, 0, 0}, {0, 1, 2, 3, 4}}, + }; #define TVCARDS (sizeof(tvcards)/sizeof(tvcard)) @@ -1834,6 +1837,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) case BTTV_PLLSET: { struct bttv_pll_info p; + if(!capable(CAP_SYS_ADMIN)) + return -EPERM; if(copy_from_user(&p , (void *) arg, sizeof(btv->pll))) return -EFAULT; btv->pll.pll_ifreq = p.pll_ifreq; @@ -2411,7 +2416,12 @@ static void idcard(int i) btv->type=BTTV_MIRO; if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0) - btv->type=BTTV_HAUPPAUGE; + { + if(btv->id>849) + btv->type=BTTV_HAUPPAUGE878; + else + btv->type=BTTV_HAUPPAUGE; + } else if (I2CRead(&(btv->i2c), I2C_STBEE)>=0) btv->type=BTTV_STB; @@ -2446,6 +2456,8 @@ static void idcard(int i) /* How do I detect the tuner type for other cards but Miro ??? */ printk(KERN_INFO "bttv%d: model: ", btv->nr); + + sprintf(btv->video_dev.name,"BT%d",btv->id); switch (btv->type) { case BTTV_MIRO: @@ -2457,31 +2469,32 @@ static void idcard(int i) I2C_DRIVERID_TUNER, TUNER_SET_TYPE,&tunertype); } - strcpy(btv->video_dev.name,"BT848(Miro)"); + strcat(btv->video_dev.name, "(Miro)"); break; case BTTV_HAUPPAUGE: + case BTTV_HAUPPAUGE878: printk("HAUPPAUGE\n"); - strcpy(btv->video_dev.name,"BT848(Hauppauge)"); + strcat(btv->video_dev.name,"(Hauppauge)"); break; case BTTV_STB: printk("STB\n"); - strcpy(btv->video_dev.name,"BT848(STB)"); + strcat(btv->video_dev.name,"(STB)"); break; case BTTV_INTEL: printk("Intel\n"); - strcpy(btv->video_dev.name,"BT848(Intel)"); + strcat(btv->video_dev.name,"(Intel)"); break; case BTTV_DIAMOND: printk("Diamond\n"); - strcpy(btv->video_dev.name,"BT848(Diamond)"); + strcat(btv->video_dev.name,"(Diamond)"); break; case BTTV_AVERMEDIA: printk("AVerMedia\n"); - strcpy(btv->video_dev.name,"BT848(AVerMedia)"); + strcat(btv->video_dev.name,"(AVerMedia)"); break; case BTTV_MATRIX_VISION: printk("MATRIX-Vision\n"); - strcpy(btv->video_dev.name,"BT848(MATRIX-Vision)"); + strcat(btv->video_dev.name,"(MATRIX-Vision)"); break; } audio(btv, AUDIO_MUTE); @@ -2981,7 +2994,7 @@ static int find_bt848(void) dev = dev->next; } if(bttv_num) - printk(KERN_INFO "bttv: %d Bt848 card(s) found.\n", bttv_num); + printk(KERN_INFO "bttv: %d BT8xx card(s) found.\n", bttv_num); return bttv_num; } diff --git a/drivers/char/bttv.h b/drivers/char/bttv.h index 2363914c15e4..f8da6c6d0a67 100644 --- a/drivers/char/bttv.h +++ b/drivers/char/bttv.h @@ -178,6 +178,7 @@ struct bttv #define BTTV_AVERMEDIA 0x06 #define BTTV_MATRIX_VISION 0x07 #define BTTV_FLYVIDEO 0x08 +#define BTTV_HAUPPAUGE878 0x09 #define AUDIO_TUNER 0x00 #define AUDIO_RADIO 0x01 diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index efd4854ceddf..fe3c6d758943 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -1,7 +1,7 @@ #define BLOCKMOVE #define Z_WAKE static char rcsid[] = -"$Revision: 2.2.1.6 $$Date: 1998/08/20 17:15:39 $"; +"$Revision: 2.2.1.7 $$Date: 1998/09/03 12:07:28 $"; /* * linux/drivers/char/cyclades.c @@ -31,6 +31,11 @@ static char rcsid[] = * void cleanup_module(void); * * $Log: cyclades.c,v $ + * Revision 2.2.1.7 1998/09/03 12:07:28 ivan + * Fixed bug in cy_close function, which was not informing HW of + * which port should have the reception disabled before doing so; + * fixed Cyclom-8YoP hardware detection bug. + * * Revision 2.2.1.6 1998/08/20 17:15:39 ivan * Fixed bug in cy_close function, which causes malfunction * of one of the first 4 ports when a higher port is closed @@ -2690,6 +2695,8 @@ cy_close(struct tty_struct * tty, struct file * filp) (cy_card[info->card].base_addr + (cy_chip_offset[channel>>2] <flags & ASYNC_INITIALIZED) { @@ -4539,7 +4546,7 @@ cy_detect_pci(void)) unsigned long pci_intr_ctrl; unsigned char cy_pci_irq = 0; uclong cy_pci_addr0, cy_pci_addr1, cy_pci_addr2; - unsigned short i,j,cy_pci_nchan; + unsigned short i,j,cy_pci_nchan, plx_ver; unsigned short device_id,dev_index = 0; uclong mailbox; uclong Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0; @@ -4651,10 +4658,26 @@ cy_detect_pci(void)) IRQ_cards[cy_pci_irq] = &cy_card[j]; /* enable interrupts in the PCI interface */ - outw(inw(cy_pci_addr1+0x68)|0x0900,cy_pci_addr1+0x68); - pci_intr_ctrl = (unsigned long) - (inw(cy_pci_addr1+0x68) + plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f; + switch (plx_ver) { + case PLX_9050: + + outw(inw(cy_pci_addr1+0x4c)|0x0040,cy_pci_addr1+0x4c); + pci_intr_ctrl = (unsigned long) + (inw(cy_pci_addr1+0x4c) + | inw(cy_pci_addr1+0x4e)<<16); + break; + + case PLX_9060: + case PLX_9080: + default: /* Old boards, use PLX_9060 */ + + outw(inw(cy_pci_addr1+0x68)|0x0900,cy_pci_addr1+0x68); + pci_intr_ctrl = (unsigned long) + (inw(cy_pci_addr1+0x68) | inw(cy_pci_addr1+0x6a)<<16); + break; + } /* print message */ printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", diff --git a/drivers/char/psaux.c b/drivers/char/psaux.c index e4a54097bcec..6b90a474d259 100644 --- a/drivers/char/psaux.c +++ b/drivers/char/psaux.c @@ -245,6 +245,9 @@ static int release_aux(struct inode * inode, struct file * file) fasync_aux(-1, file, 0); if (--aux_count) return 0; +#ifdef CONFIG_VT + pckbd_read_mask = KBD_STAT_OBF; +#endif aux_start_atomic(); aux_write_cmd(AUX_INTS_OFF); /* Disable controller ints */ poll_aux_status(); @@ -297,6 +300,10 @@ static int open_aux(struct inode * inode, struct file * file) poll_aux_status(); aux_end_atomic(); +#ifdef CONFIG_VT + pckbd_read_mask = AUX_STAT_OBF; +#endif + aux_ready = 0; return 0; } @@ -613,9 +620,6 @@ __initfunc(int psaux_init(void)) if (aux_device_present == 0xaa) { printk(KERN_INFO "PS/2 auxiliary pointing device detected -- driver installed.\n"); aux_present = 1; -#ifdef CONFIG_VT - pckbd_read_mask = AUX_STAT_OBF; -#endif } else { return -EIO; } @@ -643,6 +647,7 @@ __initfunc(int psaux_init(void)) poll_aux_status(); aux_end_atomic(); } + return 0; } diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 20e818ce646a..c661f8238154 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -100,8 +100,8 @@ #include "version.h" #else #include -#define ROCKET_VERSION "1.14b" -#define ROCKET_DATE "29-Jun-98" +#define ROCKET_VERSION "1.14c" +#define ROCKET_DATE "24-Aug-98" #endif /* LOCAL_ROCKET_H */ #define ROCKET_PARANOIA_CHECK @@ -1935,7 +1935,8 @@ static void rp_flush_buffer(struct tty_struct *tty) #ifdef ENABLE_PCI #if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */ /* For compatibility */ -static struct pci_dev *pci_find_slot(char bus, char device_fn) +static struct pci_dev *pci_find_slot(unsigned char bus, + unsigned char device_fn) { unsigned short vendor_id, device_id; int ret, error; @@ -1962,7 +1963,7 @@ static struct pci_dev *pci_find_slot(char bus, char device_fn) } #endif -__initfunc(int register_PCI(int i, char bus, char device_fn)) +__initfunc(int register_PCI(int i, unsigned int bus, unsigned int device_fn)) { int num_aiops, aiop, max_num_aiops, num_chan, chan; unsigned int aiopio[MAX_AIOPS_PER_BOARD]; diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 863b02b56e01..c06eb7251ae8 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -2569,15 +2569,21 @@ static int rs_open(struct tty_struct *tty, struct file * filp) MOD_INC_USE_COUNT; line = MINOR(tty->device) - tty->driver.minor_start; - if ((line < 0) || (line >= NR_PORTS)) + if ((line < 0) || (line >= NR_PORTS)) { + MOD_DEC_USE_COUNT; return -ENODEV; + } retval = get_async_struct(line, &info); - if (retval) + if (retval) { + MOD_DEC_USE_COUNT; return retval; + } tty->driver_data = info; info->tty = tty; - if (serial_paranoia_check(info, tty->device, "rs_open")) + if (serial_paranoia_check(info, tty->device, "rs_open")) { + MOD_DEC_USE_COUNT; return -ENODEV; + } #ifdef SERIAL_DEBUG_OPEN printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, @@ -2587,8 +2593,10 @@ static int rs_open(struct tty_struct *tty, struct file * filp) if (!tmp_buf) { page = get_free_page(GFP_KERNEL); - if (!page) + if (!page) { + MOD_DEC_USE_COUNT; return -ENOMEM; + } if (tmp_buf) free_page(page); else @@ -2602,6 +2610,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) (info->flags & ASYNC_CLOSING)) { if (info->flags & ASYNC_CLOSING) interruptible_sleep_on(&info->close_wait); + MOD_DEC_USE_COUNT; #ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); @@ -2614,11 +2623,14 @@ static int rs_open(struct tty_struct *tty, struct file * filp) * Start up serial port */ retval = startup(info); - if (retval) + if (retval) { + MOD_DEC_USE_COUNT; return retval; + } retval = block_til_ready(tty, filp, info); if (retval) { + MOD_DEC_USE_COUNT; #ifdef SERIAL_DEBUG_OPEN printk("rs_open returning after block_til_ready with %d\n", retval); diff --git a/drivers/net/arcnet.c b/drivers/net/arcnet.c index 5974f8a8a0b4..8926902a5cd7 100644 --- a/drivers/net/arcnet.c +++ b/drivers/net/arcnet.c @@ -149,8 +149,8 @@ retransmit immediately) - Add support for the new 1.3.x IP header cache, and other features. - Replace setting of debug level with the "metric" flag hack by - something better. SIOCDEVPRIVATE is a good candidate, but it would - require an extra user-level utility. + something that still exists. SIOCDEVPRIVATE is a good candidate, + but it would require an extra user-level utility. - What about cards with shared memory that can be "turned off?" (or that have none at all, like the SMC PC500longboard) @@ -428,13 +428,13 @@ arcnet_open(struct device *dev) { struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - if (dev->metric>=1000) - { - arcnet_debug=dev->metric-1000; - printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug); - dev->metric=1; - } - + /* if (dev->metric>=1000) + * { + * arcnet_debug=dev->metric-1000; + * printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug); + * dev->metric=1; + *} + */ BUGMSG(D_INIT,"arcnet_open: resetting card.\n"); /* try to put the card in a defined state - if it fails the first diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index b15197de00b0..976ba68cbe03 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -13,7 +13,7 @@ * This driver is for PCnet32 and PCnetPCI based ethercards */ -static const char *version = "pcnet32.c:v1.01 29.8.98 tsbogend@alpha.franken.de\n"; +static const char *version = "pcnet32.c:v1.02 3.9.98 tsbogend@alpha.franken.de\n"; #include #include @@ -100,7 +100,7 @@ static const int rx_copybreak = 200; * added support for byte counters in net_dev_stats * v1.01: do ring dumps, only when debugging the driver * increased the transmit timeout - * + * v1.02: fixed memory leak in pcnet32_init_ring() */ @@ -186,7 +186,7 @@ struct pcnet32_private { int pcnet32_probe(struct device *dev); static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, unsigned char irq_line, int shared); static int pcnet32_open(struct device *dev); -static void pcnet32_init_ring(struct device *dev); +static int pcnet32_init_ring(struct device *dev); static int pcnet32_start_xmit(struct sk_buff *skb, struct device *dev); static int pcnet32_rx(struct device *dev); static void pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs); @@ -443,7 +443,8 @@ pcnet32_open(struct device *dev) lp->init_block.mode = 0x0000; lp->init_block.filter[0] = 0x00000000; lp->init_block.filter[1] = 0x00000000; - pcnet32_init_ring(dev); + if (pcnet32_init_ring(dev)) + return -ENOMEM; /* Re-initialize the PCNET32, and start it when done. */ outw(0x0001, ioaddr+PCNET32_ADDR); @@ -508,28 +509,28 @@ pcnet32_purge_tx_ring(struct device *dev) /* Initialize the PCNET32 Rx and Tx rings. */ -static void +static int pcnet32_init_ring(struct device *dev) { struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; int i; - struct sk_buff *skb; lp->lock = 0, lp->tx_full = 0; lp->cur_rx = lp->cur_tx = 0; lp->dirty_rx = lp->dirty_tx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - skb = dev_alloc_skb (PKT_BUF_SZ); - if (skb) { - lp->rx_skbuff[i] = skb; - skb_reserve (skb, 2); - lp->rx_ring[i].base = (u32)le32_to_cpu(virt_to_bus(skb->tail)); - lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ); - lp->rx_ring[i].status = le16_to_cpu(0x8000); + if (lp->rx_skbuff[i] == NULL) { + if (!(lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) { + /* there is not much, we can do at this point */ + printk ("%s: pcnet32_init_ring dev_alloc_skb failed.\n",dev->name); + return -1; + } + skb_reserve (lp->rx_skbuff[i], 2); } - else - break; + lp->rx_ring[i].base = (u32)le32_to_cpu(virt_to_bus(lp->rx_skbuff[i]->tail)); + lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ); + lp->rx_ring[i].status = le16_to_cpu(0x8000); } /* The Tx buffer address is filled in as needed, but we do need to clear the upper ownership bit. */ @@ -543,6 +544,7 @@ pcnet32_init_ring(struct device *dev) lp->init_block.phys_addr[i] = dev->dev_addr[i]; lp->init_block.rx_ring = (u32)le32_to_cpu(virt_to_bus(lp->rx_ring)); lp->init_block.tx_ring = (u32)le32_to_cpu(virt_to_bus(lp->tx_ring)); + return 0; } static void @@ -552,7 +554,8 @@ pcnet32_restart(struct device *dev, unsigned int csr0_bits) unsigned int ioaddr = dev->base_addr; pcnet32_purge_tx_ring(dev); - pcnet32_init_ring(dev); + if (pcnet32_init_ring(dev)) + return; outw(0x0000, ioaddr + PCNET32_ADDR); /* ReInit Ring */ @@ -602,7 +605,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct device *dev) dev->tbusy = 0; dev->trans_start = jiffies; - + dev_kfree_skb(skb); return 0; } diff --git a/drivers/net/sdla_fr.c b/drivers/net/sdla_fr.c index 303fac4c1f51..a687135dcb96 100644 --- a/drivers/net/sdla_fr.c +++ b/drivers/net/sdla_fr.c @@ -158,7 +158,7 @@ typedef struct fr_channel { unsigned long IB_addr; /* physical address of Interface Byte */ unsigned long state_tick; /* time of the last state change */ sdla_t *card; /* -> owner */ - struct enet_statistics ifstats; /* interface statistics */ + struct net_device_stats ifstats; /* interface statistics */ unsigned long if_send_entry; unsigned long if_send_skb_null; unsigned long if_send_broadcast; @@ -252,7 +252,7 @@ static int if_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len); static int if_rebuild_hdr(struct sk_buff *skb); static int if_send(struct sk_buff *skb, struct device *dev); -static struct enet_statistics *if_stats(struct device *dev); +static struct net_device_stats *if_stats(struct device *dev); /* Interrupt handlers */ static void fr502_isr(sdla_t * card); static void fr508_isr(sdla_t * card); @@ -1225,12 +1225,15 @@ static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_ /*============================================================================ * Get Ethernet-style interface statistics. - * Return a pointer to struct enet_statistics. + * Return a pointer to struct net_device_stats. */ static struct net_device_stats *if_stats(struct device *dev) { fr_channel_t *chan = dev->priv; + if(chan==NULL) + return NULL; + return &chan->ifstats; } diff --git a/drivers/net/sdla_ppp.c b/drivers/net/sdla_ppp.c index 6b15441b5609..37c1d78899cb 100644 --- a/drivers/net/sdla_ppp.c +++ b/drivers/net/sdla_ppp.c @@ -848,7 +848,16 @@ static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_ static struct enet_statistics *if_stats(struct device *dev) { ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->card; + sdla_t *card; + + /* + * Device is down:No statistics + */ + + if(ppp_priv_area==NULL) + return NULL; + + card = ppp_priv_area->card; return &card->wandev.stats; } diff --git a/drivers/net/sdla_x25.c b/drivers/net/sdla_x25.c index 77567ebcc4e7..4f9ac70f6c95 100644 --- a/drivers/net/sdla_x25.c +++ b/drivers/net/sdla_x25.c @@ -96,7 +96,7 @@ typedef struct x25_channel struct sk_buff* tx_skb; /* transmit socket buffer */ sdla_t* card; /* -> owner */ int ch_idx; - struct enet_statistics ifstats; /* interface statistics */ + struct net_device_stats ifstats; /* interface statistics */ } x25_channel_t; typedef struct x25_call_info @@ -829,6 +829,8 @@ tx_done: static struct net_device_stats* if_stats (struct device* dev) { x25_channel_t* chan = dev->priv; + if(chan==NULL) + return chan; return &chan->ifstats; } diff --git a/drivers/net/sdladrv.c b/drivers/net/sdladrv.c index baa18b3d4d72..52f14ac2cbb7 100644 --- a/drivers/net/sdladrv.c +++ b/drivers/net/sdladrv.c @@ -421,7 +421,7 @@ int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len) return err; } } - else if (!get_option_index(dpmbase_opt, hw->dpmbase)) + else if (!get_option_index(dpmbase_opt, virt_to_phys((void *)hw->dpmbase))) { printk(KERN_ERR "%s: memory address 0x%lX is illegal!\n", modname, hw->dpmbase) @@ -437,7 +437,7 @@ int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len) return -EINVAL; } printk(KERN_INFO "%s: dual-port memory window is set at 0x%lX.\n", - modname, hw->dpmbase) + modname, virt_to_phys(hw->dpmbase)) ; printk(KERN_INFO "%s: found %luK bytes of on-board memory.\n", modname, hw->memory / 1024) @@ -495,7 +495,7 @@ int sdla_down (sdlahw_t* hw) } /*============================================================================ - * Map shared memory window into SDLA address space. + * Map shared memory window into SDLA adress space. */ EXPORT_SYMBOL(sdla_mapmem); @@ -980,7 +980,7 @@ static int sdla_autodpm (sdlahw_t* hw) for (i = opt[0]; i && err; --i) { - hw->dpmbase = opt[i]; + hw->dpmbase = (unsigned long )(phys_to_virt(opt[i])); err = sdla_setdpm(hw); } return err; @@ -1333,7 +1333,7 @@ static int init_s502a (sdlahw_t* hw) hw->regs[1] = 0xFF; /* Verify configuration options */ - i = get_option_index(s502a_dpmbase_options, hw->dpmbase); + i = get_option_index(s502a_dpmbase_options, virt_to_phys((void *)hw->dpmbase)); if (i == 0) return -EINVAL ; @@ -1372,7 +1372,7 @@ static int init_s502e (sdlahw_t* hw) ; /* Verify configuration options */ - i = get_option_index(s508_dpmbase_options, hw->dpmbase); + i = get_option_index(s508_dpmbase_options, virt_to_phys((void *)hw->dpmbase)); if (i == 0) return -EINVAL ; @@ -1416,7 +1416,7 @@ static int init_s503 (sdlahw_t* hw) ; /* Verify configuration options */ - i = get_option_index(s508_dpmbase_options, hw->dpmbase); + i = get_option_index(s508_dpmbase_options, virt_to_phys((void *)hw->dpmbase)); if (i == 0) return -EINVAL ; @@ -1458,7 +1458,7 @@ static int init_s507 (sdlahw_t* hw) ; /* Verify configuration options */ - i = get_option_index(s507_dpmbase_options, hw->dpmbase); + i = get_option_index(s507_dpmbase_options, virt_to_phys((void *)hw->dpmbase)); if (i == 0) return -EINVAL ; @@ -1515,7 +1515,7 @@ static int init_s508 (sdlahw_t* hw) ; /* Verify configuration options */ - i = get_option_index(s508_dpmbase_options, hw->dpmbase); + i = get_option_index(s508_dpmbase_options, virt_to_phys((void *)hw->dpmbase)); if (i == 0) return -EINVAL ; @@ -1776,7 +1776,7 @@ static int get_option_index (unsigned* optlist, unsigned optval) int i; for (i = 1; i <= optlist[0]; ++i) - if (optlist[i] == optval) return i + if ( optlist[i] == optval) return i ; return 0; } diff --git a/drivers/net/sdlamain.c b/drivers/net/sdlamain.c index 44fabaecb2cf..bc6288197cfe 100644 --- a/drivers/net/sdlamain.c +++ b/drivers/net/sdlamain.c @@ -45,6 +45,7 @@ #include /* WAN router definitions */ #include /* WANPIPE common user API definitions */ #include /* kernel <-> user copy */ +#include /* phys_to_virt() */ /****** Defines & Macros ****************************************************/ @@ -162,8 +163,13 @@ int init_module (void) break; } } - if (cnt) ncards = cnt; /* adjust actual number of cards */ - else kfree(card_array); + if (cnt) + ncards = cnt; /* adjust actual number of cards */ + else + { + kfree(card_array); + err = -ENODEV; + } return err; } @@ -202,6 +208,7 @@ void cleanup_module (void) * configuration structure is in kernel memory (including extended data, if * any). */ + static int setup (wan_device_t* wandev, wandev_conf_t* conf) { sdla_t* card; @@ -210,33 +217,31 @@ static int setup (wan_device_t* wandev, wandev_conf_t* conf) /* Sanity checks */ if ((wandev == NULL) || (wandev->private == NULL) || (conf == NULL)) - return -EFAULT - ; + return -EFAULT; + card = wandev->private; if (wandev->state != WAN_UNCONFIGURED) - return -EBUSY /* already configured */ - ; + return -EBUSY; /* already configured */ + if (!conf->data_size || (conf->data == NULL)) { printk(KERN_ERR "%s: firmware not found in configuration data!\n", - wandev->name) - ; + wandev->name); return -EINVAL; } if (conf->ioport <= 0) { printk(KERN_ERR "%s: can't configure without I/O port address!\n", - wandev->name) - ; + wandev->name); return -EINVAL; } + if (conf->irq <= 0) { printk(KERN_ERR "%s: can't configure without IRQ!\n", - wandev->name) - ; + wandev->name); return -EINVAL; } @@ -245,8 +250,7 @@ static int setup (wan_device_t* wandev, wandev_conf_t* conf) { printk(KERN_ERR "%s: I/O region 0x%X - 0x%X is in use!\n", wandev->name, conf->ioport, - conf->ioport + SDLA_MAXIORANGE) - ; + conf->ioport + SDLA_MAXIORANGE); return -EINVAL; } @@ -255,8 +259,7 @@ static int setup (wan_device_t* wandev, wandev_conf_t* conf) if (request_irq(irq, sdla_isr, 0, wandev->name, card)) { printk(KERN_ERR "%s: can't reserve IRQ %d!\n", - wandev->name, irq) - ; + wandev->name, irq); return -EINVAL; } @@ -264,7 +267,12 @@ static int setup (wan_device_t* wandev, wandev_conf_t* conf) memset(&card->hw, 0, sizeof(sdlahw_t)); card->hw.port = conf->ioport; card->hw.irq = (conf->irq == 9) ? 2 : conf->irq; - card->hw.dpmbase = conf->maddr; + /* Compute the virtual address of the card in kernel space */ + if(conf->maddr) + card->hw.dpmbase = (unsigned long)phys_to_virt(conf->maddr); + else /* But 0 means NULL */ + card->hw.dpmbase = conf->maddr; + card->hw.dpmsize = SDLA_WINDOWSIZE; card->hw.type = conf->hw_opt[0]; card->hw.pclk = conf->hw_opt[1]; @@ -323,10 +331,12 @@ static int setup (wan_device_t* wandev, wandev_conf_t* conf) return err; } /* Reserve I/O region and schedule background task */ +/* printk(KERN_INFO "about to request\n");*/ request_region(card->hw.port, card->hw.io_range, wandev->name); +/* printk(KERN_INFO "request done\n");*/ if (++active == 1) - queue_task(&sdla_tq, &tq_scheduler) - ; + queue_task(&sdla_tq, &tq_scheduler); + wandev->critical = 0; return 0; } @@ -345,20 +355,32 @@ static int shutdown (wan_device_t* wandev) /* sanity checks */ if ((wandev == NULL) || (wandev->private == NULL)) - return -EFAULT - ; + return -EFAULT; + if (wandev->state == WAN_UNCONFIGURED) - return 0 - ; + return 0; + + /* If wee are in a critical section we lose */ if (test_and_set_bit(0, (void*)&wandev->critical)) - return -EAGAIN - ; + return -EAGAIN; + card = wandev->private; wandev->state = WAN_UNCONFIGURED; - if (--active == 0) schedule(); /* stop background thread */ + + if (--active == 0) + schedule(); /* stop background thread */ + +/* printk(KERN_INFO "active now %d\n", active); + + printk(KERN_INFO "About to call sdla_down\n");*/ sdla_down(&card->hw); +/* printk(KERN_INFO "sdla_down done\n"); + printk(KERN_INFO "About to call free_irq\n");*/ free_irq(wandev->irq, card); +/* printk(KERN_INFO "free_irq done\n"); + printk(KERN_INFO "About to call release_region\n");*/ release_region(card->hw.port, card->hw.io_range); +/* printk(KERN_INFO "release_region done\n");*/ wandev->critical = 0; return 0; } diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index d3b7f164550c..e0070c647b56 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -32,6 +32,12 @@ /* * $Log: NCR5380.c,v $ + * Revision 1.10 1998/9/2 Alan Cox + * (alan@redhat.com) + * Fixed up the timer lockups reported so far. Things still suck. Looking + * forward to 2.3 and per device request queues. Then it'll be possible to + * SMP thread this beast and improve life no end. + * Revision 1.9 1997/7/27 Ronald van Cuijlenborg * (ronald.van.cuijlenborg@tip.nl or nutty@dds.nl) * (hopefully) fixed and enhanced USLEEP @@ -1524,8 +1530,11 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { { unsigned long timeout = jiffies + NCR_TIMEOUT; + spin_unlock_irq(&io_request_lock); while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK && jiffies < timeout); + spin_lock_irq(&io_request_lock); + if (jiffies >= timeout) printk("scsi%d: timeout at NCR5380.c:%d\n", host->host_no, __LINE__); @@ -1665,8 +1674,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) { unsigned long timeout = jiffies + 2 * NCR_TIMEOUT; + spin_unlock_irq(&io_request_lock); + while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) && jiffies < timeout); + + spin_lock_irq(&io_request_lock); + if (jiffies >= timeout) { printk("scsi: arbitration timeout at %d\n", __LINE__); NCR5380_write(MODE_REG, MR_BASE); @@ -1825,8 +1839,10 @@ part2: hostdata->selecting = 0; /* clear this pointer, because we passed the waiting period */ #else + spin_unlock_irq(&io_request_lock); while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO))); + spin_lock_irq(&io_request_lock); #endif if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { @@ -1894,8 +1910,10 @@ part2: { unsigned long timeout = jiffies + NCR_TIMEOUT; + spin_unlock_irq(&io_request_lock); while (!(NCR5380_read(STATUS_REG) & SR_REQ) && jiffies < timeout); - + spin_lock_irq(&io_request_lock); + if (jiffies >= timeout) { printk("scsi%d: timeout at NCR5380.c:%d\n", __LINE__); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index ae125308d8af..b23a61f74153 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -35,6 +35,18 @@ if [ "$CONFIG_SOUND_MSNDPIN" = "y" ]; then int 'MSND Pinnacle IRQ 5,7,9,10,11,12' CONFIG_MSNDPIN_IRQ 5 hex 'MSND Pinnacle Memory B0000,C8000,D0000,D8000,E0000,E8000' CONFIG_MSNDPIN_MEM D0000 hex 'MSND Pinnacle I/O 210,220,230,240,250,260,290,3E0' CONFIG_MSNDPIN_IO 290 + bool 'MSND Pinnacle Non-PnP Mode' CONFIG_MSNDPIN_NONPNP + if [ "$CONFIG_MSNDPIN_NONPNP" = "y" ]; then + comment 'MSND Pinnacle DSP section will be configured to above parameters.' + hex 'MSDN Pinnacle Config Port 250,260,270' CONFIG_MSNDPIN_CFG 250 + comment 'Pinnacle-specific Device Configuration (0 disables)' + hex 'MSDN Pinnacle MPU I/O (e.g. 330)' CONFIG_MSNDPIN_MPU_IO 0 + int 'MSDN Pinnacle MPU IRQ (e.g. 9)' CONFIG_MSNDPIN_MPU_IRQ 0 + hex 'MSDN Pinnacle IDE I/O 0 (e.g. 170)' CONFIG_MSNDPIN_IDE_IO0 0 + hex 'MSDN Pinnacle IDE I/O 1 (e.g. 376)' CONFIG_MSNDPIN_IDE_IO1 0 + int 'MSDN Pinnacle IDE IRQ (e.g. 15)' CONFIG_MSNDPIN_IDE_IRQ 0 + hex 'MSDN Pinnacle Joystick I/O (e.g. 200)' CONFIG_MSNDPIN_JOYSTICK_IO 0 + fi fi dep_tristate 'OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND diff --git a/drivers/sound/README.FIRST b/drivers/sound/README.FIRST index 3a6b60483497..85ecccdfce2e 100644 --- a/drivers/sound/README.FIRST +++ b/drivers/sound/README.FIRST @@ -1,4 +1,4 @@ -The modular sound driver patches where funded by Red Hat Software +The modular sound driver patches were funded by Red Hat Software (www.redhat.com). The sound driver here is thus a modified version of Hannu's code. Please bear that in mind when considering the appropriate forums for bug reporting. diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c index f08f6aaca733..54d8e5f5b67d 100644 --- a/drivers/sound/audio.c +++ b/drivers/sound/audio.c @@ -17,6 +17,7 @@ * (which is grossly misnamed btw.) because they have the same * lifetime as the rest in there and dynamic allocation saves * 12k or so + * Thomas Sailer : use more logical O_NONBLOCK semantics */ #include @@ -99,7 +100,6 @@ int audio_open(int dev, struct file *file) set_format(dev, bits); audio_devs[dev]->audio_mode = AM_NONE; - audio_devs[dev]->dev_nblock = 0; return ret; @@ -203,10 +203,10 @@ int audio_write(int dev, struct file *file, const char *buf, int count) while (c) { - if ((err = DMAbuf_getwrbuffer(dev, &dma_buf, &buf_size, audio_devs[dev]->dev_nblock)) < 0) + if ((err = DMAbuf_getwrbuffer(dev, &dma_buf, &buf_size, !!(file->f_flags & O_NONBLOCK))) < 0) { /* Handle nonblocking mode */ - if (audio_devs[dev]->dev_nblock && err == -EAGAIN) + if ((file->f_flags & O_NONBLOCK) && err == -EAGAIN) return p; /* No more space. Return # of accepted bytes */ return err; } @@ -273,14 +273,13 @@ int audio_read(int dev, struct file *file, char *buf, int count) while(c) { - if ((buf_no = DMAbuf_getrdbuffer(dev, &dmabuf, &l, - audio_devs[dev]->dev_nblock)) < 0) + if ((buf_no = DMAbuf_getrdbuffer(dev, &dmabuf, &l, !!(file->f_flags & O_NONBLOCK))) < 0) { /* * Nonblocking mode handling. Return current # of bytes */ - if (audio_devs[dev]->dev_nblock && buf_no == -EAGAIN) + if (file->f_flags & O_NONBLOCK && buf_no == -EAGAIN) return p; if (p > 0) /* Avoid throwing away data */ @@ -388,7 +387,7 @@ int audio_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) return dma_ioctl(dev, cmd, arg); case SNDCTL_DSP_NONBLOCK: - audio_devs[dev]->dev_nblock = 1; + file->f_flags |= O_NONBLOCK; return 0; case SNDCTL_DSP_GETCAPS: diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h index bf5d62bffd86..215df408a4ed 100644 --- a/drivers/sound/dev_table.h +++ b/drivers/sound/dev_table.h @@ -230,8 +230,6 @@ struct audio_operations /* fields formerly in audio.c */ int audio_mode; - /* why don't we use file->f_flags & O_NONBLOCK for the following? - ts */ - int dev_nblock; /* 1 if in nonblocking mode */ #define AM_NONE 0 #define AM_WRITE OPEN_WRITE diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c index ecabf72ab8c3..51b9d87de383 100644 --- a/drivers/sound/dmabuf.c +++ b/drivers/sound/dmabuf.c @@ -206,6 +206,7 @@ static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap dmap->dma_mode = DMODE_NONE; dmap->flags &= ~DMA_BUSY; disable_dma(dmap->dma); + sound_free_dmap(dmap); } diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c index 90d12d84b3ba..00794bf395d0 100644 --- a/drivers/sound/es1370.c +++ b/drivers/sound/es1370.c @@ -1,7 +1,7 @@ /*****************************************************************************/ /* - * es1370.c -- Ensoniq ES1370/Ashai Kasei AK4531 audio driver. + * es1370.c -- Ensoniq ES1370/Asahi Kasei AK4531 audio driver. * * Copyright (C) 1998 Thomas Sailer (sailer@ife.ee.ethz.ch) * @@ -73,6 +73,9 @@ * On module startup, set DAC2 to 11kSPS instead of 5.5kSPS, * as it produces an annoying ssssh in the lower sampling rate * Do not include modversions.h + * 22.08.98 0.12 Mixer registers actually have 5 instead of 4 bits + * pointed out by Itai Nahshon + * 31.08.98 0.13 Fix realplayer problems - dac.count issues * * some important things missing in Ensoniq documentation: * @@ -455,7 +458,7 @@ static void start_adc(struct es1370_state *s) unsigned fragremain, fshift; spin_lock_irqsave(&s->lock, flags); - if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < s->dma_adc.dmasize - 2*s->dma_adc.fragsize) + if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) && s->dma_adc.ready) { s->ctrl |= CTRL_ADC_EN; s->sctrl = (s->sctrl & ~SCTRL_R1LOOPSEL) | SCTRL_R1INTEN; @@ -486,7 +489,6 @@ extern inline void dealloc_dmabuf(struct dmabuf *db) for (map = MAP_NR(db->rawbuf); map <= mapend; map++) clear_bit(PG_reserved, &mem_map[map].flags); free_pages((unsigned long)db->rawbuf, db->buforder); - printk(KERN_DEBUG "es: freeing dmabuf %8.8lx order %d\n", (unsigned long)db->rawbuf, db->buforder); } db->rawbuf = NULL; db->mapped = db->ready = 0; @@ -511,7 +513,6 @@ static int prog_dmabuf(struct es1370_state *s, struct dmabuf *db, unsigned rate, mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); for (map = MAP_NR(db->rawbuf); map <= mapend; map++) set_bit(PG_reserved, &mem_map[map].flags); - printk(KERN_DEBUG "es: allocating dmabuf %8.8lx order %d\n", (unsigned long)db->rawbuf, db->buforder); } fmt &= ES1370_FMT_MASK; bytepersec = rate << sample_shift[fmt]; @@ -598,10 +599,10 @@ static void es1370_update_ptr(struct es1370_state *s) s->dma_adc.total_bytes += diff; s->dma_adc.count += diff; if (s->dma_adc.mapped) { - if (s->dma_adc.count >= s->dma_adc.fragsize) + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) wake_up(&s->dma_adc.wait); } else { - if (s->dma_adc.count > s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1)) { + if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) { s->ctrl &= ~CTRL_ADC_EN; outl(s->ctrl, s->io+ES1370_REG_CONTROL); s->dma_adc.error++; @@ -616,7 +617,7 @@ static void es1370_update_ptr(struct es1370_state *s) s->dma_dac1.total_bytes += diff; if (s->dma_dac1.mapped) { s->dma_dac1.count += diff; - if (s->dma_dac1.count >= s->dma_dac1.fragsize) + if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize) wake_up(&s->dma_dac1.wait); } else { s->dma_dac1.count -= diff; @@ -624,12 +625,12 @@ static void es1370_update_ptr(struct es1370_state *s) s->ctrl &= ~CTRL_DAC1_EN; outl(s->ctrl, s->io+ES1370_REG_CONTROL); s->dma_dac1.error++; - } else if (s->dma_dac1.count <= s->dma_dac1.fragsize && !s->dma_dac1.endcleared) { + } else if (s->dma_dac1.count <= (signed)s->dma_dac1.fragsize && !s->dma_dac1.endcleared) { clear_advance(s->dma_dac1.rawbuf, s->dma_dac1.dmasize, s->dma_dac1.swptr, s->dma_dac1.fragsize, (s->sctrl & SCTRL_P1SEB) ? 0 : 0x80); s->dma_dac1.endcleared = 1; } - if (s->dma_dac1.count < s->dma_dac1.dmasize) + if (s->dma_dac1.count < (signed)s->dma_dac1.dmasize) wake_up(&s->dma_dac1.wait); } } @@ -639,7 +640,7 @@ static void es1370_update_ptr(struct es1370_state *s) s->dma_dac2.total_bytes += diff; if (s->dma_dac2.mapped) { s->dma_dac2.count += diff; - if (s->dma_dac2.count >= s->dma_dac2.fragsize) + if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize) wake_up(&s->dma_dac2.wait); } else { s->dma_dac2.count -= diff; @@ -647,12 +648,12 @@ static void es1370_update_ptr(struct es1370_state *s) s->ctrl &= ~CTRL_DAC2_EN; outl(s->ctrl, s->io+ES1370_REG_CONTROL); s->dma_dac2.error++; - } else if (s->dma_dac2.count <= s->dma_dac2.fragsize && !s->dma_dac2.endcleared) { + } else if (s->dma_dac2.count <= (signed)s->dma_dac2.fragsize && !s->dma_dac2.endcleared) { clear_advance(s->dma_dac2.rawbuf, s->dma_dac2.dmasize, s->dma_dac2.swptr, s->dma_dac2.fragsize, (s->sctrl & SCTRL_P2SEB) ? 0 : 0x80); s->dma_dac2.endcleared = 1; } - if (s->dma_dac2.count < s->dma_dac2.dmasize) + if (s->dma_dac2.count < (signed)s->dma_dac2.dmasize) wake_up(&s->dma_dac2.wait); } } @@ -757,7 +758,6 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a unsigned char l, r, rl, rr; VALIDATE_STATE(s); - if (cmd == SOUND_MIXER_PRIVATE1) { /* enable/disable/query mixer preamp */ get_user_ret(val, (int *)arg, -EFAULT); @@ -886,19 +886,19 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a r = (val >> 8) & 0xff; if (r > 100) r = 100; - if (l < 10) { + if (l < 7) { rl = 0x80; l = 0; } else { - rl = 15 - ((l - 10) / 6); - l = (15 - rl) * 6 + 10; + rl = 31 - ((l - 7) / 3); + l = (31 - rl) * 3 + 7; } - if (r < 10) { + if (r < 7) { rr = 0x80; r = 0; } else { - rr = 15 - ((r - 10) / 6); - r = (15 - rr) * 6 + 10; + rr = 31 - ((r - 7) / 3); + r = (31 - rr) * 3 + 7; } wrcodec(s, mixtable[i].right, rr); } else { @@ -911,12 +911,12 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a r = l = (7 - rl) * 14 + 2; } } else { - if (l < 10) { + if (l < 7) { rl = 0x80; r = l = 0; } else { - rl = 15 - ((l - 10) / 6); - r = l = (15 - rl) * 6 + 10; + rl = 31 - ((l - 7) / 3); + r = l = (31 - rl) * 3 + 7; } } } @@ -982,10 +982,8 @@ static /*const*/ struct file_operations es1370_mixer_fops = { NULL, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ -#if 0 NULL, /* revalidate */ NULL, /* lock */ -#endif }; /* --------------------------------------------------------------------- */ @@ -1190,7 +1188,7 @@ static unsigned int es1370_poll(struct file *file, struct poll_table_struct *wai es1370_update_ptr(s); if (file->f_mode & FMODE_READ) { if (s->dma_adc.mapped) { - if (s->dma_adc.count >= s->dma_adc.fragsize) + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) mask |= POLLIN | POLLRDNORM; } else { if (s->dma_adc.count > 0) @@ -1199,10 +1197,10 @@ static unsigned int es1370_poll(struct file *file, struct poll_table_struct *wai } if (file->f_mode & FMODE_WRITE) { if (s->dma_dac2.mapped) { - if (s->dma_dac2.count >= s->dma_dac2.fragsize) + if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize) mask |= POLLOUT | POLLWRNORM; } else { - if (s->dma_dac2.dmasize > s->dma_dac2.count) + if ((signed)s->dma_dac2.dmasize > s->dma_dac2.count) mask |= POLLOUT | POLLWRNORM; } } @@ -1704,10 +1702,10 @@ static unsigned int es1370_poll_dac(struct file *file, struct poll_table_struct spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); if (s->dma_dac1.mapped) { - if (s->dma_dac1.count >= s->dma_dac1.fragsize) + if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize) mask |= POLLOUT | POLLWRNORM; } else { - if (s->dma_dac1.dmasize > s->dma_dac1.count) + if ((signed)s->dma_dac1.dmasize > s->dma_dac1.count) mask |= POLLOUT | POLLWRNORM; } spin_unlock_irqrestore(&s->lock, flags); @@ -2280,7 +2278,7 @@ __initfunc(int init_es1370(void)) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1370: version v0.10 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1370: version v0.13 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) { if (pcidev->base_address[0] == 0 || diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c index 4963d1271500..1c025fa2ea21 100644 --- a/drivers/sound/es1371.c +++ b/drivers/sound/es1371.c @@ -48,6 +48,7 @@ * 03.08.98 0.3 Do not include modversions.h * Now mixer behaviour can basically be selected between * "OSS documented" and "OSS actual" behaviour + * 31.08.98 0.4 Fix realplayer problems - dac.count issues * */ @@ -693,7 +694,7 @@ static void start_adc(struct es1371_state *s) unsigned fragremain, fshift; spin_lock_irqsave(&s->lock, flags); - if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < s->dma_adc.dmasize - 2*s->dma_adc.fragsize) + if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) && s->dma_adc.ready) { s->ctrl |= CTRL_ADC_EN; s->sctrl = (s->sctrl & ~SCTRL_R1LOOPSEL) | SCTRL_R1INTEN; @@ -838,7 +839,7 @@ static void es1371_update_ptr(struct es1371_state *s) if (s->dma_adc.count >= s->dma_adc.fragsize) wake_up(&s->dma_adc.wait); } else { - if (s->dma_adc.count > s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1)) { + if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) { s->ctrl &= ~CTRL_ADC_EN; outl(s->ctrl, s->io+ES1371_REG_CONTROL); s->dma_adc.error++; @@ -853,7 +854,7 @@ static void es1371_update_ptr(struct es1371_state *s) s->dma_dac1.total_bytes += diff; if (s->dma_dac1.mapped) { s->dma_dac1.count += diff; - if (s->dma_dac1.count >= s->dma_dac1.fragsize) + if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize) wake_up(&s->dma_dac1.wait); } else { s->dma_dac1.count -= diff; @@ -861,12 +862,12 @@ static void es1371_update_ptr(struct es1371_state *s) s->ctrl &= ~CTRL_DAC1_EN; outl(s->ctrl, s->io+ES1371_REG_CONTROL); s->dma_dac1.error++; - } else if (s->dma_dac1.count <= s->dma_dac1.fragsize && !s->dma_dac1.endcleared) { + } else if (s->dma_dac1.count <= (signed)s->dma_dac1.fragsize && !s->dma_dac1.endcleared) { clear_advance(s->dma_dac1.rawbuf, s->dma_dac1.dmasize, s->dma_dac1.swptr, s->dma_dac1.fragsize, (s->sctrl & SCTRL_P1SEB) ? 0 : 0x80); s->dma_dac1.endcleared = 1; } - if (s->dma_dac1.count < s->dma_dac1.dmasize) + if (s->dma_dac1.count < (signed)s->dma_dac1.dmasize) wake_up(&s->dma_dac1.wait); } } @@ -876,7 +877,7 @@ static void es1371_update_ptr(struct es1371_state *s) s->dma_dac2.total_bytes += diff; if (s->dma_dac2.mapped) { s->dma_dac2.count += diff; - if (s->dma_dac2.count >= s->dma_dac2.fragsize) + if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize) wake_up(&s->dma_dac2.wait); } else { s->dma_dac2.count -= diff; @@ -884,12 +885,12 @@ static void es1371_update_ptr(struct es1371_state *s) s->ctrl &= ~CTRL_DAC2_EN; outl(s->ctrl, s->io+ES1371_REG_CONTROL); s->dma_dac2.error++; - } else if (s->dma_dac2.count <= s->dma_dac2.fragsize && !s->dma_dac2.endcleared) { + } else if (s->dma_dac2.count <= (signed)s->dma_dac2.fragsize && !s->dma_dac2.endcleared) { clear_advance(s->dma_dac2.rawbuf, s->dma_dac2.dmasize, s->dma_dac2.swptr, s->dma_dac2.fragsize, (s->sctrl & SCTRL_P2SEB) ? 0 : 0x80); s->dma_dac2.endcleared = 1; } - if (s->dma_dac2.count < s->dma_dac2.dmasize) + if (s->dma_dac2.count < (signed)s->dma_dac2.dmasize) wake_up(&s->dma_dac2.wait); } } @@ -1636,7 +1637,7 @@ static unsigned int es1371_poll(struct file *file, struct poll_table_struct *wai es1371_update_ptr(s); if (file->f_flags & FMODE_READ) { if (s->dma_adc.mapped) { - if (s->dma_adc.count >= s->dma_adc.fragsize) + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) mask |= POLLIN | POLLRDNORM; } else { if (s->dma_adc.count > 0) @@ -1645,10 +1646,10 @@ static unsigned int es1371_poll(struct file *file, struct poll_table_struct *wai } if (file->f_flags & FMODE_WRITE) { if (s->dma_dac2.mapped) { - if (s->dma_dac2.count >= s->dma_dac2.fragsize) + if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize) mask |= POLLOUT | POLLWRNORM; } else { - if (s->dma_dac2.dmasize > s->dma_dac2.count) + if ((signed)s->dma_dac2.dmasize > s->dma_dac2.count) mask |= POLLOUT | POLLWRNORM; } } @@ -2150,10 +2151,10 @@ static unsigned int es1371_poll_dac(struct file *file, struct poll_table_struct spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); if (s->dma_dac1.mapped) { - if (s->dma_dac1.count >= s->dma_dac1.fragsize) + if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize) mask |= POLLOUT | POLLWRNORM; } else { - if (s->dma_dac1.dmasize > s->dma_dac1.count) + if ((signed)s->dma_dac1.dmasize > s->dma_dac1.count) mask |= POLLOUT | POLLWRNORM; } spin_unlock_irqrestore(&s->lock, flags); @@ -2716,7 +2717,7 @@ __initfunc(int init_es1371(void)) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1371: version v0.3 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1371: version v0.4 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) { if (pcidev->base_address[0] == 0 || diff --git a/drivers/sound/msnd.c b/drivers/sound/msnd.c index 8c0f99ed8446..ad7ceaa489c4 100644 --- a/drivers/sound/msnd.c +++ b/drivers/sound/msnd.c @@ -20,7 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: msnd.c,v 1.5 1998/07/18 00:12:15 andrewtv Exp $ + * $Id: msnd.c,v 1.9 1998/09/04 18:41:27 andrewtv Exp $ * ********************************************************************/ @@ -168,16 +168,8 @@ int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user) } if (user) { -#ifdef LINUX20 - if (verify_area(VERIFY_READ, buf , nwritten)) - return nwritten; - - memcpy_fromfs(f->data + f->tail, buf, nwritten); -#else if (copy_from_user(f->data + f->tail, buf, nwritten)) return -EFAULT; -#endif - } else memcpy(f->data + f->tail, buf, nwritten); @@ -214,15 +206,8 @@ int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user) } if (user) { -#ifdef LINUX20 - if (verify_area(VERIFY_WRITE, buf, nread)) - return nread; - - memcpy_tofs(buf, f->data + f->head, nread); -#else if (copy_to_user(buf, f->data + f->head, nread)) return -EFAULT; -#endif } else memcpy(buf, f->data + f->head, nread); @@ -356,8 +341,10 @@ int msnd_disable_irq(multisound_dev_t *dev) if (--dev->irq_ref > 0) return 0; - if (dev->irq_ref < 0) - dev->irq_ref = 0; + if (dev->irq_ref < 0) { + printk(KERN_WARNING LOGNAME ": IRQ ref count is %d\n", dev->irq_ref); +/* dev->irq_ref = 0; */ + } printk(KERN_DEBUG LOGNAME ": Disabling IRQ\n"); diff --git a/drivers/sound/msnd.h b/drivers/sound/msnd.h index 7cc2fa6ef41d..804cff425c45 100644 --- a/drivers/sound/msnd.h +++ b/drivers/sound/msnd.h @@ -24,16 +24,16 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: msnd.h,v 1.9 1998/08/06 21:06:14 andrewtv Exp $ + * $Id: msnd.h,v 1.18 1998/09/04 18:43:40 andrewtv Exp $ * ********************************************************************/ #ifndef __MSND_H #define __MSND_H -#define VERSION "0.7.2" +#define VERSION "0.7.13" #define DEFSAMPLERATE DSP_DEFAULT_SPEED -#define DEFSAMPLESIZE 8 +#define DEFSAMPLESIZE AFMT_U8 #define DEFCHANNELS 1 #define DEFFIFOSIZE 64 @@ -142,9 +142,9 @@ #define HDEX_MIDI_OUT_STOP (9 + HDEX_BASE) #define HDEX_AUX_REQ (10 + HDEX_BASE) -#define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF )) +#define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF)) #define LOWORD(l) ((WORD)(DWORD)(l)) -#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8 ) & 0xFF )) +#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) #define LOBYTE(w) ((BYTE)(w)) #define MAKELONG(low,hi) ((long)(((WORD)(low))|(((DWORD)((WORD)(hi)))<<16))) #define MAKEWORD(low,hi) ((WORD)(((BYTE)(low))|(((WORD)((BYTE)(hi)))<<8))) @@ -166,33 +166,31 @@ # define spin_unlock_irqrestore(junk,flags) do { restore_flags(flags); } while (0) #endif -typedef unsigned char BYTE; -typedef unsigned short USHORT; -typedef unsigned short WORD; -typedef unsigned int DWORD; -typedef -struct DAQueueDataStruct * LPDAQD; - -#define GCC_PACKED __attribute__ ((packed)) - -struct JobQueueStruct { - WORD wStart; - WORD wSize; - WORD wHead; - WORD wTail; -} GCC_PACKED; - -struct DAQueueDataStruct { - WORD wStart; - WORD wSize; - WORD wFormat; - WORD wSampleSize; - WORD wChannels; - WORD wSampleRate; - WORD wIntMsg; - WORD wFlags; -} GCC_PACKED; - +/* JobQueueStruct */ +#define JQS_wStart 0x00 +#define JQS_wSize 0x02 +#define JQS_wHead 0x04 +#define JQS_wTail 0x06 +#define JQS__size 0x08 + +/* DAQueueDataStruct */ +#define DAQDS_wStart 0x00 +#define DAQDS_wSize 0x02 +#define DAQDS_wFormat 0x04 +#define DAQDS_wSampleSize 0x06 +#define DAQDS_wChannels 0x08 +#define DAQDS_wSampleRate 0x0A +#define DAQDS_wIntMsg 0x0C +#define DAQDS_wFlags 0x0E +#define DAQDS__size 0x10 + +typedef u8 BYTE; +typedef u16 USHORT; +typedef u16 WORD; +typedef u32 DWORD; +typedef volatile BYTE * LPDAQD; + +/* Generic FIFO */ typedef struct { size_t n, len; char *data; @@ -200,12 +198,12 @@ typedef struct { } msnd_fifo; typedef struct multisound_dev { - + /* Linux device info */ char *name; int dsp_minor, mixer_minor; /* Hardware resources */ - unsigned int io, numio; + int io, numio; int memid, irqid; int irq, irq_ref; unsigned char info; @@ -214,16 +212,14 @@ typedef struct multisound_dev { spinlock_t lock; #endif - /* MultiSound DDK variables */ - enum { msndClassic, msndPinnacle } type; - struct SMA0_CommonData *SMA; /* diff. structure for classic vs. pinnacle */ - struct DAQueueDataStruct *CurDAQD; - struct DAQueueDataStruct *CurDARQD; - volatile WORD *pwDSPQData , *pwMIDQData , *pwMODQData; - volatile struct JobQueueStruct *DAPQ , *DARQ , *MODQ , *MIDQ , *DSPQ; - BYTE bCurrentMidiPatch; + /* Motorola 56k DSP SMA */ + volatile BYTE *SMA; + volatile BYTE *CurDAQD, *CurDARQD; + volatile BYTE *DAPQ, *DARQ, *MODQ, *MIDQ, *DSPQ; + volatile WORD *pwDSPQData, *pwMIDQData, *pwMODQData; /* State variables */ + enum { msndClassic, msndPinnacle } type; mode_t mode; unsigned long flags; #define F_BANKONE 0 @@ -237,7 +233,6 @@ typedef struct multisound_dev { #define F_INT_MIDI_INUSE 8 #define F_WRITEFLUSH 9 #define F_HAVEDIGITAL 10 - struct wait_queue *writeblock, *readblock; struct wait_queue *writeflush; unsigned long recsrc; @@ -248,17 +243,17 @@ typedef struct multisound_dev { int sample_size; int sample_rate; int channels; + BYTE bCurrentMidiPatch; void (*inc_ref)(void); void (*dec_ref)(void); /* Digital audio FIFOs */ - int fifosize; msnd_fifo DAPF, DARF; + int fifosize; int lastbank; /* MIDI in callback */ void (*midi_in_interrupt)(struct multisound_dev *); - } multisound_dev_t; #ifndef mdelay diff --git a/drivers/sound/msnd_classic.h b/drivers/sound/msnd_classic.h index 3ae0e0b3b9bd..bdc28ffd087e 100644 --- a/drivers/sound/msnd_classic.h +++ b/drivers/sound/msnd_classic.h @@ -24,7 +24,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: msnd_classic.h,v 1.5 1998/07/18 00:12:15 andrewtv Exp $ + * $Id: msnd_classic.h,v 1.7 1998/09/03 06:39:47 andrewtv Exp $ * ********************************************************************/ #ifndef __MSND_CLASSIC_H @@ -32,133 +32,133 @@ #include -#define DSP_NUMIO 0x10 +#define DSP_NUMIO 0x10 -#define HP_MEMM 0x08 +#define HP_MEMM 0x08 -#define HP_BITM 0x0E -#define HP_WAIT 0x0D -#define HP_DSPR 0x0A -#define HP_PROR 0x0B -#define HP_BLKS 0x0C +#define HP_BITM 0x0E +#define HP_WAIT 0x0D +#define HP_DSPR 0x0A +#define HP_PROR 0x0B +#define HP_BLKS 0x0C -#define HPPRORESET_OFF 0 -#define HPPRORESET_ON 1 +#define HPPRORESET_OFF 0 +#define HPPRORESET_ON 1 -#define HPDSPRESET_OFF 0 -#define HPDSPRESET_ON 1 +#define HPDSPRESET_OFF 0 +#define HPDSPRESET_ON 1 -#define HPBLKSEL_0 0 -#define HPBLKSEL_1 1 +#define HPBLKSEL_0 0 +#define HPBLKSEL_1 1 -#define HPWAITSTATE_0 0 -#define HPWAITSTATE_1 1 +#define HPWAITSTATE_0 0 +#define HPWAITSTATE_1 1 -#define HPBITMODE_16 0 -#define HPBITMODE_8 1 +#define HPBITMODE_16 0 +#define HPBITMODE_8 1 -#define HIDSP_INT_PLAY_UNDER 0x00 -#define HIDSP_INT_RECORD_OVER 0x01 -#define HIDSP_INPUT_CLIPPING 0x02 -#define HIDSP_MIDI_IN_OVER 0x10 +#define HIDSP_INT_PLAY_UNDER 0x00 +#define HIDSP_INT_RECORD_OVER 0x01 +#define HIDSP_INPUT_CLIPPING 0x02 +#define HIDSP_MIDI_IN_OVER 0x10 #define HIDSP_MIDI_OVERRUN_ERR 0x13 -#define HDEXAR_CLEAR_PEAKS 1 -#define HDEXAR_IN_SET_POTS 2 -#define HDEXAR_AUX_SET_POTS 3 -#define HDEXAR_CAL_A_TO_D 4 -#define HDEXAR_RD_EXT_DSP_BITS 5 - -#define TIME_PRO_RESET_DONE 0x028A -#define TIME_PRO_SYSEX 0x0040 -#define TIME_PRO_RESET 0x0032 - -#define AGND 0x01 -#define SIGNAL 0x02 - -#define EXT_DSP_BIT_DCAL 0x0001 -#define EXT_DSP_BIT_MIDI_CON 0x0002 - -#define BUFFSIZE 0x8000 -#define HOSTQ_SIZE 0x40 - -#define SRAM_CNTL_START 0x7F00 -#define SMA_STRUCT_START 0x7F40 - -#define DAP_BUFF_SIZE 0x2400 -#define DAR_BUFF_SIZE 0x2000 - -#define DAPQ_STRUCT_SIZE 0x10 -#define DARQ_STRUCT_SIZE 0x10 -#define DAPQ_BUFF_SIZE (3 * 0x10) -#define DARQ_BUFF_SIZE (3 * 0x10) -#define MODQ_BUFF_SIZE 0x400 -#define MIDQ_BUFF_SIZE 0x200 -#define DSPQ_BUFF_SIZE 0x40 - -#define DAPQ_DATA_BUFF 0x6C00 -#define DARQ_DATA_BUFF 0x6C30 -#define MODQ_DATA_BUFF 0x6C60 -#define MIDQ_DATA_BUFF 0x7060 -#define DSPQ_DATA_BUFF 0x7260 - -#define DAPQ_OFFSET SRAM_CNTL_START -#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) -#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) -#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) -#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) - -#define MOP_PROTEUS 0x10 -#define MOP_EXTOUT 0x32 -#define MOP_EXTTHRU 0x02 -#define MOP_OUTMASK 0x01 - -#define MIP_EXTIN 0x01 -#define MIP_PROTEUS 0x00 -#define MIP_INMASK 0x32 - -struct SMA0_CommonData { - WORD wCurrPlayBytes; - WORD wCurrRecordBytes; - WORD wCurrPlayVolLeft; - WORD wCurrPlayVolRight; - WORD wCurrInVolLeft; - WORD wCurrInVolRight; - WORD wUser_3; - WORD wUser_4; - DWORD dwUser_5; - DWORD dwUser_6; - WORD wUser_7; - WORD wReserved_A; - WORD wReserved_B; - WORD wReserved_C; - WORD wReserved_D; - WORD wReserved_E; - WORD wReserved_F; - WORD wReserved_G; - WORD wReserved_H; - WORD wCurrDSPStatusFlags; - WORD wCurrHostStatusFlags; - WORD wCurrInputTagBits; - WORD wCurrLeftPeak; - WORD wCurrRightPeak; - WORD wExtDSPbits; - BYTE bExtHostbits; - BYTE bBoardLevel; - BYTE bInPotPosRight; - BYTE bInPotPosLeft; - BYTE bAuxPotPosRight; - BYTE bAuxPotPosLeft; - WORD wCurrMastVolLeft; - WORD wCurrMastVolRight; - BYTE bUser_12; - BYTE bUser_13; - WORD wUser_14; - WORD wUser_15; - WORD wCalFreqAtoD; - WORD wUser_16; - WORD wUser_17; -} GCC_PACKED; +#define HDEXAR_CLEAR_PEAKS 1 +#define HDEXAR_IN_SET_POTS 2 +#define HDEXAR_AUX_SET_POTS 3 +#define HDEXAR_CAL_A_TO_D 4 +#define HDEXAR_RD_EXT_DSP_BITS 5 + +#define TIME_PRO_RESET_DONE 0x028A +#define TIME_PRO_SYSEX 0x0040 +#define TIME_PRO_RESET 0x0032 + +#define AGND 0x01 +#define SIGNAL 0x02 + +#define EXT_DSP_BIT_DCAL 0x0001 +#define EXT_DSP_BIT_MIDI_CON 0x0002 + +#define BUFFSIZE 0x8000 +#define HOSTQ_SIZE 0x40 + +#define SRAM_CNTL_START 0x7F00 +#define SMA_STRUCT_START 0x7F40 + +#define DAP_BUFF_SIZE 0x2400 +#define DAR_BUFF_SIZE 0x2000 + +#define DAPQ_STRUCT_SIZE 0x10 +#define DARQ_STRUCT_SIZE 0x10 +#define DAPQ_BUFF_SIZE (3 * 0x10) +#define DARQ_BUFF_SIZE (3 * 0x10) +#define MODQ_BUFF_SIZE 0x400 +#define MIDQ_BUFF_SIZE 0x200 +#define DSPQ_BUFF_SIZE 0x40 + +#define DAPQ_DATA_BUFF 0x6C00 +#define DARQ_DATA_BUFF 0x6C30 +#define MODQ_DATA_BUFF 0x6C60 +#define MIDQ_DATA_BUFF 0x7060 +#define DSPQ_DATA_BUFF 0x7260 + +#define DAPQ_OFFSET SRAM_CNTL_START +#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) +#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) +#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) +#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) + +#define MOP_PROTEUS 0x10 +#define MOP_EXTOUT 0x32 +#define MOP_EXTTHRU 0x02 +#define MOP_OUTMASK 0x01 + +#define MIP_EXTIN 0x01 +#define MIP_PROTEUS 0x00 +#define MIP_INMASK 0x32 + +/* Classic SMA Common Data */ +#define SMA_wCurrPlayBytes 0x0000 +#define SMA_wCurrRecordBytes 0x0002 +#define SMA_wCurrPlayVolLeft 0x0004 +#define SMA_wCurrPlayVolRight 0x0006 +#define SMA_wCurrInVolLeft 0x0008 +#define SMA_wCurrInVolRight 0x000a +#define SMA_wUser_3 0x000c +#define SMA_wUser_4 0x000e +#define SMA_dwUser_5 0x0010 +#define SMA_dwUser_6 0x0014 +#define SMA_wUser_7 0x0018 +#define SMA_wReserved_A 0x001a +#define SMA_wReserved_B 0x001c +#define SMA_wReserved_C 0x001e +#define SMA_wReserved_D 0x0020 +#define SMA_wReserved_E 0x0022 +#define SMA_wReserved_F 0x0024 +#define SMA_wReserved_G 0x0026 +#define SMA_wReserved_H 0x0028 +#define SMA_wCurrDSPStatusFlags 0x002a +#define SMA_wCurrHostStatusFlags 0x002c +#define SMA_wCurrInputTagBits 0x002e +#define SMA_wCurrLeftPeak 0x0030 +#define SMA_wCurrRightPeak 0x0032 +#define SMA_wExtDSPbits 0x0034 +#define SMA_bExtHostbits 0x0036 +#define SMA_bBoardLevel 0x0037 +#define SMA_bInPotPosRight 0x0038 +#define SMA_bInPotPosLeft 0x0039 +#define SMA_bAuxPotPosRight 0x003a +#define SMA_bAuxPotPosLeft 0x003b +#define SMA_wCurrMastVolLeft 0x003c +#define SMA_wCurrMastVolRight 0x003e +#define SMA_bUser_12 0x0040 +#define SMA_bUser_13 0x0041 +#define SMA_wUser_14 0x0042 +#define SMA_wUser_15 0x0044 +#define SMA_wCalFreqAtoD 0x0046 +#define SMA_wUser_16 0x0048 +#define SMA_wUser_17 0x004a +#define SMA__size 0x004c #ifdef HAVE_DSPCODEH # include "msndperm.c" diff --git a/drivers/sound/msnd_pinnacle.c b/drivers/sound/msnd_pinnacle.c index bed4ec1bfe7b..bebb5d49c7c1 100644 --- a/drivers/sound/msnd_pinnacle.c +++ b/drivers/sound/msnd_pinnacle.c @@ -29,7 +29,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: msnd_pinnacle.c,v 1.8 1998/08/06 21:06:14 andrewtv Exp $ + * $Id: msnd_pinnacle.c,v 1.17 1998/09/04 18:41:27 andrewtv Exp $ * ********************************************************************/ @@ -59,11 +59,7 @@ # define LOGNAME "msnd_pinnacle" #endif -#define DEVNAME dev.name -#define MIXERMINOR dev.mixer_minor -#define DSPMINOR dev.dsp_minor - -multisound_dev_t dev; +static multisound_dev_t dev; #ifndef HAVE_DSPCODEH static char *dspini, *permini; @@ -76,25 +72,22 @@ static void reset_play_queue(void) LPDAQD lpDAQ; msnd_fifo_make_empty(&dev.DAPF); - dev.DAPQ->wHead = 0; - dev.DAPQ->wTail = PCTODSP_OFFSET(2 * DAPQ_STRUCT_SIZE); + writew(0, dev.DAPQ + JQS_wHead); + writew(PCTODSP_OFFSET(2 * DAPQ_STRUCT_SIZE), dev.DAPQ + JQS_wTail); dev.CurDAQD = (LPDAQD)(dev.base + 1 * DAPQ_DATA_BUFF); outb(HPBLKSEL_0, dev.io + HP_BLKS); memset_io(dev.base, 0, DAP_BUFF_SIZE * 3); - for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, ++lpDAQ) { - - writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), &lpDAQ->wStart); - writew(DAP_BUFF_SIZE, &lpDAQ->wSize); - writew(1, &lpDAQ->wFormat); - writew(dev.sample_size, &lpDAQ->wSampleSize); - writew(dev.channels, &lpDAQ->wChannels); - writew(dev.sample_rate, &lpDAQ->wSampleRate); - writew(HIMT_PLAY_DONE * 0x100 + n, &lpDAQ->wIntMsg); - writew(n + 1, &lpDAQ->wFlags); - + for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, lpDAQ += DAQDS__size) { + writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), lpDAQ + DAQDS_wStart); + writew(DAP_BUFF_SIZE, lpDAQ + DAQDS_wSize); + writew(1, lpDAQ + DAQDS_wFormat); + writew(dev.sample_size, lpDAQ + DAQDS_wSampleSize); + writew(dev.channels, lpDAQ + DAQDS_wChannels); + writew(dev.sample_rate, lpDAQ + DAQDS_wSampleRate); + writew(HIMT_PLAY_DONE * 0x100 + n, lpDAQ + DAQDS_wIntMsg); + writew(n + 1, lpDAQ + DAQDS_wFlags); } - dev.lastbank = -1; } @@ -104,34 +97,62 @@ static void reset_record_queue(void) LPDAQD lpDAQ; msnd_fifo_make_empty(&dev.DARF); - dev.DARQ->wHead = 0; - dev.DARQ->wTail = PCTODSP_OFFSET(2 * DARQ_STRUCT_SIZE); + writew(0, dev.DARQ + JQS_wHead); + writew(PCTODSP_OFFSET(2 * DARQ_STRUCT_SIZE), dev.DARQ + JQS_wTail); dev.CurDARQD = (LPDAQD)(dev.base + 1 * DARQ_DATA_BUFF); outb(HPBLKSEL_1, dev.io + HP_BLKS); memset_io(dev.base, 0, DAR_BUFF_SIZE * 3); outb(HPBLKSEL_0, dev.io + HP_BLKS); - for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, ++lpDAQ) { - - writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, &lpDAQ->wStart); - writew(DAR_BUFF_SIZE, &lpDAQ->wSize); - writew(1, &lpDAQ->wFormat); - writew(dev.sample_size, &lpDAQ->wSampleSize); - writew(dev.channels, &lpDAQ->wChannels); - writew(dev.sample_rate, &lpDAQ->wSampleRate); - writew(HIMT_RECORD_DONE * 0x100 + n, &lpDAQ->wIntMsg); - writew(n + 1, &lpDAQ->wFlags); - + for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, lpDAQ += DAQDS__size) { + writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, lpDAQ + DAQDS_wStart); + writew(DAR_BUFF_SIZE, lpDAQ + DAQDS_wSize); + writew(1, lpDAQ + DAQDS_wFormat); + writew(dev.sample_size, lpDAQ + DAQDS_wSampleSize); + writew(dev.channels, lpDAQ + DAQDS_wChannels); + writew(dev.sample_rate, lpDAQ + DAQDS_wSampleRate); + writew(HIMT_RECORD_DONE * 0x100 + n, lpDAQ + DAQDS_wIntMsg); + writew(n + 1, lpDAQ + DAQDS_wFlags); } } static void reset_queues(void) { - dev.DSPQ->wHead = dev.DSPQ->wTail = 0; + writew(0, dev.DSPQ + JQS_wHead); + writew(0, dev.DSPQ + JQS_wTail); reset_play_queue(); reset_record_queue(); } +static int dsp_set_format(int val) +{ + int data, i; + LPDAQD lpDAQ, lpDARQ; + + lpDAQ = (LPDAQD)(dev.base + DAPQ_DATA_BUFF); + lpDARQ = (LPDAQD)(dev.base + DARQ_DATA_BUFF); + + switch (val) { + case AFMT_U8: + case AFMT_S16_LE: + data = val; + break; + default: + data = DEFSAMPLESIZE; + break; + } + + for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) { + + writew(data, lpDAQ + DAQDS_wSampleSize); + writew(data, lpDARQ + DAQDS_wSampleSize); + } + + dev.sample_size = data; + + return data; +} + static int dsp_ioctl(unsigned int cmd, unsigned long arg) { int val, i, data, tmp; @@ -154,64 +175,43 @@ static int dsp_ioctl(unsigned int cmd, unsigned long arg) case SNDCTL_DSP_SYNC: case SNDCTL_DSP_RESET: - reset_play_queue(); reset_record_queue(); - return 0; case SNDCTL_DSP_GETBLKSIZE: - tmp = dev.fifosize / 4; if (put_user(tmp, (int *)arg)) return -EFAULT; - return 0; - case SNDCTL_DSP_NONBLOCK: - - dev.mode |= O_NONBLOCK; - - return 0; - - case SNDCTL_DSP_GETCAPS: - - val = DSP_CAP_DUPLEX | DSP_CAP_BATCH; + case SNDCTL_DSP_GETFMTS: + val = AFMT_S16_LE | AFMT_U8; if (put_user(val, (int *)arg)) return -EFAULT; - return 0; - case SNDCTL_DSP_SAMPLESIZE: - + case SNDCTL_DSP_SETFMT: if (get_user(val, (int *)arg)) return -EFAULT; - switch (val) { - case 16: - case 8: - data = val; - break; - default: - data = DEFSAMPLESIZE; - break; - } - - for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + data = (val == AFMT_QUERY) ? dev.sample_size : dsp_set_format(val); - lpDAQ->wSampleSize = data; - lpDARQ->wSampleSize = data; - } - - dev.sample_size = data; - if (put_user(data, (int *)arg)) return -EFAULT; + return 0; + case SNDCTL_DSP_NONBLOCK: + dev.mode |= O_NONBLOCK; + return 0; + + case SNDCTL_DSP_GETCAPS: + val = DSP_CAP_DUPLEX | DSP_CAP_BATCH; + if (put_user(val, (int *)arg)) + return -EFAULT; return 0; case SNDCTL_DSP_SPEED: - if (get_user(val, (int *)arg)) return -EFAULT; @@ -223,21 +223,19 @@ static int dsp_ioctl(unsigned int cmd, unsigned long arg) data = val; - for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { - - lpDAQ->wSampleRate = data; - lpDARQ->wSampleRate = data; + for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) { + + writew(data, lpDAQ + DAQDS_wSampleRate); + writew(data, lpDARQ + DAQDS_wSampleRate); } dev.sample_rate = data; if (put_user(data, (int *)arg)) return -EFAULT; - return 0; case SNDCTL_DSP_CHANNELS: - if (get_user(val, (int *)arg)) return -EFAULT; @@ -251,21 +249,19 @@ static int dsp_ioctl(unsigned int cmd, unsigned long arg) break; } - for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) { - lpDAQ->wChannels = data; - lpDARQ->wChannels = data; + writew(data, lpDAQ + DAQDS_wChannels); + writew(data, lpDARQ + DAQDS_wChannels); } dev.channels = data; if (put_user(val, (int *)arg)) return -EFAULT; - return 0; case SNDCTL_DSP_STEREO: - if (get_user(val, (int *)arg)) return -EFAULT; @@ -280,17 +276,16 @@ static int dsp_ioctl(unsigned int cmd, unsigned long arg) break; } - for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) { + for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) { - lpDAQ->wChannels = data; - lpDARQ->wChannels = data; + writew(data, lpDAQ + DAQDS_wChannels); + writew(data, lpDARQ + DAQDS_wChannels); } dev.channels = data; if (put_user(val, (int *)arg)) return -EFAULT; - return 0; } @@ -319,11 +314,11 @@ static int mixer_get(int d) } } -#define update_vol(a,b,s) \ - writew(dev.left_levels[a] * readw(&dev.SMA->wCurrMastVolLeft) / 0xffff / s, \ - &dev.SMA->b##Left); \ - writew(dev.right_levels[a] * readw(&dev.SMA->wCurrMastVolRight) / 0xffff / s, \ - &dev.SMA->b##Right); +#define update_vol(a,b,s) \ + writew(dev.left_levels[a] * readw(dev.SMA + SMA_wCurrMastVolLeft) / 0xffff / s, \ + dev.SMA + SMA_##b##Left); \ + writew(dev.right_levels[a] * readw(dev.SMA + SMA_wCurrMastVolRight) / 0xffff / s, \ + dev.SMA + SMA_##b##Right); static int mixer_set(int d, int value) { @@ -346,30 +341,30 @@ static int mixer_set(int d, int value) switch (d) { case SOUND_MIXER_VOLUME: /* master volume */ - writew(wLeft / 2, &dev.SMA->wCurrMastVolLeft); - writew(wRight / 2, &dev.SMA->wCurrMastVolRight); + writew(wLeft / 2, dev.SMA + SMA_wCurrMastVolLeft); + writew(wRight / 2, dev.SMA + SMA_wCurrMastVolRight); break; /* pot controls */ case SOUND_MIXER_LINE: /* aux pot control */ - writeb(bLeft, &dev.SMA->bInPotPosLeft); - writeb(bRight, &dev.SMA->bInPotPosRight); + writeb(bLeft, dev.SMA + SMA_bInPotPosLeft); + writeb(bRight, dev.SMA + SMA_bInPotPosRight); if (msnd_send_word(&dev, 0, 0, HDEXAR_IN_SET_POTS) == 0) msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); break; #ifndef MSND_CLASSIC case SOUND_MIXER_MIC: /* mic pot control */ - writeb(bLeft, &dev.SMA->bMicPotPosLeft); - writeb(bRight, &dev.SMA->bMicPotPosRight); + writeb(bLeft, dev.SMA + SMA_bMicPotPosLeft); + writeb(bRight, dev.SMA + SMA_bMicPotPosRight); if (msnd_send_word(&dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0) msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); break; #endif case SOUND_MIXER_LINE1: /* line pot control */ - writeb(bLeft, &dev.SMA->bAuxPotPosLeft); - writeb(bRight, &dev.SMA->bAuxPotPosRight); + writeb(bLeft, dev.SMA + SMA_bAuxPotPosLeft); + writeb(bRight, dev.SMA + SMA_bAuxPotPosRight); if (msnd_send_word(&dev, 0, 0, HDEXAR_AUX_SET_POTS) == 0) msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); break; @@ -407,19 +402,14 @@ static unsigned long set_recsrc(unsigned long recsrc) #ifndef MSND_CLASSIC if (dev.recsrc & SOUND_MASK_LINE) { - if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) == 0) msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); - } else if (dev.recsrc & SOUND_MASK_SYNTH) { - if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_SYNTH_IN) == 0) msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); - } else if ((dev.recsrc & SOUND_MASK_DIGITAL1) && test_bit(F_HAVEDIGITAL, &dev.flags)) { - if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_DAT_IN) == 0) { udelay(50); msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ); @@ -457,13 +447,14 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg) set_mixer_info(); return copy_to_user((void *)arg, &info, sizeof(info)); } - else if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, (int *)arg); + else if (cmd == OSS_GETVERSION) { + int sound_version = SOUND_VERSION; + return put_user(sound_version, (int *)arg); + } else if (((cmd >> 8) & 0xff) == 'M') { int val = 0; if (_SIOC_DIR(cmd) & _SIOC_WRITE) { - switch (cmd & 0xff) { case SOUND_MIXER_RECSRC: if (get_user(val, (int *)arg)) @@ -477,9 +468,7 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg) val = mixer_set(cmd & 0xff, val); break; } - ++dev.mixer_mod_count; - return put_user(val, (int *)arg); } else { @@ -532,9 +521,9 @@ static int dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u { int minor = MINOR(inode->i_rdev); - if (minor == DSPMINOR) + if (minor == dev.dsp_minor) return dsp_ioctl(cmd, arg); - else if (minor == MIXERMINOR) + else if (minor == dev.mixer_minor) return mixer_ioctl(cmd, arg); return -EINVAL; @@ -597,14 +586,14 @@ static int dev_open(struct inode *inode, struct file *file) int minor = MINOR(inode->i_rdev); int err = 0; - if (minor == DSPMINOR) { + if (minor == dev.dsp_minor) { if (test_bit(F_AUDIO_INUSE, &dev.flags)) return -EBUSY; err = dsp_open(file); } - else if (minor == MIXERMINOR) { + else if (minor == dev.mixer_minor) { /* nothing */ } else err = -EINVAL; @@ -626,13 +615,13 @@ static int dev_close(struct inode *inode, struct file *file) int err = 0; #endif - if (minor == DSPMINOR) { + if (minor == dev.dsp_minor) { #ifndef LINUX20 err = #endif dsp_close(); } - else if (minor == MIXERMINOR) { + else if (minor == dev.mixer_minor) { /* nothing */ } #ifndef LINUX20 @@ -770,7 +759,7 @@ static ssize_t dev_read(struct file *file, char *buf, size_t count, loff_t *off) int minor = MINOR(file->f_dentry->d_inode->i_rdev); #endif - if (minor == DSPMINOR) { + if (minor == dev.dsp_minor) { return dsp_read(buf, count); @@ -788,7 +777,7 @@ static ssize_t dev_write(struct file *file, const char *buf, size_t count, loff_ int minor = MINOR(file->f_dentry->d_inode->i_rdev); #endif - if (minor == DSPMINOR) { + if (minor == dev.dsp_minor) { return dsp_write(buf, count); @@ -798,32 +787,32 @@ static ssize_t dev_write(struct file *file, const char *buf, size_t count, loff_ static void eval_dsp_msg(WORD wMessage) { + WORD wTmp; + switch (HIBYTE(wMessage)) { case HIMT_PLAY_DONE: - if (dev.lastbank == LOBYTE(wMessage)) break; dev.lastbank = LOBYTE(wMessage); - dev.CurDAQD->wSize = DAP_BUFF_SIZE; + writew(DAP_BUFF_SIZE, dev.CurDAQD + DAQDS_wSize); - if ((dev.DAPQ->wTail += PCTODSP_OFFSET(DAPQ_STRUCT_SIZE)) > dev.DAPQ->wSize) - dev.DAPQ->wTail = 0; + wTmp = readw(dev.DAPQ + JQS_wTail) + PCTODSP_OFFSET(DAPQ_STRUCT_SIZE); + if (wTmp > readw(dev.DAPQ + JQS_wSize)) + writew(0, dev.DAPQ + JQS_wTail); + else + writew(wTmp, dev.DAPQ + JQS_wTail); - if (++dev.CurDAQD > (LPDAQD)(dev.base + DAPQ_DATA_BUFF + 2 * DAPQ_STRUCT_SIZE)) + if ((dev.CurDAQD += DAQDS__size) > (LPDAQD)(dev.base + DAPQ_DATA_BUFF + 2 * DAPQ_STRUCT_SIZE)) dev.CurDAQD = (LPDAQD)(dev.base + DAPQ_DATA_BUFF); if (dev.lastbank < 3) { - if (DAPF_to_bank(dev.lastbank) > 0) { - mdelay(1); msnd_send_dsp_cmd(&dev, HDEX_PLAY_START); - } else if (!test_bit(F_WRITEBLOCK, &dev.flags)) { - clear_bit(F_WRITING, &dev.flags); #ifdef LINUX20 if (test_bit(F_WRITEFLUSH, &dev.flags)) { @@ -834,44 +823,33 @@ static void eval_dsp_msg(WORD wMessage) if (test_and_clear_bit(F_WRITEFLUSH, &dev.flags)) wake_up_interruptible(&dev.writeflush); #endif - msnd_disable_irq(&dev); - } } if (test_bit(F_WRITEBLOCK, &dev.flags)) wake_up_interruptible(&dev.writeblock); - break; - case HIMT_RECORD_DONE: { + case HIMT_RECORD_DONE: + wTmp = readw(dev.DARQ + JQS_wTail) + DARQ_STRUCT_SIZE / 2; - WORD wTemp; - - wTemp = dev.DARQ->wTail + (DARQ_STRUCT_SIZE / 2); + if (wTmp > readw(dev.DARQ + JQS_wSize)) + wTmp = 0; - if (wTemp > dev.DARQ->wSize) - wTemp = 0; + while (wTmp == readw(dev.DARQ + JQS_wHead)); - while (wTemp == dev.DARQ->wHead); - - dev.DARQ->wTail = wTemp; + writew(wTmp, dev.DARQ + JQS_wTail); outb(HPBLKSEL_1, dev.io + HP_BLKS); - if (bank_to_DARF(LOBYTE(wMessage)) == 0 && - !test_bit(F_READBLOCK, &dev.flags)) { - + if (bank_to_DARF(LOBYTE(wMessage)) == 0 && !test_bit(F_READBLOCK, &dev.flags)) { memset_io(dev.base, 0, DAR_BUFF_SIZE * 3); clear_bit(F_READING, &dev.flags); - msnd_disable_irq(&dev); - } outb(HPBLKSEL_0, dev.io + HP_BLKS); if (test_bit(F_READBLOCK, &dev.flags)) wake_up_interruptible(&dev.readblock); - - } break; + break; case HIMT_DSP: switch (LOBYTE(wMessage)) { @@ -879,12 +857,12 @@ static void eval_dsp_msg(WORD wMessage) case HIDSP_PLAY_UNDER: #endif case HIDSP_INT_PLAY_UNDER: - printk(KERN_INFO LOGNAME ": Write underflow\n"); +/* printk(KERN_INFO LOGNAME ": Write underflow\n"); */ reset_play_queue(); break; case HIDSP_INT_RECORD_OVER: - printk(KERN_INFO LOGNAME ": Read overflow\n"); +/* printk(KERN_INFO LOGNAME ": Read overflow\n"); */ reset_record_queue(); break; @@ -921,12 +899,16 @@ static void intr(int irq, void *dev_id, struct pt_regs *regs) inb(dev.io + HP_RXL); - while (dev.DSPQ->wTail != dev.DSPQ->wHead) { - - eval_dsp_msg(*(dev.pwDSPQData + dev.DSPQ->wHead)); + while (readw(dev.DSPQ + JQS_wTail) != readw(dev.DSPQ + JQS_wHead)) { + WORD wTmp; - if (++dev.DSPQ->wHead > dev.DSPQ->wSize) - dev.DSPQ->wHead = 0; + eval_dsp_msg(*(dev.pwDSPQData + readw(dev.DSPQ + JQS_wHead))); + + wTmp = readw(dev.DSPQ + JQS_wHead) + 1; + if (wTmp > readw(dev.DSPQ + JQS_wSize)) + writew(0, dev.DSPQ + JQS_wHead); + else + writew(wTmp, dev.DSPQ + JQS_wHead); } if (test_bit(F_BANKONE, &dev.flags)) @@ -944,13 +926,17 @@ static struct file_operations dev_fileops = { dev_ioctl, NULL, dev_open, - NULL, /* flush */ +#ifndef LINUX20 +# if LINUX_VERSION_CODE >= 0x020100 + 118 + NULL, +# endif /* >= 2.1.118 */ +#endif dev_close, }; __initfunc(static int reset_dsp(void)) { - int timeout = 20000; + int timeout = 100; outb(HPDSPRESET_ON, dev.io + HP_DSPR); @@ -984,7 +970,6 @@ __initfunc(static int probe_multisound(void)) #endif if (check_region(dev.io, dev.numio)) { - printk(KERN_ERR LOGNAME ": I/O port conflict\n"); return -ENODEV; } @@ -992,7 +977,6 @@ __initfunc(static int probe_multisound(void)) request_region(dev.io, dev.numio, "probing"); if (reset_dsp() < 0) { - release_region(dev.io, dev.numio); return -ENODEV; } @@ -1056,13 +1040,12 @@ __initfunc(static int init_sma(void)) outb(HPBLKSEL_0, dev.io + HP_BLKS); - dev.DAPQ = (struct JobQueueStruct *)(dev.base + DAPQ_OFFSET); - dev.DARQ = (struct JobQueueStruct *)(dev.base + DARQ_OFFSET); - dev.MODQ = (struct JobQueueStruct *)(dev.base + MODQ_OFFSET); - dev.MIDQ = (struct JobQueueStruct *)(dev.base + MIDQ_OFFSET); - dev.DSPQ = (struct JobQueueStruct *)(dev.base + DSPQ_OFFSET); - - dev.SMA = (struct SMA0_CommonData *)(dev.base + SMA_STRUCT_START); + dev.DAPQ = (BYTE *)(dev.base + DAPQ_OFFSET); + dev.DARQ = (BYTE *)(dev.base + DARQ_OFFSET); + dev.MODQ = (BYTE *)(dev.base + MODQ_OFFSET); + dev.MIDQ = (BYTE *)(dev.base + MIDQ_OFFSET); + dev.DSPQ = (BYTE *)(dev.base + DSPQ_OFFSET); + dev.SMA = (BYTE *)(dev.base + SMA_STRUCT_START); dev.CurDAQD = (LPDAQD)(dev.base + DAPQ_DATA_BUFF); dev.CurDARQD = (LPDAQD)(dev.base + DARQ_DATA_BUFF); @@ -1071,28 +1054,28 @@ __initfunc(static int init_sma(void)) dev.sample_rate = DEFSAMPLERATE; dev.channels = DEFCHANNELS; - for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, ++lpDAQ) { + for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, lpDAQ += DAQDS__size) { - writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), &lpDAQ->wStart); - writew(DAP_BUFF_SIZE, &lpDAQ->wSize); - writew(1, &lpDAQ->wFormat); - writew(dev.sample_size, &lpDAQ->wSampleSize); - writew(dev.channels, &lpDAQ->wChannels); - writew(dev.sample_rate, &lpDAQ->wSampleRate); - writew(HIMT_PLAY_DONE * 0x100 + n, &lpDAQ->wIntMsg); - writew(n + 1, &lpDAQ->wFlags); + writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), lpDAQ + DAQDS_wStart); + writew(DAP_BUFF_SIZE, lpDAQ + DAQDS_wSize); + writew(1, lpDAQ + DAQDS_wFormat); + writew(dev.sample_size, lpDAQ + DAQDS_wSampleSize); + writew(dev.channels, lpDAQ + DAQDS_wChannels); + writew(dev.sample_rate, lpDAQ + DAQDS_wSampleRate); + writew(HIMT_PLAY_DONE * 0x100 + n, lpDAQ + DAQDS_wIntMsg); + writew(n + 1, lpDAQ + DAQDS_wFlags); } - for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, ++lpDAQ) { + for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, lpDAQ += DAQDS__size) { - writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, &lpDAQ->wStart); - writew(DAR_BUFF_SIZE, &lpDAQ->wSize); - writew(1, &lpDAQ->wFormat); - writew(dev.sample_size, &lpDAQ->wSampleSize); - writew(dev.channels, &lpDAQ->wChannels); - writew(dev.sample_rate, &lpDAQ->wSampleRate); - writew(HIMT_RECORD_DONE * 0x100 + n, &lpDAQ->wIntMsg); - writew(n + 1, &lpDAQ->wFlags); + writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, lpDAQ + DAQDS_wStart); + writew(DAR_BUFF_SIZE, lpDAQ + DAQDS_wSize); + writew(1, lpDAQ + DAQDS_wFormat); + writew(dev.sample_size, lpDAQ + DAQDS_wSampleSize); + writew(dev.channels, lpDAQ + DAQDS_wChannels); + writew(dev.sample_rate, lpDAQ + DAQDS_wSampleRate); + writew(HIMT_RECORD_DONE * 0x100 + n, lpDAQ + DAQDS_wIntMsg); + writew(n + 1, lpDAQ + DAQDS_wFlags); } @@ -1100,68 +1083,68 @@ __initfunc(static int init_sma(void)) dev.pwMODQData = (WORD *)(dev.base + MODQ_DATA_BUFF); dev.pwMIDQData = (WORD *)(dev.base + MIDQ_DATA_BUFF); - writew(PCTODSP_BASED(MIDQ_DATA_BUFF), &dev.MIDQ->wStart); - writew(PCTODSP_OFFSET(MIDQ_BUFF_SIZE) - 1, &dev.MIDQ->wSize); - writew(0, &dev.MIDQ->wHead); - writew(0, &dev.MIDQ->wTail); + writew(PCTODSP_BASED(MIDQ_DATA_BUFF), dev.MIDQ + JQS_wStart); + writew(PCTODSP_OFFSET(MIDQ_BUFF_SIZE) - 1, dev.MIDQ + JQS_wSize); + writew(0, dev.MIDQ + JQS_wHead); + writew(0, dev.MIDQ + JQS_wTail); - writew(PCTODSP_BASED(MODQ_DATA_BUFF), &dev.MODQ->wStart); - writew(PCTODSP_OFFSET(MODQ_BUFF_SIZE) - 1, &dev.MODQ->wSize); - writew(0, &dev.MODQ->wHead); - writew(0, &dev.MODQ->wTail); + writew(PCTODSP_BASED(MODQ_DATA_BUFF), dev.MODQ + JQS_wStart); + writew(PCTODSP_OFFSET(MODQ_BUFF_SIZE) - 1, dev.MODQ + JQS_wSize); + writew(0, dev.MODQ + JQS_wHead); + writew(0, dev.MODQ + JQS_wTail); - writew(PCTODSP_BASED(DAPQ_DATA_BUFF), &dev.DAPQ->wStart); - writew(PCTODSP_OFFSET(DAPQ_BUFF_SIZE) - 1, &dev.DAPQ->wSize); - writew(0, &dev.DAPQ->wHead); - writew(0, &dev.DAPQ->wTail); + writew(PCTODSP_BASED(DAPQ_DATA_BUFF), dev.DAPQ + JQS_wStart); + writew(PCTODSP_OFFSET(DAPQ_BUFF_SIZE) - 1, dev.DAPQ + JQS_wSize); + writew(0, dev.DAPQ + JQS_wHead); + writew(0, dev.DAPQ + JQS_wTail); - writew(PCTODSP_BASED(DARQ_DATA_BUFF), &dev.DARQ->wStart); - writew(PCTODSP_OFFSET(DARQ_BUFF_SIZE) - 1, &dev.DARQ->wSize); - writew(0, &dev.DARQ->wHead); - writew(0, &dev.DARQ->wTail); + writew(PCTODSP_BASED(DARQ_DATA_BUFF), dev.DARQ + JQS_wStart); + writew(PCTODSP_OFFSET(DARQ_BUFF_SIZE) - 1, dev.DARQ + JQS_wSize); + writew(0, dev.DARQ + JQS_wHead); + writew(0, dev.DARQ + JQS_wTail); - writew(PCTODSP_BASED(DSPQ_DATA_BUFF), &dev.DSPQ->wStart); - writew(PCTODSP_OFFSET(DSPQ_BUFF_SIZE) - 1, &dev.DSPQ->wSize); - writew(0, &dev.DSPQ->wHead); - writew(0, &dev.DSPQ->wTail); + writew(PCTODSP_BASED(DSPQ_DATA_BUFF), dev.DSPQ + JQS_wStart); + writew(PCTODSP_OFFSET(DSPQ_BUFF_SIZE) - 1, dev.DSPQ + JQS_wSize); + writew(0, dev.DSPQ + JQS_wHead); + writew(0, dev.DSPQ + JQS_wTail); - writew(0, &dev.SMA->wCurrPlayBytes); - writew(0, &dev.SMA->wCurrRecordBytes); + writew(0, dev.SMA + SMA_wCurrPlayBytes); + writew(0, dev.SMA + SMA_wCurrRecordBytes); - writew(0, &dev.SMA->wCurrPlayVolLeft); - writew(0, &dev.SMA->wCurrPlayVolRight); + writew(0, dev.SMA + SMA_wCurrPlayVolLeft); + writew(0, dev.SMA + SMA_wCurrPlayVolRight); - writew(0, &dev.SMA->wCurrInVolLeft); - writew(0, &dev.SMA->wCurrInVolRight); + writew(0, dev.SMA + SMA_wCurrInVolLeft); + writew(0, dev.SMA + SMA_wCurrInVolRight); - writew(0, &dev.SMA->wCurrMastVolLeft); - writew(0, &dev.SMA->wCurrMastVolRight); + writew(0, dev.SMA + SMA_wCurrMastVolLeft); + writew(0, dev.SMA + SMA_wCurrMastVolRight); #ifndef MSND_CLASSIC - writel(0x00010000, &dev.SMA->dwCurrPlayPitch); - writel(0x00000001, &dev.SMA->dwCurrPlayRate); + writel(0x00010000, dev.SMA + SMA_dwCurrPlayPitch); + writel(0x00000001, dev.SMA + SMA_dwCurrPlayRate); #endif - writew(0x0000, &dev.SMA->wCurrDSPStatusFlags); - writew(0x0000, &dev.SMA->wCurrHostStatusFlags); + writew(0x0000, dev.SMA + SMA_wCurrDSPStatusFlags); + writew(0x0000, dev.SMA + SMA_wCurrHostStatusFlags); - writew(0x303, &dev.SMA->wCurrInputTagBits); - writew(0, &dev.SMA->wCurrLeftPeak); - writew(0, &dev.SMA->wCurrRightPeak); + writew(0x303, dev.SMA + SMA_wCurrInputTagBits); + writew(0, dev.SMA + SMA_wCurrLeftPeak); + writew(0, dev.SMA + SMA_wCurrRightPeak); - writeb(0, &dev.SMA->bInPotPosRight); - writeb(0, &dev.SMA->bInPotPosLeft); + writeb(0, dev.SMA + SMA_bInPotPosRight); + writeb(0, dev.SMA + SMA_bInPotPosLeft); - writeb(0, &dev.SMA->bAuxPotPosRight); - writeb(0, &dev.SMA->bAuxPotPosLeft); + writeb(0, dev.SMA + SMA_bAuxPotPosRight); + writeb(0, dev.SMA + SMA_bAuxPotPosLeft); #ifndef MSND_CLASSIC - writew(1, &dev.SMA->wCurrPlayFormat); - writew(dev.sample_size, &dev.SMA->wCurrPlaySampleSize); - writew(dev.channels, &dev.SMA->wCurrPlayChannels); - writew(dev.sample_rate, &dev.SMA->wCurrPlaySampleRate); + writew(1, dev.SMA + SMA_wCurrPlayFormat); + writew(dev.sample_size, dev.SMA + SMA_wCurrPlaySampleSize); + writew(dev.channels, dev.SMA + SMA_wCurrPlayChannels); + writew(dev.sample_rate, dev.SMA + SMA_wCurrPlaySampleRate); #endif - writew(dev.sample_rate, &dev.SMA->wCalFreqAtoD); + writew(dev.sample_rate, dev.SMA + SMA_wCalFreqAtoD); return 0; } @@ -1169,25 +1152,21 @@ __initfunc(static int init_sma(void)) __initfunc(static int calibrate_adc(WORD srate)) { if (!dev.calibrate_signal) { - printk(KERN_INFO LOGNAME ": ADC calibration to board ground "); - writew(readw(&dev.SMA->wCurrHostStatusFlags) - | 0x0001, &dev.SMA->wCurrHostStatusFlags); - } - else { - + writew(readw(dev.SMA + SMA_wCurrHostStatusFlags) + | 0x0001, dev.SMA + SMA_wCurrHostStatusFlags); + } else { printk(KERN_INFO LOGNAME ": ADC calibration to signal ground "); - writew(readw(&dev.SMA->wCurrHostStatusFlags) - & ~0x0001, &dev.SMA->wCurrHostStatusFlags); + writew(readw(dev.SMA + SMA_wCurrHostStatusFlags) + & ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags); } - writew(srate, &dev.SMA->wCalFreqAtoD); + writew(srate, dev.SMA + SMA_wCalFreqAtoD); if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) { - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + HZ; + current->timeout = jiffies + HZ / 3; schedule(); current->timeout = 0; printk("successful\n"); @@ -1221,9 +1200,7 @@ __initfunc(static int upload_dsp_code(void)) } #endif memcpy_toio(dev.base, PERMCODE, PERMCODESIZE); - if (msnd_upload_host(&dev, INITCODE, INITCODESIZE) < 0) { - printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n"); return -ENODEV; } @@ -1258,7 +1235,6 @@ __initfunc(static int initialize(void)) #endif if ((err = init_sma()) < 0) { - printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n"); return err; } @@ -1267,17 +1243,15 @@ __initfunc(static int initialize(void)) return err; if ((err = upload_dsp_code()) < 0) { - printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n"); return err; } else printk(KERN_INFO LOGNAME ": DSP upload successful\n"); - timeout = 2000; + timeout = 200; while (readw(dev.base)) { - mdelay(1); if (--timeout < 0) return -EIO; @@ -1292,17 +1266,15 @@ __initfunc(static int attach_multisound(void)) printk(KERN_DEBUG LOGNAME ": Intializing DSP\n"); - if ((err = request_irq(dev.irq, intr, SA_SHIRQ, DEVNAME, &dev)) < 0) { - + if ((err = request_irq(dev.irq, intr, SA_SHIRQ, dev.name, &dev)) < 0) { printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq); return err; } - request_region(dev.io, dev.numio, DEVNAME); + request_region(dev.io, dev.numio, dev.name); if ((err = initialize()) < 0) { - printk(KERN_WARNING LOGNAME ": Initialization failure\n"); release_region(dev.io, dev.numio); free_irq(dev.irq, &dev); @@ -1311,41 +1283,34 @@ __initfunc(static int attach_multisound(void)) } if ((err = msnd_register(&dev)) < 0) { - printk(KERN_ERR LOGNAME ": Unable to register MultiSound\n"); release_region(dev.io, dev.numio); free_irq(dev.irq, &dev); return err; } - if ((DSPMINOR = register_sound_dsp(&dev_fileops)) < 0) { - + if ((dev.dsp_minor = register_sound_dsp(&dev_fileops)) < 0) { printk(KERN_ERR LOGNAME ": Unable to register DSP operations\n"); msnd_unregister(&dev); release_region(dev.io, dev.numio); free_irq(dev.irq, &dev); - return DSPMINOR; + return dev.dsp_minor; } - if ((MIXERMINOR = register_sound_mixer(&dev_fileops)) < 0) { - + if ((dev.mixer_minor = register_sound_mixer(&dev_fileops)) < 0) { printk(KERN_ERR LOGNAME ": Unable to register mixer operations\n"); - unregister_sound_mixer(MIXERMINOR); + unregister_sound_mixer(dev.mixer_minor); msnd_unregister(&dev); release_region(dev.io, dev.numio); free_irq(dev.irq, &dev); - return MIXERMINOR; + return dev.mixer_minor; } - printk(KERN_INFO LOGNAME ": Using DSP minor %d, mixer minor %d\n", MIXERMINOR, DSPMINOR); + printk(KERN_INFO LOGNAME ": Using DSP minor %d, mixer minor %d\n", dev.dsp_minor, dev.mixer_minor); calibrate_adc(dev.sample_rate); #ifndef MSND_CLASSIC - printk(KERN_INFO LOGNAME ": Setting recording source to Line In\n"); - if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) != 0 || - msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ) != 0) { - printk(KERN_DEBUG LOGNAME ": Error setting Line In as recording source\n"); - } - dev.recsrc = SOUND_MASK_LINE; + printk(KERN_INFO LOGNAME ": Setting initial recording source to Line In\n"); + set_recsrc(SOUND_MASK_LINE); #endif return 0; @@ -1355,8 +1320,8 @@ static void unload_multisound(void) { release_region(dev.io, dev.numio); free_irq(dev.irq, &dev); - unregister_sound_mixer(MIXERMINOR); - unregister_sound_dsp(DSPMINOR); + unregister_sound_mixer(dev.mixer_minor); + unregister_sound_dsp(dev.dsp_minor); msnd_unregister(&dev); } @@ -1370,6 +1335,155 @@ static void mod_dec_ref(void) MOD_DEC_USE_COUNT; } +#ifndef MSND_CLASSIC + +/* Pinnacle/Fiji Logical Device Configuration */ + +__initfunc(static int msnd_write_cfg(int cfg, int reg, int value)) +{ + outb(reg, cfg); + outb(value, cfg + 1); + if (value != inb(cfg + 1)) { + printk(KERN_ERR LOGNAME ": msnd_write_cfg: I/O error\n"); + return -EIO; + } + return 0; +} + +__initfunc(static int msnd_write_cfg_io0(int cfg, int num, WORD io)) +{ + if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io))) + return -EIO; + if (msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io))) + return -EIO; + return 0; +} + +__initfunc(static int msnd_write_cfg_io1(int cfg, int num, WORD io)) +{ + if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io))) + return -EIO; + if (msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io))) + return -EIO; + return 0; +} + +__initfunc(static int msnd_write_cfg_irq(int cfg, int num, WORD irq)) +{ + if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq))) + return -EIO; + if (msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE)) + return -EIO; + return 0; +} + +__initfunc(static int msnd_write_cfg_mem(int cfg, int num, int mem)) +{ + WORD wmem; + + mem >>= 8; + mem &= 0xfff; + wmem = (WORD)mem; + if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem))) + return -EIO; + if (msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem))) + return -EIO; + if (wmem && msnd_write_cfg(cfg, IREG_MEMCONTROL, (MEMTYPE_HIADDR | MEMTYPE_16BIT))) + return -EIO; + return 0; +} + +__initfunc(static int msnd_activate_logical(int cfg, int num)) +{ + if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE)) + return -EIO; + return 0; +} + +__initfunc(static int msnd_write_cfg_logical(int cfg, int num, WORD io0, WORD io1, WORD irq, int mem)) +{ + if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (msnd_write_cfg_io0(cfg, num, io0)) + return -EIO; + if (msnd_write_cfg_io1(cfg, num, io1)) + return -EIO; + if (msnd_write_cfg_irq(cfg, num, irq)) + return -EIO; + if (msnd_write_cfg_mem(cfg, num, mem)) + return -EIO; + if (msnd_activate_logical(cfg, num)) + return -EIO; + return 0; +} + +typedef struct msnd_pinnacle_cfg_device { + WORD io0, io1, irq; + int mem; +} msnd_pinnacle_cfg_t[4]; + +__initfunc(static int msnd_pinnacle_cfg_devices(int cfg, int reset, msnd_pinnacle_cfg_t device)) +{ + int i; + + /* Reset devices if told to */ + if (reset) { + printk(KERN_INFO LOGNAME ": Resetting all devices\n"); + for (i = 0; i < 4; ++i) + if (msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0)) + return -EIO; + } + + /* Configure specified devices */ + for (i = 0; i < 4; ++i) { + + switch (i) { + case 0: /* DSP */ + if (!(device[i].io0 && device[i].irq && device[i].mem)) + continue; + break; + case 1: /* MPU */ + if (!(device[i].io0 && device[i].irq)) + continue; + printk(KERN_INFO LOGNAME + ": Configuring MPU to I/O 0x%x IRQ %d\n", + device[i].io0, device[i].irq); + break; + case 2: /* IDE */ + if (!(device[i].io0 && device[i].io1 && device[i].irq)) + continue; + printk(KERN_INFO LOGNAME + ": Configuring IDE to I/O 0x%x, 0x%x IRQ %d\n", + device[i].io0, device[i].io1, device[i].irq); + break; + case 3: /* Joystick */ + if (!(device[i].io0)) + continue; + printk(KERN_INFO LOGNAME + ": Configuring joystick to I/O 0x%x\n", + device[i].io0); + break; + } + + /* Configure the device */ + if (msnd_write_cfg_logical(cfg, i, device[i].io0, device[i].io1, device[i].irq, device[i].mem)) + return -EIO; + } + + return 0; +} +#endif + #ifdef MODULE MODULE_AUTHOR ("Andrew Veliath "); MODULE_DESCRIPTION ("Turtle Beach " LONGNAME " Linux Driver"); @@ -1381,39 +1495,118 @@ MODULE_PARM (fifosize, "i"); MODULE_PARM (calibrate_signal, "i"); #ifndef MSND_CLASSIC MODULE_PARM (digital, "i"); +MODULE_PARM (cfg, "i"); +MODULE_PARM (reset, "i"); +MODULE_PARM (mpu_io, "i"); +MODULE_PARM (mpu_irq, "i"); +MODULE_PARM (ide_io0, "i"); +MODULE_PARM (ide_io1, "i"); +MODULE_PARM (ide_irq, "i"); +MODULE_PARM (joystick_io, "i"); #endif static int io __initdata = -1; static int irq __initdata = -1; static int mem __initdata = -1; + #ifndef MSND_CLASSIC +/* Pinnacle/Fiji non-PnP Config Port */ +static int cfg __initdata = -1; + +/* Extra Peripheral Configuration */ +static int reset __initdata; +static int mpu_io __initdata; +static int mpu_irq __initdata; +static int ide_io0 __initdata; +static int ide_io1 __initdata; +static int ide_irq __initdata; +static int joystick_io __initdata; + +/* If we have the digital daugherboard... */ static int digital __initdata; #endif + static int fifosize __initdata = DEFFIFOSIZE; static int calibrate_signal __initdata; +/* If we're a module, this is just init_module */ + int init_module(void) + #else /* not a module */ + #ifdef MSND_CLASSIC static int io __initdata = CONFIG_MSNDCLAS_IO; static int irq __initdata = CONFIG_MSNDCLAS_IRQ; static int mem __initdata = CONFIG_MSNDCLAS_MEM; #else /* Pinnacle/Fiji */ + static int io __initdata = CONFIG_MSNDPIN_IO; static int irq __initdata = CONFIG_MSNDPIN_IRQ; static int mem __initdata = CONFIG_MSNDPIN_MEM; + +/* Pinnacle/Fiji non-PnP Config Port */ +#ifdef CONFIG_MSNDPIN_NONPNP +# ifndef CONFIG_MSNDPIN_CFG +# define CONFIG_MSNDPIN_CFG 0x250 +# endif +#else +# ifdef CONFIG_MSNDPIN_CFG +# undef CONFIG_MSNDPIN_CFG +# endif +# define CONFIG_MSNDPIN_CFG -1 +#endif +static int cfg __initdata = CONFIG_MSNDPIN_CFG; +/* If not a module, we don't need to bother with reset=1 */ +static int reset __initdata; + +/* Extra Peripheral Configuration (Default: Disable) */ +#ifndef CONFIG_MSNDPIN_MPU_IO +# define CONFIG_MSNDPIN_MPU_IO 0 +#endif +static int mpu_io __initdata = CONFIG_MSNDPIN_MPU_IO; + +#ifndef CONFIG_MSNDPIN_MPU_IRQ +# define CONFIG_MSNDPIN_MPU_IRQ 0 +#endif +static int mpu_irq __initdata = CONFIG_MSNDPIN_MPU_IRQ; + +#ifndef CONFIG_MSNDPIN_IDE_IO0 +# define CONFIG_MSNDPIN_IDE_IO0 0 +#endif +static int ide_io0 __initdata = CONFIG_MSNDPIN_IDE_IO0; + +#ifndef CONFIG_MSNDPIN_IDE_IO1 +# define CONFIG_MSNDPIN_IDE_IO1 0 +#endif +static int ide_io1 __initdata = CONFIG_MSNDPIN_IDE_IO1; + +#ifndef CONFIG_MSNDPIN_IDE_IRQ +# define CONFIG_MSNDPIN_IDE_IRQ 0 +#endif +static int ide_irq __initdata = CONFIG_MSNDPIN_IDE_IRQ; + +#ifndef CONFIG_MSNDPIN_JOYSTICK_IO +# define CONFIG_MSNDPIN_JOYSTICK_IO 0 +#endif +static int joystick_io __initdata = CONFIG_MSNDPIN_JOYSTICK_IO; + +/* Have SPDIF (Digital) Daughterboard */ #ifndef CONFIG_MSNDPIN_DIGITAL # define CONFIG_MSNDPIN_DIGITAL 0 #endif static int digital __initdata = CONFIG_MSNDPIN_DIGITAL; + #endif /* MSND_CLASSIC */ + #ifndef CONFIG_MSND_FIFOSIZE # define CONFIG_MSND_FIFOSIZE DEFFIFOSIZE -#endif /* CONFIG_MSND_FIFOSIZE */ +#endif static int fifosize __initdata = CONFIG_MSND_FIFOSIZE; + #ifndef CONFIG_MSND_CALSIGNAL # define CONFIG_MSND_CALSIGNAL 0 -#endif /* CONFIG_MSND_CALSIGNAL */ +#endif static int calibrate_signal __initdata = CONFIG_MSND_CALSIGNAL; @@ -1422,9 +1615,13 @@ __initfunc(int msnd_classic_init(void)) #else __initfunc(int msnd_pinnacle_init(void)) #endif /* MSND_CLASSIC */ -#endif + +#endif /* MODULE */ { int err; +#ifndef MSND_CLASSIC + static msnd_pinnacle_cfg_t pinnacle_devs; +#endif /* MSND_CLASSIC */ printk(KERN_INFO LOGNAME ": Turtle Beach " LONGNAME " Linux Driver Version " VERSION ", Copyright (C) 1998 Andrew Veliath\n"); @@ -1433,7 +1630,7 @@ __initfunc(int msnd_pinnacle_init(void)) printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n"); } - + if (io == -1 || !(io == 0x290 || io == 0x260 || @@ -1444,7 +1641,7 @@ __initfunc(int msnd_pinnacle_init(void)) io == 0x210 || io == 0x3e0)) { - printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set\n"); + printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, or 0x3E0\n"); return -EINVAL; } @@ -1491,6 +1688,47 @@ __initfunc(int msnd_pinnacle_init(void)) case 0xe0000: dev.memid = HPMEM_E000; break; case 0xe8000: dev.memid = HPMEM_E800; break; } +#else + if (cfg == -1) { + printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); + } else if (cfg != 0x250 && cfg != 0x260 && cfg != 0x270) { + printk(KERN_INFO LOGNAME ": Config port must be 0x250, 0x260 or 0x270 (or unspecified for PnP mode)\n"); + return -EINVAL; + } else { + printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%x\n", cfg); + + /* DSP */ + pinnacle_devs[0].io0 = io; + pinnacle_devs[0].irq = irq; + pinnacle_devs[0].mem = mem; + + /* The following are Pinnacle specific */ + + /* MPU */ + pinnacle_devs[1].io0 = mpu_io; + pinnacle_devs[1].irq = mpu_irq; + + /* IDE */ + pinnacle_devs[2].io0 = ide_io0; + pinnacle_devs[2].io1 = ide_io1; + pinnacle_devs[2].irq = ide_irq; + + /* Joystick */ + pinnacle_devs[3].io0 = joystick_io; + + if (check_region(cfg, 2)) { + printk(KERN_ERR LOGNAME ": Config port 0x%x conflict\n", cfg); + return -EIO; + } + + request_region(cfg, 2, "Pinnacle/Fiji Config"); + if (msnd_pinnacle_cfg_devices(cfg, reset, pinnacle_devs)) { + printk(KERN_ERR LOGNAME ": Device configuration error\n"); + release_region(cfg, 2); + return -EIO; + } + release_region(cfg, 2); + } #endif /* MSND_CLASSIC */ if (fifosize < 16) diff --git a/drivers/sound/msnd_pinnacle.h b/drivers/sound/msnd_pinnacle.h index f6971c949846..0ae9a1026627 100644 --- a/drivers/sound/msnd_pinnacle.h +++ b/drivers/sound/msnd_pinnacle.h @@ -24,7 +24,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: msnd_pinnacle.h,v 1.5 1998/07/18 00:12:16 andrewtv Exp $ + * $Id: msnd_pinnacle.h,v 1.8 1998/09/03 06:39:47 andrewtv Exp $ * ********************************************************************/ #ifndef __MSND_PINNACLE_H @@ -32,189 +32,196 @@ #include -#define DSP_NUMIO 0x08 - -#define HP_DSPR 0x04 -#define HP_BLKS 0x04 - -#define HPDSPRESET_OFF 2 -#define HPDSPRESET_ON 0 - -#define HPBLKSEL_0 2 -#define HPBLKSEL_1 3 - -#define HIMT_DAT_OFF 0x03 - -#define HIDSP_PLAY_UNDER 0x00 -#define HIDSP_INT_PLAY_UNDER 0x01 -#define HIDSP_SSI_TX_UNDER 0x02 -#define HIDSP_RECQ_OVERFLOW 0x08 -#define HIDSP_INT_RECORD_OVER 0x09 -#define HIDSP_SSI_RX_OVERFLOW 0x0a - -#define HIDSP_MIDI_IN_OVER 0x10 - -#define HIDSP_MIDI_FRAME_ERR 0x11 -#define HIDSP_MIDI_PARITY_ERR 0x12 -#define HIDSP_MIDI_OVERRUN_ERR 0x13 - -#define HIDSP_INPUT_CLIPPING 0x20 -#define HIDSP_MIX_CLIPPING 0x30 -#define HIDSP_DAT_IN_OFF 0x21 - -#define HDEXAR_SET_ANA_IN 0 -#define HDEXAR_CLEAR_PEAKS 1 -#define HDEXAR_IN_SET_POTS 2 -#define HDEXAR_AUX_SET_POTS 3 -#define HDEXAR_CAL_A_TO_D 4 -#define HDEXAR_RD_EXT_DSP_BITS 5 - -#define HDEXAR_SET_SYNTH_IN 4 -#define HDEXAR_READ_DAT_IN 5 -#define HDEXAR_MIC_SET_POTS 6 -#define HDEXAR_SET_DAT_IN 7 - -#define HDEXAR_SET_SYNTH_48 8 -#define HDEXAR_SET_SYNTH_44 9 - -#define TIME_PRO_RESET_DONE 0x028A -#define TIME_PRO_SYSEX 0x001E -#define TIME_PRO_RESET 0x0032 - -#define AGND 0x01 -#define SIGNAL 0x02 - -#define EXT_DSP_BIT_DCAL 0x0001 -#define EXT_DSP_BIT_MIDI_CON 0x0002 - -#define BUFFSIZE 0x8000 -#define HOSTQ_SIZE 0x40 - -#define SRAM_CNTL_START 0x7F00 -#define SMA_STRUCT_START 0x7F40 - -#define DAP_BUFF_SIZE 0x2400 -#define DAR_BUFF_SIZE 0x2000 - -#define DAPQ_STRUCT_SIZE 0x10 -#define DARQ_STRUCT_SIZE 0x10 -#define DAPQ_BUFF_SIZE (3 * 0x10) -#define DARQ_BUFF_SIZE (3 * 0x10) -#define MODQ_BUFF_SIZE 0x400 -#define MIDQ_BUFF_SIZE 0x800 -#define DSPQ_BUFF_SIZE 0x5A0 - -#define DAPQ_DATA_BUFF 0x6C00 -#define DARQ_DATA_BUFF 0x6C30 -#define MODQ_DATA_BUFF 0x6C60 -#define MIDQ_DATA_BUFF 0x7060 -#define DSPQ_DATA_BUFF 0x7860 - -#define DAPQ_OFFSET SRAM_CNTL_START -#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) -#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) -#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) -#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) - -#define WAVEHDR_MOP 0 -#define EXTOUT_MOP 1 -#define HWINIT_MOP 0xFE -#define NO_MOP 0xFF - -#define MAX_MOP 1 - -#define EXTIN_MIP 0 -#define WAVEHDR_MIP 1 -#define HWINIT_MIP 0xFE - -#define MAX_MIP 1 - -struct SMA0_CommonData { - WORD wCurrPlayBytes; - WORD wCurrRecordBytes; - WORD wCurrPlayVolLeft; - WORD wCurrPlayVolRight; - - WORD wCurrInVolLeft; - WORD wCurrInVolRight; - WORD wCurrMHdrVolLeft; - WORD wCurrMHdrVolRight; - - DWORD dwCurrPlayPitch; - DWORD dwCurrPlayRate; - - WORD wCurrMIDIIOPatch; - - WORD wCurrPlayFormat; - WORD wCurrPlaySampleSize; - WORD wCurrPlayChannels; - WORD wCurrPlaySampleRate; - - WORD wCurrRecordFormat; - WORD wCurrRecordSampleSize; - WORD wCurrRecordChannels; - WORD wCurrRecordSampleRate; - - WORD wCurrDSPStatusFlags; - WORD wCurrHostStatusFlags; - - WORD wCurrInputTagBits; - WORD wCurrLeftPeak; - WORD wCurrRightPeak; - - BYTE bMicPotPosLeft; - BYTE bMicPotPosRight; - - BYTE bMicPotMaxLeft; - BYTE bMicPotMaxRight; - - BYTE bInPotPosLeft; - BYTE bInPotPosRight; - - BYTE bAuxPotPosLeft; - BYTE bAuxPotPosRight; - - BYTE bInPotMaxLeft; - BYTE bInPotMaxRight; - BYTE bAuxPotMaxLeft; - BYTE bAuxPotMaxRight; - BYTE bInPotMaxMethod; - BYTE bAuxPotMaxMethod; - - WORD wCurrMastVolLeft; - WORD wCurrMastVolRight; - - WORD wCalFreqAtoD; - - WORD wCurrAuxVolLeft; - WORD wCurrAuxVolRight; - - WORD wCurrPlay1VolLeft; - WORD wCurrPlay1VolRight; - WORD wCurrPlay2VolLeft; - WORD wCurrPlay2VolRight; - WORD wCurrPlay3VolLeft; - WORD wCurrPlay3VolRight; - WORD wCurrPlay4VolLeft; - WORD wCurrPlay4VolRight; - WORD wCurrPlay1PeakLeft; - WORD wCurrPlay1PeakRight; - WORD wCurrPlay2PeakLeft; - WORD wCurrPlay2PeakRight; - WORD wCurrPlay3PeakLeft; - WORD wCurrPlay3PeakRight; - WORD wCurrPlay4PeakLeft; - WORD wCurrPlay4PeakRight; - WORD wCurrPlayPeakLeft; - WORD wCurrPlayPeakRight; - - WORD wCurrDATSR; - WORD wCurrDATRXCHNL; - WORD wCurrDATTXCHNL; - WORD wCurrDATRXRate; - - DWORD dwDSPPlayCount; -} GCC_PACKED; +#define DSP_NUMIO 0x08 + +#define IREG_LOGDEVICE 0x07 +#define IREG_ACTIVATE 0x30 +#define LD_ACTIVATE 0x01 +#define LD_DISACTIVATE 0x00 +#define IREG_EECONTROL 0x3F +#define IREG_MEMBASEHI 0x40 +#define IREG_MEMBASELO 0x41 +#define IREG_MEMCONTROL 0x42 +#define IREG_MEMRANGEHI 0x43 +#define IREG_MEMRANGELO 0x44 +#define MEMTYPE_8BIT 0x00 +#define MEMTYPE_16BIT 0x02 +#define MEMTYPE_RANGE 0x00 +#define MEMTYPE_HIADDR 0x01 +#define IREG_IO0_BASEHI 0x60 +#define IREG_IO0_BASELO 0x61 +#define IREG_IO1_BASEHI 0x62 +#define IREG_IO1_BASELO 0x63 +#define IREG_IRQ_NUMBER 0x70 +#define IREG_IRQ_TYPE 0x71 +#define IRQTYPE_HIGH 0x02 +#define IRQTYPE_LOW 0x00 +#define IRQTYPE_LEVEL 0x01 +#define IRQTYPE_EDGE 0x00 + +#define HP_DSPR 0x04 +#define HP_BLKS 0x04 + +#define HPDSPRESET_OFF 2 +#define HPDSPRESET_ON 0 + +#define HPBLKSEL_0 2 +#define HPBLKSEL_1 3 + +#define HIMT_DAT_OFF 0x03 + +#define HIDSP_PLAY_UNDER 0x00 +#define HIDSP_INT_PLAY_UNDER 0x01 +#define HIDSP_SSI_TX_UNDER 0x02 +#define HIDSP_RECQ_OVERFLOW 0x08 +#define HIDSP_INT_RECORD_OVER 0x09 +#define HIDSP_SSI_RX_OVERFLOW 0x0a + +#define HIDSP_MIDI_IN_OVER 0x10 + +#define HIDSP_MIDI_FRAME_ERR 0x11 +#define HIDSP_MIDI_PARITY_ERR 0x12 +#define HIDSP_MIDI_OVERRUN_ERR 0x13 + +#define HIDSP_INPUT_CLIPPING 0x20 +#define HIDSP_MIX_CLIPPING 0x30 +#define HIDSP_DAT_IN_OFF 0x21 + +#define HDEXAR_SET_ANA_IN 0 +#define HDEXAR_CLEAR_PEAKS 1 +#define HDEXAR_IN_SET_POTS 2 +#define HDEXAR_AUX_SET_POTS 3 +#define HDEXAR_CAL_A_TO_D 4 +#define HDEXAR_RD_EXT_DSP_BITS 5 + +#define HDEXAR_SET_SYNTH_IN 4 +#define HDEXAR_READ_DAT_IN 5 +#define HDEXAR_MIC_SET_POTS 6 +#define HDEXAR_SET_DAT_IN 7 + +#define HDEXAR_SET_SYNTH_48 8 +#define HDEXAR_SET_SYNTH_44 9 + +#define TIME_PRO_RESET_DONE 0x028A +#define TIME_PRO_SYSEX 0x001E +#define TIME_PRO_RESET 0x0032 + +#define AGND 0x01 +#define SIGNAL 0x02 + +#define EXT_DSP_BIT_DCAL 0x0001 +#define EXT_DSP_BIT_MIDI_CON 0x0002 + +#define BUFFSIZE 0x8000 +#define HOSTQ_SIZE 0x40 + +#define SRAM_CNTL_START 0x7F00 +#define SMA_STRUCT_START 0x7F40 + +#define DAP_BUFF_SIZE 0x2400 +#define DAR_BUFF_SIZE 0x2000 + +#define DAPQ_STRUCT_SIZE 0x10 +#define DARQ_STRUCT_SIZE 0x10 +#define DAPQ_BUFF_SIZE (3 * 0x10) +#define DARQ_BUFF_SIZE (3 * 0x10) +#define MODQ_BUFF_SIZE 0x400 +#define MIDQ_BUFF_SIZE 0x800 +#define DSPQ_BUFF_SIZE 0x5A0 + +#define DAPQ_DATA_BUFF 0x6C00 +#define DARQ_DATA_BUFF 0x6C30 +#define MODQ_DATA_BUFF 0x6C60 +#define MIDQ_DATA_BUFF 0x7060 +#define DSPQ_DATA_BUFF 0x7860 + +#define DAPQ_OFFSET SRAM_CNTL_START +#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) +#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) +#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) +#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) + +#define WAVEHDR_MOP 0 +#define EXTOUT_MOP 1 +#define HWINIT_MOP 0xFE +#define NO_MOP 0xFF + +#define MAX_MOP 1 + +#define EXTIN_MIP 0 +#define WAVEHDR_MIP 1 +#define HWINIT_MIP 0xFE + +#define MAX_MIP 1 + +/* Pinnacle/Fiji SMA Common Data */ +#define SMA_wCurrPlayBytes 0x0000 +#define SMA_wCurrRecordBytes 0x0002 +#define SMA_wCurrPlayVolLeft 0x0004 +#define SMA_wCurrPlayVolRight 0x0006 +#define SMA_wCurrInVolLeft 0x0008 +#define SMA_wCurrInVolRight 0x000a +#define SMA_wCurrMHdrVolLeft 0x000c +#define SMA_wCurrMHdrVolRight 0x000e +#define SMA_dwCurrPlayPitch 0x0010 +#define SMA_dwCurrPlayRate 0x0014 +#define SMA_wCurrMIDIIOPatch 0x0018 +#define SMA_wCurrPlayFormat 0x001a +#define SMA_wCurrPlaySampleSize 0x001c +#define SMA_wCurrPlayChannels 0x001e +#define SMA_wCurrPlaySampleRate 0x0020 +#define SMA_wCurrRecordFormat 0x0022 +#define SMA_wCurrRecordSampleSize 0x0024 +#define SMA_wCurrRecordChannels 0x0026 +#define SMA_wCurrRecordSampleRate 0x0028 +#define SMA_wCurrDSPStatusFlags 0x002a +#define SMA_wCurrHostStatusFlags 0x002c +#define SMA_wCurrInputTagBits 0x002e +#define SMA_wCurrLeftPeak 0x0030 +#define SMA_wCurrRightPeak 0x0032 +#define SMA_bMicPotPosLeft 0x0034 +#define SMA_bMicPotPosRight 0x0035 +#define SMA_bMicPotMaxLeft 0x0036 +#define SMA_bMicPotMaxRight 0x0037 +#define SMA_bInPotPosLeft 0x0038 +#define SMA_bInPotPosRight 0x0039 +#define SMA_bAuxPotPosLeft 0x003a +#define SMA_bAuxPotPosRight 0x003b +#define SMA_bInPotMaxLeft 0x003c +#define SMA_bInPotMaxRight 0x003d +#define SMA_bAuxPotMaxLeft 0x003e +#define SMA_bAuxPotMaxRight 0x003f +#define SMA_bInPotMaxMethod 0x0040 +#define SMA_bAuxPotMaxMethod 0x0041 +#define SMA_wCurrMastVolLeft 0x0042 +#define SMA_wCurrMastVolRight 0x0044 +#define SMA_wCalFreqAtoD 0x0046 +#define SMA_wCurrAuxVolLeft 0x0048 +#define SMA_wCurrAuxVolRight 0x004a +#define SMA_wCurrPlay1VolLeft 0x004c +#define SMA_wCurrPlay1VolRight 0x004e +#define SMA_wCurrPlay2VolLeft 0x0050 +#define SMA_wCurrPlay2VolRight 0x0052 +#define SMA_wCurrPlay3VolLeft 0x0054 +#define SMA_wCurrPlay3VolRight 0x0056 +#define SMA_wCurrPlay4VolLeft 0x0058 +#define SMA_wCurrPlay4VolRight 0x005a +#define SMA_wCurrPlay1PeakLeft 0x005c +#define SMA_wCurrPlay1PeakRight 0x005e +#define SMA_wCurrPlay2PeakLeft 0x0060 +#define SMA_wCurrPlay2PeakRight 0x0062 +#define SMA_wCurrPlay3PeakLeft 0x0064 +#define SMA_wCurrPlay3PeakRight 0x0066 +#define SMA_wCurrPlay4PeakLeft 0x0068 +#define SMA_wCurrPlay4PeakRight 0x006a +#define SMA_wCurrPlayPeakLeft 0x006c +#define SMA_wCurrPlayPeakRight 0x006e +#define SMA_wCurrDATSR 0x0070 +#define SMA_wCurrDATRXCHNL 0x0072 +#define SMA_wCurrDATTXCHNL 0x0074 +#define SMA_wCurrDATRXRate 0x0076 +#define SMA_dwDSPPlayCount 0x0078 +#define SMA__size 0x007c #ifdef HAVE_DSPCODEH # include "pndsperm.c" diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c index 0643420881a0..82d0461a4bdb 100644 --- a/drivers/sound/sonicvibes.c +++ b/drivers/sound/sonicvibes.c @@ -46,6 +46,7 @@ * 03.08.98 0.6 Do not include modversions.h * Now mixer behaviour can basically be selected between * "OSS documented" and "OSS actual" behaviour + * 31.08.98 0.7 Fix realplayer problems - dac.count issues * */ @@ -619,7 +620,7 @@ static void start_adc(struct sv_state *s) unsigned long flags; spin_lock_irqsave(&s->lock, flags); - if ((s->dma_adc.mapped || s->dma_adc.count < s->dma_adc.dmasize - 2*s->dma_adc.fragsize) + if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) && s->dma_adc.ready) { s->enable |= SV_CENABLE_RE; wrindir(s, SV_CIENABLE, s->enable); @@ -763,10 +764,10 @@ static void sv_update_ptr(struct sv_state *s) s->dma_adc.total_bytes += diff; s->dma_adc.count += diff; if (s->dma_adc.mapped) { - if (s->dma_adc.count >= s->dma_adc.fragsize) + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) wake_up(&s->dma_adc.wait); } else { - if (s->dma_adc.count > s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1)) { + if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) { s->enable &= ~SV_CENABLE_RE; wrindir(s, SV_CIENABLE, s->enable); s->dma_adc.error++; @@ -783,7 +784,7 @@ static void sv_update_ptr(struct sv_state *s) s->dma_dac.total_bytes += diff; if (s->dma_dac.mapped) { s->dma_dac.count += diff; - if (s->dma_dac.count >= s->dma_dac.fragsize) + if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) wake_up(&s->dma_dac.wait); } else { s->dma_dac.count -= diff; @@ -791,11 +792,11 @@ static void sv_update_ptr(struct sv_state *s) s->enable &= ~SV_CENABLE_PE; wrindir(s, SV_CIENABLE, s->enable); s->dma_dac.error++; - } else if (s->dma_dac.count <= s->dma_dac.fragsize && !s->dma_dac.endcleared) { + } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) { clear_advance(s); s->dma_dac.endcleared = 1; } - if (s->dma_dac.count < s->dma_dac.dmasize) + if (s->dma_dac.count < (signed)s->dma_dac.dmasize) wake_up(&s->dma_dac.wait); } } @@ -1391,7 +1392,7 @@ static unsigned int sv_poll(struct file *file, struct poll_table_struct *wait) sv_update_ptr(s); if (file->f_flags & FMODE_READ) { if (s->dma_adc.mapped) { - if (s->dma_adc.count >= s->dma_adc.fragsize) + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) mask |= POLLIN | POLLRDNORM; } else { if (s->dma_adc.count > 0) @@ -1400,10 +1401,10 @@ static unsigned int sv_poll(struct file *file, struct poll_table_struct *wait) } if (file->f_flags & FMODE_WRITE) { if (s->dma_dac.mapped) { - if (s->dma_dac.count >= s->dma_dac.fragsize) + if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) mask |= POLLOUT | POLLWRNORM; } else { - if (s->dma_dac.dmasize > s->dma_dac.count) + if ((signed)s->dma_dac.dmasize > s->dma_dac.count) mask |= POLLOUT | POLLWRNORM; } } @@ -2282,7 +2283,7 @@ __initfunc(int init_sonicvibes(void)) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "sv: version v0.6 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "sv: version v0.7 time " __TIME__ " " __DATE__ "\n"); #if 0 if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c index 63322ec2ba12..3600284212bb 100644 --- a/drivers/sound/sound_core.c +++ b/drivers/sound/sound_core.c @@ -168,7 +168,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit) * 6 -- sndstat (obsolete) * 7 *16 unused * 8 -- alternate sequencer (see above) - * 9 *16 unused + * 9 *16 raw synthesizer access * 10 *16 unused * 11 *16 unused * 12 *16 unused @@ -212,6 +212,13 @@ int register_sound_dsp(struct file_operations *fops) EXPORT_SYMBOL(register_sound_dsp); +int register_sound_synth(struct file_operations *fops) +{ + return sound_insert_unit(&chains[9], fops, 9, 137); +} + +EXPORT_SYMBOL(register_sound_synth); + void unregister_sound_special(int unit) { sound_remove_unit(&chains[unit&15], unit); @@ -240,6 +247,12 @@ void unregister_sound_dsp(int unit) EXPORT_SYMBOL(unregister_sound_dsp); +void unregister_sound_synth(int unit) +{ + return sound_remove_unit(&chains[9], unit); +} + +EXPORT_SYMBOL(unregister_sound_synth); /* * Now our file operations diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index e96cb18d5e03..f4d37d3c5e7e 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -397,6 +397,8 @@ static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs MAP_FIXED|MAP_PRIVATE, 0); read_exec(bprm->dentry, 32, (char *) 0, ex.a_text+ex.a_data, 0); #endif + flush_icache_range((unsigned long) 0, + (unsigned long) ex.a_text+ex.a_data); } else { if ((ex.a_text & 0xfff || ex.a_data & 0xfff) && (N_MAGIC(ex) != NMAGIC)) @@ -414,6 +416,9 @@ static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs MAP_FIXED|MAP_PRIVATE, 0); read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0); + flush_icache_range((unsigned long) N_TXTADDR(ex), + (unsigned long) N_TXTADDR(ex) + + ex.a_text+ex.a_data); goto beyond_if; } diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 2f0f868789b6..4da714208a59 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -14,7 +14,6 @@ extern int coda_debug; extern int coda_print_entry; /* cnode.c */ - static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr) { CDEBUG(D_SUPER, "ino: %ld\n", inode->i_ino); @@ -117,7 +116,6 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) return 0; } - inline int coda_fideq(ViceFid *fid1, ViceFid *fid2) { int eq; @@ -127,6 +125,27 @@ inline int coda_fideq(ViceFid *fid1, ViceFid *fid2) return eq; } +void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid, + struct ViceFid *newfid) +{ + struct coda_inode_info *cnp; + struct coda_sb_info *sbi= coda_sbp(inode->i_sb); + + cnp = ITOC(inode); + + if ( ! coda_fideq(&cnp->c_fid, oldfid) ) + printk("What? oldfid != cnp->c_fid. Call 911.\n"); + + cnp->c_fid = *newfid; + + list_del(&cnp->c_volrootlist); + if ( !coda_fid_is_weird(newfid) ) + list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead); + + return; +} + + /* convert a fid to an inode. Mostly we can compute diff --git a/fs/coda/dir.c b/fs/coda/dir.c index b555415328a8..e074ca34629e 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -96,7 +96,7 @@ struct file_operations coda_dir_operations = { NULL, /* ioctl */ NULL, /* mmap */ coda_open, /* open */ - NULL, /* flush */ + NULL, coda_release, /* release */ coda_fsync, /* fsync */ NULL, diff --git a/fs/coda/file.c b/fs/coda/file.c index 3635c8ec9470..cbc81542f531 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -66,7 +66,7 @@ struct file_operations coda_file_operations = { NULL, /* ioctl */ coda_file_mmap, /* mmap */ coda_open, /* open */ - NULL, /* flush */ + NULL, coda_release, /* release */ coda_fsync, /* fsync */ NULL, /* fasync */ diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 9f86a7ac2151..4a98361aa71c 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -65,7 +65,7 @@ struct file_operations coda_ioctl_operations = { coda_pioctl, /* ioctl */ NULL, /* mmap */ coda_ioctl_open, /* open */ - NULL, /* flush */ + NULL, coda_ioctl_release, /* release */ NULL, /* fsync */ }; diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 3618940e3638..144162f5af50 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -47,13 +47,7 @@ #include #include - -/* - * Where is the prototype? - */ - -int proc_register_dynamic(struct proc_dir_entry * dir, - struct proc_dir_entry * dp); +extern struct proc_dir_entry proc_sys_root; /* * Coda stuff @@ -391,7 +385,7 @@ static struct file_operations coda_psdev_fops = { NULL, /* ioctl */ NULL, /* coda_psdev_mmap */ coda_psdev_open, /* open */ - NULL, /* flush */ + NULL, coda_psdev_release, /* release */ NULL, /* fsync */ NULL, /* fasync */ @@ -403,7 +397,6 @@ static struct file_operations coda_psdev_fops = { #ifdef CONFIG_PROC_FS -extern struct proc_dir_entry proc_sys_root; struct proc_dir_entry proc_sys_coda = { 0, 4, "coda", @@ -490,6 +483,7 @@ struct proc_dir_entry proc_coda_cache_inv_control = { #endif + __initfunc(int init_coda(void)) { int status; @@ -547,14 +541,12 @@ int init_coda_psdev(void) #ifdef MODULE -EXPORT_NO_SYMBOLS; - MODULE_AUTHOR("Peter J. Braam "); int init_module(void) { int status; - printk(KERN_INFO "Coda Kernel/Venus communications (module), v4.6.0, braam@cs.cmu.edu\n"); + printk(KERN_INFO "Coda Kernel/Venus communications (module), v4.7.1, braam@cs.cmu.edu.\n"); status = init_coda_psdev(); if ( status ) { diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 041845e33fde..dadf27c7e754 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -39,8 +39,6 @@ #include #include -extern void coda_purge_dentries(struct inode *inode); -extern void coda_purge_children(struct inode *inode); static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize, union inputArgs *buffer); @@ -537,16 +535,12 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid, inp->cfs_ioctl.data = (char *)(INSIZE(ioctl)); /* get the data out of user space */ -#ifdef L20 - memcpy_fromfs((char*)inp + (int)inp->cfs_ioctl.data, - data->vi.in, data->vi.in_size); -#else if ( copy_from_user((char*)inp + (int)inp->cfs_ioctl.data, data->vi.in, data->vi.in_size) ) { error = EINVAL; goto exit; } -#endif + error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); if (error) { @@ -565,18 +559,13 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid, error = verify_area(VERIFY_WRITE, data->vi.out, data->vi.out_size); if ( error ) goto exit; -#ifdef L20 - memcpy_tofs(data->vi.out, - (char *)outp + (int)outp->cfs_ioctl.data, - data->vi.out_size); -#else + if (copy_to_user(data->vi.out, (char *)outp + (int)outp->cfs_ioctl.data, data->vi.out_size)) { error = EINVAL; goto exit; } -#endif } exit: @@ -891,18 +880,19 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) case CFS_REPLACE : { struct inode *inode; - ViceFid *fid = &out->cfs_replace.OldFid; + ViceFid *oldfid = &out->cfs_replace.OldFid; + ViceFid *newfid = &out->cfs_replace.NewFid; clstats(CFS_REPLACE); CDEBUG(D_DOWNCALL, "CFS_REPLACE\n"); - inode = coda_fid_to_inode(fid, sb); + inode = coda_fid_to_inode(oldfid, sb); if ( inode ) { CDEBUG(D_DOWNCALL, "replacefid: inode = %ld\n", inode->i_ino); - coda_purge_children(inode); - coda_purge_dentries(inode); + coda_replace_fid(inode, oldfid, newfid); }else CDEBUG(D_DOWNCALL, "purgefid: no inode\n"); + return 0; - } + } } return 0; } diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 2c4d1e47d3df..6685fc3ed26f 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -133,31 +133,23 @@ static int strnicmp(const char *s1, const char *s2, int len) /* Yes, Virginia, it had better be unsigned */ unsigned char c1, c2; - while (len) { + c1 = 0; c2 = 0; + while (len > 0) { c1 = *s1; c2 = *s2; s1++; s2++; if (!c1) - goto end_of_string1; + break; if (!c2) - goto end_of_string2; - if (c1 != c2) { - c1 = tolower(c1); - c2 = tolower(c2); - if (c1 != c2) - goto different; - } + break; + if (c1 == c2) + continue; + c1 = tolower(c1); + c2 = tolower(c2); + if (c1 != c2) + break; len--; } - return 0; - -end_of_string1: - return c2 ? -1 : 0; - -end_of_string2: - return 1; - -different: - return c1 < c2 ? -1 : 1; + return (int)c1 - (int)c2; } /* diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 4f94d88456fe..6bdcef4e8ffc 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -36,7 +36,7 @@ #define NLMDBG_FACILITY NLMDBG_SVC #define LOCKD_BUFSIZE (1024 + NLMSSVC_XDRSIZE) -#define ALLOWED_SIGS (sigmask(SIGKILL) | sigmask(SIGSTOP)) +#define ALLOWED_SIGS (sigmask(SIGKILL)) extern struct svc_program nlmsvc_program; struct nlmsvc_binding * nlmsvc_ops = NULL; @@ -80,6 +80,12 @@ lockd(struct svc_rqst *rqstp) current->pgrp = 1; sprintf(current->comm, "lockd"); + /* Process request with signals blocked. */ + spin_lock_irq(¤t->sigmask_lock); + siginitsetinv(¤t->blocked, sigmask(SIGKILL)); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + /* kick rpciod */ rpciod_up(); @@ -160,19 +166,8 @@ lockd(struct svc_rqst *rqstp) nlmsvc_ops->exp_getclient(&rqstp->rq_addr); } - /* Process request with signals blocked. */ - spin_lock_irq(¤t->sigmask_lock); - siginitsetinv(¤t->blocked, ALLOWED_SIGS); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - svc_process(serv, rqstp); - spin_lock_irq(¤t->sigmask_lock); - sigemptyset(¤t->blocked); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - /* Unlock export hash tables */ if (nlmsvc_ops) nlmsvc_ops->exp_unlock(); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 3e5e59affdf9..a45c26cb3882 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -29,11 +29,6 @@ #include /* for fs functions */ -#define NFS_MAX_AGE 10*HZ /* max age for dentry validation */ - -/* needed by smbfs as well ... move to dcache? */ -extern void nfs_renew_times(struct dentry *); - #define NFS_PARANOIA 1 /* #define NFS_DEBUG_VERBOSE 1 */ @@ -376,6 +371,7 @@ nfs_free_dircache(void) nfs_invalidate_dircache_sb(NULL); } +#define NFS_REVALIDATE_INTERVAL (5*HZ) /* * This is called every time the dcache has a lookup hit, * and we should check whether we can really trust that @@ -384,36 +380,69 @@ nfs_free_dircache(void) * NOTE! The hit can be a negative hit too, don't assume * we have an inode! * - * The decision to drop the dentry should probably be - * smarter than this. Right now we believe in directories - * for 10 seconds, and in normal files for five.. + * If the dentry is older than the revalidation interval, + * we do a new lookup and verify that the dentry is still + * correct. */ static int nfs_lookup_revalidate(struct dentry * dentry) { + struct dentry * parent = dentry->d_parent; + struct inode * inode = dentry->d_inode; unsigned long time = jiffies - dentry->d_time; - unsigned long max = 5*HZ; + int error; + struct nfs_fh fhandle; + struct nfs_fattr fattr; - if (dentry->d_inode) { - if (is_bad_inode(dentry->d_inode)) { + if (inode && is_bad_inode(inode)) { #ifdef NFS_PARANOIA printk("nfs_lookup_validate: %s/%s has dud inode\n", -dentry->d_parent->d_name.name, dentry->d_name.name); +parent->d_name.name, dentry->d_name.name); #endif - goto bad; - } - if (S_ISDIR(dentry->d_inode->i_mode)) - max = NFS_MAX_AGE; + goto out_bad; + } + + if (time < NFS_REVALIDATE_INTERVAL) + goto out_valid; + /* + * Don't bother looking up a negative dentry ... + */ + if (!inode) + goto out_bad; + + if (IS_ROOT(dentry)) + goto out_valid; + /* + * Do a new lookup and check the dentry attributes. + */ + error = nfs_proc_lookup(NFS_DSERVER(parent), NFS_FH(parent), + dentry->d_name.name, &fhandle, &fattr); + if (error) { +printk("nfs_lookup_revalidate: error=%d\n", error); + goto out_bad; + } + + /* Inode number matches? */ + if (fattr.fileid != inode->i_ino) { +printk("nfs_lookup_revalidate: %s/%s inode mismatch, old=%ld, new=%u\n", +parent->d_name.name, dentry->d_name.name, inode->i_ino, fattr.fileid); + goto out_bad; + } + /* Filehandle matches? */ + if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) { +printk("nfs_lookup_revalidate: %s/%s fh changed\n", +parent->d_name.name, dentry->d_name.name); + goto out_bad; } - return (time < max) || IS_ROOT(dentry); -bad: +out_valid: + return 1; +out_bad: return 0; } /* * This is called from dput() when d_count is going to 0. - * We use it to clean up silly-renamed files, and to check - * for dentries that have already expired. + * We use it to clean up silly-renamed files. */ static void nfs_dentry_delete(struct dentry *dentry) { @@ -433,14 +462,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name); dentry->d_parent->d_name.name, dentry->d_name.name, error); } - /* - * Check whether to expire the dentry ... - */ - else { - unsigned long age = jiffies - dentry->d_time; - if (age > NFS_MAX_AGE) - d_drop(dentry); - } #ifdef NFS_PARANOIA /* @@ -523,17 +544,12 @@ static void show_dentry(struct list_head * dlist) #endif /* - * Whenever a lookup succeeds, we know the parent directories - * are all valid, so we want to update the dentry timestamps. + * Whenever an NFS operation succeeds, we know that the dentry + * is valid, so we update the revalidation timestamp. */ -void nfs_renew_times(struct dentry * dentry) +static inline void nfs_renew_times(struct dentry * dentry) { - for (;;) { - dentry->d_time = jiffies; - if (dentry == dentry->d_parent) - break; - dentry = dentry->d_parent; - } + dentry->d_time = jiffies; } static int nfs_lookup(struct inode *dir, struct dentry * dentry) @@ -546,11 +562,6 @@ static int nfs_lookup(struct inode *dir, struct dentry * dentry) dfprintk(VFS, "NFS: lookup(%s/%s)\n", dentry->d_parent->d_name.name, dentry->d_name.name); - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("nfs_lookup: inode is NULL or not a directory\n"); - return -ENOENT; - } - error = -ENAMETOOLONG; if (dentry->d_name.len > NFS_MAXNAMLEN) goto out; @@ -635,12 +646,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode) struct nfs_fh fhandle; dfprintk(VFS, "NFS: create(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, dentry->d_name.name); - - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("nfs_create: inode is NULL or not a directory\n"); - return -ENOENT; - } + dir->i_dev, dir->i_ino, dentry->d_name.name); error = -ENAMETOOLONG; if (dentry->d_name.len > NFS_MAXNAMLEN) @@ -675,12 +681,7 @@ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rde struct nfs_fh fhandle; dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, dentry->d_name.name); - - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("nfs_mknod: inode is NULL or not a directory\n"); - return -ENOENT; - } + dir->i_dev, dir->i_ino, dentry->d_name.name); if (dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; @@ -712,12 +713,7 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) struct nfs_fh fhandle; dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, dentry->d_name.name); - - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("nfs_mkdir: inode is NULL or not a directory\n"); - return -ENOENT; - } + dir->i_dev, dir->i_ino, dentry->d_name.name); error = -ENAMETOOLONG; if (dentry->d_name.len > NFS_MAXNAMLEN) @@ -754,12 +750,7 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) int error, rehash = 0; dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, dentry->d_name.name); - - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("nfs_rmdir: inode is NULL or not a directory\n"); - return -ENOENT; - } + dir->i_dev, dir->i_ino, dentry->d_name.name); error = -ENAMETOOLONG; if (dentry->d_name.len > NFS_MAXNAMLEN) @@ -1010,12 +1001,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) int error; dfprintk(VFS, "NFS: unlink(%x/%ld, %s)\n", - dir->i_dev, dir->i_ino, dentry->d_name.name); - - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("nfs_unlink: inode is NULL or not a directory\n"); - return -ENOENT; - } + dir->i_dev, dir->i_ino, dentry->d_name.name); error = -ENAMETOOLONG; if (dentry->d_name.len > NFS_MAXNAMLEN) @@ -1039,12 +1025,7 @@ nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) int error; dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n", - dir->i_dev, dir->i_ino, dentry->d_name.name, symname); - - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("nfs_symlink: inode is NULL or not a directory\n"); - return -ENOENT; - } + dir->i_dev, dir->i_ino, dentry->d_name.name, symname); error = -ENAMETOOLONG; if (dentry->d_name.len > NFS_MAXNAMLEN) @@ -1096,11 +1077,6 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) old_dentry->d_parent->d_name.name, old_dentry->d_name.name, dentry->d_parent->d_name.name, dentry->d_name.name); - if (!dir || !S_ISDIR(dir->i_mode)) { - printk("nfs_link: dir is NULL or not a directory\n"); - return -ENOENT; - } - error = -ENAMETOOLONG; if (dentry->d_name.len > NFS_MAXNAMLEN) goto out; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 005c2e78705e..afe99a7f5f24 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -61,6 +61,7 @@ static void nfs_wback_lock(struct rpc_task *task); static void nfs_wback_result(struct rpc_task *task); +static void nfs_cancel_request(struct nfs_wreq *req); /* * Cache parameters @@ -248,7 +249,7 @@ nfs_find_dentry_request(struct inode *inode, struct dentry *dentry) req = head = NFS_WRITEBACK(inode); while (req != NULL) { - if (req->wb_dentry == dentry) { + if (req->wb_dentry == dentry && !WB_CANCELLED(req)) { found = 1; break; } @@ -474,6 +475,7 @@ wait_on_write_request(struct nfs_wreq *req) if (!PageLocked(page)) break; retval = -ERESTARTSYS; + checksignals(); if (signalled()) break; schedule(); @@ -585,8 +587,11 @@ done: transfer_page_lock(req); /* rpc_execute(&req->wb_task); */ if (sync) { - /* N.B. if signalled, result not ready? */ - wait_on_write_request(req); + /* if signalled, ensure request is cancelled */ + if ((count = wait_on_write_request(req)) != 0) { + nfs_cancel_request(req); + status = count; + } if ((count = nfs_write_error(inode)) < 0) status = count; } diff --git a/fs/proc/array.c b/fs/proc/array.c index f235a56df5ae..4b28aec2e6fb 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -530,14 +530,12 @@ static unsigned long get_wchan(struct task_struct *p) unsigned long fp, pc; unsigned long stack_page; int count = 0; - extern int sys_pause (void); - stack_page = p->kernel_stack_page; - if (!stack_page) - return 0; + stack_page = (unsigned long)p; fp = ((struct switch_stack *)p->tss.ksp)->a6; do { - if (fp < stack_page || fp >= 4088+stack_page) + if (fp < stack_page+sizeof(struct task_struct) || + fp >= 8184+stack_page) return 0; pc = ((unsigned long *)fp)[1]; /* FIXME: This depends on the order of these functions. */ diff --git a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c index 170f1179c27e..b73f36deb2e3 100644 --- a/fs/qnx4/bitmap.c +++ b/fs/qnx4/bitmap.c @@ -13,6 +13,7 @@ * 28-06-1998 by Frank Denis : qnx4_free_inode (to be fixed) . */ +#include #include #include #include diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c index 189c1a2e1fd1..119930667393 100644 --- a/fs/qnx4/dir.c +++ b/fs/qnx4/dir.c @@ -11,6 +11,7 @@ * 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support. */ +#include #include #include #include diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c index 0e67165a9ecd..f26733d9a9ec 100644 --- a/fs/qnx4/file.c +++ b/fs/qnx4/file.c @@ -12,6 +12,7 @@ * 27-06-1998 by Frank Denis : file overwriting. */ +#include #include #include #include diff --git a/fs/qnx4/fsync.c b/fs/qnx4/fsync.c index 8e7df0512976..826ee8a093ea 100644 --- a/fs/qnx4/fsync.c +++ b/fs/qnx4/fsync.c @@ -10,6 +10,7 @@ * 24-03-1998 by Richard Frowijn : first release. */ +#include #include #include #include diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 0aa37dd87fd2..87d1803dbdf8 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -12,6 +12,7 @@ * 30-06-1998 by Frank Denis : first step to write inodes. */ +#include #include #include #include diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c index 4d91a2d99c50..99cbf05eb764 100644 --- a/fs/qnx4/namei.c +++ b/fs/qnx4/namei.c @@ -12,6 +12,7 @@ * 04-07-1998 by Frank Denis : first step for rmdir/unlink. */ +#include #include #include #include diff --git a/fs/qnx4/symlinks.c b/fs/qnx4/symlinks.c index 326360197b29..f590d04a6d97 100644 --- a/fs/qnx4/symlinks.c +++ b/fs/qnx4/symlinks.c @@ -13,6 +13,7 @@ /* THIS FILE HAS TO BE REWRITTEN */ +#include #include #include #include diff --git a/fs/qnx4/truncate.c b/fs/qnx4/truncate.c index 928416dcfc1a..a25bf1daff7d 100644 --- a/fs/qnx4/truncate.c +++ b/fs/qnx4/truncate.c @@ -10,6 +10,7 @@ * 30-06-1998 by Frank DENIS : ugly filler. */ +#include #include #include #include diff --git a/fs/ufs/acl.c b/fs/ufs/acl.c index 934e474a1600..2b67683527b6 100644 --- a/fs/ufs/acl.c +++ b/fs/ufs/acl.c @@ -3,7 +3,7 @@ * * Copyright (C) 1998 * Daniel Pirkl - * Charles Uiversity, Faculty of Mathematics and Physics + * Charles University, Faculty of Mathematics and Physics * * from * @@ -16,8 +16,7 @@ */ /* - * This file will contain the Access Control Lists management for the - * second extended file system. + * This file will contain the Access Control Lists management for UFS */ #include @@ -39,8 +38,8 @@ int ufs_permission (struct inode * inode, int mask) * Nobody gets write access to a file on a readonly-fs */ if ((mask & S_IWOTH) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) && - IS_RDONLY(inode)) + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) && + IS_RDONLY(inode)) return -EROFS; /* * Nobody gets write access to an immutable file @@ -57,7 +56,7 @@ int ufs_permission (struct inode * inode, int mask) mode >>= 3; /* * Access is always granted for root. We now check last, - * though, for BSD process accounting correctness + * though, for BSD process accounting correctness */ if (((mode & mask & S_IRWXO) == mask) || fsuser()) return 0; diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 1022ad3836e8..6567c515b904 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -32,7 +32,7 @@ #define UFSDM \ ufs_print_cylinder_stuff (ucg, swab); \ printk("inode: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nifree), \ -swab32(sb->fs_cs(ucpi->c_cgx).cs_nifree), SWAB32(ucg->cg_cs.cs_nifree)); \ +SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nifree), SWAB32(ucg->cg_cs.cs_nifree)); \ printk("block: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree), \ SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nbfree), SWAB32(ucg->cg_cs.cs_nbfree)); \ printk("fragment: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nffree), \ @@ -133,7 +133,7 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count if (sb->s_flags & MS_SYNCHRONOUS) { ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi); ubh_wait_on_buffer (UCPI_UBH); - } + } sb->s_dirt = 1; unlock_super (sb); @@ -211,7 +211,7 @@ do_more: cylno = ufs_cbtocylno(i); INC_SWAB16(ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i))); INC_SWAB32(ubh_cg_blktot(ucpi, cylno)); - } + } UFSDM @@ -220,7 +220,7 @@ do_more: if (sb->s_flags & MS_SYNCHRONOUS) { ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi); ubh_wait_on_buffer (UCPI_UBH); - } + } if (overflow) { fragment += count; @@ -249,7 +249,7 @@ failed: mark_buffer_dirty (bh, 1); \ if (IS_SYNC(inode)) { \ ll_rw_block (WRITE, 1, &bh); \ - wait_on_buffer (bh); \ + wait_on_buffer (bh); \ } \ brelse (bh); \ } @@ -328,7 +328,7 @@ unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment, * allocate new fragment */ if (oldcount == 0) { - result = ufs_alloc_fragments (inode, cgno, goal, count, err); + result = ufs_alloc_fragments (inode, cgno, goal, count, err); if (result) { *p = SWAB32(result); *err = 0; @@ -373,7 +373,7 @@ unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment, request = uspi->s_fpb; if (SWAB32(usb1->fs_cstotal.cs_nffree) < uspi->s_dsize * (uspi->s_minfree - 2) / 100) - break; + break; usb1->fs_optim = SWAB32(UFS_OPTSPACE); break; } @@ -532,7 +532,7 @@ unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno, } /* - * 3. brute force search + * 3. brute force search * We start at i = 2 ( 0 is checked at 1.step, 1 at 2.step ) */ cgno = (oldcg + 1) % uspi->s_ncg; @@ -642,7 +642,7 @@ unsigned ufs_alloccg_block (struct inode * inode, goto norot; } goal = ufs_blknum (goal); - goal = ufs_dtogd (goal); + goal = ufs_dtogd (goal); /* * If the requested block is available, use it. @@ -652,7 +652,7 @@ unsigned ufs_alloccg_block (struct inode * inode, goto gotit; } - /*** This function should be optimalized later ***/ + /*** This function should be optimized later ***/ norot: result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb); diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 03d95fda57a0..470847dca6be 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -6,7 +6,7 @@ * Laboratory for Computer Science Research Computing Facility * Rutgers, The State University of New Jersey * - * swab support by Francois-Rene Rideau 19970406 + * swab support by Francois-Rene Rideau 19970406 * * 4.4BSD (FreeBSD) support added on February 1st 1998 by * Niels Kristian Bech Jensen partially based @@ -46,14 +46,14 @@ ufs_readdir (struct file * filp, void * dirent, filldir_t filldir) /* Isn't that already done in the upper layer??? - * the VFS layer really needs some explicit documentation! - */ + * the VFS layer really needs some explicit documentation! + */ if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; sb = inode->i_sb; swab = sb->u.ufs_sb.s_swab; - flags = sb->u.ufs_sb.s_flags; + flags = sb->u.ufs_sb.s_flags; UFSD(("ENTER, ino %lu f_pos %lu\n", inode->i_ino, (unsigned long) filp->f_pos)) @@ -63,14 +63,14 @@ ufs_readdir (struct file * filp, void * dirent, filldir_t filldir) while (!error && !stored && filp->f_pos < inode->i_size) { lblk = (filp->f_pos) >> sb->s_blocksize_bits; - /* XXX - ufs_bmap() call needs error checking */ - blk = ufs_bmap(inode, lblk); + /* XXX - ufs_bmap() call needs error checking */ + blk = ufs_bmap(inode, lblk); bh = bread (sb->s_dev, blk, sb->s_blocksize); if (!bh) { - /* XXX - error - skip to the next block */ - printk("ufs_readdir: " + /* XXX - error - skip to the next block */ + printk("ufs_readdir: " "dir inode %lu has a hole at offset %lu\n", - inode->i_ino, (unsigned long int)filp->f_pos); + inode->i_ino, (unsigned long int)filp->f_pos); filp->f_pos += sb->s_blocksize - offset; continue; } @@ -103,23 +103,23 @@ revalidate: while (!error && filp->f_pos < inode->i_size && offset < sb->s_blocksize) { de = (struct ufs_dir_entry *) (bh->b_data + offset); - /* XXX - put in a real ufs_check_dir_entry() */ - if ((de->d_reclen == 0) || (ufs_namlen(de) == 0)) { + /* XXX - put in a real ufs_check_dir_entry() */ + if ((de->d_reclen == 0) || (ufs_namlen(de) == 0)) { /* SWAB16() was unneeded -- compare to 0 */ - filp->f_pos = (filp->f_pos & - (sb->s_blocksize - 1)) + - sb->s_blocksize; - brelse(bh); - return stored; - } + filp->f_pos = (filp->f_pos & + (sb->s_blocksize - 1)) + + sb->s_blocksize; + brelse(bh); + return stored; + } #if 0 /* XXX */ if (!ext2_check_dir_entry ("ext2_readdir", inode, de, /* XXX - beware about de having to be swabped somehow */ bh, offset)) { /* On error, skip the f_pos to the - next block. */ + next block. */ filp->f_pos = (filp->f_pos & - (sb->s_blocksize - 1)) + + (sb->s_blocksize - 1)) + sb->s_blocksize; brelse (bh); return stored; @@ -139,7 +139,7 @@ revalidate: UFSD(("filldir(%s,%u)\n", de->d_name, SWAB32(de->d_ino))) UFSD(("namlen %u\n", ufs_namlen(de))) error = filldir(dirent, de->d_name, ufs_namlen(de), - filp->f_pos, SWAB32(de->d_ino)); + filp->f_pos, SWAB32(de->d_ino)); if (error) break; if (version != inode->i_version) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 123a76a753ad..afea7180a660 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -91,7 +91,7 @@ static inline unsigned ufs_block_bmap (struct buffer_head * bh, unsigned nr, return 0; tmp = SWAB32(((u32 *) bh->b_data)[nr >> uspi->s_fpbshift]) + (nr & uspi->s_fpbmask); brelse (bh); - UFSD(("EXIT, resutl %u\n", tmp)) + UFSD(("EXIT, result %u\n", tmp)) return tmp; } @@ -254,7 +254,7 @@ repeat: */ else /* (lastblock > block) */ { if (lastblock && (tmp = SWAB32(inode->u.ufs_i.i_u1.i_data[lastblock-1]))) - goal = tmp + uspi->s_fpb; + goal = tmp + uspi->s_fpb; tmp = ufs_new_fragments (inode, p, fragment - blockoff, goal, uspi->s_fpb, err); } @@ -322,10 +322,10 @@ repeat: *err = -EFBIG; return NULL; } - if (block && (tmp = SWAB32(((u32*)bh->b_data)[block-1]) + uspi->s_fpb)) - goal = tmp + uspi->s_fpb; - else - goal = bh->b_blocknr + uspi->s_fpb; + if (block && (tmp = SWAB32(((u32*)bh->b_data)[block-1]) + uspi->s_fpb)) + goal = tmp + uspi->s_fpb; + else + goal = bh->b_blocknr + uspi->s_fpb; tmp = ufs_new_fragments (inode, p, ufs_blknum(new_fragment), goal, uspi->s_fpb, err); if (!tmp) { if (SWAB32(*p)) { @@ -345,7 +345,7 @@ repeat: inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); brelse (bh); - UFSD(("EXIT, resutl %u\n", tmp + blockoff)) + UFSD(("EXIT, result %u\n", tmp + blockoff)) return result; } @@ -492,7 +492,7 @@ void ufs_read_inode (struct inode * inode) } /* - * Linux i_size can be 32 on some architektures. We will mark + * Linux i_size can be 32 on some architectures. We will mark * big files as read only and let user access first 32 bits. */ inode->u.ufs_i.i_size = SWAB64(ufs_inode->ui_size); diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 309b31665cbe..9542d27707c4 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -266,9 +266,9 @@ static struct buffer_head * ufs_add_entry (struct inode * dir, de = (struct ufs_dir_entry *) bh->b_data; *err = -ENOSPC; while (1) { - if ((char *)de >= SECTOR_SIZE + bh->b_data) { + if ((char *)de >= UFS_SECTOR_SIZE + bh->b_data) { fragoff = offset & ~uspi->s_fmask; - if (fragoff != 0 && fragoff != SECTOR_SIZE) + if (fragoff != 0 && fragoff != UFS_SECTOR_SIZE) ufs_error (sb, "ufs_add_entry", "internal error" " fragoff %u", fragoff); if (!fragoff) { @@ -285,9 +285,9 @@ static struct buffer_head * ufs_add_entry (struct inode * dir, } de = (struct ufs_dir_entry *) (bh->b_data + fragoff); de->d_ino = SWAB32(0); - de->d_reclen = SWAB16(SECTOR_SIZE); + de->d_reclen = SWAB16(UFS_SECTOR_SIZE); de->d_u.d_namlen = SWAB16(0); - dir->i_size = offset + SECTOR_SIZE; + dir->i_size = offset + UFS_SECTOR_SIZE; mark_inode_dirty(dir); } else { de = (struct ufs_dir_entry *) bh->b_data; @@ -384,11 +384,11 @@ static int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir, return 0; } i += SWAB16(de->d_reclen); - if (i == SECTOR_SIZE) pde = NULL; + if (i == UFS_SECTOR_SIZE) pde = NULL; else pde = de; de = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen)); - if (i == SECTOR_SIZE && SWAB16(de->d_reclen) == 0) + if (i == UFS_SECTOR_SIZE && SWAB16(de->d_reclen) == 0) break; } UFSD(("EXIT\n")) @@ -537,7 +537,7 @@ int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) goto out; inode->i_op = &ufs_dir_inode_operations; - inode->i_size = SECTOR_SIZE; + inode->i_size = UFS_SECTOR_SIZE; dir_block = ufs_bread (inode, 0, 1, &err); if (!dir_block) { inode->i_nlink--; /* is this nlink == 0? */ @@ -545,7 +545,7 @@ int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) iput (inode); return err; } - inode->i_blocks = sb->s_blocksize / SECTOR_SIZE; + inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE; de = (struct ufs_dir_entry *) dir_block->b_data; de->d_ino = SWAB32(inode->i_ino); de->d_u.d_namlen = SWAB16(1); @@ -553,7 +553,7 @@ int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) strcpy (de->d_name, "."); de = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen)); de->d_ino = SWAB32(dir->i_ino); - de->d_reclen = SWAB16(SECTOR_SIZE - UFS_DIR_REC_LEN(1)); + de->d_reclen = SWAB16(UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1)); de->d_u.d_namlen = SWAB16(2); strcpy (de->d_name, ".."); inode->i_nlink = 2; @@ -605,7 +605,7 @@ static int ufs_empty_dir (struct inode * inode) if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) || !(bh = ufs_bread (inode, 0, 0, &err))) { - ufs_warning (inode->i_sb, "empty_dir", + ufs_warning (inode->i_sb, "empty_dir", "bad directory (dir #%lu) - no data block", inode->i_ino); return 1; @@ -614,7 +614,7 @@ static int ufs_empty_dir (struct inode * inode) de1 = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen)); if (SWAB32(de->d_ino) != inode->i_ino || !SWAB32(de1->d_ino) || strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) { - ufs_warning (inode->i_sb, "empty_dir", + ufs_warning (inode->i_sb, "empty_dir", "bad directory (dir #%lu) - no `.' or `..'", inode->i_ino); return 1; @@ -625,7 +625,7 @@ static int ufs_empty_dir (struct inode * inode) if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) { brelse (bh); bh = ufs_bread (inode, offset >> sb->s_blocksize_bits, 1, &err); - if (!bh) { + if (!bh) { ufs_error (sb, "empty_dir", "directory #%lu contains a hole at offset %lu", inode->i_ino, offset); diff --git a/fs/ufs/super.c b/fs/ufs/super.c index b68af57713d6..d4426ad5dfa9 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -15,7 +15,7 @@ * Gertjan van Wingerde * * Clean swab support on 19970406 by - * Francois-Rene Rideau + * Francois-Rene Rideau * * 4.4BSD (FreeBSD) support added on February 1st 1998 by * Niels Kristian Bech Jensen partially based @@ -26,10 +26,10 @@ * * write support Daniel Pirkl 1998 * - */ #include +#include #include #include @@ -130,7 +130,7 @@ void ufs_print_cylinder_stuff(struct ufs_cylinder_group *cg, unsigned swab) /* * Called while file system is mounted, read super block - * and create important imtermal structures. + * and create important internal structures. */ struct super_block * ufs_read_super ( struct super_block * sb, @@ -148,7 +148,7 @@ struct super_block * ufs_read_super ( unsigned flags, swab; s64 tmp; static unsigned offsets[] = {0, 96, 160}; /* different superblock locations */ - + UFSD(("ENTER\n")) uspi = NULL; @@ -156,13 +156,12 @@ struct super_block * ufs_read_super ( base = space = NULL; sb->u.ufs_sb.s_ucg = NULL; flags = 0; - swab = 0; /* sb->s_dev and sb->s_flags are set by our caller * data is the mystery argument to sys_mount() * * Our caller also sets s_dev, s_covered, s_rd_only, s_dirt, - * and s_type when we return. + * and s_type when we return. */ MOD_INC_USE_COUNT; @@ -183,7 +182,7 @@ struct super_block * ufs_read_super ( i = 0; uspi->s_sbbase = offsets[i]; -again: +again: set_blocksize (sb->s_dev, block_size); /* @@ -199,30 +198,47 @@ again: /* * Check ufs magic number + * This code uses goto, because it's a lesser evil than unbalanced + * structure in conditional code. Brought to you by Fare' as a minimal + * hack to live with Daniel's (unnecessary, IMNSHO) manual swab + * optimization -- see swab.h. */ - if (usb3->fs_magic != UFS_MAGIC) { - switch (le32_to_cpup(&usb3->fs_magic)) { +#if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN) /* sane bytesex */ + switch (usb3->fs_magic) { case UFS_MAGIC: - swab = UFS_LITTLE_ENDIAN; break; + swab = UFS_NATIVE_ENDIAN; + goto magic_found; case UFS_CIGAM: - swab = UFS_BIG_ENDIAN; break; - default: - /* - * Try another super block location - */ - if (++i < sizeof(offsets)/sizeof(unsigned)) { - ubh_brelse2(ubh); - ubh = NULL; - uspi->s_sbbase = offsets[i]; - goto again; - } - else { - printk("ufs_read_super: super block loacation not in { 0, 96, 160} or bad magic number\n"); - goto failed; - } - } + swab = UFS_SWABBED_ENDIAN; + goto magic_found; } - +#else /* bytesex perversion */ + switch (le32_to_cpup(&usb3->fs_magic)) { + case UFS_MAGIC: + swab = UFS_LITTLE_ENDIAN; + goto magic_found; + case UFS_CIGAM: + swab = UFS_BIG_ENDIAN; + goto magic_found; + } +#endif + /* + * Magic number not found -- try another super block location + */ + if (++i < sizeof(offsets)/sizeof(unsigned)) { + ubh_brelse2(ubh); + ubh = NULL; + uspi->s_sbbase = offsets[i]; + goto again; + } else { + printk("ufs_read_super: " + "super block location not in " + "{ 0, 96, 160} " + "or bad magic number\n"); + goto failed; + } + magic_found: + /* * Check block and fragment sizes */ @@ -231,23 +247,27 @@ again: uspi->s_sbsize = SWAB32(usb1->fs_sbsize); if (uspi->s_bsize != 4096 && uspi->s_bsize != 8192) { - printk("ufs_read_super: fs_bsize %u != {4096, 8192}\n", uspi->s_bsize); + printk("ufs_read_super: fs_bsize %u != {4096, 8192}\n", + uspi->s_bsize); goto failed; } if (uspi->s_fsize != 512 && uspi->s_fsize != 1024) { - printk("ufs_read_super: fs_fsize %u != {512, 1024}\n", uspi->s_fsize); - goto failed; + printk("ufs_read_super: fs_fsize %u != {512, 1024}\n", + uspi->s_fsize); + goto failed; } /* - * Block size is not 1024, set block_size to 512, - * free buffers and read it again + * Block size is not 1024. Free buffers, set block_size and + * super_block_size to superblock-declared values, and try again. */ if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) { ubh_brelse2(ubh); ubh = NULL; uspi->s_fmask = SWAB32(usb1->fs_fmask); uspi->s_fshift = SWAB32(usb1->fs_fshift); + block_size = uspi->s_fsize; + super_block_size = uspi->s_sbsize; goto again; } @@ -255,54 +275,59 @@ again: ufs_print_super_stuff (usb1, usb2, usb3, swab); #endif /* - * Check file system type + * Check file system flavor */ flags |= UFS_VANILLA; /* XXX more consistency check */ UFSD(("ufs_read_super: maxsymlinklen 0x%8.8x\n", usb3->fs_u.fs_44.fs_maxsymlinklen)) if (usb3->fs_u.fs_44.fs_maxsymlinklen >= 0) { if (usb3->fs_u.fs_44.fs_inodefmt >= UFS_44INODEFMT) { - UFSD(("44BSD\n")) + UFSD(("Flavor: 44BSD\n")) flags |= UFS_44BSD; sb->s_flags |= MS_RDONLY; } else { - UFSD(("OLD\n")) + UFSD(("Flavor: OLD\n")) sb->s_flags |= UFS_OLD; /* 4.2BSD */ } } else if (uspi->s_sbbase > 0) { - UFSD(("NEXT\n")) + UFSD(("Flavor: NEXT\n")) flags |= UFS_NEXT; sb->s_flags |= MS_RDONLY; } else { - UFSD(("SUN\n")) + UFSD(("Flavor: SUN\n")) flags |= UFS_SUN; - } + } /* - * Check, if file system was correctly unmounted. + * Check whether file system was correctly unmounted. * If not, make it read only. */ - if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) || - ((flags & UFS_ST_MASK) == UFS_ST_OLD) || - ((flags & UFS_ST_MASK) == UFS_ST_NEXT) || - (((flags & UFS_ST_MASK) == UFS_ST_SUN) && - ufs_state(usb3) == UFS_FSOK - usb1->fs_time)) { + if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) || + ((flags & UFS_ST_MASK) == UFS_ST_OLD) || + ((flags & UFS_ST_MASK) == UFS_ST_NEXT) || + (((flags & UFS_ST_MASK) == UFS_ST_SUN) && + ufs_state(usb3) == UFS_FSOK - usb1->fs_time)) { switch(usb1->fs_clean) { - case UFS_FSCLEAN: - UFSD(("fs is clean\n")) - break; - case UFS_FSSTABLE: - UFSD(("fs is stable\n")) - break; - case UFS_FSACTIVE: + case UFS_FSACTIVE: /* 0x00 */ printk("ufs_read_super: fs is active\n"); sb->s_flags |= MS_RDONLY; break; - case UFS_FSBAD: + case UFS_FSCLEAN: /* 0x01 */ + UFSD(("ufs_read_super: fs is clean\n")) + break; + case UFS_FSSTABLE: + UFSD(("ufs_read_super: fs is stable\n")) + break; + case UFS_FSOSF1: /* 0x03 */ + /* XXX - is this the correct interpretation under DEC OSF/1? */ + printk("ufs_read_super: " + "fs is clean and stable (OSF/1)\n"); + break; + case UFS_FSBAD: /* 0xFF */ printk("ufs_read_super: fs is bad\n"); sb->s_flags |= MS_RDONLY; break; - default: + default: printk("ufs_read_super: can't grok fs_clean 0x%x\n", usb1->fs_clean); sb->s_flags |= MS_RDONLY; @@ -335,7 +360,7 @@ again: /* s_bsize already set */ /* s_fsize already set */ uspi->s_fpb = SWAB32(usb1->fs_frag); - uspi->s_minfree = SWAB32(usb1->fs_minfree); + uspi->s_minfree = SWAB32(usb1->fs_minfree); uspi->s_bmask = SWAB32(usb1->fs_bmask); uspi->s_fmask = SWAB32(usb1->fs_fmask); uspi->s_bshift = SWAB32(usb1->fs_bshift); @@ -345,7 +370,7 @@ again: /* s_sbsize already set */ uspi->s_csmask = SWAB32(usb1->fs_csmask); uspi->s_csshift = SWAB32(usb1->fs_csshift); - uspi->s_nindir = SWAB32(usb1->fs_nindir); + uspi->s_nindir = SWAB32(usb1->fs_nindir); uspi->s_inopb = SWAB32(usb1->fs_inopb); uspi->s_nspf = SWAB32(usb1->fs_nspf); uspi->s_npsect = SWAB32(usb1->fs_npsect); @@ -360,11 +385,11 @@ again: uspi->s_ipg = SWAB32(usb1->fs_ipg); uspi->s_fpg = SWAB32(usb1->fs_fpg); uspi->s_cpc = SWAB32(usb2->fs_cpc); - ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qbmask[0]; - ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qbmask[1]; + ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qbmask[0]; + ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qbmask[1]; uspi->s_qbmask = SWAB64(tmp); - ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qfmask[0]; - ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qfmask[1]; + ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qfmask[0]; + ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qfmask[1]; uspi->s_qfmask = SWAB64(tmp); uspi->s_postblformat = SWAB32(usb3->fs_postblformat); uspi->s_nrpos = SWAB32(usb3->fs_nrpos); @@ -372,7 +397,7 @@ again: uspi->s_rotbloff = SWAB32(usb3->fs_rotbloff); /* - * Compute another fraquently used values + * Compute another frequently used values */ uspi->s_fpbmask = uspi->s_fpb - 1; uspi->s_apbshift = uspi->s_bshift - 2; @@ -382,15 +407,18 @@ again: uspi->s_2apb = 1 << uspi->s_2apbshift; uspi->s_3apb = 1 << uspi->s_3apbshift; uspi->s_apbmask = uspi->s_apb - 1; - uspi->s_nspfshift = uspi->s_fshift - SECTOR_BITS; + uspi->s_nspfshift = uspi->s_fshift - UFS_SECTOR_BITS; uspi->s_nspb = uspi->s_nspf << uspi->s_fpbshift; uspi->s_inopf = uspi->s_inopb >> uspi->s_fpbshift; - + + /* we could merge back s_swab and s_flags by having + foo.s_flags = flags | swab; here, and #defining + s_swab to s_flags & UFS_BYTESEX in swab.h */ sb->u.ufs_sb.s_flags = flags; sb->u.ufs_sb.s_swab = swab; sb->u.ufs_sb.s_rename_lock = 0; sb->u.ufs_sb.s_rename_wait = NULL; - + sb->s_root = d_alloc_root(iget(sb, UFS_ROOTINO), NULL); /* @@ -419,6 +447,7 @@ again: /* * Read cylinder group (we read only first fragment from block * at this time) and prepare internal data structures for cg caching. + * XXX - something here fails on CDROMs from DEC! */ if (!(sb->u.ufs_sb.s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL))) goto failed; @@ -669,7 +698,7 @@ static struct file_system_type ufs_fs_type = { }; -int init_ufs_fs(void) +__initfunc(int init_ufs_fs(void)) { return(register_filesystem(&ufs_fs_type)); } diff --git a/fs/ufs/swab.h b/fs/ufs/swab.h index 534c26981896..590b8f1a4cf0 100644 --- a/fs/ufs/swab.h +++ b/fs/ufs/swab.h @@ -1,7 +1,7 @@ /* - * linux/fs/ufs/ufs_swab.h + * linux/fs/ufs/swab.h * - * Copyright (C) 1997 Francois-Rene Rideau + * Copyright (C) 1997, 1998 Francois-Rene Rideau * Copyright (C) 1998 Jakub Jelinek */ @@ -14,6 +14,29 @@ * in case there are ufs implementations that have strange bytesexes, * you'll need to modify code here as well as in ufs_super.c and ufs_fs.h * to support them. + * + * WE ALSO ASSUME A REMOTELY SANE ARCHITECTURE BYTESEX. + * We are not ready to confront insane bytesexual perversions where + * conversion to/from little/big-endian is not an involution. + * That is, we require that XeYZ_to_cpu(x) == cpu_to_XeYZ(x) + * + * NOTE that swab macros depend on a variable (or macro) swab being in + * scope and properly initialized (usually from sb->u.ufs_sb.s_swab). + * Its meaning depends on whether the architecture is sane-endian or not. + * For sane architectures, it's a flag taking values UFS_NATIVE_ENDIAN (0) + * or UFS_SWABBED_ENDIAN (1), indicating whether to swab or not. + * For pervert architectures, it's either UFS_LITTLE_ENDIAN or + * UFS_BIG_ENDIAN whose meaning you'll have to guess. + * + * It is important to keep these conventions in synch with ufs_fs.h + * and super.c. Failure to do so (initializing swab to 0 both for + * NATIVE_ENDIAN and LITTLE_ENDIAN) led to nasty crashes on big endian + * machines reading little endian UFSes. Search for "swab =" in super.c. + * + * I also suspect the whole UFS code to trust the on-disk structures + * much too much, which might lead to losing badly when mounting + * inconsistent partitions as UFS filesystems. fsck required (but of + * course, no fsck.ufs has yet to be ported from BSD to Linux as of 199808). */ #include @@ -28,23 +51,23 @@ #define SWAB64(x) ufs_swab64(swab,x) /* - * We often use swabing, when we want to increment/decrement some value, so these - * macros might become handy and increase readability. (Daniel) + * We often use swabing, when we want to increment/decrement some value, + * so these macros might become handy and increase readability. (Daniel) */ -#define INC_SWAB16(x) x=ufs_swab16_add(swab,x,1) -#define INC_SWAB32(x) x=ufs_swab32_add(swab,x,1) -#define INC_SWAB64(x) x=ufs_swab64_add(swab,x,1) -#define DEC_SWAB16(x) x=ufs_swab16_add(swab,x,-1) -#define DEC_SWAB32(x) x=ufs_swab32_add(swab,x,-1) -#define DEC_SWAB64(x) x=ufs_swab64_add(swab,x,-1) -#define ADD_SWAB16(x,y) x=ufs_swab16_add(swab,x,y) -#define ADD_SWAB32(x,y) x=ufs_swab32_add(swab,x,y) -#define ADD_SWAB64(x,y) x=ufs_swab64_add(swab,x,y) -#define SUB_SWAB16(x,y) x=ufs_swab16_add(swab,x,-(y)) -#define SUB_SWAB32(x,y) x=ufs_swab32_add(swab,x,-(y)) -#define SUB_SWAB64(x,y) x=ufs_swab64_add(swab,x,-(y)) +#define INC_SWAB16(x) ((x)=ufs_swab16_add(swab,x,1)) +#define INC_SWAB32(x) ((x)=ufs_swab32_add(swab,x,1)) +#define INC_SWAB64(x) ((x)=ufs_swab64_add(swab,x,1)) +#define DEC_SWAB16(x) ((x)=ufs_swab16_add(swab,x,-1)) +#define DEC_SWAB32(x) ((x)=ufs_swab32_add(swab,x,-1)) +#define DEC_SWAB64(x) ((x)=ufs_swab64_add(swab,x,-1)) +#define ADD_SWAB16(x,y) ((x)=ufs_swab16_add(swab,x,y)) +#define ADD_SWAB32(x,y) ((x)=ufs_swab32_add(swab,x,y)) +#define ADD_SWAB64(x,y) ((x)=ufs_swab64_add(swab,x,y)) +#define SUB_SWAB16(x,y) ((x)=ufs_swab16_add(swab,x,-(y))) +#define SUB_SWAB32(x,y) ((x)=ufs_swab32_add(swab,x,-(y))) +#define SUB_SWAB64(x,y) ((x)=ufs_swab64_add(swab,x,-(y))) -#ifndef __PDP_ENDIAN +#if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN) /* sane bytesex */ extern __inline__ __const__ __u16 ufs_swab16(unsigned swab, __u16 x) { if (swab) return swab16(x); @@ -81,21 +104,21 @@ extern __inline__ __const__ __u64 ufs_swab64_add(unsigned swab, __u64 x, __u64 y else return x + y; } -#else /* __PDP_ENDIAN */ +#else /* bytesexual perversion -- BEWARE! Read note at top of file! */ extern __inline__ __const__ __u16 ufs_swab16(unsigned swab, __u16 x) { - if (swab & UFS_LITTLE_ENDIAN) + if (swab == UFS_LITTLE_ENDIAN) return le16_to_cpu(x); else return be16_to_cpu(x); } extern __inline__ __const__ __u32 ufs_swab32(unsigned swab, __u32 x) { - if (swab & UFS_LITTLE_ENDIAN) + if (swab == UFS_LITTLE_ENDIAN) return le32_to_cpu(x); else return be32_to_cpu(x); } extern __inline__ __const__ __u64 ufs_swab64(unsigned swab, __u64 x) { - if (swab & UFS_LITTLE_ENDIAN) + if (swab == UFS_LITTLE_ENDIAN) return le64_to_cpu(x); else return be64_to_cpu(x); @@ -109,6 +132,6 @@ extern __inline__ __const__ __u32 ufs_swab32_add(unsigned swab, __u32 x, __u32 y extern __inline__ __const__ __u64 ufs_swab64_add(unsigned swab, __u64 x, __u64 y) { return ufs_swab64(swab, ufs_swab64(swab, x) + y); } -#endif /* __PDP_ENDIAN */ +#endif /* byte sexuality */ #endif /* _UFS_SWAB_H */ diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c index 9d18c5f53fbf..f1004733a325 100644 --- a/fs/ufs/symlink.c +++ b/fs/ufs/symlink.c @@ -109,7 +109,7 @@ static int ufs_readlink (struct dentry * dentry, char * buffer, int buflen) i++; if (copy_to_user(buffer, link, i)) i = -EFAULT; - UPDATE_ATIME(inode); + UPDATE_ATIME(inode); if (bh) brelse (bh); UFSD(("ENTER\n")) diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index c6dca7358c25..3fec735a288d 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -3,7 +3,7 @@ * * Copyright (C) 1998 * Daniel Pirkl - * Charles Uiversity, Faculty of Mathematics and Physics + * Charles University, Faculty of Mathematics and Physics * * from * @@ -68,7 +68,7 @@ static int ufs_trunc_direct (struct inode * inode) struct ufs_sb_private_info * uspi; struct buffer_head * bh; u32 * p; - unsigned frag1, frag2, frag3, frag4, block1, block2; + unsigned frag1, frag2, frag3, frag4, block1, block2; unsigned frag_to_free, free_count; unsigned i, j, tmp; int retry; diff --git a/fs/ufs/util.c b/fs/ufs/util.c index 4d7fd2d57431..527ba02aaca6 100644 --- a/fs/ufs/util.c +++ b/fs/ufs/util.c @@ -3,7 +3,7 @@ * * Copyright (C) 1998 * Daniel Pirkl - * Charles Uiversity, Faculty of Mathematics and Physics + * Charles University, Faculty of Mathematics and Physics */ #include @@ -194,4 +194,3 @@ void _ubh_memcpyubh_(struct ufs_sb_private_info * uspi, bhno++; } } - \ No newline at end of file diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 8f5e66727833..7443f9fc914e 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -11,7 +11,7 @@ /* - * some usefull marcos + * some useful macros */ #define in_range(b,first,len) ((b)>=(first)&&(b)<(first)+(len)) #define howmany(x,y) (((x)+(y)-1)/(y)) @@ -28,7 +28,7 @@ : (usb3)->fs_u.fs_44.fs_state /* 4.4BSD way */) /* - * namlen, it's format depends of flags + * namlen, its format depends of flags */ #define ufs_namlen(de) _ufs_namlen_(de,flags,swab) static inline __u16 _ufs_namlen_(struct ufs_dir_entry * de, unsigned flags, unsigned swab) { @@ -43,7 +43,7 @@ static inline __u16 _ufs_namlen_(struct ufs_dir_entry * de, unsigned flags, unsi * Here is how the uid is computed: * if the file system is 4.2BSD, get it from oldids. * if it has sun extension and oldids is USEEFT, get it from ui_sun. - * if it is 4.4 or Hurd, get it from ui_44 (which is the same as ui_hurd). + * if it is 4.4 or Hurd, get it from ui_44 (which is the same as from ui_hurd). */ #define ufs_uid(inode) _ufs_uid_(inode,flags,swab) static inline __u32 _ufs_uid_(struct ufs_inode * inode, unsigned flags, unsigned swab) { @@ -72,13 +72,13 @@ static inline __u32 _ufs_gid_(struct ufs_inode * inode, unsigned flags, unsigned } /* - * marcros used for retyping + * macros used to avoid needless retyping */ #define UCPI_UBH ((struct ufs_buffer_head *)ucpi) #define USPI_UBH ((struct ufs_buffer_head *)uspi) /* - * This functions manipulate with ufs_buffers + * These functions manipulate ufs buffers */ #define ubh_bread(dev,fragment,size) _ubh_bread_(uspi,dev,fragment,size) extern struct ufs_buffer_head * _ubh_bread_(struct ufs_sb_private_info *, kdev_t, unsigned, unsigned); @@ -106,11 +106,11 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head #define ubh_get_usb_second(ubh) \ ((struct ufs_super_block_second *)(ubh)-> \ - bh[SECTOR_SIZE >> uspi->s_fshift]->b_data + (SECTOR_SIZE & ~uspi->s_fmask)) + bh[UFS_SECTOR_SIZE >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE & ~uspi->s_fmask)) #define ubh_get_usb_third(ubh) \ ((struct ufs_super_block_third *)((ubh)-> \ - bh[SECTOR_SIZE*2 >> uspi->s_fshift]->b_data + (SECTOR_SIZE*2 & ~uspi->s_fmask))) + bh[UFS_SECTOR_SIZE*2 >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE*2 & ~uspi->s_fmask))) #define ubh_get_ucg(ubh) \ ((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data)) @@ -160,7 +160,7 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head SWAB32((usb)->fs_cstotal.cs_nffree) - (uspi->s_dsize * (percentreserved) / 100)) /* - * Macros for access to cylinder group array structures + * Macros to access cylinder group array structures */ #define ubh_cg_blktot(ucpi,cylno) \ (*((__u32*)ubh_get_addr(UCPI_UBH, (ucpi)->c_btotoff + ((cylno) << 2)))) @@ -170,12 +170,12 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head (ucpi)->c_boff + (((cylno) * uspi->s_nrpos + (rpos)) << 1 )))) /* - * Bitmap operation - * This functions work like classical bitmap operations. The diference - * is that we havn't the whole bitmap in one continuous part of memory, - * but in a few buffers. - * The parameter of each function is super_block, ufs_buffer_head and - * position of the begining of the bitmap. + * Bitmap operations + * These functions work like classical bitmap operations. + * The difference is that we don't have the whole bitmap + * in one contiguous chunk of memory, but in several buffers. + * The parameters of each function are super_block, ufs_buffer_head and + * position of the beginning of the bitmap. */ #define ubh_setbit(ubh,begin,bit) \ (*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) |= (1 << ((bit) & 7))) @@ -188,8 +188,11 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head #define ubh_isclr(ubh,begin,bit) (!ubh_isset(ubh,begin,bit)) -#define ubh_find_first_zero_bit(ubh,begin,size) _ubh_find_next_zero_bit_(uspi,ubh,begin,size,0) -#define ubh_find_next_zero_bit(ubh,begin,size,offset) _ubh_find_next_zero_bit_(uspi,ubh,begin,size,offset) +#define ubh_find_first_zero_bit(ubh,begin,size) \ + _ubh_find_next_zero_bit_(uspi,ubh,begin,size,0) +#define ubh_find_next_zero_bit(ubh,begin,size,offset) \ + _ubh_find_next_zero_bit_(uspi,ubh,begin,size,offset) + static inline unsigned _ubh_find_next_zero_bit_( struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned size, unsigned offset) @@ -213,14 +216,17 @@ static inline unsigned _ubh_find_next_zero_bit_( return (base << (uspi->s_fshift + 3)) + offset - begin; } -#define ubh_isblockclear(ubh,begin,block) (!_ubh_isblockset_(uspi,ubh,begin,block)) -#define ubh_isblockset(ubh,begin,block) _ubh_isblockset_(uspi,ubh,begin,block) +#define ubh_isblockclear(ubh,begin,block) \ + (!_ubh_isblockset_(uspi,ubh,begin,block)) +#define ubh_isblockset(ubh,begin,block) \ + _ubh_isblockset_(uspi,ubh,begin,block) + static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned block) { switch (uspi->s_fpb) { case 8: - return (*ubh_get_addr (ubh, begin + block) == 0xff); + return (*ubh_get_addr (ubh, begin + block) == 0xff); case 4: return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2))); case 2: @@ -237,8 +243,8 @@ static inline void _ubh_clrblock_(struct ufs_sb_private_info * uspi, { switch (uspi->s_fpb) { case 8: - *ubh_get_addr (ubh, begin + block) = 0x00; - return; + *ubh_get_addr (ubh, begin + block) = 0x00; + return; case 4: *ubh_get_addr (ubh, begin + (block >> 1)) &= ~(0x0f << ((block & 0x01) << 2)); return; @@ -257,8 +263,8 @@ static inline void _ubh_setblock_(struct ufs_sb_private_info * uspi, { switch (uspi->s_fpb) { case 8: - *ubh_get_addr(ubh, begin + block) = 0xff; - return; + *ubh_get_addr(ubh, begin + block) = 0xff; + return; case 4: *ubh_get_addr(ubh, begin + (block >> 1)) |= (0x0f << ((block & 0x01) << 2)); return; @@ -295,7 +301,8 @@ static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap, ADD_SWAB32(fraglist[fragsize], cnt); } -#define ubh_scanc(ubh,begin,size,table,mask) _ubh_scanc_(uspi,ubh,begin,size,table,mask) +#define ubh_scanc(ubh,begin,size,table,mask) \ + _ubh_scanc_(uspi,ubh,begin,size,table,mask) static inline unsigned _ubh_scanc_(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned size, unsigned char * table, unsigned char mask) { diff --git a/fs/umsdos/Makefile b/fs/umsdos/Makefile index 000fb698fe0d..5e87aa4fc51b 100644 --- a/fs/umsdos/Makefile +++ b/fs/umsdos/Makefile @@ -1,11 +1,11 @@ # -# Makefile for the umsdos unix-like filesystem routines. +# Makefile for the umsdos Unix-like filesystem routines. # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). +# unless it's something special (not a .c file). # -# Note 2! The CFLAGS definitions are now in the main makefile... +# Note 2: the CFLAGS definitions are now in the main makefile. O_TARGET := umsdos.o O_OBJS := dir.o file.o inode.o ioctl.o mangle.o namei.o \ diff --git a/fs/umsdos/README-WIP.txt b/fs/umsdos/README-WIP.txt index 05d3001c563b..f63a1144f5b3 100644 --- a/fs/umsdos/README-WIP.txt +++ b/fs/umsdos/README-WIP.txt @@ -1,45 +1,50 @@ Changes by Matija Nalis (mnalis@jagor.srce.hr) on umsdos dentry fixing (started by Peter T. Waltenberg ) ---------- WARNING --------- WARNING --------- WARNING ----------- -THIS IS TRULY EXPERIMENTAL. IT IS NOT BETA YET. PLEASE EXCUSE MY -YELLING, BUT ANY USE OF THIS MODULES MAY VERY WELL DESTROY YOUR +---------- WARNING --------- WARNING --------- WARNING ----------- +THIS IS TRULY EXPERIMENTAL. IT IS NOT BETA YET. PLEASE EXCUSE MY +YELLING, BUT ANY USE OF THIS MODULE MAY VERY WELL DESTROY YOUR UMSDOS FILESYSTEM, AND MAYBE EVEN OTHER FILESYSTEMS IN USE. YOU'VE BEEN WARNED. ---------- WARNING --------- WARNING --------- WARNING ----------- +---------- WARNING --------- WARNING --------- WARNING ----------- -Current status (980428) - UMSDOS dentry-WIP-Beta 0.82-4: +Current status (980901) - UMSDOS dentry-WIP-Beta 0.82-7: (1) pure MSDOS (no --linux-.--- EMD file): -- readdir - works -- lookup - works -- read file - works ++ readdir - works ++ lookup - works ++ read file - works -- creat file - works -- write file - works -- mkdir - works -- rmdir - QUESTIONABLE. probable problem on non-empty dirs. ++ creat file - works ++ delete file - works ++ write file - works ++ rename file (same dir) - works ++ rename file (dif. dir) - works ++ rename dir (same dir) - works ++ rename dir (dif. dir) - works ++ mkdir - works +- rmdir - QUESTIONABLE. probable problem on non-empty dirs. Notes: possible very minor problems with dentry/inode/... kernel structures (very rare) (2) umsdos (with --linux-.--- EMD file): -- readdir - works. -- lookup - works. -- permissions/owners stuff - works -- long file names - works -- read file - works -- switching MSDOS/UMSDOS - works? -- switching UMSDOS/MSDOS - works? -- pseudo root things - COMPLETELY UNTESTED -- resolve symlink - seems to work fully now! -- dereference symlink - seems to work fully now! -- hard links - seems to work now -- special files (block/char device, fifos, sockets...) - seems to work ok. -- other ioctls - some UNTESTED -- dangling symlink - UNTESTED ! ++ readdir - works ++ lookup - works ++ permissions/owners stuff - works ++ long file names - works ++ read file - works +- switching MSDOS/UMSDOS - works? +- switching UMSDOS/MSDOS - works? +- pseudo root things - COMPLETELY UNTESTED (commented out currently!) ++ resolve symlink - works ++ dereference symlink - works +- hard links - broken again... ++ special files (block/char devices, FIFOs, sockets...) - seems to work. +- other ioctls - some UNTESTED ++ dangling symlink - works - create symlink - seems to work both on short & long names now ! - create hardlink - WARNING: NOT FIXED YET! @@ -57,65 +62,62 @@ Notes: possible very minor problems with dentry/inode/... kernel structures (ver - rmdir - may work, but readdir blocks linux afterwards. to be FIXED! - umssyncing - seems to work, but NEEDS MORE TESTING -- CVF-FAT stuff (compressed DOS filesystem) - there is some support from - Frank Gockel to use it even under - umsdosfs. But I have no way of testing it -- please let me know if there - are problems that are specific to umsdos (eg. it works under msdosfs, but - not under umsdosfs) ++ CVF-FAT stuff (compressed DOS filesystem) - there is some support from Frank + Gockel to use it even under umsdosfs, but I + have no way of testing it -- please let me know if there are problems specific + to umsdos (for instance, it works under msdosfs, but not under umsdosfs). -Notes: moderate dentry/inode kernel structures trashing. Probably some other -kernel structures compromised. Have SysRq support compiled in, and use -Sync/Emergency-remount-RO. And if you don't try mounting read/write - -you should have no big problems... +Notes: there is moderate trashing of dentry/inode kernel structures. Probably +some other kernel structures are compromised. You should have SysRq support +compiled in, and use Sync/Emergency-remount-RO. If you don't try mounting +read/write, you should have no big problems. When most things begin to work, +I'll get to finding/fixing those inode/dentry ?_count leakages. -Notes2: kernel structures trashing seems to be _MUCH_ lower if no -symlinks/hardlink present. (hardlinks seem to be biggest problem) +Note 4: rmdir(2) fails with EBUSY - sdir->i_count > 1 (like 7 ??). It may be +some error with dir->i_count++, or something related to iput(). See if +number changes if we access the directory in different ways. -Notes3: Notes2 is probably somewhat outdated now that hardlink/symlink stuff -is supposed to be fixed enough to work, but I haven't got the time to test -it. +Note 5: there is a problem with unmounting umsdosfs. It seems to stay +registered or something. Remounting the same device on any mount point with a +different fstype (such as msdos or vfat) ignores the new fstype and umsdosfs +kicks back in. Should be fixed in 0.82-6 (at least, with nothing in between)! +Much of inode/dentry corruption is fixed in 0.82-7, especially when mounting +read-only. -Note5: rmdir(2) fails with EBUSY - sdir->i_count > 1 (like 7 ??). It must be -some error with dir->i_count++, or something related to iput() ? See if -number changes if we access the dir in different ways.. - -Note6: there is problem with unmounting umsdosfs, it seems to stay -registered or something. Remounting same device on any mount point with -different fstype (like msdos or vfat) ignores fstype and umsdosfs kicks back -in. - -Note7: also we screwed umount(2)-ing the fs at times (EBUSY), by removing -all those iput/dput's. When rest of code is fixed, we'll put them back at -(hopefully) correct places. +Note 6: also we screwed umount(2)-ing the fs at times (EBUSY), by missing +some of those iput/dput's. When most of the rest of the code is fixed, we'll +put them back at the correct places (hopefully). Also much better in 0.82-7. ------------------------------------------------------------------------------ Some general notes: -There is great amount of kernel log messages. Use SysRq log-level 5 to turn -most of them off, or 4 to turn all but really fatal ones off. Probably good -idea to kill klogd/syslogd so it will only go to console. +There is a great amount of kernel log messages. Use SysRq log-level 5 to turn +most of them off, or 4 to turn all but really fatal ones off. Probably good +idea to kill klogd/syslogd so it will only go to console. You can also +comment out include/linux/umsdos_fs.h definition of UMS_DEBUG to get rid of +most debugging messages. Please don't turn it off without good reason. -It should work enough to test it, even enough to give you few chances to +It should work enough to test it, even enough to give you a few chances to umount/rmmod module, recompile it, and reinsert it again (but probably -screaming about still used inodes on device and stuff). This is first on +screaming about still used inodes on device and stuff). This is first on my list of things to get fixed, as it would greatly improve speed of compile/test/reboot/set_environment/recompile cycle by removing -'reboot/set_environment' component that now occures every few cycles. +'reboot/set_environment' component that now occurs every few cycles. -But I need some help from someone knowing about dentries/inodes use more -than I. If you can help, please contact me... I'm mostly worried about +I need some help from someone who knows more than I about the use of dentries +and inodes. If you can help, please contact me. I'm mostly worried about iget/iput and dget/dput, and deallocating temporary dentries we create. -should we destroy temp dentries ? using d_invalidate ? using d_drop ? just -dput them ? +Should we destroy temp dentries? using d_invalidate? using d_drop? just +dput them? -I'm unfortunatelly somewhat out of time to read linux-kernel, but I do check -for any messages having UMSDOS in subject, and read them. I might miss it in -all that volume, though. I should reply to any direct Email in few days. If -I don't - probably I never got your message. You can try mnalis@open.hr or -mnalis@voyager.hr; however mnalis@jagor.srce.hr is preferable one. +I'm unfortunately somewhat out of time to read linux-kernel, but I do check +for messages having "UMSDOS" in the subject, and read them. I might miss +some in all that volume, though. I should reply to any direct e-mail in few +days. If I don't, probably I never got your message. You can try +mnalis@voyager.hr; however mnalis@jagor.srce.hr is preferable. ------------------------------------------------------------------------------ @@ -126,34 +128,33 @@ some of my notes for myself /mn/: - iput: device 00:00 inode 318 still has aliases! problem. Check in iput() for device 0,0. Probably null pointer passed around when it shouldn't be ? - dput/iput problem... -- what about .dotfiles ? working ? multiple dots ? etc.... -- fix stuff like dir->i_count++ to atomic_inc(&dir->i_count) and simular? +- What about .dotfiles? Are they working? How about multiple dots? +- fix stuff like dir->i_count++ to atomic_inc(&dir->i_count) and similar? + +- should check what happen when multiple UMSDOSFS are mounted - chase down all "FIXME", "DELME", "CNT", check_dentry, check_inode, kill_dentry and fix it properly. -- umsdos_create_any - calling msdos_create will create dentry for shor name. Hmmmm..? -- kill_dentry - put it where is needed. Also dput() at needed places. - -- when should dput()/iput() be used ?!! +- umsdos_create_any - calling msdos_create will create dentry for short name. Hmmmm..? - what is dir->i_count++ ? locking directory ? should this be lock_parent or something ? -- i_binary=2 is for CVF (compressed filesystem). ++ i_binary=2 is for CVF (compressed filesystem). - SECURITY WARNING: short dentries should be invalidated, or they could be accessed instead of proper long names. -- I've put many check_dentry() calls to trace down problems. those should be - removed in final version. +- I've put many check_dentry_path(), check_inode() calls to trace down + problems. those should be removed in final version. -- iput()s with "FIXME?" comment are uncomented and probably ok. Those with - "FIXME??" should be tested but prolly work. Commented iput()s with +- iput()s with a "FIXME?" comment are uncommented and probably OK. Those with + "FIXME??" should be tested but probably work. Commented iput()s with any "FIXME" comments should probably be uncommented and tested. At some places we may need dput() instead of iput(), but that should be checked. -- as for iput() : (my only pointer so far. anyone else ?) ++ as for iput(): (my only pointer so far. anyone else?) >development I only know about iput. All functions that get an inode as >argument and don't return it have to call iput on it before exit, i.e. when diff --git a/fs/umsdos/check.c b/fs/umsdos/check.c index 717a0df3941b..434ea75c8273 100644 --- a/fs/umsdos/check.c +++ b/fs/umsdos/check.c @@ -1,7 +1,5 @@ /* * linux/fs/umsdos/check.c - * - * */ #include @@ -51,6 +49,6 @@ void check_page_tables (void) } } if (err) - printk ("\nErreur MM %d\n", err); + printk ("\nError MM %d\n", err); } } diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c index 5cc8f57277fd..84380a93cc80 100644 --- a/fs/umsdos/dir.c +++ b/fs/umsdos/dir.c @@ -19,9 +19,6 @@ #include -#define PRINTK(x) -#define Printk(x) printk x - #define UMSDOS_SPECIAL_DIRFPOS 3 extern struct inode *pseudo_root; @@ -30,55 +27,56 @@ extern struct inode *pseudo_root; * I've retained this to facilitate the lookup of some of the hard-wired files/directories UMSDOS * uses. It's easier to do once than hack all the other instances. Probably safer as well */ + +/* + * d_dir is directory to search for file, name&len define the file. + * compat_umsdos_real_lookup returns dentry pointing to wanted file, + * or NULL if not found. Calling code is respondible to call fin_dentry (result) + */ -/* FIXME: it returns inode with i_count of 0. this should be redesigned to return dentry instead, - and correct dentry (with correct d_parent) */ - -int compat_umsdos_real_lookup (struct inode *dir, const char *name, int len, struct inode **inode) +struct dentry *compat_umsdos_real_lookup (struct dentry *d_dir, const char *name, int len) { int rv; struct dentry *dentry; - unsigned long ino; - Printk ((KERN_DEBUG "compat_umsdos_real_lookup !!CNTx!!: start\n")); - check_inode (dir); - dentry = creat_dentry (name, len, NULL, NULL); - rv = umsdos_real_lookup (dir, dentry); - iput (dir); /* should be here, because umsdos_real_lookup does inc_count(dir) */ + PRINTK ((KERN_DEBUG "compat_umsdos_real_lookup !!CNTx!!: start\n")); + + check_dentry_path (d_dir, "compat_umsdos_real_lookup B4 dir"); + dentry = creat_dentry (name, len, NULL, d_dir); + +/* check_dentry_path (dentry, "compat_umsdos_real_lookup B4");*/ + + rv = umsdos_real_lookup (d_dir->d_inode, dentry); + check_dentry_path (dentry, "compat_umsdos_real_lookup END"); if (rv) { - Printk ((KERN_WARNING "compat_umsdos_real_lookup failed with %d\n", rv)); - return rv; + printk (KERN_WARNING "compat_umsdos_real_lookup failed with %d\n", rv); + return NULL; } - if (!inode) { - Printk ((KERN_ERR "inode should be set here. Arrgh! segfaulting...\n")); - } - - ino = dentry->d_inode->i_ino; - *inode = dentry->d_inode; - dput (dentry); /* we are done with it: FIXME: does this work /mn/ ? */ - - check_dentry (dentry); - check_inode (dir); + PRINTK ((KERN_DEBUG "compat_umsdos_real_lookup !!CNTx!!: end\n")); - Printk ((KERN_DEBUG "compat_umsdos_real_lookup !!CNTx!!: end\n")); + if (dentry->d_inode) return dentry; /* all OK */ - return rv; + /* otherwise, we have a negative dentry. return NULL */ + Printk ((KERN_DEBUG "compat_umsdos_real_lookup: negative dentry - file not found\n")); + fin_dentry (dentry); + return NULL; } int compat_msdos_create (struct inode *dir, const char *name, int len, int mode, struct inode **inode) { int rv; - struct dentry *dentry; + struct dentry *dentry, *d_dir; check_inode (dir); - dentry = creat_dentry (name, len, NULL, NULL); - check_dentry (dentry); + d_dir = geti_dentry (dir); + dentry = creat_dentry (name, len, NULL, d_dir); + check_dentry_path (dentry, "compat_msdos_create START"); rv = msdos_create (dir, dentry, mode); - check_dentry (dentry); + check_dentry_path (dentry, "compat_msdos_create END"); if (inode != NULL) *inode = dentry->d_inode; @@ -91,7 +89,7 @@ int compat_msdos_create (struct inode *dir, const char *name, int len, int mode, * So grep * doesn't complain in the presence of directories. */ -int UMSDOS_dir_read (struct file *filp, char *buff, size_t size, loff_t *count) +int dummy_dir_read (struct file *filp, char *buff, size_t size, loff_t *count) { return -EISDIR; } @@ -120,7 +118,7 @@ static int umsdos_dir_once ( void *buf, struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf; if (d->count == 0) { - PRINTK ((KERN_DEBUG "dir_once :%.*s: offset %Ld\n", dentry->d_len, dentry->d_name, offset)); + PRINTK ((KERN_DEBUG "dir_once :%.*s: offset %Ld\n", len, name, offset)); ret = d->filldir (d->dirbuf, name, len, offset, ino); d->stop = ret < 0; d->count = 1; @@ -139,8 +137,7 @@ static int umsdos_dir_once ( void *buf, * inode. See umsdos_locate_ancestor() below. */ -static int umsdos_readdir_x ( - struct inode *dir, /* Point to a description of the super block */ +static int umsdos_readdir_x ( struct inode *dir, /* Point to a description of the super block */ struct file *filp, /* Point to a directory which is read */ void *dirbuf, /* Will hold count directory entry */ /* but filled by the filldir function */ @@ -150,6 +147,7 @@ static int umsdos_readdir_x ( filldir_t filldir) { int ret = 0; + struct dentry *old_dent; umsdos_startlookup (dir); if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS @@ -179,7 +177,7 @@ static int umsdos_readdir_x ( /* #Specification: readdir / . and .. - * The msdos filesystem manage the . and .. entry properly + * The msdos filesystem manages the . and .. entry properly * so the EMD file won't hold any info about it. * * In readdir, we assume that for the root directory @@ -232,23 +230,22 @@ static int umsdos_readdir_x ( if (u_entry != NULL) u_entry->flags = 0; } else { - struct inode *emd_dir; - Printk (("umsdos_readdir_x: normal file /mn/?\n")); - emd_dir = umsdos_emd_dir_lookup (dir, 0); - if (emd_dir != NULL) { + old_dent = filp->f_dentry; /* save dentry of directory */ + + if (fix_emd_filp (filp) == 0) { off_t start_fpos = filp->f_pos; - Printk (("umsdos_readdir_x: emd_dir->i_ino=%ld\n", emd_dir->i_ino)); + Printk (("umsdos_readdir_x: emd_dir->i_ino=%ld\n", filp->f_dentry->d_inode->i_ino)); if (filp->f_pos <= UMSDOS_SPECIAL_DIRFPOS + 1) filp->f_pos = 0; - Printk (("f_pos %Ld i_size %ld\n", filp->f_pos, emd_dir->i_size)); + Printk (("f_pos %Ld i_size %ld\n", filp->f_pos, filp->f_dentry->d_inode->i_size)); ret = 0; - while (filp->f_pos < emd_dir->i_size) { + while (filp->f_pos < filp->f_dentry->d_inode->i_size) { struct umsdos_dirent entry; off_t cur_f_pos = filp->f_pos; - if (umsdos_emd_dir_readentry (emd_dir, filp, &entry) != 0) { + if (umsdos_emd_dir_readentry (filp, &entry) != 0) { ret = -EIO; break; } else if (entry.name_len != 0) { @@ -271,55 +268,50 @@ static int umsdos_readdir_x ( * So the easy way is used! */ struct umsdos_info info; - struct inode *inode; - - int lret; + struct dentry *d_dir, *dret; umsdos_parse (entry.name, entry.name_len, &info); info.f_pos = cur_f_pos; umsdos_manglename (&info); - lret = compat_umsdos_real_lookup (dir, info.fake.fname, info.fake.len, &inode); - Printk (("Cherche inode de %s lret %d flags %d\n", info.fake.fname, lret, entry.flags)); - if (lret == 0 - && (entry.flags & UMSDOS_HLINK) - && follow_hlink) { - struct inode *rinode; - - Printk ((KERN_DEBUG "umsdos_hlink2inode now\n")); - lret = umsdos_hlink2inode (inode, &rinode); - inode = rinode; + d_dir = geti_dentry (dir); + dret = compat_umsdos_real_lookup (d_dir, info.fake.fname, info.fake.len); + + Printk (("Looking for inode of %s dret %p flags %d\n", info.fake.fname, dret, entry.flags)); + if (dret && !IS_ERR(dret) + && (entry.flags & UMSDOS_HLINK) + && follow_hlink) { + dret = umsdos_solve_hlink (dret); } - if (lret == 0) { - /* #Specification: pseudo root / reading real root + + if (dret && !IS_ERR(dret)) { + /* #Specification: pseudo root / reading real root * The pseudo root (/linux) is logically - * erased from the real root. This mean that + * erased from the real root. This means that * ls /DOS, won't show "linux". This avoids - * infinite recursion /DOS/linux/DOS/linux while + * infinite recursion (/DOS/linux/DOS/linux/...) while * walking the file system. */ - if (inode != pseudo_root - && (internal_read - || !(entry.flags & UMSDOS_HIDDEN))) { + if (dret->d_inode != pseudo_root + && (internal_read || !(entry.flags & UMSDOS_HIDDEN))) { Printk ((KERN_DEBUG "filldir now\n")); - if (filldir (dirbuf, entry.name, entry.name_len, cur_f_pos, inode->i_ino) < 0) { + if (filldir (dirbuf, entry.name, entry.name_len, cur_f_pos, dret->d_inode->i_ino) < 0) { filp->f_pos = cur_f_pos; } - Printk (("Trouve ino %ld ", inode->i_ino)); + Printk (("Found ino %ld ", dret->d_inode->i_ino)); if (u_entry != NULL) *u_entry = entry; - iput (inode); /* FIXME? */ + fin_dentry (dret); break; } - Printk ((KERN_DEBUG " dir.c:Putting inode %lu with i_count=%d\n", inode->i_ino, inode->i_count)); - iput (inode); /* FIXME? */ + fin_dentry (dret); } else { - /* #Specification: umsdos / readdir / not in MSDOS + /* #Specification: umsdos / readdir / not in MSDOS * During a readdir operation, if the file is not - * in the MSDOS directory anymore, the entry is + * in the MS-DOS directory any more, the entry is * removed from the EMD file silently. */ Printk (("'Silently' removing EMD for file\n")); - ret = umsdos_writeentry (dir, emd_dir, &info, 1); + ret = umsdos_writeentry (dir, filp->f_dentry->d_inode, &info, 1); if (ret != 0) { break; } @@ -334,25 +326,26 @@ static int umsdos_readdir_x ( */ if (filp->f_pos == 0) filp->f_pos = start_fpos; - Printk ((KERN_DEBUG " dir.c:Putting emd_dir %lu with i_count=%d\n", emd_dir->i_ino, emd_dir->i_count)); - iput (emd_dir); /* FIXME? */ + Printk ((KERN_DEBUG "dir.c: putting emd_dir %lu with i_count=%d\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_count)); + + fin_dentry (filp->f_dentry); + filp->f_dentry = old_dent; /* restore dentry of directory */ } } umsdos_endlookup (dir); - Printk (("read dir %p pos %Ld ret %d\n", dir, filp->f_pos, ret)); + Printk ((KERN_DEBUG "read dir %p pos %Ld ret %d\n", dir, filp->f_pos, ret)); return ret; } /* - * Read count directory entries from directory filp + * Read count directory entries from directory filp. * Return a negative value from linux/errno.h. - * Return 0 or positive if successful + * Return 0 or positive if successful. */ -static int UMSDOS_readdir ( - struct file *filp, /* Point to a directory which is read */ +static int UMSDOS_readdir ( struct file *filp, /* Point to a directory which is read. */ void *dirbuf, /* Will hold directory entries */ filldir_t filldir) { @@ -370,46 +363,46 @@ static int UMSDOS_readdir ( struct umsdos_dirent entry; bufk.count = 0; - Printk (("UMSDOS_readdir: calling _x (%p,%p,%p,%d,%p,%d,%p)\n", dir, filp, &bufk, 0, &entry, 1, umsdos_dir_once)); + PRINTK (("UMSDOS_readdir: calling _x (%p,%p,%p,%d,%p,%d,%p)\n", dir, filp, &bufk, 0, &entry, 1, umsdos_dir_once)); ret = umsdos_readdir_x (dir, filp, &bufk, 0, &entry, 1, umsdos_dir_once); if (bufk.count == 0) break; count += bufk.count; } + /* FIXME: do we first need to deallocate old dentry ? look/check. see also all other instances of fix_emd_filp */ Printk (("UMSDOS_readdir out %d count %d pos %Ld\n", ret, count, filp->f_pos)); return count ? : ret; } /* - * Complete the inode content with info from the EMD file + * Complete the inode content with info from the EMD file. */ -void umsdos_lookup_patch ( - struct inode *dir, +void umsdos_lookup_patch ( struct inode *dir, struct inode *inode, struct umsdos_dirent *entry, off_t emd_pos) { /* - * This function modify the state of a dir inode. It decides - * if the dir is a umsdos dir or a dos dir. This is done + * This function modifies the state of a dir inode. It decides + * whether the dir is a UMSDOS or DOS directory. This is done * deeper in umsdos_patch_inode() called at the end of this function. * - * umsdos_patch_inode() may block because it is doing disk access. + * Because it is does disk access, umsdos_patch_inode() may block. * At the same time, another process may get here to initialise - * the same dir inode. There is 3 cases. + * the same directory inode. There are three cases. * - * 1-The inode is already initialised. We do nothing. - * 2-The inode is not initialised. We lock access and do it. - * 3-Like 2 but another process has lock the inode, so we try - * to lock it and right after check if initialisation is still - * needed. + * 1) The inode is already initialised. We do nothing. + * 2) The inode is not initialised. We lock access and do it. + * 3) Like 2 but another process has locked the inode, so we try + * to lock it and check right afterward check whether + * initialisation is still needed. * * - * Thanks to the mem option of the kernel command line, it was + * Thanks to the "mem" option of the kernel command line, it was * possible to consistently reproduce this problem by limiting - * my mem to 4 meg and running X. + * my memory to 4 MB and running X. */ /* * Do this only if the inode is freshly read, because we will lose @@ -437,10 +430,10 @@ void umsdos_lookup_patch ( * mtime will be meaningful. We do this only for regular * file. * - * We don't rely on MSDOS for mtime for directory because - * the MSDOS directory date is creation time (strange - * MSDOS behavior) which fit nowhere in the three UNIX - * time stamp. + * We don't rely on MS-DOS for mtime for directories + * because the MS-DOS date on a directory is its + * creation time (strange MSDOS behavior) which + * corresponds to none of the three Unix time stamps. */ if (S_ISREG (entry->mode)) entry->mtime = inode->i_mtime; @@ -452,35 +445,35 @@ void umsdos_lookup_patch ( inode->i_uid = entry->uid; inode->i_gid = entry->gid; /* #Specification: umsdos / conversion mode - * The msdos fs can do some inline conversion - * of the data of a file. It can translate - * silently from MsDOS text file format to Unix - * one (crlf -> lf) while reading, and the reverse + * The msdos filesystem can do some inline conversion + * of the data of a file. It can translate silently + * from the MS-DOS text file format to the Unix one + * (CRLF -> LF) while reading, and the reverse * while writing. This is activated using the mount * option conv=.... * - * This is not useful for Linux file in promoted - * directory. It can even be harmful. For this + * This is not useful for Linux files in a promoted + * directory. It can even be harmful. For this * reason, the binary (no conversion) mode is * always activated. */ /* #Specification: umsdos / conversion mode / todo * A flag could be added to file and directories * forcing an automatic conversion mode (as - * done with the msdos fs). + * done with the msdos filesystem). * * This flag could be setup on a directory basis - * (instead of file) and all file in it would - * logically inherited. If the conversion mode + * (instead of file) and all files in it would + * logically inherit it. If the conversion mode * is active (conv=) then the i_binary flag would * be left untouched in those directories. * - * It was proposed that the sticky bit was used - * to set this. The problem is that new file would - * be written incorrectly. The other problem is that + * It was proposed that the sticky bit be used to set + * this. A problem with that is that new files would + * be written incorrectly. The other problem is that * the sticky bit has a meaning for directories. So * another bit should be used (there is some space - * in the EMD file for it) and a special utilities + * in the EMD file for it) and a special utility * would be used to assign the flag to a directory). * I don't think it is useful to assign this flag * on a single file. @@ -488,18 +481,18 @@ void umsdos_lookup_patch ( MSDOS_I (inode)->i_binary = 1; /* #Specification: umsdos / i_nlink - * The nlink field of an inode is maintain by the MSDOS file system - * for directory and by UMSDOS for other file. The logic is that + * The nlink field of an inode is maintained by the MSDOS file system + * for directory and by UMSDOS for other files. The logic is that * MSDOS is already figuring out what to do for directories and - * does nothing for other files. For MSDOS, there are no hard link - * so all file carry nlink==1. UMSDOS use some info in the + * does nothing for other files. For MSDOS, there are no hard links + * so all file carry nlink==1. UMSDOS use some info in the * EMD file to plug the correct value. */ if (!S_ISDIR (entry->mode)) { if (entry->nlink > 0) { inode->i_nlink = entry->nlink; } else { - printk (KERN_ERR "UMSDOS: lookup_patch entry->nlink < 1 ???\n"); + printk (KERN_ERR "UMSDOS: lookup_patch entry->nlink < 1 ???\n"); } } umsdos_patch_inode (inode, dir, emd_pos); @@ -507,7 +500,7 @@ void umsdos_lookup_patch ( if (S_ISDIR (inode->i_mode)) umsdos_unlockcreate (inode); if (inode->u.umsdos_i.i_emd_owner == 0) - printk (KERN_WARNING "emd_owner still 0 ???\n"); + printk (KERN_WARNING "UMSDOS: emd_owner still 0?\n"); } } @@ -523,8 +516,7 @@ struct UMSDOS_DIRENT_K { * Just to record the offset of one entry. */ -static int umsdos_filldir_k ( - void *buf, +static int umsdos_filldir_k ( void *buf, const char *name, int len, off_t offset, @@ -543,8 +535,7 @@ struct UMSDOS_DIR_SEARCH { ino_t search_ino; }; -static int umsdos_dir_search ( - void *buf, +static int umsdos_dir_search ( void *buf, const char *name, int len, off_t offset, @@ -569,15 +560,14 @@ static int umsdos_dir_search ( * Locate entry of an inode in a directory. * Return 0 or a negative error code. * - * Normally, this function must succeed. It means a strange corruption + * Normally, this function must succeed. It means a strange corruption * in the file system if not. */ -int umsdos_inode2entry ( - struct inode *dir, +int umsdos_inode2entry ( struct inode *dir, struct inode *inode, - struct umsdos_dirent *entry) -{ /* Will hold the entry */ + struct umsdos_dirent *entry) /* Will hold the entry */ +{ int ret = -ENOENT; if (pseudo_root && inode == pseudo_root) { @@ -591,14 +581,14 @@ int umsdos_inode2entry ( } else { struct inode *emddir = umsdos_emd_dir_lookup (dir, 0); - iput (emddir); /* FIXME? */ + /* iput (emddir); / * FIXME? */ if (emddir == NULL) { - /* This is a DOS directory */ + /* This is a DOS directory. */ struct UMSDOS_DIR_SEARCH bufk; struct file filp; struct dentry *i2e; - i2e = creat_dentry ("i2e.nul", 7, dir, NULL); + i2e = creat_dentry ("@i2e.nul@", 9, dir, NULL); fill_new_filp (&filp, i2e); @@ -619,7 +609,7 @@ int umsdos_inode2entry ( struct file filp; struct dentry *i2e; - i2e = creat_dentry ("i2e.nn", 6, dir, NULL); + i2e = creat_dentry ("@i2e.nn@", 8, dir, NULL); fill_new_filp (&filp, i2e); filp.f_reada = 1; @@ -627,14 +617,15 @@ int umsdos_inode2entry ( Printk ((KERN_ERR "umsdos_inode2entry skip...: WARNING: Known filp problem. segfaulting :) fixed ?/mn/\n")); while (1) { struct UMSDOS_DIRENT_K bufk; + struct dentry *old_dent; - if (umsdos_readdir_x (dir, &filp, &bufk - ,1, entry, 0, umsdos_filldir_k) < 0) { - printk ("UMSDOS: can't locate inode %ld in EMD file???\n" - ,inode->i_ino); + old_dent = filp.f_dentry; + if (umsdos_readdir_x (dir, &filp, &bufk, 1, entry, 0, umsdos_filldir_k) < 0) { + printk ("UMSDOS: can't locate inode %ld in EMD file???\n", inode->i_ino); break; } else if (bufk.ino == inode->i_ino) { ret = 0; + filp.f_dentry = old_dent; umsdos_lookup_patch (dir, inode, entry, bufk.f_pos); break; } @@ -650,21 +641,24 @@ int umsdos_inode2entry ( * Return 0 or a negative error code. */ -static int umsdos_locate_ancestor ( - struct inode *dir, +static int umsdos_locate_ancestor ( struct inode *dir, struct inode **result, struct umsdos_dirent *entry) { - int ret; + int ret=-99; + struct dentry *dret, *d_dir = creat_dentry ("@d_dir2@", 7, dir, NULL); umsdos_patch_inode (dir, NULL, 0); /* FIXME */ - ret = compat_umsdos_real_lookup (dir, "..", 2, result); - Printk (("result %d %p ", ret, *result)); - if (ret == 0) { - struct inode *adir = *result; + dret = compat_umsdos_real_lookup (d_dir, "..", 2); + Printk (("result %p %p ", dret, *result)); + if (dret) { + struct inode *adir; + *result = dret->d_inode; + adir = *result; ret = umsdos_inode2entry (adir, dir, entry); + fin_dentry (dret); } Printk (("\n")); return ret; @@ -678,8 +672,7 @@ static int umsdos_locate_ancestor ( * It uses the same strategy as the standard getcwd(). */ -int umsdos_locate_path ( - struct inode *inode, +int umsdos_locate_path ( struct inode *inode, char *path) { int ret = 0; @@ -733,7 +726,7 @@ int umsdos_locate_path ( kfree (bpath); } Printk (("\n")); - iput (dir); /* FIXME?? */ + /* iput (dir); / * FIXME?? */ return ret; } @@ -742,8 +735,7 @@ int umsdos_locate_path ( * Return != 0 if an entry is the pseudo DOS entry in the pseudo root. */ -int umsdos_is_pseudodos ( - struct inode *dir, +int umsdos_is_pseudodos ( struct inode *dir, struct dentry *dentry) { /* #Specification: pseudo root / DOS hard coded @@ -763,28 +755,33 @@ int umsdos_is_pseudodos ( /* - * Check if a file exist in the current directory. - * Return 0 if ok, negative error code if not (ex: -ENOENT). + * Check if a file exists in the current directory. + * Return 0 if OK, negative error code if not (ex: -ENOENT). + * + * fills dentry->d_inode with found inode, and increments its count. + * if not found, return -ENOENT. */ -int umsdos_lookup_x ( - struct inode *dir, +int umsdos_lookup_x ( struct inode *dir, struct dentry *dentry, - int nopseudo) -{ /* Don't care about pseudo root mode */ + int nopseudo) /* Don't care about pseudo root mode */ +{ int ret = -ENOENT; struct inode *root_inode; int len = dentry->d_name.len; const char *name = dentry->d_name.name; + - PRINTK ((KERN_DEBUG "umsdos_lookup_x: /mn/ name=%.*s, dir=%lu (i_count=%d), d_parent=%p\n", (int) dentry->d_name.len, dentry->d_name.name, dir->i_ino, dir->i_count, dentry->d_parent)); /* FIXME /mn/ debug only */ +#if UMS_DEBUG + Printk ((KERN_DEBUG "umsdos_lookup_x: /mn/ name=%.*s, dir=%lu (i_count=%d), d_parent=%p\n", (int) dentry->d_name.len, dentry->d_name.name, dir->i_ino, dir->i_count, dentry->d_parent)); /* FIXME /mn/ debug only */ if (dentry->d_parent) - PRINTK ((KERN_DEBUG " d_parent is %.*s\n", (int) dentry->d_parent->d_name.len, dentry->d_parent->d_name.name)); /* FIXME : delme /mn/ */ + Printk ((KERN_DEBUG " d_parent is %.*s\n", (int) dentry->d_parent->d_name.len, dentry->d_parent->d_name.name)); /* FIXME : delme /mn/ */ +#endif root_inode = iget (dir->i_sb, UMSDOS_ROOT_INO); - Printk ((KERN_ERR "umsdos_lookup_x (CNT!): entering root_count=%d, dir %lu _count=%d\n", root_inode->i_count, dir->i_ino, dir->i_count)); /* FIXME: DEBUG, DELME */ + Printk ((KERN_ERR "umsdos_lookup_x (CNT!): entering root_count+1=%d, dir %lu _count=%d\n", root_inode->i_count, dir->i_ino, dir->i_count)); /* FIXME: DEBUG, DELME */ - d_instantiate (dentry, NULL); + dentry->d_inode = NULL; umsdos_startlookup (dir); if (len == 1 && name[0] == '.') { d_add (dentry, dir); @@ -802,26 +799,32 @@ int umsdos_lookup_x ( inc_count (pseudo_root); } else { /* #Specification: locating .. / strategy - * We use the msdos filesystem to locate the parent directory. - * But it is more complicated than that. + * We use the msdos filesystem to locate the parent directory, + * but it is more complicated than that: * - * We have to step back even further to + * we have to step back even further to * get the parent of the parent, so we can get the EMD - * of the parent of the parent. Using the EMD file, we can - * locate all the info on the parent, such a permissions - * and owner. + * of the parent of the parent. Using the EMD file, we + * can locate all the info on the parent, such as + * permissions and ownership. */ + struct dentry *dret, *d_dir = creat_dentry ("@d_dir3@", 5, dir, NULL); - ret = compat_umsdos_real_lookup (dir, "..", 2, &dentry->d_inode); - Printk (("ancestor ret %d dir %p *result %p ", ret, dir, dentry->d_inode)); - if (ret == 0 + + dret = compat_umsdos_real_lookup (d_dir, "..", 2); + Printk (("ancestor ret %p dir %p *result %p ", dret, dir, dentry->d_inode)); + if (dret && dentry->d_inode != root_inode && dentry->d_inode != pseudo_root) { struct inode *aadir; struct umsdos_dirent entry; + + Printk ((KERN_ERR "WARNING: umsdos_lookup_x: this won't work!\n")); + + dentry->d_inode = dret->d_inode; /* FIXME! this should be rewritten ! it won't work this way! */ ret = umsdos_locate_ancestor (dentry->d_inode, &aadir, &entry); - iput (aadir); /* FIXME */ + fin_dentry (dret); } } } else if (umsdos_is_pseudodos (dir, dentry)) { @@ -830,7 +833,7 @@ int umsdos_lookup_x ( * and return the inode of the real root. */ d_add (dentry, root_inode); - inc_count (dentry->d_inode); + inc_count (dentry->d_inode); /* FIXME?! */ ret = 0; } else { struct umsdos_info info; @@ -838,59 +841,61 @@ int umsdos_lookup_x ( ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); if (ret == 0) ret = umsdos_findentry (dir, &info, 0); - Printk (("lookup %.*s pos %lu ret %d len %d ", info.fake.len, info.fake.fname, info.f_pos, ret - ,info.fake.len)); + Printk (("lookup %.*s pos %lu ret %d len %d ", info.fake.len, info.fake.fname, info.f_pos, ret, info.fake.len)); if (ret == 0) { /* #Specification: umsdos / lookup - * A lookup for a file is done in two step. First, we locate - * the file in the EMD file. If not present, we return - * an error code (-ENOENT). If it is there, we repeat the - * operation on the msdos file system. If this fails, it means - * that the file system is not in sync with the emd file. - * We silently remove this entry from the emd file, - * and return ENOENT. + * A lookup for a file is done in two steps. First, we + * locate the file in the EMD file. If not present, we + * return an error code (-ENOENT). If it is there, we + * repeat the operation on the msdos file system. If + * this fails, it means that the file system is not in + * sync with the EMD file. We silently remove this + * entry from the EMD file, and return ENOENT. */ - struct inode *inode; - - ret = compat_umsdos_real_lookup (dir, info.fake.fname, info.fake.len, &inode); + struct dentry *dret, *dir_dentry; + + dir_dentry = geti_dentry (dir); + dret = compat_umsdos_real_lookup (dir_dentry, info.fake.fname, info.fake.len); + - Printk ((KERN_DEBUG "umsdos_lookup_x: compat_umsdos_real_lookup for %.*s returned %d with inode=%p\n", info.fake.len, info.fake.fname, ret, inode)); + PRINTK ((KERN_DEBUG "umsdos_lookup_x: compat_umsdos_real_lookup for %.*s returned %p\n", info.fake.len, info.fake.fname, dret)); - if (inode == NULL) { - printk (KERN_WARNING "UMSDOS: Erase entry %.*s, out of sync with MsDOS\n" - ,info.fake.len, info.fake.fname); + if (dret == NULL) { + printk (KERN_WARNING "UMSDOS: Erase entry %.*s, out of sync with MS-DOS\n", info.fake.len, info.fake.fname); umsdos_delentry (dir, &info, S_ISDIR (info.entry.mode)); } else { - Printk ((KERN_DEBUG "umsdos_lookup_x /mn/ debug: ino=%li\n", inode->i_ino)); - - /* we've found it. now put inode in dentry */ - d_add (dentry, inode); + Printk ((KERN_DEBUG "umsdos_lookup_x /mn/ debug: ino=%li\n", dret->d_inode->i_ino)); - umsdos_lookup_patch (dir, inode, &info.entry, info.f_pos); - Printk (("lookup ino %ld flags %d\n", inode->i_ino, info.entry.flags)); + umsdos_lookup_patch (dir, dret->d_inode, &info.entry, info.f_pos); + Printk (("lookup ino %ld flags %d\n", dret->d_inode->i_ino, info.entry.flags)); if (info.entry.flags & UMSDOS_HLINK) { - Printk ((KERN_DEBUG "umsdos_lookup_x: here goes HLINK\n")); - ret = umsdos_hlink2inode (inode, &dentry->d_inode); + dret = umsdos_solve_hlink (dret); } - if (pseudo_root && dentry->d_inode == pseudo_root && !nopseudo) { + if (pseudo_root && dret->d_inode == pseudo_root && !nopseudo) { /* #Specification: pseudo root / dir lookup * For the same reason as readdir, a lookup in /DOS for * the pseudo root directory (linux) will fail. */ /* - * This has to be allowed for resolving hard link + * This has to be allowed for resolving hard links * which are recorded independently of the pseudo-root * mode. */ Printk ((KERN_ERR "umsdos_lookup_x: warning: untested /mn/ Pseudo_root thingy\n")); - iput (pseudo_root); /* FIXME?? */ - d_instantiate (dentry, NULL); /* FIXME: should be dput(dentry) ? */ + /* iput (pseudo_root); / * FIXME?? */ + d_instantiate (dentry, NULL); /* negative lookup */ ret = -ENOENT; + } else { + /* We've found it OK. Now put inode in dentry. */ + inc_count (dret->d_inode); /* lookup should return incremented i_count */ + d_add (dentry, dret->d_inode); } + fin_dentry (dret); } } } umsdos_endlookup (dir); + iput (root_inode); /* pair to iget() above.WHY is it not needed ?! */ PRINTK ((KERN_DEBUG "umsdos_lookup_x: returning %d : name=%.*s (i_count=%d), dir=%lu (i_count=%d)\n", ret, (int) dentry->d_name.len, dentry->d_name.name, dentry->d_inode->i_count, dir->i_ino, dir->i_count)); Printk ((KERN_ERR "umsdos_lookup_x (CNT!): exiting root_count=%d, dir %lu _count=%d\n", root_inode->i_count, dir->i_ino, dir->i_count)); /* FIXME: DEBUG, DELME */ return ret; @@ -898,90 +903,82 @@ int umsdos_lookup_x ( /* - * Check if a file exist in the current directory. - * Return 0 if ok, negative error code if not (ex: -ENOENT). - * + * Check whether a file exists in the current directory. + * Return 0 if OK, negative error code if not (ex: -ENOENT). * + * called by VFS. should fill dentry->d_inode (via d_add), and + * set (increment) dentry->d_inode->i_count. + * */ -int UMSDOS_lookup ( - struct inode *dir, +int UMSDOS_lookup ( struct inode *dir, struct dentry *dentry) { int ret; - check_dentry (dentry); ret = umsdos_lookup_x (dir, dentry, 0); - check_dentry (dentry); -#if 1 if (ret == -ENOENT) { Printk ((KERN_DEBUG "UMSDOS_lookup: converting -ENOENT to negative dentry !\n")); - d_add (dentry, NULL); /* create negative dentry if not found */ + d_add (dentry, NULL); /* Create negative dentry if not found. */ ret = 0; } -#endif return ret; } - /* - * Locate the inode pointed by a (pseudo) hard link - * Return 0 if ok, a negative error code if not. + * gets dentry which points to pseudo-hardlink + * + * it should try to find file it points to + * if file is found, it should dput() original dentry and return new one (with d_count = i_count = 1) + * Otherwise, it should return with error, with dput()ed original dentry. + * */ -int umsdos_hlink2inode (struct inode *hlink, struct inode **result) +struct dentry *umsdos_solve_hlink (struct dentry *hlink) { - struct inode *root_inode; + struct dentry *base = hlink->d_sb->s_root; /* root is our root for resolving pseudo-hardlink */ + struct dentry *final = NULL; + struct inode *result; int ret = -EIO; - struct dentry *dentry_src, *dentry_dst; + struct dentry *dentry_dst, *d_dir; char *path; -#if 0 /* FIXME: DELME */ - Printk (("FIXME: just test. hlink2inode returning -ENOENT\n /mn/\n")); - return -ENOENT; /* /mn/ FIXME just for test */ -#endif + check_dentry_path (hlink, "HLINK BEGIN hlink"); path = (char *) kmalloc (PATH_MAX, GFP_KERNEL); - root_inode = iget (hlink->i_sb, UMSDOS_ROOT_INO); - *result = NULL; + result = NULL; + if (path == NULL) { - ret = -ENOMEM; - iput (hlink); /* FIXME? */ + final = ERR_PTR (-ENOMEM); } else { struct file filp; - loff_t offs = 0; - - dentry_src = creat_dentry ("hlink-mn", 8, hlink, NULL); - - fill_new_filp (&filp, dentry_src); + fill_new_filp (&filp, hlink); filp.f_flags = O_RDONLY; + filp.f_pos = 0; Printk (("hlink2inode ")); - if (umsdos_file_read_kmem (hlink, &filp, path, hlink->i_size, &offs) == hlink->i_size) { + if (umsdos_file_read_kmem (&filp, path, hlink->d_inode->i_size) == hlink->d_inode->i_size) { struct inode *dir; char *pt = path; - dir = root_inode; - path[hlink->i_size] = '\0'; - iput (hlink); /* FIXME? */ - inc_count (dir); + dir = base->d_inode; /* start at root inode */ + path[hlink->d_inode->i_size] = '\0'; + inc_count (dir); /* since we're going to iput() it in the loop below... */ + while (1) { char *start = pt; int len; - while (*pt != '\0' && *pt != '/') - pt++; + while (*pt != '\0' && *pt != '/') pt++; len = (int) (pt - start); - if (*pt == '/') - *pt++ = '\0'; - /* FIXME. /mn/ fixed ? */ - - dentry_dst = creat_dentry (start, len, NULL, NULL); + if (*pt == '/') *pt++ = '\0'; + d_dir = geti_dentry (dir); + dentry_dst = creat_dentry (start, len, NULL, d_dir); if (dir->u.umsdos_i.i_emd_dir == 0) { /* This is a DOS directory */ @@ -991,31 +988,48 @@ int umsdos_hlink2inode (struct inode *hlink, struct inode **result) Printk (("hlink2inode /mn/: doing umsdos_lookup_x on %.*s\n", (int) dentry_dst->d_name.len, dentry_dst->d_name.name)); ret = umsdos_lookup_x (dir, dentry_dst, 1); } + + iput (dir); /* dir no longer needed */ Printk ((" returned %d\n", ret)); - *result = dentry_dst->d_inode; /* /mn/ ok ? */ + result = dentry_dst->d_inode; + inc_count (result); /* we need inode to survive. We'll iput it in next loop */ + + fin_dentry (dentry_dst); /* no longer needed - this is pair to creat_dentry */ Printk (("h2n lookup :%s: -> %d ", start, ret)); - if (ret == 0 && *pt != '\0') { - dir = *result; - } else { + + if (ret != 0) { + iput (result); /* we have no longer any use for it... */ + final = ERR_PTR (ret); /* path componenet not found ! */ break; + } else { + if (*pt != '\0') { + dir = result; + } else { /* we're finished! */ + final = creat_dentry (hlink->d_name.name, hlink->d_name.len, result, hlink->d_parent); + break; + } } - } + } /* end while */ } else { - Printk (("umsdos_hlink2inode: all those iput's() frighten me /mn/. Whatabout dput() ? FIXME!\n")); - iput (hlink); /* FIXME? */ + Printk (("umsdos_solve_hlink: failed reading pseudolink!\n")); } - Printk (("hlink2inode ret = %d %p -> %p\n", ret, hlink, *result)); + + Printk (("hlink2inode ret = %d %p -> %p\n", ret, hlink, result)); kfree (path); } - return ret; -} + + fin_dentry (hlink); /* original hlink no longer needed */ + check_dentry_path (hlink, "HLINK FIN hlink"); + check_dentry_path (final, "HLINK RET final"); + return final; +} static struct file_operations umsdos_dir_operations = { NULL, /* lseek - default */ - UMSDOS_dir_read, /* read */ + dummy_dir_read, /* read */ NULL, /* write - bad */ UMSDOS_readdir, /* readdir */ NULL, /* poll - default */ diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c index bf52a4d9662e..162706b47786 100644 --- a/fs/umsdos/emd.c +++ b/fs/umsdos/emd.c @@ -20,35 +20,24 @@ #include -#define PRINTK(x) -#define Printk(x) printk x /* * Read a file into kernel space memory * returns how many bytes read (from fat_file_read) */ -ssize_t umsdos_file_read_kmem ( struct inode *emd_dir, - struct file *filp, +ssize_t umsdos_file_read_kmem ( struct file *filp, char *buf, - size_t count, - loff_t *offs) + size_t count) { int ret; - struct dentry *old_dentry; mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); - old_dentry = filp->f_dentry; /* save it */ - filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, NULL); - *offs = filp->f_pos; - - PRINTK ((KERN_DEBUG "umsdos_file_read_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs)); - PRINTK ((KERN_DEBUG " using emd=%ld\n", emd_dir->i_ino)); + PRINTK ((KERN_DEBUG "umsdos_file_read_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d\n", filp, buf, count)); PRINTK ((KERN_DEBUG " inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size)); - PRINTK ((KERN_DEBUG " ofs=%ld\n", (unsigned long) *offs)); PRINTK ((KERN_DEBUG " f_pos=%Lu\n", filp->f_pos)); PRINTK ((KERN_DEBUG " name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name)); PRINTK ((KERN_DEBUG " i_binary(sb)=%d\n", MSDOS_I (filp->f_dentry->d_inode)->i_binary)); @@ -58,25 +47,11 @@ ssize_t umsdos_file_read_kmem ( struct inode *emd_dir, PRINTK ((KERN_DEBUG " f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin)); MSDOS_I (filp->f_dentry->d_inode)->i_binary = 2; - ret = fat_file_read (filp, buf, count, offs); - PRINTK ((KERN_DEBUG "fat_file_read returned with %d!\n", ret)); - - filp->f_pos = *offs; /* we needed *filp only for this? grrrr... /mn/ */ - /* FIXME: I have no idea what f_pos is used for. It seems to be used this way before offs was introduced. - * this probably needs fixing /mn/ */ - d_drop (filp->f_dentry); /* FIXME: hmmmm... we should not dispose of it in this way ? */ - filp->f_dentry = old_dentry; /* restore orig. dentry (it is dentry of file we need info about. Dunno why it gets passed to us - * since we have no use for it, expect to store totally unrelated data of offset of EMD_FILE - * end not directory in it. But what the hell now... fat_file_read requires it also, but prolly expects - * it to be file* of EMD not file we want to read EMD entry about... ugh. complicated to explain :) /mn/ */ - - /* FIXME: we probably need to destroy original filp->f_dentry first ? Do we ? And how ? this way we leave all sorts of dentries, inodes etc. lying around */ - /* Also FIXME: all the same problems in umsdos_file_write_kmem */ + ret = fat_file_read (filp, buf, count, &filp->f_pos); + PRINTK ((KERN_DEBUG "fat_file_read returned with %d!\n", ret)); - PRINTK ((KERN_DEBUG " (ret) using emd=%lu\n", emd_dir->i_ino)); PRINTK ((KERN_DEBUG " (ret) inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size)); - PRINTK ((KERN_DEBUG " (ret) ofs=%Lu\n", *offs)); PRINTK ((KERN_DEBUG " (ret) f_pos=%Lu\n", filp->f_pos)); PRINTK ((KERN_DEBUG " (ret) name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name)); PRINTK ((KERN_DEBUG " (ret) i_binary(sb)=%d\n", MSDOS_I (filp->f_dentry->d_inode)->i_binary)); @@ -89,9 +64,9 @@ ssize_t umsdos_file_read_kmem ( struct inode *emd_dir, { struct umsdos_dirent *mydirent = buf; - PRINTK ((KERN_DEBUG " (DDD) uid=%d\n", mydirent->uid)); - PRINTK ((KERN_DEBUG " (DDD) gid=%d\n", mydirent->gid)); - PRINTK ((KERN_DEBUG " (DDD) name=>%.20s<\n", mydirent->name)); + Printk ((KERN_DEBUG " (DDD) uid=%d\n", mydirent->uid)); + Printk ((KERN_DEBUG " (DDD) gid=%d\n", mydirent->gid)); + Printk ((KERN_DEBUG " (DDD) name=>%.20s<\n", mydirent->name)); } #endif @@ -102,25 +77,23 @@ ssize_t umsdos_file_read_kmem ( struct inode *emd_dir, /* * Write to file from kernel space. - * Does the real job, assumes all structures are initialized ! + * Does the real job, assumes all structures are initialized! */ ssize_t umsdos_file_write_kmem_real (struct file * filp, const char *buf, - size_t count, - loff_t * offs) + size_t count) { ssize_t ret; mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); - PRINTK ((KERN_DEBUG "umsdos_file_write_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs)); + PRINTK ((KERN_DEBUG "umsdos_file_write_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d\n", filp, buf, count)); PRINTK ((KERN_DEBUG " struct dentry=%p\n", filp->f_dentry)); PRINTK ((KERN_DEBUG " struct inode=%p\n", filp->f_dentry->d_inode)); PRINTK ((KERN_DEBUG " inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size)); - PRINTK ((KERN_DEBUG " ofs=%ld\n", (unsigned long) *offs)); PRINTK ((KERN_DEBUG " f_pos=%Lu\n", filp->f_pos)); PRINTK ((KERN_DEBUG " name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name)); PRINTK ((KERN_DEBUG " i_binary(sb)=%d\n", MSDOS_I (filp->f_dentry->d_inode)->i_binary)); @@ -131,13 +104,13 @@ ssize_t umsdos_file_write_kmem_real (struct file * filp, /* note: i_binary=2 is for CVF-FAT. We put it here, instead of * umsdos_file_write_kmem, since it is also wise not to compress symlinks - * (in unlikely event that they are > 512 bytes and can be compressed - * FIXME: should we set it when reading symlink too ? */ + * (in the unlikely event that they are > 512 bytes and can be compressed + * FIXME: should we set it when reading symlinks too? */ MSDOS_I (filp->f_dentry->d_inode)->i_binary = 2; - ret = fat_file_write (filp, buf, count, offs); - PRINTK ((KERN_DEBUG "fat_file_write returned with %ld!\n", ret)); + ret = fat_file_write (filp, buf, count, &filp->f_pos); + Printk ((KERN_DEBUG "fat_file_write returned with %ld!\n", (long int) ret)); set_fs (old_fs); return ret; @@ -145,32 +118,22 @@ ssize_t umsdos_file_write_kmem_real (struct file * filp, /* - * Write to a file from kernel space + * Write to a file from kernel space. */ -ssize_t umsdos_file_write_kmem (struct inode * emd_dir, - struct file * filp, +ssize_t umsdos_file_write_kmem (struct file *filp, const char *buf, - size_t count, - loff_t * offs) + size_t count) { int ret; - struct dentry *old_dentry; - Printk ((KERN_DEBUG " STARTED WRITE_KMEM /mn/\n")); - Printk ((KERN_DEBUG " using emd=%ld\n", emd_dir->i_ino)); - - old_dentry = filp->f_dentry; /* save it */ - filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, NULL); - - *offs = filp->f_pos; /* FIXME, in read_kmem also: offs is not used so why pass it ?!!! /mn/ */ - - ret = umsdos_file_write_kmem_real (filp, buf, count, offs); + ret = umsdos_file_write_kmem_real (filp, buf, count); +#warning Should d_drop be here ? +#if 0 d_drop (filp->f_dentry); - filp->f_pos = *offs; - filp->f_dentry = old_dentry; +#endif return ret; } @@ -182,24 +145,18 @@ ssize_t umsdos_file_write_kmem (struct inode * emd_dir, * Write a block of bytes into one EMD file. * The block of data is NOT in user space. * - * Return 0 if ok, a negative error code if not. + * Return 0 if OK, a negative error code if not. */ -ssize_t umsdos_emd_dir_write ( struct inode * emd_dir, - struct file * filp, +ssize_t umsdos_emd_dir_write ( struct file *filp, char *buf, /* buffer in kernel memory, not in user space */ - size_t count, - loff_t * offs) + size_t count) { int written; - loff_t myofs = 0; #ifdef __BIG_ENDIAN struct umsdos_dirent *d = (struct umsdos_dirent *) buf; -#endif - filp->f_flags = 0; -#ifdef __BIG_ENDIAN d->nlink = cpu_to_le16 (d->nlink); d->uid = cpu_to_le16 (d->uid); d->gid = cpu_to_le16 (d->gid); @@ -210,13 +167,10 @@ ssize_t umsdos_emd_dir_write ( struct inode * emd_dir, d->mode = cpu_to_le16 (d->mode); #endif - if (offs) - myofs = *offs; /* if offs is not NULL, read it */ - Printk (("umsdos_emd_dir_write /mn/: calling write_kmem with %p, %p, %p, %d, %Ld\n", emd_dir, filp, buf, count, myofs)); - written = umsdos_file_write_kmem (emd_dir, filp, buf, count, &myofs); + filp->f_flags = 0; + Printk (("umsdos_emd_dir_write /mn/: calling write_kmem with %p, %p, %d, %Ld\n", filp, buf, count, filp->f_pos)); + written = umsdos_file_write_kmem (filp, buf, count); Printk (("umsdos_emd_dir_write /mn/: write_kmem returned\n")); - if (offs) - *offs = myofs; /* if offs is not NULL, store myofs there */ #ifdef __BIG_ENDIAN d->nlink = le16_to_cpu (d->nlink); @@ -229,29 +183,27 @@ ssize_t umsdos_emd_dir_write ( struct inode * emd_dir, d->mode = le16_to_cpu (d->mode); #endif -#if 1 +#if UMS_DEBUG if (written != count) Printk ((KERN_ERR "umsdos_emd_dir_write: ERROR: written (%d) != count (%d)\n", written, count)); #endif + return written != count ? -EIO : 0; } /* - * Read a block of bytes from one EMD file. + * Read a block of bytes from one EMD file. * The block of data is NOT in user space. - * Return 0 if ok, -EIO if any error. + * Return 0 if OK, -EIO if any error. */ -ssize_t umsdos_emd_dir_read (struct inode * emd_dir, - struct file * filp, +ssize_t umsdos_emd_dir_read (struct file *filp, char *buf, /* buffer in kernel memory, not in user space */ - size_t count, - loff_t * offs) + size_t count) { - loff_t myofs = 0; long int ret = 0; int sizeread; @@ -261,12 +213,10 @@ ssize_t umsdos_emd_dir_read (struct inode * emd_dir, #endif - if (offs) - myofs = *offs; /* if offs is not NULL, read it */ filp->f_flags = 0; - sizeread = umsdos_file_read_kmem (emd_dir, filp, buf, count, &myofs); + sizeread = umsdos_file_read_kmem (filp, buf, count); if (sizeread != count) { - printk ("UMSDOS: problem with EMD file. Can't read pos = %Ld (%d != %d)\n", filp->f_pos, sizeread, count); + printk ("UMSDOS: problem with EMD file: can't read pos = %Ld (%d != %d)\n", filp->f_pos, sizeread, count); ret = -EIO; } #ifdef __BIG_ENDIAN @@ -279,42 +229,88 @@ ssize_t umsdos_emd_dir_read (struct inode * emd_dir, d->rdev = le16_to_cpu (d->rdev); d->mode = le16_to_cpu (d->mode); #endif - if (offs) - *offs = myofs; /* if offs is not NULL, store myofs there */ return ret; } +/* + * this checks weather filp points to directory or file, + * and if directory, it assumes that it has not yet been + * converted to point to EMD_FILE, and fixes it + * + * calling code should save old filp->f_dentry, call fix_emd_filp + * and if it succeeds (return code 0), do fin_dentry (filp->f_dentry) + * when it is over. It should also restore old filp->f_dentry. + * + */ + +int fix_emd_filp (struct file *filp) +{ + struct inode *dir=filp->f_dentry->d_inode; + struct inode *emd_dir; + + /* is current file (which should be EMD or directory) EMD? */ + if (dir->u.umsdos_i.i_emd_owner == 0xffffffff) { + dget (filp->f_dentry); + Printk ((KERN_WARNING "\nfix_emd_filp: EMD already done (should not be !)\n\n")); + return 0; + } + /* it is not, we need to make it so */ + + emd_dir = umsdos_emd_dir_lookup (dir, 0); + if (emd_dir == NULL) { + Printk ((KERN_ERR "\nfix_emd_filp: EMD not found (should never happen)!!!\n\n")); + return -99; + } + + filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, filp->f_dentry); /* filp->f_dentry is dir containing EMD file, so it IS the parent dentry... */ + + return 0; +} + /* - * Locate the EMD file in a directory . + * Locate the EMD file in a directory. * - * Return NULL if error. If ok, dir->u.umsdos_i.emd_inode + * Return NULL if error, dir->u.umsdos_i.emd_inode if OK. + * caller must iput() returned inode when finished with it! */ struct inode *umsdos_emd_dir_lookup (struct inode *dir, int creat) { struct inode *ret = NULL; - int res; + struct dentry *d_dir=NULL, *dlook=NULL; + int rv; Printk ((KERN_DEBUG "Entering umsdos_emd_dir_lookup\n")); + if (!dir) printk (KERN_CRIT "umsdos FATAL: should never happen: dir=NULL!\n"); + check_inode (dir); + if (dir->u.umsdos_i.i_emd_dir != 0) { ret = iget (dir->i_sb, dir->u.umsdos_i.i_emd_dir); - Printk (("umsdos_emd_dir_lookup: deja trouve %ld %p\n" - ,dir->u.umsdos_i.i_emd_dir, ret)); + Printk (("umsdos_emd_dir_lookup: deja trouve %ld %p\n", dir->u.umsdos_i.i_emd_dir, ret)); } else { PRINTK ((KERN_DEBUG "umsdos /mn/: Looking for %.*s -", UMSDOS_EMD_NAMELEN, UMSDOS_EMD_FILE)); - res = compat_umsdos_real_lookup (dir, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, &ret); - PRINTK ((KERN_DEBUG "-returned %d\n", res)); + + d_dir = geti_dentry (dir); + dlook = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, d_dir); + rv = umsdos_real_lookup (dir, dlook); + + PRINTK ((KERN_DEBUG "-returned %d\n", rv)); Printk ((KERN_INFO "emd_dir_lookup ")); - if (ret != NULL) { + + ret = dlook->d_inode; + if (ret) { Printk (("Found --linux ")); dir->u.umsdos_i.i_emd_dir = ret->i_ino; + inc_count (ret); /* we'll need the inode */ + fin_dentry (dlook); /* but not dentry */ + check_inode (ret); } else if (creat) { int code; - + Printk ((" * ERROR * /mn/: creat not yet implemented? not fixed? ")); Printk (("avant create ")); inc_count (dir); @@ -330,14 +326,15 @@ struct inode *umsdos_emd_dir_lookup (struct inode *dir, int creat) printk (KERN_WARNING "UMSDOS: Can't create EMD file\n"); } } + if (ret != NULL) { /* Disable UMSDOS_notify_change() for EMD file */ + /* inc_count (ret); // we need to return with incremented inode. FIXME: didn't umsdos_real_lookup already did that? and compat_msdos_create ? */ ret->u.umsdos_i.i_emd_owner = 0xffffffff; } - } -#if 1 +#if UMS_DEBUG Printk ((KERN_DEBUG "umsdos_emd_dir_lookup returning %p /mn/\n", ret)); if (ret != NULL) Printk ((KERN_DEBUG " returning ino=%lu\n", ret->i_ino)); @@ -350,7 +347,7 @@ struct inode *umsdos_emd_dir_lookup (struct inode *dir, int creat) /* * creates an EMD file * - * Return NULL if error. If ok, dir->u.umsdos_i.emd_inode + * Return NULL if error, dir->u.umsdos_i.emd_inode if OK. */ struct inode *umsdos_emd_dir_create (struct inode *dir, struct dentry *dentry, int mode) @@ -387,30 +384,33 @@ struct inode *umsdos_emd_dir_create (struct inode *dir, struct dentry *dentry, i /* * Read an entry from the EMD file. * Support variable length record. - * Return -EIO if error, 0 if ok. + * Return -EIO if error, 0 if OK. + * + * does not change {d,i}_count */ -int umsdos_emd_dir_readentry ( - struct inode *emd_dir, - struct file *filp, +int umsdos_emd_dir_readentry ( struct file *filp, struct umsdos_dirent *entry) { int ret; Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: entering.\n")); - Printk (("umsdos_emd_dir_readentry /mn/: trying to lookup %.*s (ino=%lu) using EMD %lu\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name, filp->f_dentry->d_inode->i_ino, emd_dir->i_ino)); + Printk (("umsdos_emd_dir_readentry /mn/: reading EMD %.*s (ino=%lu) at pos=%d\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name, filp->f_dentry->d_inode->i_ino, (int) filp->f_pos)); - ret = umsdos_emd_dir_read (emd_dir, filp, (char *) entry, UMSDOS_REC_SIZE, NULL); - if (ret == 0) { /* note /mn/: is this wrong? ret is always 0 or -EIO. but who knows. It used to work this way... */ + ret = umsdos_emd_dir_read (filp, (char *) entry, UMSDOS_REC_SIZE); + if (ret == 0) { /* if no error */ /* Variable size record. Maybe, we have to read some more */ int recsize = umsdos_evalrecsize (entry->name_len); - Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: FIXME if %d > %d?\n", recsize, UMSDOS_REC_SIZE)); if (recsize > UMSDOS_REC_SIZE) { - ret = umsdos_emd_dir_read (emd_dir, filp, ((char *) entry) + UMSDOS_REC_SIZE, recsize - UMSDOS_REC_SIZE, NULL); + Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: %d > %d!\n", recsize, UMSDOS_REC_SIZE)); + ret = umsdos_emd_dir_read (filp, ((char *) entry) + UMSDOS_REC_SIZE, recsize - UMSDOS_REC_SIZE); } } - Printk (("umsdos_emd_dir_readentry /mn/: returning %d.\n", ret)); + Printk (("umsdos_emd_dir_readentry /mn/: ret=%d.\n", ret)); + if (entry && ret == 0) { + Printk (("umsdos_emd_dir_readentry /mn/: returning len=%d,name=%.*s\n", (int) entry->name_len, (int) entry->name_len, entry->name)); + } return ret; } @@ -419,16 +419,15 @@ int umsdos_emd_dir_readentry ( /* * Write an entry in the EMD file. - * Return 0 if ok, -EIO if some error. + * Return 0 if OK, -EIO if some error. */ -int umsdos_writeentry ( - struct inode *dir, +int umsdos_writeentry ( struct inode *dir, struct inode *emd_dir, struct umsdos_info *info, int free_entry) -{ /* This entry is deleted, so Write all 0's */ +{ /* This entry is deleted, so write all 0's. */ int ret = 0; struct dentry *emd_dentry; struct file filp; @@ -438,11 +437,11 @@ int umsdos_writeentry ( fill_new_filp (&filp, NULL); Printk (("umsdos_writeentry /mn/: entering...\n")); - emd_dentry = creat_dentry ("wremd_mn", 8, emd_dir, NULL); + emd_dentry = geti_dentry (emd_dir); if (free_entry) { /* #Specification: EMD file / empty entries - * Unused entry in the EMD file are identify + * Unused entry in the EMD file are identified * by the name_len field equal to 0. However to * help future extension (or bug correction :-( ), * empty entries are filled with 0. @@ -453,26 +452,26 @@ int umsdos_writeentry ( memset (entry->name + entry->name_len, '\0', sizeof (entry->name) - entry->name_len); /* #Specification: EMD file / spare bytes * 10 bytes are unused in each record of the EMD. They - * are set to 0 all the time. So it will be possible + * are set to 0 all the time, so it will be possible * to do new stuff and rely on the state of those - * bytes in old EMD file around. + * bytes in old EMD files. */ memset (entry->spare, 0, sizeof (entry->spare)); } Printk (("umsdos_writeentry /mn/: if passed...\n")); if (!info) - printk (KERN_ERR "umsdosfs: /mn/ info is empty ! ooops...\n"); + printk (KERN_ERR "UMSDOS: /mn/ info is empty! Oops!\n"); filp.f_pos = info->f_pos; filp.f_reada = 0; filp.f_flags = O_RDWR; filp.f_dentry = emd_dentry; - filp.f_op = &umsdos_file_operations; /* /mn/ - we have to fill it with dummy values so we won't segfault */ + filp.f_op = &umsdos_file_operations; /* /mn/ - We have to fill it with dummy values so we won't segfault. */ - ret = umsdos_emd_dir_write (emd_dir, &filp, (char *) entry, info->recsize, NULL); + ret = umsdos_emd_dir_write (&filp, (char *) entry, info->recsize); Printk (("emd_dir_write returned with %d!\n", ret)); if (ret != 0) { - printk ("UMSDOS: problem with EMD file. Can't write\n"); + printk ("UMSDOS: problem with EMD file: can't write\n"); } else { dir->i_ctime = dir->i_mtime = CURRENT_TIME; /* dir->i_dirt = 1; FIXME iput/dput ??? */ @@ -500,7 +499,7 @@ struct find_buffer { * Fill the read buffer and take care of the byte remaining inside. * Unread bytes are simply move to the beginning. * - * Return -ENOENT if EOF, 0 if ok, a negative error code if any problem. + * Return -ENOENT if EOF, 0 if OK, a negative error code if any problem. */ static int umsdos_fillbuf ( @@ -511,6 +510,7 @@ static int umsdos_fillbuf ( int mustmove = buf->size - buf->pos; int mustread; int remain; + struct inode *old_ino; PRINTK ((KERN_DEBUG "Entering umsdos_fillbuf, for inode %lu, buf=%p\n", inode->i_ino, buf)); @@ -523,7 +523,10 @@ static int umsdos_fillbuf ( if (remain < mustread) mustread = remain; if (mustread > 0) { - ret = umsdos_emd_dir_read (inode, &buf->filp, buf->buffer + mustmove, mustread, NULL); + old_ino = buf->filp.f_dentry->d_inode; /* FIXME: do we need to save/restore it ? */ + buf->filp.f_dentry->d_inode = inode; + ret = umsdos_emd_dir_read (&buf->filp, buf->buffer + mustmove, mustread); + buf->filp.f_dentry->d_inode = old_ino; if (ret == 0) buf->size = mustmove + mustread; } else if (mustmove) { @@ -555,43 +558,73 @@ static int umsdos_fillbuf ( * * All this to say that umsdos_writeentry must be call after this * function since it rely on the f_pos field of info. + * + * calling code is expected to iput() returned *pt_emd_dir + * */ -static int umsdos_find ( - struct inode *dir, +static int umsdos_find ( struct inode *dir, struct umsdos_info *info, /* Hold name and name_len */ /* Will hold the entry found */ struct inode **pt_emd_dir) /* Will hold the emd_dir inode or NULL if not found */ { /* #Specification: EMD file structure - * The EMD file uses a fairly simple layout. It is made of records - * (UMSDOS_REC_SIZE == 64). When a name can't be written is a single - * record, multiple contiguous record are allocated. + * The EMD file uses a fairly simple layout. It is made of records + * (UMSDOS_REC_SIZE == 64). When a name can't be written in a single + * record, multiple contiguous records are allocated. */ int ret = -ENOENT; struct inode *emd_dir; struct umsdos_dirent *entry = &info->entry; Printk (("umsdos_find: locating %.*s in dir %lu\n", entry->name_len, entry->name, dir->i_ino)); + check_inode (dir); emd_dir = umsdos_emd_dir_lookup (dir, 1); if (emd_dir != NULL) { int recsize = info->recsize; struct { off_t posok; /* Position available to store the entry */ - int found; /* A valid empty position has been found */ + int found; /* A valid empty position has been found. */ off_t one; /* One empty position -> maybe <- large enough */ int onesize; /* size of empty region starting at one */ } empty; - /* Read several entries at a time to speed up the search */ + /* Read several entries at a time to speed up the search. */ struct find_buffer buf; - struct dentry *dentry; - - dentry = creat_dentry ("umsfind-mn", 10, emd_dir, NULL); + struct dentry *demd; - fill_new_filp (&buf.filp, dentry); + Printk (("umsdos_find: check emd_dir...\n")); + check_inode (emd_dir); + +#if 0 /* FIXME! not needed. but there are count wraps. somewhere before umsdos_find there should be inc_count/iput pair around umsdos_find call.... */ + inc_count (emd_dir); /* since we are going to fin_dentry, and need emd_dir afterwards -- caling code will iput() it */ +#endif + demd = geti_dentry (emd_dir); + if (demd) { + dget (demd); /* because we'll have to dput it */ + } else { + /* + * We don't have dentry alias for this inode. Too bad. + * So we'll fake something (as best as we can). + * (maybe we should do it in any case just to keep it simple?) + * + * Note that this is legal for EMD file, since in some places + * we keep inode, but discard dentry (since we would have no way + * to discard it later). Yes, this probably should be fixed somehow, + * it is just that I don't have idea how right now, and I've spent + * quite some time to track it down why it dies here. Maybe new emd_dir_lookup + * which returns dentry ? hmmmm... FIXME... + * + */ + Printk ((KERN_WARNING "umsdos_find: inode has no alias for EMD inode, fake it\n")); + demd = creat_dentry ("@emd_find@", 10, emd_dir, NULL); + } + + check_dentry_path (demd, " EMD_DIR_DENTRY umsdos_find"); + + fill_new_filp (&buf.filp, demd); buf.pos = 0; buf.size = 0; @@ -613,20 +646,20 @@ static int umsdos_find ( } } else if (rentry->name_len == 0) { /* We are looking for an empty section at least */ - /* recsize large */ + /* as large as recsize. */ if (entry->name_len == 0) { info->f_pos = file_pos; ret = 0; break; } else if (!empty.found) { if (empty.onesize == 0) { - /* This is the first empty record of a section */ + /* This is the first empty record of a section. */ empty.one = file_pos; } /* grow the empty section */ empty.onesize += UMSDOS_REC_SIZE; if (empty.onesize == recsize) { - /* here is a large enough section */ + /* Here is a large enough section. */ empty.posok = empty.one; empty.found = 1; } @@ -643,10 +676,9 @@ static int umsdos_find ( break; } } else { - empty.onesize = 0; /* Reset the free slot search */ + empty.onesize = 0; /* Reset the free slot search. */ if (entry->name_len == rentry->name_len - && memcmp (entry->name, rentry->name, rentry->name_len) - == 0) { + && memcmp (entry->name, rentry->name, rentry->name_len) == 0) { info->f_pos = file_pos; *entry = *rentry; ret = 0; @@ -658,6 +690,7 @@ static int umsdos_find ( } } umsdos_manglename (info); + fin_dentry (demd); } *pt_emd_dir = emd_dir; @@ -667,15 +700,14 @@ static int umsdos_find ( /* - * Add a new entry in the emd file - * Return 0 if ok or a negative error code. - * Return -EEXIST if the entry already exist. + * Add a new entry in the EMD file. + * Return 0 if OK or a negative error code. + * Return -EEXIST if the entry already exists. * * Complete the information missing in info. */ -int umsdos_newentry ( - struct inode *dir, +int umsdos_newentry ( struct inode *dir, struct umsdos_info *info) { struct inode *emd_dir; @@ -687,18 +719,17 @@ int umsdos_newentry ( ret = umsdos_writeentry (dir, emd_dir, info, 0); Printk (("umsdos_writeentry EMD ret = %d\n", ret)); } - iput (emd_dir); /* FIXME? */ + iput (emd_dir); return ret; } /* * Create a new hidden link. - * Return 0 if ok, an error code if not. + * Return 0 if OK, an error code if not. */ -int umsdos_newhidden ( - struct inode *dir, +int umsdos_newhidden ( struct inode *dir, struct umsdos_info *info) { struct inode *emd_dir; @@ -707,28 +738,26 @@ int umsdos_newhidden ( umsdos_parse ("..LINK", 6, info); info->entry.name_len = 0; ret = umsdos_find (dir, info, &emd_dir); - iput (emd_dir); /* FIXME? */ + iput (emd_dir); if (ret == -ENOENT || ret == 0) { /* #Specification: hard link / hidden name * When a hard link is created, the original file is renamed * to a hidden name. The name is "..LINKNNN" where NNN is a * number define from the entry offset in the EMD file. */ - info->entry.name_len = sprintf (info->entry.name, "..LINK%ld" - ,info->f_pos); + info->entry.name_len = sprintf (info->entry.name, "..LINK%ld", info->f_pos); ret = 0; } return ret; } /* - * Remove an entry from the emd file - * Return 0 if ok, a negative error code otherwise. + * Remove an entry from the EMD file. + * Return 0 if OK, a negative error code otherwise. * * Complete the information missing in info. */ -int umsdos_delentry ( - struct inode *dir, +int umsdos_delentry ( struct inode *dir, struct umsdos_info *info, int isdir) { @@ -748,38 +777,41 @@ int umsdos_delentry ( } } } - iput(emd_dir); /* FIXME? */ + iput (emd_dir); return ret; } /* - * Verify is a EMD directory is empty. - * Return 0 if not empty - * 1 if empty - * 2 if empty, no EMD file. + * Verify that a EMD directory is empty. Return + * 0 if not empty, + * 1 if empty, + * 2 if empty or no EMD file. */ int umsdos_isempty (struct inode *dir) { - struct dentry *dentry; + struct dentry *dentry, *d_dir; int ret = 2; struct inode *emd_dir = umsdos_emd_dir_lookup (dir, 0); - /* If the EMD file does not exist, it is certainly empty :-) */ + /* If the EMD file does not exist, it is certainly empty. :-) */ if (emd_dir != NULL) { struct file filp; - dentry = creat_dentry ("isempty-mn", 10, dir, NULL); + d_dir = geti_dentry (dir); + dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, d_dir); + check_dentry_path (dentry, "umsdos_isempty BEGIN"); fill_new_filp (&filp, dentry); + filp.f_pos = 0; filp.f_flags = O_RDONLY; ret = 1; while (filp.f_pos < emd_dir->i_size) { struct umsdos_dirent entry; - if (umsdos_emd_dir_readentry (emd_dir, &filp, &entry) != 0) { + if (umsdos_emd_dir_readentry (&filp, &entry) != 0) { ret = 0; break; } else if (entry.name_len != 0) { @@ -787,24 +819,28 @@ int umsdos_isempty (struct inode *dir) break; } } - iput (emd_dir); /* FIXME? */ + fin_dentry (dentry); + check_dentry_path (dentry, "umsdos_isempty END"); + iput (emd_dir); } return ret; } /* * Locate an entry in a EMD directory. - * Return 0 if ok, errcod if not, generally -ENOENT. + * Return 0 if OK, error code if not, generally -ENOENT. + * + * does not change i_count */ -int umsdos_findentry ( - struct inode *dir, +int umsdos_findentry ( struct inode *dir, struct umsdos_info *info, int expect) -{ /* 0: anything */ - /* 1: file */ - /* 2: directory */ - struct inode *emd_dir; + /* 0: anything */ + /* 1: file */ + /* 2: directory */ +{ + struct inode *emd_dir=NULL; int ret = umsdos_find (dir, info, &emd_dir); if (ret == 0) { @@ -817,7 +853,7 @@ int umsdos_findentry ( } } } - iput (emd_dir); /* FIXME? */ + iput (emd_dir); Printk (("umsdos_findentry: returning %d\n", ret)); return ret; } diff --git a/fs/umsdos/file.c b/fs/umsdos/file.c index 99bf747cc09e..5277c95481b0 100644 --- a/fs/umsdos/file.c +++ b/fs/umsdos/file.c @@ -19,10 +19,6 @@ #include #include -#define PRINTK(x) -#define Printk(x) printk x - - /* * Read a file into user space memory */ diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c index 4bf2a65ce648..6853d7eaab0e 100644 --- a/fs/umsdos/inode.c +++ b/fs/umsdos/inode.c @@ -3,7 +3,6 @@ * * Written 1993 by Jacques Gelinas * Inspired from linux/fs/msdos/... by Werner Almesberger - * */ #include @@ -24,28 +23,11 @@ extern struct inode_operations umsdos_rdir_inode_operations; struct inode *pseudo_root = NULL; /* Useful to simulate the pseudo DOS */ - - /* directory. See UMSDOS_readdir_x() */ - -/* #Specification: convention / PRINTK Printk and printk - * Here is the convention for the use of printk inside fs/umsdos - * - * printk carry important message (error or status). - * Printk is for debugging (it is a macro defined at the beginning of - * most source. - * PRINTK is a nulled Printk macro. - * - * This convention makes the source easier to read, and Printk easier - * to shut off. - */ -#define PRINTK(x) -#define Printk(x) printk x - - + /* directory. See UMSDOS_readdir_x() */ /* - * makes return inode->i_dentry + * returns inode->i_dentry * */ @@ -53,14 +35,25 @@ inline struct dentry *geti_dentry (struct inode *inode) { struct dentry *ret; if (!inode) { - printk (KERN_ERR "geti_dentry: inode is NULL!\n"); + printk (KERN_ERR "geti_dentry: ERROR: inode is NULL!\n"); return NULL; } - ret = list_entry (inode->i_dentry.next, struct dentry, d_alias); /* FIXME: does this really work ? :) */ - Printk ((KERN_DEBUG "geti_dentry : inode %lu: i_dentry is %p\n", inode->i_ino, ret)); + if (inode->i_dentry.next == inode->i_dentry.next->next) { + printk (KERN_WARNING "geti_dentry: WARNING: inode does not have an dentry. returning NULL.\n"); + return NULL; + } + ret = list_entry (inode->i_dentry.next, struct dentry, d_alias); + + if (IS_ERR(ret)) { + Printk ((KERN_WARNING "geti_dentry: checking dentry... it is ERR(%ld) !\n", PTR_ERR(ret))); + } + + PRINTK ((KERN_DEBUG "geti_dentry : inode %lu: i_dentry is %p\n", inode->i_ino, ret)); return ret; } + + /* * makes inode->i_count++ * @@ -69,7 +62,7 @@ inline struct dentry *geti_dentry (struct inode *inode) inline void inc_count (struct inode *inode) { inode->i_count++; - Printk ((KERN_DEBUG "inc_count: inode %lu incremented count to %d\n", inode->i_ino, inode->i_count)); + PRINTK ((KERN_DEBUG "inc_count: inode %lu incremented count to %d\n", inode->i_ino, inode->i_count)); } @@ -95,6 +88,9 @@ void fill_new_filp (struct file *filp, struct dentry *dentry) filp->f_op = &umsdos_file_operations; /* /mn/ - we have to fill it with SOMETHING */ } + + +#if UMS_DEBUG /* * check a superblock */ @@ -146,6 +142,56 @@ void check_inode (struct inode *inode) } } +/* + * checks all inode->i_dentry + * + */ +void checkd_inode (struct inode *inode) +{ + struct dentry *ret; + struct list_head *cur; + int count = 0; + if (!inode) { + printk (KERN_ERR "checkd_inode: inode is NULL!\n"); + return; + } + + Printk ((KERN_DEBUG "checkd_inode: inode %lu\n", inode->i_ino)); + cur = inode->i_dentry.next; + while (count++ < 10) { + PRINTK (("1...")); + if (!cur) { + Printk ((KERN_ERR "checkd_inode: *** NULL reached. exit.\n")); + return; + } + PRINTK (("2...")); + ret = list_entry (cur, struct dentry, d_alias); + PRINTK (("3...")); + if (cur == cur->next) { + Printk ((KERN_DEBUG "checkd_inode: *** cur=cur->next: normal exit.\n")); + return; + } + PRINTK (("4...")); + if (!ret) { + Printk ((KERN_ERR "checkd_inode: *** ret dentry is NULL. exit.\n")); + return; + } + PRINTK (("5... (ret=%p)...", ret)); + PRINTK (("5.1.. (ret->d_dname=%p)...", &(ret->d_name))); + PRINTK (("5.1.1. (ret->d_dname.len=%d)...", (int) ret->d_name.len)); + PRINTK (("5.1.2. (ret->d_dname.name=%c)...", ret->d_name.name)); + Printk ((KERN_DEBUG "checkd_inode: i_dentry is %.*s\n", (int) ret->d_name.len, ret->d_name.name)); + PRINTK (("6...")); + cur = cur->next; + PRINTK (("7...")); +#if 1 + Printk ((KERN_DEBUG "checkd_inode: *** finished after count 1 (operator forced)\n")); + return; +#endif + } + Printk ((KERN_ERR "checkd_inode: *** OVER LIMIT (loop?) !\n")); + return; +} /* * internal part of check_dentry. does the real job. @@ -155,9 +201,9 @@ void check_inode (struct inode *inode) void check_dent_int (struct dentry *dentry, int parent) { if (parent) { - Printk ((KERN_DEBUG "* parent dentry: %.*s\n", (int) dentry->d_name.len, dentry->d_name.name)); + Printk ((KERN_DEBUG "* parent(%d) dentry: %.*s\n", parent, (int) dentry->d_name.len, dentry->d_name.name)); } else { - Printk ((KERN_DEBUG "\n*** checking dentry: %.*s\n", (int) dentry->d_name.len, dentry->d_name.name)); + Printk ((KERN_DEBUG "* checking dentry: %.*s\n", (int) dentry->d_name.len, dentry->d_name.name)); } check_inode (dentry->d_inode); Printk ((KERN_DEBUG "* d_count=%d", dentry->d_count)); @@ -170,32 +216,53 @@ void check_dent_int (struct dentry *dentry, int parent) } /* - * checks dentry and prints info + * checks dentry with full traceback to root and prints info. Limited to 10 recursive depths to avoid infinite loops. * */ -void check_dentry (struct dentry *dentry) +void check_dentry_path (struct dentry *dentry, const char *desc) { + int count=0; + Printk ((KERN_DEBUG "*** check_dentry_path: %.60s\n", desc)); + if (!dentry) { - Printk ((KERN_DEBUG "\n*** checking dentry... it is NULL !\n")); + Printk ((KERN_DEBUG "*** checking dentry... it is NULL !\n")); return; } - check_dent_int (dentry, 0); - - if (dentry->d_parent) { - check_dent_int (dentry->d_parent, 1); - } else { - Printk ((KERN_DEBUG "* has no parent.\n")); + if (IS_ERR(dentry)) { + Printk ((KERN_DEBUG "*** checking dentry... it is ERR(%ld) !\n", PTR_ERR(dentry))); + return; + } + + while (dentry && count < 10) { + check_dent_int (dentry, count++); + if (dentry == dentry->d_parent) { + Printk ((KERN_DEBUG "*** end checking dentry (root reached ok)\n")); + break; + } + dentry = dentry->d_parent; } - Printk ((KERN_DEBUG "*** end checking dentry\n")); + if (count >= 10) { /* if infinite loop detected */ + Printk ((KERN_ERR "*** WARNING ! INFINITE LOOP ! check_dentry_path aborted !\n")); + } + + if (!dentry) { + Printk ((KERN_ERR "*** WARNING ! found NULL dentry ! check_dentry_path aborted !\n")); + } } +#else +void check_sb (struct super_block *sb, const char c) {}; +void check_inode (struct inode *inode) {}; +void checkd_inode (struct inode *inode) {}; +void check_dentry_path (struct dentry *dentry, const char *desc) {}; +#endif /* UMS_DEBUG */ + /* - * makes dentry. for name name with length len. /mn/ + * makes dentry. for name name with length len. * if inode is not NULL, puts it also. - * */ struct dentry *creat_dentry (const char *name, const int len, struct inode *inode, struct dentry *parent) @@ -206,68 +273,111 @@ struct dentry *creat_dentry (const char *name, const int len, struct inode *inod struct qstr qname; if (inode) - Printk ((KERN_DEBUG "/mn/ creat_dentry: creating dentry with inode=%lu for %.*s\n", inode->i_ino, len, name)); + Printk ((KERN_DEBUG "creat_dentry: creating dentry with inode=%lu for %.*s\n", inode->i_ino, len, name)); else - Printk ((KERN_DEBUG "/mn/ creat_dentry: creating empty dentry for %.*s\n", len, name)); + Printk ((KERN_DEBUG "creat_dentry: creating empty dentry for %.*s\n", len, name)); qname.name = name; qname.len = len; +#if 1 + #warning is full_name_hash OK for normal filenames? And for MSDOSFS accessed EMD files? + qname.hash = full_name_hash (name, len); +#else qname.hash = 0; +#endif ret = d_alloc (parent, &qname); /* create new dentry */ ret->d_inode = NULL; - if (!parent) { + if (parent) { +#if 0 + Printk ((KERN_DEBUG "creat_dentry: cloning parent d_op !\n")); + ret->d_op = parent->d_op; +#else + ret->d_op = NULL; +#endif + } else { ret->d_parent = ret; - Printk ((KERN_WARNING "creat_dentry: WARNING: NO parent! faking! beware !\n")); + Printk ((KERN_WARNING "creat_dentry: WARNING: NO parent! faking root! beware !\n")); } if (inode) { - ret->d_sb = inode->i_sb; /* try to fill it in if avalaible. If avalaible in parent->d_sb, d_alloc will add it automatically */ + if (!ret->d_sb) ret->d_sb = inode->i_sb; /* try to fill it in if available. If available in parent->d_sb, d_alloc will add it automatically */ d_add (ret, inode); } + if (!ret->d_sb) { + printk (KERN_ERR "creat_dentry: ERROR: NO d_sb !\n"); + } else if (!ret->d_sb->s_dev) { + printk (KERN_WARNING "creat_dentry: WARNING: NO s_dev. Ugh. !\n"); + } + return ret; } /* * removes temporary dentry created by creat_dentry + * it must have d_count of 1, and associated inode i_count of 1 + * to be completely cleared. * */ void kill_dentry (struct dentry *dentry) { if (dentry) { - Printk (("/mn/ kill_dentry: kill_dentry %.*s :", (int) dentry->d_name.len, dentry->d_name.name)); - if (dentry->d_inode) - Printk (("inode=%lu (i_count=%d)\n", dentry->d_inode->i_ino, dentry->d_inode->i_count)); - else - Printk (("inode is NULL\n")); - - /* FIXME: is this ok ?! /mn/ */ - /* d_drop (dentry); */ - /* d_invalidate (dentry); */ - /*dput (dentry); */ - /*d_delete (dentry) */ + check_dentry_path (dentry, "KILL_DENTRY B4"); + /* this idea for killing dentry (d_drop/dput pair) from NFS code. dcache.c code&comments seems to agree */ +#if 0 + d_drop (dentry); + dput (dentry); /* we are done with it */ +#endif + check_dentry_path (dentry, "KILL_DENTRY AFT"); } else { - Printk (("/mn/ kill_dentry: dentry is NULL ?!\n")); + Printk (("kill_dentry: dentry is NULL ?!\n")); } - Printk ((KERN_DEBUG "/mn/ kill_dentry: exiting...\n")); + Printk ((KERN_DEBUG "kill_dentry: exiting...\n")); return; } +/* + * finishes work with dentry + * it must have d_count of 1, and associated inode i_count of 1 + * to be completely cleared. + * + * Currently, this is same as kill_dentry, but this may (will) change. + * kill_dentry will eventualy be killed (he who lives by the sword, dies + * by the sword :-) when all faked dentries are nuked out... + * + */ +void fin_dentry (struct dentry *dentry) +{ + if (dentry) { + if (IS_ERR(dentry)) { + Printk ((KERN_WARNING "fin_dentry: dentry is IS_ERR (%ld)?!\n", PTR_ERR (dentry))); + } else { + /* this idea for killing dentry (d_drop/dput pair) from NFS code. dcache.c code&comments seems to agree */ + d_drop (dentry); + dput (dentry); /* we are done with it */ + } + } else { + Printk ((KERN_WARNING "fin_dentry: dentry is NULL ?!\n")); + } + PRINTK ((KERN_DEBUG "fin_dentry: exiting...\n")); + return; +} void UMSDOS_put_inode (struct inode *inode) { - PRINTK ((KERN_DEBUG "put inode %p (%lu) owner %lu pos %lu dir %lu count=%d\n", inode, inode->i_ino + PRINTK ((KERN_DEBUG "put inode %p (%lu) owner %lu pos %lu dir %lu count=%d\n", inode + ,inode->i_ino ,inode->u.umsdos_i.i_emd_owner, inode->u.umsdos_i.pos ,inode->u.umsdos_i.i_emd_dir, inode->i_count)); @@ -282,6 +392,7 @@ void UMSDOS_put_inode (struct inode *inode) void UMSDOS_put_super (struct super_block *sb) { Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n")); + check_dentry_path (sb->s_root, "put_super: START"); msdos_put_super (sb); MOD_DEC_USE_COUNT; } @@ -290,18 +401,18 @@ void UMSDOS_put_super (struct super_block *sb) /* * Call msdos_lookup, but set back the original msdos function table. - * Return 0 if ok, or a negative error code if not. + * Return 0 if OK, or a negative error code if not. */ -int umsdos_real_lookup ( - struct inode *dir, - struct dentry *dentry -) -{ /* Will hold inode of the file, if successful */ +int umsdos_real_lookup ( struct inode *dir, + struct dentry *dentry) /* Will hold inode of the file, if successful */ +{ int ret; - PRINTK ((KERN_DEBUG "umsdos_real_lookup: looking for %s /", dentry->d_name.name)); - inc_count (dir); /* should be here ? Causes all kind of missing iput()'s all around, but panics w/o it /mn/ */ + PRINTK ((KERN_DEBUG "umsdos_real_lookup: looking for %.*s /", dentry->d_name.len, dentry->d_name.name)); + inc_count (dir); ret = msdos_lookup (dir, dentry); + dentry->d_op = NULL; /* FIXME: Not needed? - if it was good once for MSDOS, it will be good any other time also. I hope :) */ + iput (dir); /* pair to inc_count(dir) above */ PRINTK (("/ returned %d\n", ret)); return ret; @@ -312,6 +423,8 @@ int umsdos_real_lookup ( * First, it completes the function pointers, then * it locates the EMD file. If the EMD is there, then plug the * umsdos function table. If not, use the msdos one. + * + * {i,d}_counts are untouched by this function. */ void umsdos_setup_dir_inode (struct inode *inode) { @@ -319,8 +432,12 @@ void umsdos_setup_dir_inode (struct inode *inode) { struct inode *emd_dir; + Printk ((KERN_DEBUG "umsdos_setup_dir_inode: Entering for inode=%lu\n", inode->i_ino)); + check_inode (inode); emd_dir = umsdos_emd_dir_lookup (inode, 0); - Printk ((KERN_DEBUG "umsdos_setup_dir_inode: umsdos_emd_dir_lookup for inode=%p returned %p\n", inode, emd_dir)); + Printk ((KERN_DEBUG "umsdos_setup_dir_inode: umsdos_emd_dir_lookup for inode=%lu returned %p\n", inode->i_ino, emd_dir)); + check_inode (inode); + check_inode (emd_dir); if (emd_dir == NULL) { Printk ((KERN_DEBUG "umsdos_setup_dir_inode /mn/: Setting up rdir_inode_ops --> eg. NOT using EMD.\n")); @@ -328,9 +445,8 @@ void umsdos_setup_dir_inode (struct inode *inode) } else { Printk ((KERN_DEBUG "umsdos_setup_dir_inode /mn/: Setting up dir_inode_ops --> eg. using EMD.\n")); inode->i_op = &umsdos_dir_inode_operations; + iput (emd_dir); } - - iput (emd_dir); /* FIXME? OK? */ } } @@ -338,20 +454,19 @@ void umsdos_setup_dir_inode (struct inode *inode) /* * Add some info into an inode so it can find its owner quickly */ -void umsdos_set_dirinfo ( - struct inode *inode, +void umsdos_set_dirinfo ( struct inode *inode, struct inode *dir, off_t f_pos) { struct inode *emd_owner; - /* FIXME, I don't have a clue on this one - /mn/ hmmm ? ok ? */ + /* FIXME, I don't have a clue on this one - /mn/ Hmmm? OK? */ /* Printk ((KERN_WARNING "umsdos_set_dirinfo: /mn/ FIXME: no clue. inode=%lu dir=%lu\n", inode->i_ino, dir->i_ino)); */ emd_owner = umsdos_emd_dir_lookup (dir, 1); Printk (("umsdos_set_dirinfo: emd_owner is %lu for dir %lu\n", emd_owner->i_ino, dir->i_ino)); inode->u.umsdos_i.i_dir_owner = dir->i_ino; inode->u.umsdos_i.i_emd_owner = emd_owner->i_ino; - iput (emd_owner); /* FIXME? */ + /* iput (emd_owner); / * FIXME? */ inode->u.umsdos_i.pos = f_pos; } @@ -374,16 +489,17 @@ int umsdos_isinit (struct inode *inode) /* * Connect the proper tables in the inode and add some info. + * i_counts is not changed. */ -void umsdos_patch_inode ( - struct inode *inode, + +void umsdos_patch_inode ( struct inode *inode, struct inode *dir, /* May be NULL */ off_t f_pos) { /* * This function is called very early to setup the inode, somewhat * too early (called by UMSDOS_read_inode). At this point, we can't - * do to much, such as lookup up EMD files and so on. This causes + * do too much, such as lookup up EMD files and so on. This causes * confusion in the kernel. This is why some initialisation * will be done when dir != NULL only. * @@ -404,18 +520,18 @@ void umsdos_patch_inode ( if (S_ISREG (inode->i_mode)) { if (MSDOS_SB (inode->i_sb)->cvf_format) { if (MSDOS_SB (inode->i_sb)->cvf_format->flags & CVF_USE_READPAGE) { - Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_readpage\n")); + Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: setting i_op = umsdos_file_inode_operations_readpage\n")); inode->i_op = &umsdos_file_inode_operations_readpage; } else { - Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_no_bmap\n")); + Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: setting i_op = umsdos_file_inode_operations_no_bmap\n")); inode->i_op = &umsdos_file_inode_operations_no_bmap; } } else { if (inode->i_op->bmap != NULL) { - Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations\n")); + Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: setting i_op = umsdos_file_inode_operations\n")); inode->i_op = &umsdos_file_inode_operations; } else { - Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_no_bmap\n")); + Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: setting i_op = umsdos_file_inode_operations_no_bmap\n")); inode->i_op = &umsdos_file_inode_operations_no_bmap; } } @@ -424,13 +540,13 @@ void umsdos_patch_inode ( umsdos_setup_dir_inode (inode); } } else if (S_ISLNK (inode->i_mode)) { - Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_symlink_inode_operations\n")); + Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: setting i_op = umsdos_symlink_inode_operations\n")); inode->i_op = &umsdos_symlink_inode_operations; } else if (S_ISCHR (inode->i_mode)) { - Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = chrdev_inode_operations\n")); + Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: setting i_op = chrdev_inode_operations\n")); inode->i_op = &chrdev_inode_operations; } else if (S_ISBLK (inode->i_mode)) { - Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = blkdev_inode_operations\n")); + Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: setting i_op = blkdev_inode_operations\n")); inode->i_op = &blkdev_inode_operations; } else if (S_ISFIFO (inode->i_mode)) { Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: uhm, init_fifo\n")); @@ -460,7 +576,7 @@ void umsdos_patch_inode ( Printk ((KERN_WARNING "umsdos_patch_inode: /mn/ Warning: untested emd_owner thingy...\n")); emd_owner = umsdos_emd_dir_lookup (dir, 1); - iput (emd_owner); /* FIXME? */ + /* iput (emd_owner); / * FIXME? */ if (emd_owner->i_ino != inode->u.umsdos_i.i_emd_owner) { printk ("UMSDOS: *** EMD_OWNER ??? *** ino = %ld %ld <> %ld " ,inode->i_ino, emd_owner->i_ino, inode->u.umsdos_i.i_emd_owner); @@ -471,12 +587,11 @@ void umsdos_patch_inode ( /* * Get the inode of the directory which owns this inode. - * Return 0 if ok, -EIO if error. + * Return 0 if OK, -EIO if error. */ -int umsdos_get_dirowner ( - struct inode *inode, - struct inode **result) -{ /* Hold NULL if any error */ +int umsdos_get_dirowner ( struct inode *inode, + struct inode **result) /* Hold NULL if any error */ +{ /* else, the inode of the directory */ int ret = -EIO; unsigned long ino = inode->u.umsdos_i.i_dir_owner; @@ -489,7 +604,7 @@ int umsdos_get_dirowner ( if (dir != NULL) { umsdos_patch_inode (dir, NULL, 0); - /* iput (dir); / * FIXME: /mn/ added this. Is it ok ? */ + /* iput (dir); / * FIXME: /mn/ added this. Is it OK? */ ret = 0; } } @@ -503,9 +618,9 @@ int umsdos_get_dirowner ( */ void UMSDOS_read_inode (struct inode *inode) { - Printk ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ", inode, inode->i_ino)); + PRINTK ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ", inode, inode->i_ino)); msdos_read_inode (inode); - Printk (("ino after msdos_read_inode= %lu i_count=%d\n", inode->i_ino, inode->i_count)); + PRINTK (("ino after msdos_read_inode= %lu i_count=%d\n", inode->i_ino, inode->i_count)); if (S_ISDIR (inode->i_mode) && (inode->u.umsdos_i.u.dir_info.creating != 0 || inode->u.umsdos_i.u.dir_info.looking != 0 @@ -537,7 +652,7 @@ int internal_notify_change (struct inode *inode, struct iattr *attr) int ret = 0; struct inode *root; - PRINTK ((KERN_DEBUG "UMSDOS_notify_change: entering\n")); + Printk ((KERN_DEBUG "UMSDOS_notify_change: entering\n")); if ((ret = inode_change_ok (inode, attr)) != 0) return ret; @@ -564,7 +679,7 @@ int internal_notify_change (struct inode *inode, struct iattr *attr) * UMSDOS_notify_change() (right here). * * I am not sure of the behavior of the root inode for - * a real UNIX file system. For now, this is a nop. + * a real Unix file system. For now, this is a nop. */ } else if (i_emd_owner != 0xffffffff && i_emd_owner != 0) { /* This inode is not a EMD file nor an inode used internally @@ -582,18 +697,16 @@ int internal_notify_change (struct inode *inode, struct iattr *attr) struct file filp; struct umsdos_dirent entry; struct dentry *emd_dentry; - loff_t offs; - emd_dentry = creat_dentry ("notify_emd", 10, emd_owner, NULL); + emd_dentry = geti_dentry (emd_owner); /* FIXME? */ fill_new_filp (&filp, emd_dentry); filp.f_pos = inode->u.umsdos_i.pos; filp.f_reada = 0; - offs = filp.f_pos; /* FIXME: /mn/ is this ok ? */ Printk (("pos = %Lu ", filp.f_pos)); /* Read only the start of the entry since we don't touch */ /* the name */ - ret = umsdos_emd_dir_read (emd_owner, &filp, (char *) &entry, UMSDOS_REC_SIZE, &offs); + ret = umsdos_emd_dir_read (&filp, (char *) &entry, UMSDOS_REC_SIZE); if (ret == 0) { if (attr->ia_valid & ATTR_UID) entry.uid = attr->ia_uid; @@ -610,22 +723,19 @@ int internal_notify_change (struct inode *inode, struct iattr *attr) entry.nlink = inode->i_nlink; filp.f_pos = inode->u.umsdos_i.pos; - offs = filp.f_pos; /* FIXME: /mn/ is this ok ? */ - ret = umsdos_emd_dir_write (emd_owner, &filp, (char *) &entry, UMSDOS_REC_SIZE, &offs); + ret = umsdos_emd_dir_write (&filp, (char *) &entry, UMSDOS_REC_SIZE); - Printk (("notify pos %lu ret %d nlink %d " - ,inode->u.umsdos_i.pos - ,ret, entry.nlink)); + Printk (("notify pos %lu ret %d nlink %d ", inode->u.umsdos_i.pos, ret, entry.nlink)); /* #Specification: notify_change / msdos fs * notify_change operation are done only on the * EMD file. The msdos fs is not even called. */ } - iput (emd_owner); /* FIXME? /mn/ */ + /* iput (emd_owner); / * FIXME? /mn/ */ } Printk (("\n")); } - iput (root); /* FIXME - /mn/ this is hopefully ok */ + /* iput (root); / * FIXME - /mn/ This is should be OK. */ } if (ret == 0) inode_setattr (inode, attr); @@ -660,7 +770,7 @@ void UMSDOS_write_inode (struct inode *inode) /* * internal_notify_change (inode, &newattrs); - * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work... we need to remove ourselfs from list on dirty inodes /mn/ */ + * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work. We need to remove ourselves from list on dirty inodes. /mn/ */ } @@ -668,13 +778,13 @@ void UMSDOS_write_inode (struct inode *inode) /* #Specification: function name / convention - * A simple convention for function name has been used in - * the UMSDOS file system. First all function use the prefix - * umsdos_ to avoid name clash with other part of the kernel. + * A simple convention for function names has been used in + * the UMSDOS filesystem. First, all functions use the prefix + * umsdos_ to avoid name clashes with other parts of the kernel. * - * And standard VFS entry point use the prefix UMSDOS (upper case) + * Standard VFS entry points use the prefix UMSDOS (upper case) * so it's easier to tell them apart. - * N.B. (FIXME) PTW, the order and contents of this struct changed + * N.B. (FIXME) PTW, the order and contents of this struct changed. */ static struct super_operations umsdos_sops = @@ -693,8 +803,7 @@ static struct super_operations umsdos_sops = /* * Read the super block of an Extended MS-DOS FS. */ -struct super_block *UMSDOS_read_super ( - struct super_block *sb, +struct super_block *UMSDOS_read_super ( struct super_block *sb, void *data, int silent) { @@ -716,27 +825,39 @@ struct super_block *UMSDOS_read_super ( Printk ((KERN_DEBUG "UMSDOS /mn/: starting UMSDOS_read_super\n")); MOD_INC_USE_COUNT; - PRINTK ((KERN_DEBUG "UMSDOS /mn/: sb = %p\n", sb)); + Printk ((KERN_DEBUG "UMSDOS /mn/: sb = %p\n", sb)); + + MSDOS_SB(sb)->options.isvfat = 0; res = msdos_read_super (sb, data, silent); - PRINTK ((KERN_DEBUG "UMSDOS /mn/: res = %p\n", res)); - printk (KERN_INFO "UMSDOS dentry-WIP-Beta 0.82-4 (compatibility level %d.%d, fast msdos)\n", UMSDOS_VERSION, UMSDOS_RELEASE); + sb->s_op = &umsdos_sops; + Printk ((KERN_DEBUG "UMSDOS /mn/: res = %p\n", res)); + printk (KERN_INFO "UMSDOS dentry-WIP-Beta 0.82-7 (compatibility level %d.%d, fast msdos)\n", UMSDOS_VERSION, UMSDOS_RELEASE); if (res == NULL) { + sb->s_dev = 0; MOD_DEC_USE_COUNT; + Printk ((KERN_DEBUG "UMSDOS: msdos_read_super failed ! mount aborted.\n")); return NULL; } + MSDOS_SB (res)->options.dotsOK = 0; /* disable hidden==dotfile */ - res->s_op = &umsdos_sops; +#if 1 + res->s_root->d_op = NULL; /* FIXME:?? clear d_op on root so it will not be inherited */ +#endif + Printk ((KERN_DEBUG "umsdos /mn/: here goes the iget ROOT_INO\n")); - pseudo = iget (res, UMSDOS_ROOT_INO); - Printk ((KERN_DEBUG "umsdos_read_super %p\n", pseudo)); +/* pseudo = iget (res, UMSDOS_ROOT_INO); // we probably could do it as below (and remove iput() below), but we want use_count to go up. Do we ? :) */ + pseudo = res->s_root->d_inode; /* msdos_read_super already did iget() it */ + + Printk ((KERN_DEBUG "umsdos_read_super pseudo=%p\n", pseudo)); umsdos_setup_dir_inode (pseudo); Printk ((KERN_DEBUG "umsdos_setup_dir_inode passed. pseudo i_count=%d\n", pseudo->i_count)); /* if (s == super_blocks){ FIXME, super_blocks no longer exported */ if (pseudo) { +#if 0 /* FIXME URGENT: disable pseudo root-for the moment of testing. re-enable this before release ! */ /* #Specification: pseudo root / mount * When a umsdos fs is mounted, a special handling is done * if it is the root partition. We check for the presence @@ -769,8 +890,8 @@ struct super_block *UMSDOS_read_super ( */ struct dentry *root, *etc, *etc_rc, *sbin, *init = NULL; - root = creat_dentry (UMSDOS_PSDROOT_NAME, strlen (UMSDOS_PSDROOT_NAME), NULL, NULL); - sbin = creat_dentry ("sbin", 4, NULL, NULL); + root = creat_dentry (UMSDOS_PSDROOT_NAME, strlen (UMSDOS_PSDROOT_NAME), NULL, res->s_root); + sbin = creat_dentry ("sbin", 4, NULL, NULL); /* FIXME: should last NULL be root or res->s_root ? Not NULL in any case.. */ Printk ((KERN_DEBUG "Mounting root\n")); if (umsdos_real_lookup (pseudo, root) == 0 @@ -791,14 +912,14 @@ struct super_block *UMSDOS_read_super ( init = creat_dentry ("init", 4, NULL, etc); etc_rc = creat_dentry ("rc", 2, NULL, etc); - /* if ((umsdos_real_lookup (etc,"init",4,init)==0 */ if ((umsdos_real_lookup (pseudo, init) == 0 && S_ISREG (init->d_inode->i_mode)) - /* || (umsdos_real_lookup (etc,"rc",2,&rc)==0 */ || (umsdos_real_lookup (pseudo, etc_rc) == 0 && S_ISREG (etc_rc->d_inode->i_mode))) { pseudo_ok = 1; } + /* iput (pseudo); iput (pseudo); / * because msdos_real_lookup does inc_count (pseudo) */ + /* FIXME !!!!!! */ /* iput(init); */ /* iput(rc); */ @@ -809,11 +930,11 @@ struct super_block *UMSDOS_read_super ( && S_ISDIR (sbin->d_inode->i_mode)) { Printk ((KERN_DEBUG "/%s/sbin is there\n", UMSDOS_PSDROOT_NAME)); - /* if (umsdos_real_lookup (sbin,"init",4,init)==0 */ if (umsdos_real_lookup (pseudo, init) == 0 && S_ISREG (init->d_inode->i_mode)) { pseudo_ok = 1; } + /*iput (pseudo);*/ /* FIXME !!! * iput (init); */ } @@ -830,8 +951,17 @@ struct super_block *UMSDOS_read_super ( * iput (etc); */ } - iput (pseudo); +#endif + /*iput (pseudo); // iget was removed... so this no longer needed ? */ + } +#if 1 + #warning UMSDOS: using ugly mount kludge only if necessary (DEBUG) + if (res->s_root->d_count != 1) { /* if it is not 1, mount will fail with -EBUSY! */ + printk (KERN_ERR "UMSDOS: mount kludge activated: root d_count was %d !\n", res->s_root->d_count); + res->s_root->d_count = 1; } +#endif + check_dentry_path (res->s_root, "ROOT dentry check"); Printk ((KERN_DEBUG "umsdos_read_super /mn/: (pseudo=%lu, i_count=%d) returning %p\n", pseudo->i_ino, pseudo->i_count, res)); return res; } diff --git a/fs/umsdos/ioctl.c b/fs/umsdos/ioctl.c index a379ba368711..7071156b80a8 100644 --- a/fs/umsdos/ioctl.c +++ b/fs/umsdos/ioctl.c @@ -15,9 +15,6 @@ #include #include -#define PRINTK(x) -#define Printk(x) printk x - struct UMSDOS_DIR_ONCE { struct dirent *ent; int count; @@ -53,14 +50,14 @@ static int umsdos_ioctl_fill ( /* * Perform special function on a directory */ -int UMSDOS_ioctl_dir ( - struct inode *dir, +int UMSDOS_ioctl_dir ( struct inode *dir, struct file *filp, unsigned int cmd, unsigned long data) { int ret = -EPERM; int err; + struct dentry *old_dent; /* forward non-umsdos ioctls - this hopefully doesn't cause conflicts */ if (cmd != UMSDOS_GETVERSION @@ -154,18 +151,18 @@ int UMSDOS_ioctl_dir ( * * Return > 0 if success. */ - struct inode *emd_dir = umsdos_emd_dir_lookup (dir, 0); - if (emd_dir != NULL) { + old_dent = filp->f_dentry; + if (fix_emd_filp (filp) == 0) { while (1) { - if (filp->f_pos >= emd_dir->i_size) { + if (filp->f_pos >= filp->f_dentry->d_inode->i_size) { ret = 0; break; } else { struct umsdos_dirent entry; off_t f_pos = filp->f_pos; - ret = umsdos_emd_dir_readentry (emd_dir, filp, &entry); + ret = umsdos_emd_dir_readentry (filp, &entry); if (ret < 0) { break; } else if (entry.name_len > 0) { @@ -175,15 +172,15 @@ int UMSDOS_ioctl_dir ( umsdos_parse (entry.name, entry.name_len, &info); info.f_pos = f_pos; umsdos_manglename (&info); - copy_to_user (&idata->umsdos_dirent, &entry - ,sizeof (entry)); - copy_to_user (&idata->dos_dirent.d_name - ,info.fake.fname, info.fake.len + 1); + copy_to_user (&idata->umsdos_dirent, &entry, sizeof (entry)); + copy_to_user (&idata->dos_dirent.d_name, info.fake.fname, info.fake.len + 1); break; } } } - iput (emd_dir); /* FIXME? */ + fin_dentry (filp->f_dentry); + filp->f_dentry = old_dent; + /* iput (filp->f_dentry->d_inode); / * FIXME? */ } else { /* The absence of the EMD is simply seen as an EOF */ ret = 0; @@ -204,7 +201,7 @@ int UMSDOS_ioctl_dir ( struct inode *emd_dir = umsdos_emd_dir_lookup (dir, 1); ret = emd_dir != NULL; - iput (emd_dir); /* FIXME?? */ + /* iput (emd_dir); / * FIXME?? */ dir->i_op = ret ? &umsdos_dir_inode_operations @@ -251,7 +248,7 @@ int UMSDOS_ioctl_dir ( * ,dir * ,data.umsdos_dirent.name,data.umsdos_dirent.name_len); */ - old_dentry = creat_dentry (data.dos_dirent.d_name, data.dos_dirent.d_reclen, NULL, geti_dentry (dir)); /* FIXME: prolly should fill inode part */ + old_dentry = creat_dentry (data.dos_dirent.d_name, data.dos_dirent.d_reclen, NULL, geti_dentry (dir)); /* FIXME: probably should fill inode part */ new_dentry = creat_dentry (data.umsdos_dirent.name, data.umsdos_dirent.name_len, NULL, geti_dentry (dir)); ret = msdos_rename (dir, old_dentry, dir, new_dentry); } else if (cmd == UMSDOS_UNLINK_EMD) { @@ -283,10 +280,10 @@ int UMSDOS_ioctl_dir ( * * Return 0 if success. */ - inc_count (dir); - dp = creat_dentry (data.dos_dirent.d_name, data.dos_dirent.d_reclen, dir, NULL); - dentry = creat_dentry ("ioctl_unlink", 12, NULL, dp); + dp = geti_dentry (dir); + dentry = compat_umsdos_real_lookup (dp, data.dos_dirent.d_name, data.dos_dirent.d_reclen); ret = msdos_unlink (dir, dentry); + dput (dentry); /* FIXME: is this OK now? */ } else if (cmd == UMSDOS_RMDIR_DOS) { struct dentry *dentry, *dp; @@ -298,10 +295,10 @@ int UMSDOS_ioctl_dir ( * * Return 0 if success. */ - inc_count (dir); - dp = creat_dentry (data.dos_dirent.d_name, data.dos_dirent.d_reclen, dir, NULL); - dentry = creat_dentry ("ioctl_unlink", 12, NULL, dp); + dp = geti_dentry (dir); + dentry = compat_umsdos_real_lookup (dp, data.dos_dirent.d_name, data.dos_dirent.d_reclen); ret = msdos_rmdir (dir, dentry); + dput (dentry); /* FIXME: is this OK now? */ } else if (cmd == UMSDOS_STAT_DOS) { /* #Specification: ioctl / UMSDOS_STAT_DOS @@ -315,9 +312,12 @@ int UMSDOS_ioctl_dir ( * Return 0 if success. */ struct inode *inode; + struct dentry *d_dir, *dret; - ret = compat_umsdos_real_lookup (dir, data.dos_dirent.d_name, data.dos_dirent.d_reclen, &inode); - if (ret == 0) { + d_dir = geti_dentry (dir); + dret = compat_umsdos_real_lookup (d_dir, data.dos_dirent.d_name, data.dos_dirent.d_reclen); + if (dret) { + inode = dret->d_inode; data.stat.st_ino = inode->i_ino; data.stat.st_mode = inode->i_mode; data.stat.st_size = inode->i_size; @@ -325,20 +325,20 @@ int UMSDOS_ioctl_dir ( data.stat.st_ctime = inode->i_ctime; data.stat.st_mtime = inode->i_mtime; copy_to_user (&idata->stat, &data.stat, sizeof (data.stat)); - /* iput (inode); FIXME */ + fin_dentry (dret); } } else if (cmd == UMSDOS_DOS_SETUP) { /* #Specification: ioctl / UMSDOS_DOS_SETUP * The UMSDOS_DOS_SETUP ioctl allow changing the - * default permission of the MsDOS file system driver - * on the fly. The MsDOS driver apply global permission + * default permission of the MS-DOS filesystem driver + * on the fly. The MS-DOS driver applies global permissions * to every file and directory. Normally these permissions * are controlled by a mount option. This is not * available for root partition, so a special utility * (umssetup) is provided to do this, normally in * /etc/rc.local. * - * Be aware that this apply ONLY to MsDOS directory + * Be aware that this applies ONLY to MS-DOS directories * (those without EMD --linux-.---). Umsdos directory * have independent (standard) permission for each * and every file. diff --git a/fs/umsdos/mangle.c b/fs/umsdos/mangle.c index ecd62f4c30bc..bf957b0a4dca 100644 --- a/fs/umsdos/mangle.c +++ b/fs/umsdos/mangle.c @@ -4,7 +4,7 @@ * Written 1993 by Jacques Gelinas * * Control the mangling of file name to fit msdos name space. - * Many optimisation by GLU == dglaude@is1.vub.ac.be (GLAUDE DAVID) + * Many optimisations by GLU == dglaude@is1.vub.ac.be (Glaude David) */ #include @@ -47,7 +47,7 @@ void umsdos_manglename (struct umsdos_info *info) * different extensions which should not clash with any useful * extension already popular or meaningful. Since most directory * have much less than 32 * 32 files in it, the first character - * of the extension of any mangle name will be {. + * of the extension of any mangled name will be {. * * Here are the reason to do this (this kind of mangling). * @@ -72,10 +72,11 @@ void umsdos_manglename (struct umsdos_info *info) } u; char *pt = info->fake.fname + info->fake.len; - /* lookup for encoding the last character of the extension */ - /* It contain valid character after the ugly one to make sure */ - /* even if someone overflow the 32 * 32 * 9 limit, it still do */ - /* something */ + /* lookup for encoding the last character of the extension + * It contains valid character after the ugly one to make sure + * even if someone overflows the 32 * 32 * 9 limit, it still + * does something + */ #define SPECIAL_MANGLING '{','}','(',')','!','`','^','&','@' static char lookup3[] = { @@ -89,7 +90,7 @@ void umsdos_manglename (struct umsdos_info *info) #define lookup12 (lookup3+9) u.entry_num = info->f_pos / UMSDOS_REC_SIZE; if (u.entry_num > (9 * 32 * 32)) { - printk ("UMSDOS: More than 9216 file in a directory.\n" + printk (KERN_WARNING "UMSDOS: more than 9216 files in a directory.\n" "This may break the mangling strategy.\n" "Not a killer problem. See doc.\n"); } @@ -136,7 +137,7 @@ int umsdos_evalrecsize_old (int len) /* * Fill the struct info with the full and msdos name of a file - * Return 0 if all is ok, a negative error code otherwise. + * Return 0 if all is OK, a negative error code otherwise. */ int umsdos_parse ( const char *fname, @@ -153,10 +154,10 @@ int umsdos_parse ( if (len > UMSDOS_MAXNAME) len = UMSDOS_MAXNAME; { - const char *firstpt = NULL; /* First place we saw a . in fname */ + const char *firstpt = NULL; /* First place we saw a "." in fname */ /* #Specification: file name / non MSDOS conforming / base length 0 - * file name beginning with a period '.' are invalid for MsDOS. + * file names beginning with a period '.' are invalid for MS-DOS. * It needs absolutely a base name. So the file name is mangled */ int ivldchar = fname[0] == '.'; /* At least one invalid character */ @@ -164,8 +165,8 @@ int umsdos_parse ( int base_len; /* - * cardinal_per_size tells if there exist at least one - * DOS pseudo devices on length n. See the test below. + * cardinal_per_size tells if there exists at least one + * DOS pseudo device on length n. See the test below. */ static const char cardinal_per_size[9] = { @@ -175,15 +176,15 @@ int umsdos_parse ( /* * lkp translate all character to acceptable character (for DOS). * When lkp[n] == n, it means also it is an acceptable one. - * So it serve both as a flag and as a translator. + * So it serves both as a flag and as a translator. */ static char lkp[256]; static char is_init = 0; if (!is_init) { /* - * Initialisation of the array is easier and less error prone - * like this. + * Initialisation of the array is easier and less error + * prone like this. */ int i; static const char *spc = "\"*+,/:;<=>?[\\]|~"; @@ -205,9 +206,9 @@ int umsdos_parse ( lkp[(unsigned char) (*spc++)] = '#'; } /* GLU - * file name which are longer than 8+'.'+3 are invalid for MsDOS. - * So the file name is to be mangled no more test needed. - * This Speed Up for long and very long name. + * File names longer than 8+'.'+3 are invalid for MS-DOS, + * so the file name is to be mangled--no further test is needed. + * This speeds up handling of long names. * The position of the last point is no more necessary anyway. */ if (len <= (8 + 1 + 3)) { @@ -235,8 +236,8 @@ int umsdos_parse ( } else if (extlen == 1) { /* #Specification: file name / non MSDOS conforming / last char == . * If the last character of a file name is - * a period, mangling is applied. MsDOS do - * not support those file name. + * a period, mangling is applied. MS-DOS does + * not support those file names. */ ivldchar = 1; break; @@ -244,7 +245,7 @@ int umsdos_parse ( /* #Specification: file name / non MSDOS conforming / mangling clash * To avoid clash with the umsdos mangling, any file * with a special character as the first character - * of the extension will be mangled. This solve the + * of the extension will be mangled. This solves the * following problem: * * # @@ -285,7 +286,7 @@ int umsdos_parse ( * name. So UMSDOS does not restrict its use. */ /* #Specification: file name / non MSDOS conforming / mangling - * Non MSDOS conforming file name must use some alias to fit + * Non MSDOS conforming file names must use some alias to fit * in the MSDOS name space. * * The strategy is simple. The name is simply truncated to @@ -294,15 +295,15 @@ int umsdos_parse ( * to the entry number in the EMD file. The EMD file * only need to carry the real name. * - * Upper case is also convert to lower case. + * Upper case is also converted to lower case. * Control character are converted to #. - * Space are converted to #. - * The following character are also converted to #. + * Spaces are converted to #. + * The following characters are also converted to #. * # * " * + , / : ; < = > ? [ \ ] | ~ * # * - * Sometime, the problem is not in MsDOS itself but in + * Sometimes the problem is not in MS-DOS itself but in * command.com. */ int i; @@ -316,7 +317,7 @@ int umsdos_parse ( memcpy (info->fake.fname, fname, msdos_len); for (i = 0; i < msdos_len; i++, pt++) *pt = lkp[(unsigned char) (*pt)]; - *pt = '\0'; /* GLU C'est sur on a un 0 a la fin */ + *pt = '\0'; /* GLU We force null termination. */ info->msdos_reject = 1; /* * The numeric extension is added only when we know @@ -332,15 +333,15 @@ int umsdos_parse ( } if (cardinal_per_size[base_len]) { /* #Specification: file name / MSDOS devices / mangling - * To avoid unreachable file from MsDOS, any MsDOS conforming - * file with a basename equal to one of the MsDOS pseudo + * To avoid unreachable file from MS-DOS, any MS-DOS conforming + * file with a basename equal to one of the MS-DOS pseudo * devices will be mangled. * * If a file such as "prn" was created, it would be unreachable - * under MsDOS because prn is assumed to be the printer, even + * under MS-DOS because "prn" is assumed to be the printer, even * if the file does have an extension. * - * Since the extension is unimportant to MsDOS, we must patch + * Since the extension is unimportant to MS-DOS, we must patch * the basename also. We simply insert a minus '-'. To avoid * conflict with valid file with a minus in front (such as * "-prn"), we add an mangled extension like any other @@ -359,10 +360,10 @@ int umsdos_parse ( * * "emmxxxx0","xmsxxxx0","setverxx" * - * (Thanks to Chris Hall - * for pointing these to me). + * (Thanks to Chris Hall + * for pointing these out to me). * - * Is there one missing ? + * Is there one missing? */ /* This table must be ordered by length */ static const char *tbdev[] = @@ -386,13 +387,13 @@ int umsdos_parse ( for (i = start_ind_dev[base_len - 1]; i < start_ind_dev[base_len]; i++) { if (memcmp (info->fake.fname, tbdev[i], base_len) == 0) { memcpy (basen, info->fake.fname, base_len); - basen[base_len] = '\0'; /* GLU C'est sur on a un 0 a la fin */ + basen[base_len] = '\0'; /* GLU We force null termination. */ /* - * GLU On ne fait cela que si necessaire, on essaye d'etre le - * GLU simple dans le cas general (le plus frequent). + * GLU We do that only if necessary; we try to do the + * GLU simple thing in the usual circumstance. */ info->fake.fname[0] = '-'; - strcpy (info->fake.fname + 1, basen); /* GLU C'est sur on a un 0 a la fin */ + strcpy (info->fake.fname + 1, basen); /* GLU We already guaranteed a null would be at the end. */ msdos_len = (base_len == 8) ? 8 : base_len + 1; info->msdos_reject = 1; break; @@ -400,15 +401,16 @@ int umsdos_parse ( } } info->fake.fname[msdos_len] = '\0'; /* Help doing printk */ - /* GLU Ce zero devrais deja y etre ! (invariant ?) */ + /* GLU This zero should (always?) be there already. */ info->fake.len = msdos_len; - /* Pourquoi ne pas utiliser info->fake.len partout ??? plus long ? */ + /* Why not use info->fake.len everywhere? Is it longer? + */ memcpy (info->entry.name, fname, len); info->entry.name_len = len; ret = 0; } /* - * Evaluate how many record are needed to store this entry. + * Evaluate how many records are needed to store this entry. */ info->recsize = umsdos_evalrecsize (len); return ret; @@ -435,15 +437,15 @@ struct MANG_TEST tb[] = "Hello.c", 1, "hello.c", #elseif /* - * Je trouve les trois exemples ci-dessous tres "malheureux". - * Je propose de mettre en minuscule dans un passe preliminaire, - * et de tester apres si il y a d'autres caracters "mechants". - * Bon, je ne l'ai pas fait, parceque ce n'est pas si facilement - * modifiable que ca. Mais c'est pour le principe. - * Evidemment cela augmente les chances de "Collision", - * par exemple: entre "HELLO" et "Hello", mais ces problemes - * peuvent etre traiter ailleur avec les autres collisions. + * I find the three examples below very unfortunate. I propose to + * convert them to lower case in a quick preliminary pass, then test + * whether there are other troublesome characters. I have not made + * this change, because it is not easy, but I wanted to mention the + * principle. Obviously something like that would increase the chance + * of collisions, for example between "HELLO" and "Hello", but these + * can be treated elsewhere along with the other collisions. */ + "HELLO", 1, "hello", "Hello.1", 1, "hello_1", "Hello.c", 1, "hello_c", @@ -465,11 +467,12 @@ struct MANG_TEST tb[] = "prn.abc", 1, "-prn", "PRN", 1, "-prn", /* - * GLU ATTENTION : Le resultat de ceux-ci sont differents avec ma version - * GLU du mangle par rapport au mangle originale. - * GLU CAUSE: La maniere de calculer la variable baselen. - * GLU Pour toi c'est toujours 3 - * GLU Pour moi c'est respectivement 7, 8 et 8 + * GLU WARNING: the results of these are different with my version + * GLU of mangling compared to the original one. + * GLU CAUSE: the manner of calculating the baselen variable. + * GLU For you they are always 3. + * GLU For me they are respectively 7, 8, and 8. + */ "PRN.abc", 1, "prn_abc", "Prn.abcd", 1, "prn_abcd", diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c index 387ed4fe32cf..95d2eed96167 100644 --- a/fs/umsdos/namei.c +++ b/fs/umsdos/namei.c @@ -18,9 +18,6 @@ #include #include -#define PRINTK(x) -#define Printk(x) printk x - #if 1 /* * Wait for creation exclusivity. @@ -230,7 +227,7 @@ static int umsdos_create_any ( struct dentry *fake; Printk (("umsdos_create_any /mn/: create %.*s in dir=%lu - nevercreat=/", (int) dentry->d_name.len, dentry->d_name.name, dir->i_ino)); - check_dentry (dentry); + check_dentry_path (dentry, "umsdos_create_any"); ret = umsdos_nevercreat (dir, dentry, -EEXIST); Printk (("%d/\n", ret)); if (ret == 0) { @@ -262,8 +259,14 @@ static int umsdos_create_any ( Printk (("Creation OK: [dir %lu] %.*s pid=%d pos %ld\n", dir->i_ino, info.fake.len, info.fake.fname, current->pid, info.f_pos)); + check_dentry_path (dentry, "umsdos_create_any: BEG dentry"); + check_dentry_path (fake, "umsdos_create_any: BEG fake"); d_instantiate (dentry, inode); /* long name also gets inode info */ - dput (fake); /* FIXME: is this ok ? we try to kill short name dentry that we don't need */ + inc_count (fake->d_inode); /* we must do it, since dput(fake) will iput(our_inode) which we still need for long name (dentry) */ + /* dput (fake); / * FIXME: is this OK ? we try to kill short name dentry that we don't need */ + check_dentry_path (dentry, "umsdos_create_any: END dentry"); + check_dentry_path (fake, "umsdos_create_any: END fake"); + } else { /* #Specification: create / file exist in DOS * Here is a situation. Trying to create a file with @@ -350,14 +353,12 @@ static int umsdos_rename_f ( /* != 0, this is the value of flags */ int ret = -EPERM; struct umsdos_info old_info; - int old_ret = umsdos_parse (old_dentry->d_name.name, - old_dentry->d_name.len, &old_info); + int old_ret = umsdos_parse (old_dentry->d_name.name, old_dentry->d_name.len, &old_info); struct umsdos_info new_info; - int new_ret = umsdos_parse (new_dentry->d_name.name, - new_dentry->d_name.len, &new_info); + int new_ret = umsdos_parse (new_dentry->d_name.name, new_dentry->d_name.len, &new_info); - check_dentry (old_dentry); - check_dentry (new_dentry); + check_dentry_path (old_dentry, "umsdos_rename_f OLD"); + check_dentry_path (new_dentry, "umsdos_rename_f OLD"); chkstk (); Printk (("umsdos_rename %d %d ", old_ret, new_ret)); @@ -386,10 +387,12 @@ static int umsdos_rename_f ( chkstk (); Printk (("ret %d %d ", ret, new_info.fake.len)); if (ret == 0) { - struct dentry *old, *new; + struct dentry *old, *new, *d_old_dir, *dret; struct inode *oldid = NULL; - ret = compat_umsdos_real_lookup (old_dir, old_info.fake.fname, old_info.fake.len, &oldid); + d_old_dir = creat_dentry ("@d_old_dir@", 11, old_dir, NULL); + dret = compat_umsdos_real_lookup (d_old_dir, old_info.fake.fname, old_info.fake.len); + if (dret) oldid = dret->d_inode; old = creat_dentry (old_info.fake.fname, old_info.fake.len, oldid, old_dentry->d_parent); new = creat_dentry (new_info.fake.fname, new_info.fake.len, NULL, new_dentry->d_parent); @@ -398,7 +401,9 @@ static int umsdos_rename_f ( inc_count (old_dir); inc_count (new_dir); /* Both inode are needed later */ - check_dentry (old); check_dentry (new); /* FIXME: debug only */ + check_dentry_path (old, "umsdos_rename_f OLD2"); + check_dentry_path (new, "umsdos_rename_f NEW2"); + ret = msdos_rename (old_dir, old, new_dir, new); chkstk (); Printk (("after m_rename ret %d ", ret)); @@ -441,6 +446,7 @@ static int umsdos_rename_f ( /* iput (inode); FIXME */ } } + fin_dentry (dret); } } } else { @@ -458,8 +464,8 @@ static int umsdos_rename_f ( umsdos_unlockcreate (old_dir); umsdos_unlockcreate (new_dir); } - check_dentry (old_dentry); - check_dentry (new_dentry); + check_dentry_path (old_dentry, "umsdos_rename_f OLD3"); + check_dentry_path (new_dentry, "umsdos_rename_f NEW3"); Printk ((" _ret=%d\n", ret)); return ret; @@ -467,7 +473,7 @@ static int umsdos_rename_f ( /* * Setup un Symbolic link or a (pseudo) hard link - * Return a negative error code or 0 if ok. + * Return a negative error code or 0 if OK. */ static int umsdos_symlink_x ( struct inode *dir, @@ -497,14 +503,14 @@ static int umsdos_symlink_x ( if (ret == 0) { int len = strlen (symname); struct file filp; - loff_t myofs = 0; fill_new_filp (&filp, dentry); + filp.f_pos = 0; /* Make the inode acceptable to MSDOS FIXME */ - Printk ((KERN_WARNING "umsdos_symlink_x: /mn/ Is this ok?\n")); + Printk ((KERN_WARNING "umsdos_symlink_x: /mn/ is this OK?\n")); Printk ((KERN_WARNING " symname=%s ; dentry name=%.*s (ino=%lu)\n", symname, (int) dentry->d_name.len, dentry->d_name.name, dentry->d_inode->i_ino)); - ret = umsdos_file_write_kmem_real (&filp, symname, len, &myofs); + ret = umsdos_file_write_kmem_real (&filp, symname, len); /* dput(dentry); ?? where did this come from FIXME */ if (ret >= 0) { @@ -528,7 +534,7 @@ static int umsdos_symlink_x ( /* * Setup un Symbolic link. - * Return a negative error code or 0 if ok. + * Return a negative error code or 0 if OK. */ int UMSDOS_symlink ( struct inode *dir, @@ -550,19 +556,18 @@ int UMSDOS_link ( struct inode *oldinode = olddentry->d_inode; /* #Specification: hard link / strategy - * Well ... hard link are difficult to implement on top of an - * MsDOS fat file system. Unlike UNIX file systems, there are no - * inode. A directory entry hold the functionality of the inode - * and the entry. + * Hard links are difficult to implement on top of an MS-DOS FAT file + * system. Unlike Unix file systems, there are no inodes. A directory + * entry holds the functionality of the inode and the entry. * * We will used the same strategy as a normal Unix file system - * (with inode) except we will do it symbolically (using paths). + * (with inodes) except we will do it symbolically (using paths). * * Because anything can happen during a DOS session (defragment, - * directory sorting, etc...), we can't rely on MsDOS pseudo + * directory sorting, etc.), we can't rely on an MS-DOS pseudo * inode number to record the link. For this reason, the link * will be done using hidden symbolic links. The following - * scenario illustrate how it work. + * scenario illustrates how it works. * * Given a file /foo/file * @@ -733,9 +738,12 @@ int UMSDOS_create ( int mode /* Permission bit + file type ??? */ ) { /* Will hold the inode of the newly created file */ + int ret; Printk ((KERN_ERR "UMSDOS_create: entering\n")); - check_dentry (dentry); - return umsdos_create_any (dir, dentry, mode, 0, 0); + check_dentry_path (dentry, "UMSDOS_create START"); + ret = umsdos_create_any (dir, dentry, mode, 0, 0); + check_dentry_path (dentry, "UMSDOS_create END"); + return ret; } @@ -771,7 +779,7 @@ int UMSDOS_mkdir ( if (ret == 0) { struct dentry *temp, *tdir; - tdir = creat_dentry ("mkd-dir", 7, dir, NULL); + tdir = creat_dentry ("@mkd-dir@", 9, dir, NULL); temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir); inc_count (dir); ret = msdos_mkdir (dir, temp, mode); @@ -789,15 +797,17 @@ int UMSDOS_mkdir ( * create immediately an EMD file in the new * sub-directory so it inherit UMSDOS semantic. */ - struct inode *subdir; + struct inode *subdir=NULL; + struct dentry *d_dir, *dret; - ret = compat_umsdos_real_lookup (dir, info.fake.fname, - info.fake.len, &subdir); - if (ret == 0) { - struct dentry *tdentry, - *tdsub; + d_dir = creat_dentry ("@d_dir5@", 7, dir, NULL); + dret = compat_umsdos_real_lookup (d_dir, info.fake.fname, info.fake.len); + if (dret) { + struct dentry *tdentry, *tdsub; + + subdir = dret->d_inode; - tdsub = creat_dentry ("mkd-emd", 7, subdir, NULL); + tdsub = creat_dentry ("@mkd-emd@", 9, subdir, NULL); tdentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, tdsub); ret = msdos_create (subdir, tdentry, S_IFREG | 0777); kill_dentry (tdentry); /* we don't want empty EMD file to be visible ! too bad kill_dentry does nothing at the moment :-) FIXME */ @@ -806,11 +816,12 @@ int UMSDOS_mkdir ( subdir = NULL; d_instantiate (dentry, temp->d_inode); /* iput (result); FIXME */ + fin_dentry (dret); } if (ret < 0) { printk ("UMSDOS: Can't create empty --linux-.---\n"); } - /* iput (subdir); FIXME */ + /*iput (subdir); FIXME*/ } } umsdos_unlockcreate (dir); @@ -847,9 +858,9 @@ int UMSDOS_mknod ( int ret; - check_dentry (dentry); + check_dentry_path (dentry, "UMSDOS_mknod START"); ret = umsdos_create_any (dir, dentry, mode, rdev, 0); - check_dentry (dentry); + check_dentry_path (dentry, "UMSDOS_mknod END"); /* dput(dentry); / * /mn/ FIXME! */ return ret; @@ -864,19 +875,19 @@ int UMSDOS_rmdir ( { /* #Specification: style / iput strategy * In the UMSDOS project, I am trying to apply a single - * programming style regarding inode management. Many - * entry point are receiving an inode to act on, and must + * programming style regarding inode management. Many + * entry points are receiving an inode to act on, and must * do an iput() as soon as they are finished with * the inode. * - * For simple case, there is no problem. When you introduce - * error checking, you end up with many iput placed around the + * For simple cases, there is no problem. When you introduce + * error checking, you end up with many iput() calls in the * code. * * The coding style I use all around is one where I am trying * to provide independent flow logic (I don't know how to - * name this). With this style, code is easier to understand - * but you rapidly get iput() all around. Here is an exemple + * name this). With this style, code is easier to understand + * but you must do iput() everywhere. Here is an example * of what I am trying to avoid. * * # @@ -887,7 +898,7 @@ int UMSDOS_rmdir ( * } * ... * if (c){ - * // Complex state. Was b true ? + * // Complex state. Was b true? * ... * } * ... @@ -896,19 +907,19 @@ int UMSDOS_rmdir ( * if (d){ * // ... * } - * // Was iput finally done ? + * // Was iput finally done? * return status; * # * - * Here is the style I am using. Still sometime I do the - * first when things are very simple (or very complicated :-( ) + * Here is the style I am using. Still sometimes I do the + * first when things are very simple (or very complicated :-( ). * * # * if (a){ * if (b){ * ... * }else if (c){ - * // A single state gets here + * // A single state gets here. * } * }else if (d){ * ... @@ -926,7 +937,7 @@ int UMSDOS_rmdir ( * to do an iput()). One iput by inode. There is also one iput() * at the places where a successful operation is achieved. This * iput() is often done by a sub-function (often from the msdos - * file system). So I get one too many iput() ? At the place + * file system). So I get one too many iput()? At the place * where an iput() is done, the inode is simply nulled, disabling * the last one. * @@ -954,7 +965,7 @@ int UMSDOS_rmdir ( ret = umsdos_nevercreat (dir, dentry, -EPERM); if (ret == 0) { - volatile struct inode *sdir; + /* volatile - DELME: I see no reason vor volatile /mn/ */ struct inode *sdir; inc_count (dir); ret = umsdos_lookup_x (dir, dentry, 0); @@ -974,7 +985,7 @@ int UMSDOS_rmdir ( } else if ((empty = umsdos_isempty (sdir)) != 0) { struct dentry *tdentry, *tedir; - tedir = creat_dentry ("emd-rmd", 7, dir, NULL); + tedir = creat_dentry ("@emd-rmd@", 9, dir, NULL); tdentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, tedir); umsdos_real_lookup (dir, tdentry); /* fill inode part */ Printk (("isempty %d i_count %d ", empty, sdir->i_count)); @@ -1002,7 +1013,7 @@ int UMSDOS_rmdir ( /* the mangling */ umsdos_findentry (dir, &info, 2); - tdir = creat_dentry ("dir-rmd", 7, dir, NULL); + tdir = creat_dentry ("@dir-rmd@", 9, dir, NULL); temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir); umsdos_real_lookup (dir, temp); /* fill inode part */ @@ -1078,7 +1089,7 @@ int UMSDOS_unlink ( current->fsuid == dir->i_uid) { if (info.entry.flags & UMSDOS_HLINK) { /* #Specification: hard link / deleting a link - * When we deletes a file, and this file is a link + * When we delete a file, and this file is a link * we must subtract 1 to the nlink field of the * hidden link. * @@ -1123,9 +1134,9 @@ int UMSDOS_unlink ( struct dentry *temp, *tdir; - Printk (("Avant msdos_unlink %.*s ", info.fake.len, info.fake.fname)); - inc_count (dir); /* FIXME /mn/ is this needed anymore now that msdos_unlink locks dir using d_parent ? */ - tdir = creat_dentry ("dir-del", 7, dir, NULL); /* FIXME /mn/: do we need iget(dir->i_ino) or would dir itself suffice ? */ + Printk (("Before msdos_unlink %.*s ", info.fake.len, info.fake.fname)); + /* inc_count (dir); / * FIXME /mn/ is this needed any more now that msdos_unlink locks directories using d_parent ? */ + tdir = creat_dentry ("@dir-del@", 9, dir, NULL); /* FIXME /mn/: do we need iget(dir->i_ino) or would dir itself suffice ? */ temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir); umsdos_real_lookup (dir, temp); /* fill inode part */ @@ -1141,7 +1152,7 @@ int UMSDOS_unlink ( } } else { /* sticky bit set and we've not got permission */ - Printk (("sticky set ")); + Printk (("Sticky bit set. ")); ret = -EPERM; } } @@ -1156,7 +1167,7 @@ int UMSDOS_unlink ( /* - * Rename a file (move) in the file system. + * Rename (move) a file. */ int UMSDOS_rename ( struct inode *old_dir, @@ -1166,14 +1177,14 @@ int UMSDOS_rename ( { /* #Specification: weakness / rename * There is a case where UMSDOS rename has a different behavior - * than normal UNIX file system. Renaming an open file across - * directory boundary does not work. Renaming an open file within - * a directory does work however. + * than a normal Unix file system. Renaming an open file across + * directory boundary does not work. Renaming an open file within + * a directory does work, however. * - * The problem (not sure) is in the linux VFS msdos driver. + * The problem may is in Linux VFS driver for msdos. * I believe this is not a bug but a design feature, because - * an inode number represent some sort of directory address - * in the MSDOS directory structure. So moving the file into + * an inode number represents some sort of directory address + * in the MSDOS directory structure, so moving the file into * another directory does not preserve the inode number. */ int ret = umsdos_nevercreat (new_dir, new_dentry, -EEXIST); @@ -1185,9 +1196,9 @@ int UMSDOS_rename ( ret = umsdos_rename_f (old_dir, old_dentry, new_dir, new_dentry, 0); if (ret == -EEXIST) { /* #Specification: rename / new name exist - * If the destination name already exist, it will - * silently be removed. EXT2 does it this way - * and this is the spec of SUNOS. So does UMSDOS. + * If the destination name already exists, it will + * silently be removed. EXT2 does it this way + * and this is the spec of SunOS. So does UMSDOS. * * If the destination is an empty directory it will * also be removed. @@ -1195,19 +1206,19 @@ int UMSDOS_rename ( /* #Specification: rename / new name exist / possible flaw * The code to handle the deletion of the target (file * and directory) use to be in umsdos_rename_f, surrounded - * by proper directory locking. This was insuring that only + * by proper directory locking. This was ensuring that only * one process could achieve a rename (modification) operation - * in the source and destination directory. This was also - * insuring the operation was "atomic". + * in the source and destination directory. This was also + * ensuring the operation was "atomic". * - * This has been changed because this was creating a kernel - * stack overflow (stack is only 4k in the kernel). To avoid + * This has been changed because this was creating a + * stack overflow (the stack is only 4 kB) in the kernel. To avoid * the code doing the deletion of the target (if exist) has * been moved to a upper layer. umsdos_rename_f is tried * once and if it fails with EEXIST, the target is removed * and umsdos_rename_f is done again. * - * This makes the code cleaner and (not sure) solve a + * This makes the code cleaner and may solve a * deadlock problem one tester was experiencing. * * The point is to mention that possibly, the semantic of @@ -1217,7 +1228,7 @@ int UMSDOS_rename ( * same target at the same time. Again, I am not sure it * is a problem at all. */ - /* This is not super efficient but should work */ + /* This is not terribly efficient but should work. */ inc_count (new_dir); ret = UMSDOS_unlink (new_dir, new_dentry); chkstk (); diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c index 5d5cd55af86b..9119220e5f38 100644 --- a/fs/umsdos/rdir.c +++ b/fs/umsdos/rdir.c @@ -30,8 +30,7 @@ struct RDIR_FILLDIR { int real_root; }; -static int rdir_filldir ( - void *buf, +static int rdir_filldir ( void *buf, const char *name, int name_len, off_t offset, @@ -116,6 +115,7 @@ int umsdos_rlookup_x ( * is the pseudo root (c:\linux). */ } else { + inc_count (dir); ret = umsdos_real_lookup (dir, dentry); inode = dentry->d_inode; @@ -142,13 +142,13 @@ int umsdos_rlookup_x ( } else if (S_ISDIR (inode->i_mode)) { /* We must place the proper function table */ - /* depending if this is a MsDOS directory or an UMSDOS directory */ + /* depending on whether this is an MS-DOS or a UMSDOS directory */ Printk ((KERN_DEBUG "umsdos_rlookup_x: setting up setup_dir_inode %lu...\n", inode->i_ino)); umsdos_setup_dir_inode (inode); } } + iput (dir); } - iput (dir); /* FIXME? */ PRINTK ((KERN_DEBUG "umsdos_rlookup_x: returning %d\n", ret)); return ret; } @@ -170,7 +170,7 @@ static int UMSDOS_rrmdir ( { /* #Specification: dual mode / rmdir in a DOS directory * In a DOS (not EMD in it) directory, we use a reverse strategy - * compared with an Umsdos directory. We assume that a subdirectory + * compared with a UMSDOS directory. We assume that a subdirectory * of a DOS directory is also a DOS directory. This is not always * true (umssync may be used anywhere), but make sense. * @@ -189,7 +189,7 @@ static int UMSDOS_rrmdir ( * The pseudo sub-directory /DOS can't be removed! * This is done even if the pseudo root is not a Umsdos * directory anymore (very unlikely), but an accident (under - * MsDOS) is always possible. + * MS-DOS) is always possible. * * EPERM is returned. */ @@ -219,11 +219,11 @@ static int UMSDOS_rrmdir ( */ ret = -ENOTEMPTY; } else if (empty == 1) { - /* We have to removed the EMD file */ + /* We have to remove the EMD file. */ struct dentry *temp; - Printk ((KERN_WARNING "UMSDOS_rmdir: hmmm... whatabout inode ? FIXME\n")); - temp = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, NULL); /* FIXME: prolly should fill inode part ? */ + Printk ((KERN_WARNING "UMSDOS_rmdir: hmmm... what about inode? FIXME\n")); + temp = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, NULL); /* FIXME: probably should fill inode part ? */ ret = msdos_unlink (sdir, temp); sdir = NULL; if (ret == 0) { @@ -240,17 +240,18 @@ static int UMSDOS_rrmdir ( umsdos_unlockcreate (dir); } /* iput (dir); FIXME */ + check_inode (dir); return ret; } /* #Specification: dual mode / introduction * One goal of UMSDOS is to allow a practical and simple coexistence - * between MsDOS and Linux in a single partition. Using the EMD file - * in each directory, UMSDOS add Unix semantics and capabilities to - * normal DOS file system. To help and simplify coexistence, here is + * between MS-DOS and Linux in a single partition. Using the EMD file + * in each directory, UMSDOS adds Unix semantics and capabilities to + * a normal DOS filesystem. To help and simplify coexistence, here is * the logic related to the EMD file. * - * If it is missing, then the directory is managed by the MsDOS driver. + * If it is missing, then the directory is managed by the MS-DOS driver. * The names are limited to DOS limits (8.3). No links, no device special * and pipe and so on. * @@ -259,12 +260,12 @@ static int UMSDOS_rrmdir ( * of the real DOS directory and the EMD. * * Whenever umssync is applied to a directory without EMD, one is - * created on the fly. The directory is promoted to full unix semantic. + * created on the fly. The directory is promoted to full Unix semantics. * Of course, the ls command will show exactly the same content as before * the umssync session. * - * It is believed that the user/admin will promote directories to unix - * semantic as needed. + * It is believed that the user/admin will promote directories to Unix + * semantics as needed. * * The strategy to implement this is to use two function table (struct * inode_operations). One for true UMSDOS directory and one for directory @@ -272,12 +273,12 @@ static int UMSDOS_rrmdir ( * * Functions related to the DOS semantic (but aware of UMSDOS) generally * have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate - * from the one with full UMSDOS semantic. + * from the one with full UMSDOS semantics. */ static struct file_operations umsdos_rdir_operations = { NULL, /* lseek - default */ - UMSDOS_dir_read, /* read */ + dummy_dir_read, /* read */ NULL, /* write - bad */ UMSDOS_rreaddir, /* readdir */ NULL, /* poll - default */ diff --git a/fs/umsdos/symlink.c b/fs/umsdos/symlink.c index 696059ce21c9..dc639a7a4420 100644 --- a/fs/umsdos/symlink.c +++ b/fs/umsdos/symlink.c @@ -19,9 +19,6 @@ #include #include -#define PRINTK(x) -#define Printk(x) printk x - static struct file_operations umsdos_symlink_operations; @@ -31,10 +28,9 @@ static struct file_operations umsdos_symlink_operations; * */ -static int umsdos_readlink_x ( - struct dentry *dentry, - char *buffer, - int bufsiz) +int umsdos_readlink_x ( struct dentry *dentry, + char *buffer, + int bufsiz) { int ret; loff_t loffs = 0; @@ -42,7 +38,10 @@ static int umsdos_readlink_x ( ret = dentry->d_inode->i_size; - check_dentry (dentry); + if (!(dentry->d_inode)) { + return -EBADF; + } + fill_new_filp (&filp, dentry); filp.f_reada = 0; @@ -68,7 +67,7 @@ static int umsdos_readlink_x ( if (fat_file_read (&filp, buffer, (size_t) ret, &loffs) != ret) { ret = -EIO; } -#if 0 /* DEBUG */ +#if 0 { struct umsdos_dirent *mydirent = buffer; @@ -89,9 +88,11 @@ static int UMSDOS_readlink (struct dentry *dentry, char *buffer, int buflen) int ret; PRINTK ((KERN_DEBUG "UMSDOS_readlink: calling umsdos_readlink_x for %.*s\n", (int) dentry->d_name.len, dentry->d_name.name)); + ret = umsdos_readlink_x (dentry, buffer, buflen); PRINTK ((KERN_DEBUG "readlink %d bufsiz %d\n", ret, buflen)); - /* dput(dentry); / * FIXME /mn/ */ + /* dput(dentry); / * FIXME /mn/? It seems it is unneeded. d_count is not changed by umsdos_readlink_x */ + Printk ((KERN_WARNING "UMSDOS_readlink /mn/: FIXME! skipped dput(dentry). returning %d\n", ret)); return ret; diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 29f024b51203..025403081caf 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -31,6 +31,8 @@ struct cpuinfo_x86 { __u32 x86_capability; char x86_vendor_id[16]; char x86_model_id[64]; + int x86_cache_size; /* in KB - valid for CPUS which support this + call */ int fdiv_bug; int f00f_bug; unsigned long loops_per_sec; diff --git a/include/asm-m68k/adb_mouse.h b/include/asm-m68k/adb_mouse.h new file mode 100644 index 000000000000..824113662401 --- /dev/null +++ b/include/asm-m68k/adb_mouse.h @@ -0,0 +1,23 @@ +#ifndef _ASM_ADB_MOUSE_H +#define _ASM_ADB_MOUSE_H + +/* + * linux/include/asm-m68k/adb_mouse.h + * header file for Macintosh ADB mouse driver + * 27-10-97 Michael Schmitz + * copied from: + * header file for Atari Mouse driver + * by Robert de Vries (robert@and.nl) on 19Jul93 + */ + +struct mouse_status { + char buttons; + short dx; + short dy; + int ready; + int active; + struct wait_queue *wait; + struct fasync_struct *fasyncptr; +}; + +#endif diff --git a/include/asm-m68k/amigahw.h b/include/asm-m68k/amigahw.h index a5d1059797dd..39dd49979e4f 100644 --- a/include/asm-m68k/amigahw.h +++ b/include/asm-m68k/amigahw.h @@ -20,7 +20,7 @@ * Different Amiga models */ -extern u_long amiga_model; +extern unsigned long amiga_model; #define AMI_UNKNOWN (0) #define AMI_500 (1) @@ -44,7 +44,7 @@ extern u_long amiga_model; * Chipsets */ -extern u_long amiga_chipset; +extern unsigned long amiga_chipset; #define CS_STONEAGE (0) #define CS_OCS (1) @@ -56,12 +56,12 @@ extern u_long amiga_chipset; * Miscellaneous */ -extern u_long amiga_eclock; /* 700 kHz E Peripheral Clock */ -extern u_long amiga_masterclock; /* 28 MHz Master Clock */ -extern u_long amiga_colorclock; /* 3.5 MHz Color Clock */ -extern u_long amiga_chip_size; /* Chip RAM Size (bytes) */ -extern u_char amiga_vblank; /* VBLANK Frequency */ -extern u_char amiga_psfreq; /* Power Supply Frequency */ +extern unsigned long amiga_eclock; /* 700 kHz E Peripheral Clock */ +extern unsigned long amiga_masterclock; /* 28 MHz Master Clock */ +extern unsigned long amiga_colorclock; /* 3.5 MHz Color Clock */ +extern unsigned long amiga_chip_size; /* Chip RAM Size (bytes) */ +extern unsigned char amiga_vblank; /* VBLANK Frequency */ +extern unsigned char amiga_psfreq; /* Power Supply Frequency */ #define AMIGAHW_DECLARE(name) unsigned name : 1 @@ -111,122 +111,122 @@ struct amiga_hw_present { extern struct amiga_hw_present amiga_hw_present; struct CUSTOM { - u_short bltddat; - u_short dmaconr; - u_short vposr; - u_short vhposr; - u_short dskdatr; - u_short joy0dat; - u_short joy1dat; - u_short clxdat; - u_short adkconr; - u_short pot0dat; - u_short pot1dat; - u_short potgor; - u_short serdatr; - u_short dskbytr; - u_short intenar; - u_short intreqr; - u_char *dskptr; - u_short dsklen; - u_short dskdat; - u_short refptr; - u_short vposw; - u_short vhposw; - u_short copcon; - u_short serdat; - u_short serper; - u_short potgo; - u_short joytest; - u_short strequ; - u_short strvbl; - u_short strhor; - u_short strlong; - u_short bltcon0; - u_short bltcon1; - u_short bltafwm; - u_short bltalwm; - u_char *bltcpt; - u_char *bltbpt; - u_char *bltapt; - u_char *bltdpt; - u_short bltsize; - u_char pad2d; - u_char bltcon0l; - u_short bltsizv; - u_short bltsizh; - u_short bltcmod; - u_short bltbmod; - u_short bltamod; - u_short bltdmod; - u_short spare2[4]; - u_short bltcdat; - u_short bltbdat; - u_short bltadat; - u_short spare3[3]; - u_short deniseid; - u_short dsksync; - u_short *cop1lc; - u_short *cop2lc; - u_short copjmp1; - u_short copjmp2; - u_short copins; - u_short diwstrt; - u_short diwstop; - u_short ddfstrt; - u_short ddfstop; - u_short dmacon; - u_short clxcon; - u_short intena; - u_short intreq; - u_short adkcon; + unsigned short bltddat; + unsigned short dmaconr; + unsigned short vposr; + unsigned short vhposr; + unsigned short dskdatr; + unsigned short joy0dat; + unsigned short joy1dat; + unsigned short clxdat; + unsigned short adkconr; + unsigned short pot0dat; + unsigned short pot1dat; + unsigned short potgor; + unsigned short serdatr; + unsigned short dskbytr; + unsigned short intenar; + unsigned short intreqr; + unsigned char *dskptr; + unsigned short dsklen; + unsigned short dskdat; + unsigned short refptr; + unsigned short vposw; + unsigned short vhposw; + unsigned short copcon; + unsigned short serdat; + unsigned short serper; + unsigned short potgo; + unsigned short joytest; + unsigned short strequ; + unsigned short strvbl; + unsigned short strhor; + unsigned short strlong; + unsigned short bltcon0; + unsigned short bltcon1; + unsigned short bltafwm; + unsigned short bltalwm; + unsigned char *bltcpt; + unsigned char *bltbpt; + unsigned char *bltapt; + unsigned char *bltdpt; + unsigned short bltsize; + unsigned char pad2d; + unsigned char bltcon0l; + unsigned short bltsizv; + unsigned short bltsizh; + unsigned short bltcmod; + unsigned short bltbmod; + unsigned short bltamod; + unsigned short bltdmod; + unsigned short spare2[4]; + unsigned short bltcdat; + unsigned short bltbdat; + unsigned short bltadat; + unsigned short spare3[3]; + unsigned short deniseid; + unsigned short dsksync; + unsigned short *cop1lc; + unsigned short *cop2lc; + unsigned short copjmp1; + unsigned short copjmp2; + unsigned short copins; + unsigned short diwstrt; + unsigned short diwstop; + unsigned short ddfstrt; + unsigned short ddfstop; + unsigned short dmacon; + unsigned short clxcon; + unsigned short intena; + unsigned short intreq; + unsigned short adkcon; struct { - u_short *audlc; - u_short audlen; - u_short audper; - u_short audvol; - u_short auddat; - u_short audspare[2]; + unsigned short *audlc; + unsigned short audlen; + unsigned short audper; + unsigned short audvol; + unsigned short auddat; + unsigned short audspare[2]; } aud[4]; - u_char *bplpt[8]; - u_short bplcon0; - u_short bplcon1; - u_short bplcon2; - u_short bplcon3; - u_short bpl1mod; - u_short bpl2mod; - u_short bplcon4; - u_short clxcon2; - u_short bpldat[8]; - u_char *sprpt[8]; + unsigned char *bplpt[8]; + unsigned short bplcon0; + unsigned short bplcon1; + unsigned short bplcon2; + unsigned short bplcon3; + unsigned short bpl1mod; + unsigned short bpl2mod; + unsigned short bplcon4; + unsigned short clxcon2; + unsigned short bpldat[8]; + unsigned char *sprpt[8]; struct { - u_short pos; - u_short ctl; - u_short dataa; - u_short datab; + unsigned short pos; + unsigned short ctl; + unsigned short dataa; + unsigned short datab; } spr[8]; - u_short color[32]; - u_short htotal; - u_short hsstop; - u_short hbstrt; - u_short hbstop; - u_short vtotal; - u_short vsstop; - u_short vbstrt; - u_short vbstop; - u_short sprhstrt; - u_short sprhstop; - u_short bplhstrt; - u_short bplhstop; - u_short hhposw; - u_short hhposr; - u_short beamcon0; - u_short hsstrt; - u_short vsstrt; - u_short hcenter; - u_short diwhigh; - u_short spare4[11]; - u_short fmode; + unsigned short color[32]; + unsigned short htotal; + unsigned short hsstop; + unsigned short hbstrt; + unsigned short hbstop; + unsigned short vtotal; + unsigned short vsstop; + unsigned short vbstrt; + unsigned short vbstop; + unsigned short sprhstrt; + unsigned short sprhstop; + unsigned short bplhstrt; + unsigned short bplhstop; + unsigned short hhposw; + unsigned short hhposr; + unsigned short beamcon0; + unsigned short hsstrt; + unsigned short vsstrt; + unsigned short hcenter; + unsigned short diwhigh; + unsigned short spare4[11]; + unsigned short fmode; }; /* @@ -249,21 +249,21 @@ struct CUSTOM { #define DMAF_ALL (0x01FF) struct CIA { - u_char pra; char pad0[0xff]; - u_char prb; char pad1[0xff]; - u_char ddra; char pad2[0xff]; - u_char ddrb; char pad3[0xff]; - u_char talo; char pad4[0xff]; - u_char tahi; char pad5[0xff]; - u_char tblo; char pad6[0xff]; - u_char tbhi; char pad7[0xff]; - u_char todlo; char pad8[0xff]; - u_char todmid; char pad9[0xff]; - u_char todhi; char pada[0x1ff]; - u_char sdr; char padb[0xff]; - u_char icr; char padc[0xff]; - u_char cra; char padd[0xff]; - u_char crb; char pade[0xff]; + unsigned char pra; char pad0[0xff]; + unsigned char prb; char pad1[0xff]; + unsigned char ddra; char pad2[0xff]; + unsigned char ddrb; char pad3[0xff]; + unsigned char talo; char pad4[0xff]; + unsigned char tahi; char pad5[0xff]; + unsigned char tblo; char pad6[0xff]; + unsigned char tbhi; char pad7[0xff]; + unsigned char todlo; char pad8[0xff]; + unsigned char todmid; char pad9[0xff]; + unsigned char todhi; char pada[0x1ff]; + unsigned char sdr; char padb[0xff]; + unsigned char icr; char padc[0xff]; + unsigned char cra; char padd[0xff]; + unsigned char crb; char pade[0xff]; }; #define zTwoBase (0x80000000) diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h index 97aac09b2d98..e17fdf7f8dad 100644 --- a/include/asm-m68k/bitops.h +++ b/include/asm-m68k/bitops.h @@ -236,8 +236,6 @@ extern __inline__ int ffs(int x) #define hweight16(x) generic_hweight16(x) #define hweight8(x) generic_hweight8(x) -#endif /* __KERNEL__ */ - /* Bitmap functions for the minix filesystem */ extern __inline__ int @@ -366,4 +364,6 @@ ext2_find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset) return (p - addr) * 32 + res; } +#endif /* __KERNEL__ */ + #endif /* _M68K_BITOPS_H */ diff --git a/include/asm-m68k/checksum.h b/include/asm-m68k/checksum.h index d4a6e6fb9acf..f5236490a696 100644 --- a/include/asm-m68k/checksum.h +++ b/include/asm-m68k/checksum.h @@ -16,7 +16,7 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum); /* - * the same as csum_partial_copy, but copies from src while it + * the same as csum_partial, but copies from src while it * checksums * * here even more important to align src and dst on a 32-bit (or even @@ -33,13 +33,9 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum); * better 64-bit) boundary */ -unsigned int csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum); +extern unsigned int csum_partial_copy_from_user(const char *src, char *dst, + int len, int sum, int *csum_err); -extern unsigned int -csum_partial_copy_from_user ( const char *src, char *dst, - int len, int sum, int *csum_err); - -/* FIXME: this needs to be written to really do no check -- Cort */ #define csum_partial_copy_nocheck(src, dst, len, sum) \ csum_partial_copy((src), (dst), (len), (sum)) diff --git a/include/asm-m68k/hardirq.h b/include/asm-m68k/hardirq.h index 350fc0f699b0..acae65fc6aa5 100644 --- a/include/asm-m68k/hardirq.h +++ b/include/asm-m68k/hardirq.h @@ -7,12 +7,12 @@ extern unsigned int local_irq_count[NR_CPUS]; #define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0) -#define hardirq_trylock(cpu) (++local_irq_count[cpu], (cpu) == 0) -#define hardirq_endlock(cpu) (--local_irq_count[cpu]) +#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) +#define hardirq_endlock(cpu) do { } while (0) #define hardirq_enter(cpu) (local_irq_count[cpu]++) #define hardirq_exit(cpu) (local_irq_count[cpu]--) -#define synchronize_irq() do { } while (0) +#define synchronize_irq() barrier() #endif diff --git a/include/asm-m68k/io.h b/include/asm-m68k/io.h index a002fe2a0318..d6009638474b 100644 --- a/include/asm-m68k/io.h +++ b/include/asm-m68k/io.h @@ -3,8 +3,7 @@ #ifdef __KERNEL__ -#include /* CONFIG_ATARI, CONFIG_HADES */ -#include +#include #ifdef CONFIG_ATARI #include @@ -12,6 +11,8 @@ #define SLOW_DOWN_IO do { if (MACH_IS_ATARI) MFPDELAY(); } while (0) #endif +#include + /* * readX/writeX() are used to access memory mapped devices. On some * architectures the memory mapped IO stuff needs to be accessed @@ -42,34 +43,6 @@ #define outb(x,addr) ((void) writeb(x,addr)) #define outb_p(x,addr) outb(x,addr) -/* - * Change virtual addresses to physical addresses and vv. - */ -extern unsigned long mm_vtop(unsigned long addr) __attribute__ ((const)); -extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const)); - -extern inline unsigned long virt_to_phys(volatile void * address) -{ - return mm_vtop((unsigned long)address); -} - -extern inline void * phys_to_virt(unsigned long address) -{ - return (void *) mm_ptov(address); -} - -/* - * IO bus memory addresses are 1:1 with the physical address, - * except on the PCI bus of the Hades. - */ -#ifdef CONFIG_HADES -#define virt_to_bus(a) (virt_to_phys(a) + (MACH_IS_HADES ? 0x80000000 : 0)) -#define bus_to_virt(a) (phys_to_virt((a) - (MACH_IS_HADES ? 0x80000000 : 0))) -#else -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt -#endif - #endif /* __KERNEL__ */ #endif /* _M68K_IO_H */ diff --git a/include/asm-m68k/linux_logo.h b/include/asm-m68k/linux_logo.h index e57168b1ec9e..85f7d03f1e0f 100644 --- a/include/asm-m68k/linux_logo.h +++ b/include/asm-m68k/linux_logo.h @@ -26,9 +26,1422 @@ #define LINUX_LOGO_COLORS 221 #ifdef INCLUDE_LINUX_LOGO_DATA +unsigned char linux_logo_red[] __initdata = { + 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, + 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5, + 0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5, + 0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6, + 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD, + 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D, + 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, + 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, + 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03, + 0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6, + 0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2, + 0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A, + 0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4, + 0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2, + 0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC, + 0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC, + 0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7, + 0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3, + 0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4, + 0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4, + 0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87, + 0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78, + 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, + 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, + 0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E, + 0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B, + 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11, + 0x1D, 0x14, 0x06, 0x02, 0x00 +}; -#define INCLUDE_LINUX_LOGO16 -#include +unsigned char linux_logo_green[] __initdata = { + 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, + 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3, + 0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9, + 0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6, + 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD, + 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95, + 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, + 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, + 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02, + 0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD, + 0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6, + 0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C, + 0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4, + 0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E, + 0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC, + 0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5, + 0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96, + 0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80, + 0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F, + 0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C, + 0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54, + 0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78, + 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, + 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, + 0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E, + 0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B, + 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D, + 0x1D, 0x14, 0x06, 0x02, 0x00 +}; + +unsigned char linux_logo_blue[] __initdata = { + 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE, + 0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5, + 0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84, + 0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6, + 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD, + 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87, + 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99, + 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, + 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7, + 0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77, + 0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59, + 0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E, + 0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14, + 0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D, + 0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14, + 0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08, + 0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E, + 0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E, + 0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20, + 0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06, + 0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17, + 0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78, + 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62, + 0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46, + 0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14, + 0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A, + 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09, + 0x1D, 0x14, 0x06, 0x02, 0x00 +}; + +unsigned char linux_logo[] __initdata = { + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, + 0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61, + 0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E, + 0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58, + 0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, + 0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C, + 0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A, + 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52, + 0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53, + 0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, + 0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49, + 0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B, + 0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, + 0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB, + 0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C, + 0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49, + 0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5, + 0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58, + 0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51, + 0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54, + 0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5, + 0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61, + 0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C, + 0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B, + 0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53, + 0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC, + 0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59, + 0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48, + 0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61, + 0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63, + 0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48, + 0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51, + 0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52, + 0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB, + 0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B, + 0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53, + 0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53, + 0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC, + 0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F, + 0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61, + 0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57, + 0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D, + 0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, + 0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57, + 0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC, + 0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC, + 0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48, + 0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52, + 0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61, + 0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A, + 0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, + 0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B, + 0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC, + 0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC, + 0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49, + 0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F, + 0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB, + 0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47, + 0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54, + 0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D, + 0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC, + 0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC, + 0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45, + 0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44, + 0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64, + 0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48, + 0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, + 0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D, + 0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC, + 0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA, + 0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55, + 0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45, + 0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D, + 0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B, + 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, + 0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A, + 0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC, + 0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8, + 0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD, + 0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A, + 0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56, + 0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, + 0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, + 0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54, + 0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC, + 0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB, + 0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27, + 0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34, + 0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F, + 0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E, + 0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60, + 0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51, + 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57, + 0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51, + 0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC, + 0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE, + 0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A, + 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30, + 0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41, + 0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65, + 0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C, + 0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A, + 0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC, + 0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C, + 0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1, + 0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32, + 0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30, + 0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41, + 0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC, + 0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A, + 0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, + 0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E, + 0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC, + 0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88, + 0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB, + 0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33, + 0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31, + 0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E, + 0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63, + 0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49, + 0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, + 0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55, + 0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC, + 0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C, + 0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8, + 0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F, + 0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F, + 0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48, + 0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A, + 0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A, + 0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57, + 0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53, + 0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC, + 0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88, + 0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4, + 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70, + 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, + 0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E, + 0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47, + 0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D, + 0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58, + 0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55, + 0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC, + 0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E, + 0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9, + 0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73, + 0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70, + 0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF, + 0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E, + 0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57, + 0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58, + 0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C, + 0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC, + 0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C, + 0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC, + 0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78, + 0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73, + 0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1, + 0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C, + 0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D, + 0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58, + 0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E, + 0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC, + 0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8, + 0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42, + 0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73, + 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73, + 0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2, + 0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41, + 0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62, + 0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B, + 0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60, + 0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC, + 0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7, + 0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41, + 0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73, + 0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74, + 0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB, + 0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41, + 0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64, + 0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E, + 0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C, + 0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB, + 0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE, + 0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20, + 0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75, + 0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76, + 0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D, + 0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C, + 0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64, + 0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, + 0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58, + 0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC, + 0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81, + 0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23, + 0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76, + 0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76, + 0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48, + 0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40, + 0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61, + 0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C, + 0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52, + 0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB, + 0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E, + 0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22, + 0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8, + 0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, + 0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C, + 0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57, + 0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D, + 0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A, + 0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65, + 0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC, + 0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40, + 0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD, + 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47, + 0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF, + 0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A, + 0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57, + 0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5, + 0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C, + 0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26, + 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6, + 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52, + 0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9, + 0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42, + 0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51, + 0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6, + 0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21, + 0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7, + 0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93, + 0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D, + 0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF, + 0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40, + 0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52, + 0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1, + 0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21, + 0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8, + 0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93, + 0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40, + 0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0, + 0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F, + 0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59, + 0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E, + 0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23, + 0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7, + 0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93, + 0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F, + 0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC, + 0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47, + 0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54, + 0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D, + 0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24, + 0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24, + 0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A, + 0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5, + 0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93, + 0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60, + 0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC, + 0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47, + 0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B, + 0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D, + 0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28, + 0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D, + 0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD, + 0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93, + 0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7, + 0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44, + 0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45, + 0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B, + 0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D, + 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20, + 0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6, + 0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90, + 0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0, + 0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44, + 0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45, + 0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51, + 0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF, + 0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7, + 0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5, + 0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2, + 0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58, + 0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C, + 0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55, + 0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1, + 0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB, + 0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6, + 0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3, + 0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58, + 0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58, + 0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C, + 0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC, + 0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7, + 0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, + 0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0, + 0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58, + 0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60, + 0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60, + 0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB, + 0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7, + 0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7, + 0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE, + 0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B, + 0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61, + 0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64, + 0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC, + 0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8, + 0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5, + 0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C, + 0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E, + 0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62, + 0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC, + 0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB, + 0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7, + 0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5, + 0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57, + 0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47, + 0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60, + 0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0, + 0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0, + 0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8, + 0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6, + 0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57, + 0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B, + 0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C, + 0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3, + 0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB, + 0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8, + 0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7, + 0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57, + 0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C, + 0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58, + 0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1, + 0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC, + 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED, + 0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, + 0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58, + 0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60, + 0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56, + 0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0, + 0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC, + 0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6, + 0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, + 0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B, + 0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C, + 0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59, + 0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0, + 0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC, + 0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6, + 0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6, + 0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B, + 0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56, + 0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60, + 0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF, + 0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9, + 0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9, + 0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, + 0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52, + 0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B, + 0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD, + 0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE, + 0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65, + 0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6, + 0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D, + 0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58, + 0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F, + 0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4, + 0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE, + 0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0, + 0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D, + 0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57, + 0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40, + 0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9, + 0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE, + 0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC, + 0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9, + 0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38, + 0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52, + 0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40, + 0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC, + 0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF, + 0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99, + 0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6, + 0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, + 0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B, + 0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43, + 0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC, + 0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0, + 0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C, + 0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23, + 0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, + 0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49, + 0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A, + 0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC, + 0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2, + 0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94, + 0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA, + 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, + 0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E, + 0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D, + 0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC, + 0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4, + 0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B, + 0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23, + 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7, + 0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E, + 0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0, + 0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA, + 0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9, + 0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89, + 0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22, + 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA, + 0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2, + 0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E, + 0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA, + 0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA, + 0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6, + 0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97, + 0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D, + 0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, + 0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9, + 0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D, + 0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45, + 0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB, + 0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6, + 0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99, + 0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A, + 0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC, + 0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4, + 0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C, + 0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47, + 0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD, + 0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4, + 0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A, + 0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98, + 0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC, + 0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4, + 0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89, + 0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B, + 0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD, + 0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0, + 0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0, + 0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A, + 0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC, + 0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, + 0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2, + 0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A, + 0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49, + 0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC, + 0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63, + 0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B, + 0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84, + 0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC, + 0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, + 0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99, + 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B, + 0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51, + 0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC, + 0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A, + 0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95, + 0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E, + 0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA, + 0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22, + 0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99, + 0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94, + 0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B, + 0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA, + 0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D, + 0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C, + 0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A, + 0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB, + 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23, + 0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99, + 0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E, + 0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87, + 0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3, + 0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48, + 0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94, + 0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95, + 0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6, + 0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40, + 0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99, + 0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95, + 0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98, + 0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC, + 0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45, + 0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89, + 0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C, + 0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4, + 0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99, + 0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87, + 0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC, + 0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58, + 0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40, + 0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94, + 0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B, + 0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6, + 0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C, + 0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94, + 0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE, + 0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C, + 0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41, + 0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98, + 0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C, + 0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6, + 0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B, + 0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B, + 0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0, + 0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62, + 0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44, + 0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6, + 0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89, + 0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8, + 0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99, + 0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98, + 0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1, + 0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB, + 0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49, + 0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA, + 0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2, + 0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA, + 0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2, + 0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0, + 0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF, + 0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD, + 0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52, + 0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA, + 0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA, + 0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1, + 0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8, + 0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0, + 0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9, + 0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD, + 0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53, + 0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56, + 0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0, + 0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9, + 0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0, + 0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3, + 0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF, + 0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2, + 0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3, + 0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE, + 0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56, + 0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57, + 0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC, + 0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA, + 0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4, + 0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3, + 0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1, + 0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6, + 0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE, + 0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD, + 0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58, + 0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D, + 0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47, + 0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6, + 0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4, + 0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5, + 0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9, + 0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC, + 0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3, + 0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64, + 0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C, + 0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A, + 0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A, + 0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0, + 0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE, + 0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6, + 0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6, + 0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE, + 0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5, + 0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E, + 0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D, + 0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E, + 0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E, + 0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8, + 0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5, + 0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1, + 0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60, + 0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9, + 0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5, + 0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47, + 0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E, + 0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45, + 0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51, + 0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB, + 0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0, + 0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D, + 0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0, + 0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5, + 0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2, + 0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D, + 0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60, + 0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45, + 0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63, + 0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7, + 0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3, + 0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E, + 0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2, + 0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0, + 0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC, + 0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C, + 0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61, + 0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45, + 0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2, + 0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3, + 0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2, + 0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47, + 0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2, + 0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E, + 0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3, + 0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63, + 0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62, + 0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49, + 0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3, + 0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF, + 0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2, + 0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58, + 0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE, + 0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B, + 0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4, + 0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE, + 0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62, + 0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A, + 0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5, + 0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE, + 0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3, + 0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53, + 0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3, + 0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48, + 0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3, + 0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF, + 0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57, +}; + +unsigned char linux_logo_bw[] __initdata = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, + 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, + 0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, + 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7, + 0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, + 0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, + 0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C, + 0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29, + 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F, + 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, + 0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, + 0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF, + 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19, + 0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E, + 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00, + 0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, + 0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF, + 0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11, + 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00, + 0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1, + 0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF, + 0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10, + 0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00, + 0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00, + 0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7, + 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, + 0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, + 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01, + 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, + 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F, + 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, + 0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18, + 0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03, + 0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00, + 0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF, + 0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01, + 0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00, + 0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00, + 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40, + 0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF, + 0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23, + 0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80, + 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, + 0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF, + 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04, + 0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10, + 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80, + 0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF, + 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0, + 0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40, + 0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00, + 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF, + 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40, + 0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0, + 0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF, + 0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F, + 0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF, + 0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F, + 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F, + 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07, + 0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +unsigned char linux_logo16_red[] __initdata = { + 0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x35, 0x83, 0xa5, + 0x65, 0x8f, 0x98, 0xc9, 0xdb, 0xe1, 0xe7, 0xf8 +}; + +unsigned char linux_logo16_green[] __initdata = { + 0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x2e, 0x83, 0xa5, + 0x65, 0x6e, 0x98, 0x89, 0xbf, 0xac, 0xda, 0xf8 +}; + +unsigned char linux_logo16_blue[] __initdata = { + 0x00, 0x90, 0xaf, 0x9c, 0xf7, 0x2b, 0x82, 0xa5, + 0x65, 0x41, 0x97, 0x1e, 0x60, 0x29, 0xa5, 0xf8 +}; + +unsigned char linux_logo16[] __initdata = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa1, 0x11, 0x11, + 0x61, 0x16, 0x66, 0x66, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0xa8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x87, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x73, 0x33, 0x33, 0x3a, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x27, 0x77, 0x77, 0x77, 0x33, 0x3a, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xa3, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x55, 0x50, 0x08, 0x33, 0x77, 0x77, + 0x77, 0x72, 0x72, 0x27, 0x77, 0x77, 0x33, 0x33, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xa3, 0x33, 0x33, 0x77, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x58, 0x85, 0x00, 0x11, 0x11, 0xaa, + 0xa3, 0x37, 0x77, 0x72, 0x22, 0x22, 0x77, 0x73, + 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, + 0x33, 0x37, 0x77, 0x33, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x56, 0x85, 0x00, 0x06, 0x66, 0x11, + 0x11, 0x1a, 0xa3, 0x37, 0x77, 0x72, 0x22, 0x77, + 0x73, 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, + 0x33, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x55, 0x00, 0x00, 0x06, 0x66, 0x66, + 0x66, 0x66, 0x11, 0x1a, 0xa3, 0x77, 0x72, 0x22, + 0x77, 0x73, 0x3a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, + 0x33, 0x33, 0x33, 0xa0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x66, 0x66, 0x66, 0x66, 0x11, 0xa3, 0x77, 0x22, + 0x22, 0x77, 0x33, 0x33, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33, + 0x33, 0x3a, 0xa1, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x33, + 0xaa, 0x11, 0x16, 0x66, 0x66, 0x61, 0x1a, 0x37, + 0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x33, + 0x3a, 0xa1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x22, + 0x22, 0x77, 0x3a, 0x11, 0x66, 0x66, 0x66, 0x1a, + 0x37, 0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33, 0x3a, + 0xa1, 0x11, 0x11, 0x10, 0x00, 0x00, 0x50, 0x00, + 0x00, 0x05, 0x80, 0x50, 0x00, 0x00, 0x07, 0x72, + 0x22, 0x22, 0x22, 0x73, 0xa1, 0x66, 0x66, 0x61, + 0x1a, 0x77, 0x22, 0x27, 0x73, 0x33, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x3a, 0xaa, + 0x11, 0x11, 0x1a, 0xa0, 0x08, 0x71, 0x05, 0x00, + 0x00, 0x12, 0x22, 0x50, 0x00, 0x00, 0x07, 0x77, + 0x77, 0x72, 0x22, 0x22, 0x27, 0x31, 0x16, 0x66, + 0x61, 0x13, 0x77, 0x22, 0x77, 0x33, 0x3a, 0xaa, + 0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xa1, + 0x11, 0x1a, 0x33, 0x70, 0x07, 0x2e, 0x70, 0x00, + 0x01, 0x44, 0x42, 0x60, 0x00, 0x00, 0x02, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x31, 0x66, + 0x66, 0x61, 0xa3, 0x72, 0x22, 0x77, 0x33, 0xaa, + 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xaa, 0x11, + 0x1a, 0x33, 0x77, 0x30, 0x04, 0x82, 0x40, 0x00, + 0x54, 0x48, 0x54, 0x40, 0x00, 0x00, 0x01, 0xaa, + 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x31, + 0x66, 0x66, 0x11, 0x37, 0x22, 0x27, 0x73, 0x3a, + 0xaa, 0xaa, 0xa3, 0x33, 0x3a, 0xaa, 0xaa, 0xaa, + 0xa3, 0x77, 0xaa, 0x10, 0x50, 0x08, 0x46, 0x05, + 0x54, 0x80, 0x50, 0x42, 0x00, 0x00, 0x08, 0x66, + 0x66, 0x1a, 0x32, 0x22, 0x22, 0x22, 0x22, 0x27, + 0x31, 0x66, 0x66, 0x13, 0x72, 0x22, 0x77, 0x33, + 0xaa, 0xaa, 0xaa, 0x33, 0xaa, 0xa1, 0xaa, 0xa3, + 0x37, 0xa1, 0x1a, 0x30, 0x50, 0x06, 0x26, 0x00, + 0x54, 0x00, 0x00, 0x44, 0x00, 0x00, 0x08, 0xe2, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, 0x22, + 0x27, 0xa6, 0x66, 0x61, 0xa7, 0x72, 0x27, 0x73, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, + 0x31, 0x11, 0x37, 0x70, 0x02, 0x00, 0xab, 0xbb, + 0xb6, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, + 0x22, 0x23, 0x16, 0x66, 0x1a, 0x37, 0x22, 0x77, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x3a, + 0x11, 0xa7, 0x33, 0x10, 0x04, 0x09, 0xbd, 0xdd, + 0xbd, 0xd0, 0x04, 0x45, 0x00, 0x0e, 0xee, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, + 0x22, 0x22, 0x71, 0x66, 0x66, 0x13, 0x72, 0x27, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x11, + 0xa3, 0x73, 0xa1, 0x60, 0x08, 0xbd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdb, 0x90, 0x00, 0x02, 0xec, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0x22, + 0x22, 0x22, 0x27, 0xa6, 0x66, 0x61, 0x37, 0x27, + 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x1a, + 0x33, 0xa1, 0x16, 0x60, 0x0b, 0xbd, 0xdd, 0xdd, + 0xcd, 0xdd, 0xdd, 0xd9, 0x00, 0x00, 0xec, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0xa2, + 0x22, 0x22, 0x22, 0x7a, 0x66, 0x66, 0x13, 0x77, + 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x11, 0x33, + 0xaa, 0x11, 0x66, 0x60, 0x9b, 0xdd, 0xdd, 0xdd, + 0xcd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0xec, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x61, + 0x72, 0x22, 0x22, 0x22, 0xa1, 0x66, 0x61, 0x37, + 0x1a, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x13, 0x3a, + 0x11, 0x11, 0x11, 0x10, 0x5b, 0xdd, 0xdd, 0xdc, + 0xdd, 0xdd, 0xbd, 0xd9, 0x00, 0x00, 0xec, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x86, + 0x17, 0x22, 0x22, 0x22, 0x23, 0x16, 0x66, 0xaa, + 0xaa, 0xa3, 0x3a, 0xaa, 0xaa, 0x1a, 0x3a, 0xa1, + 0x11, 0x11, 0x1a, 0x70, 0x05, 0xbd, 0xdd, 0xdd, + 0xdb, 0x5b, 0xdd, 0xb0, 0x00, 0x60, 0x2e, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe6, 0x88, + 0x66, 0x32, 0x22, 0x22, 0x22, 0x36, 0x66, 0x11, + 0x33, 0x33, 0x3a, 0xaa, 0x11, 0xaa, 0xaa, 0xa1, + 0x11, 0x1a, 0x3a, 0x60, 0x02, 0x99, 0xbb, 0xb9, + 0x9b, 0xbb, 0xbc, 0x22, 0x00, 0x86, 0x5e, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe1, 0x68, + 0x86, 0x63, 0x22, 0x22, 0x22, 0x2a, 0x66, 0x66, + 0x33, 0x33, 0xaa, 0xaa, 0x1a, 0xaa, 0xaa, 0x11, + 0x1a, 0xa7, 0x68, 0x80, 0x02, 0x2b, 0xbd, 0xbb, + 0xbb, 0xb9, 0x22, 0x22, 0x00, 0x06, 0x6e, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0xa6, + 0x88, 0x86, 0x32, 0x22, 0x22, 0x27, 0xa6, 0x66, + 0x33, 0x3a, 0xaa, 0xa1, 0xaa, 0xaa, 0xa1, 0x11, + 0xa3, 0xa6, 0x88, 0x80, 0x02, 0x22, 0x9b, 0xbb, + 0xbb, 0x22, 0x24, 0xf4, 0x60, 0x00, 0x0c, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc2, 0x21, + 0x68, 0x88, 0x63, 0x22, 0x22, 0x22, 0x71, 0x66, + 0x33, 0x3a, 0x11, 0x11, 0xaa, 0xaa, 0x11, 0xaa, + 0x71, 0x88, 0x88, 0x00, 0x02, 0xe2, 0x26, 0x99, + 0x22, 0x22, 0x4f, 0xf4, 0x40, 0x00, 0x0c, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x22, 0x22, + 0x16, 0x88, 0x86, 0xa2, 0x22, 0x22, 0x27, 0x11, + 0x33, 0xa1, 0x11, 0x11, 0xaa, 0x31, 0x1a, 0xa3, + 0x68, 0x88, 0x81, 0x00, 0x54, 0x42, 0x22, 0x22, + 0x22, 0x44, 0xff, 0xff, 0x48, 0x00, 0x00, 0x99, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x22, + 0x21, 0x88, 0x88, 0x6a, 0x22, 0x22, 0x22, 0x31, + 0x3a, 0xa1, 0x11, 0x1a, 0xa3, 0x11, 0x33, 0x36, + 0x88, 0x86, 0x30, 0x00, 0x4f, 0x44, 0x22, 0x22, + 0x24, 0xff, 0xff, 0xff, 0x44, 0x00, 0x00, 0x99, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x95, 0x22, 0x72, + 0x22, 0x18, 0x88, 0x86, 0x32, 0x22, 0x22, 0x27, + 0xaa, 0x11, 0x11, 0x1a, 0x31, 0x13, 0x33, 0x68, + 0x88, 0x6a, 0x00, 0x02, 0x4f, 0x4f, 0x42, 0x24, + 0x4f, 0xff, 0xff, 0xff, 0xf4, 0x50, 0x00, 0x99, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x73, + 0x72, 0x26, 0x88, 0x88, 0x63, 0x22, 0x22, 0x22, + 0x11, 0x11, 0x11, 0xa3, 0xa1, 0x73, 0xa6, 0x88, + 0x81, 0xa5, 0x00, 0x04, 0x4f, 0x4f, 0x44, 0x4f, + 0xff, 0xff, 0xff, 0xff, 0xf4, 0x40, 0x00, 0x99, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x12, 0x27, + 0xaa, 0x22, 0x68, 0x55, 0x86, 0x72, 0x22, 0x22, + 0x11, 0x11, 0x1a, 0x33, 0x13, 0x3a, 0x18, 0x88, + 0x1a, 0x10, 0x00, 0x44, 0x4f, 0x4f, 0xff, 0x4f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x99, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x61, 0x22, + 0x3a, 0xa2, 0x26, 0x85, 0x58, 0x67, 0x22, 0x22, + 0x61, 0x61, 0x1a, 0x7a, 0x37, 0x31, 0x88, 0x81, + 0x11, 0x00, 0x05, 0xe4, 0x44, 0xff, 0xff, 0xff, + 0x4f, 0xf4, 0x44, 0xff, 0xff, 0xf5, 0x00, 0x99, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x12, + 0x2a, 0xaa, 0x72, 0x68, 0x55, 0x81, 0x22, 0x22, + 0x66, 0x61, 0xa3, 0x33, 0x73, 0x16, 0x88, 0x11, + 0x10, 0x00, 0x08, 0x74, 0x44, 0x4f, 0x44, 0x44, + 0xf4, 0xf4, 0x44, 0x44, 0xe2, 0x44, 0x00, 0x99, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x81, + 0x22, 0xaa, 0xa7, 0x26, 0x85, 0x88, 0x12, 0x22, + 0x66, 0x61, 0x37, 0xa7, 0x3a, 0x66, 0x66, 0x11, + 0x80, 0x00, 0x0a, 0x72, 0x44, 0x4f, 0x44, 0x4f, + 0xff, 0x44, 0x44, 0x22, 0x22, 0x24, 0x00, 0x99, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x85, 0x88, + 0x12, 0x2a, 0xaa, 0x22, 0x68, 0x58, 0x63, 0x22, + 0x66, 0x1a, 0x73, 0x77, 0x31, 0x66, 0x61, 0x11, + 0x00, 0x00, 0x07, 0x44, 0xff, 0x4f, 0xf4, 0x4f, + 0xff, 0x4f, 0x44, 0xf4, 0x42, 0x22, 0x40, 0x9b, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x85, 0x55, + 0x81, 0x27, 0xaa, 0xa2, 0x78, 0x88, 0x86, 0x72, + 0x66, 0x13, 0x77, 0x73, 0x11, 0x66, 0x61, 0x76, + 0x00, 0x50, 0x84, 0xf4, 0xff, 0x4f, 0xf4, 0xff, + 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x42, 0x40, 0x9b, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x68, 0x55, + 0x58, 0x12, 0x3a, 0xaa, 0x23, 0x88, 0x88, 0xa7, + 0x66, 0xa7, 0x77, 0x7a, 0x16, 0x66, 0x1a, 0x15, + 0x05, 0x00, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff, + 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0x24, 0x9b, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x26, 0x55, + 0x55, 0x81, 0x23, 0xaa, 0x32, 0x18, 0x88, 0x6a, + 0x61, 0x37, 0x77, 0x31, 0x66, 0x66, 0x17, 0x60, + 0x05, 0x08, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff, + 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4e, 0x99, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0xa2, 0x65, + 0x55, 0x58, 0xa2, 0x7a, 0xa2, 0x26, 0x88, 0x61, + 0x61, 0x32, 0x27, 0xa1, 0x66, 0x61, 0x31, 0x60, + 0x00, 0x04, 0x4f, 0xf4, 0xff, 0x44, 0x44, 0xff, + 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x9b, 0xaa, 0x26, + 0x55, 0x55, 0x87, 0x27, 0x33, 0x27, 0x68, 0x61, + 0x1a, 0x72, 0x27, 0xa6, 0x66, 0x6a, 0x71, 0x00, + 0x80, 0x84, 0xff, 0xf4, 0xff, 0x44, 0x44, 0xff, + 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99, + 0x9b, 0x9b, 0x99, 0xb9, 0xb9, 0x99, 0xaa, 0xa2, + 0x85, 0x55, 0x56, 0x22, 0x27, 0x22, 0x36, 0x66, + 0x13, 0x22, 0x23, 0x16, 0x86, 0x63, 0x73, 0x00, + 0x00, 0x44, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff, + 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4f, 0x99, + 0x9b, 0x99, 0x99, 0x99, 0xb9, 0x99, 0xaa, 0xaa, + 0x28, 0x55, 0x58, 0x12, 0x22, 0x22, 0x21, 0x11, + 0xa3, 0x27, 0x7a, 0x66, 0x86, 0x17, 0x75, 0x05, + 0x05, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff, + 0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x44, 0x4f, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x3a, 0xaa, + 0xa2, 0x85, 0x58, 0x67, 0x72, 0x22, 0x27, 0xa1, + 0x37, 0x27, 0x7a, 0x68, 0x86, 0xa2, 0x70, 0x00, + 0x02, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f, + 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xf4, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x23, 0xaa, + 0xa7, 0x78, 0x88, 0x81, 0x77, 0x22, 0x27, 0x3a, + 0x72, 0x73, 0x71, 0x68, 0x66, 0x32, 0x50, 0x00, + 0x04, 0x4f, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f, + 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x95, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x55, 0x12, 0x3a, + 0xaa, 0x21, 0x88, 0x81, 0x77, 0x27, 0x73, 0x73, + 0x72, 0x33, 0x36, 0x86, 0x61, 0x72, 0x00, 0x00, + 0x04, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f, + 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x8a, 0x27, + 0xaa, 0x77, 0x68, 0x61, 0x23, 0x71, 0x11, 0x3a, + 0x27, 0xa3, 0x36, 0x86, 0x61, 0x20, 0x00, 0x00, + 0x04, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f, + 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x59, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x95, 0x58, 0x77, + 0x27, 0x32, 0x36, 0x63, 0x23, 0x71, 0x66, 0x11, + 0x27, 0x13, 0xa6, 0x86, 0x6a, 0x20, 0x00, 0x50, + 0x04, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, + 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x99, + 0x9b, 0xbb, 0xbb, 0xbb, 0xb9, 0x99, 0x68, 0x13, + 0x32, 0x22, 0x73, 0xa7, 0x2a, 0x31, 0x88, 0x66, + 0x7a, 0x13, 0x18, 0x66, 0x63, 0x20, 0x00, 0x06, + 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, + 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x49, 0x95, + 0xa9, 0xa9, 0x99, 0x97, 0x92, 0x99, 0x65, 0x6a, + 0x17, 0x22, 0x23, 0x72, 0x27, 0xaa, 0x88, 0x88, + 0xa1, 0x17, 0x68, 0x66, 0x67, 0x70, 0x00, 0x05, + 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, + 0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x49, 0x9c, + 0x2e, 0xee, 0xee, 0xee, 0xee, 0xa9, 0x65, 0x8a, + 0x1a, 0xaa, 0x37, 0x72, 0x27, 0x37, 0x88, 0x88, + 0x11, 0x17, 0x68, 0x66, 0x67, 0x10, 0x9d, 0xd0, + 0x84, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0xf4, 0x4f, + 0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x4f, 0x69, + 0xcc, 0xee, 0xee, 0xee, 0xec, 0x99, 0x88, 0x63, + 0x61, 0x68, 0x61, 0x72, 0x22, 0x7a, 0x68, 0x88, + 0x11, 0x17, 0x88, 0x66, 0x12, 0x1b, 0xdd, 0xdd, + 0x02, 0x44, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, + 0xff, 0x4f, 0x44, 0xff, 0xff, 0x4f, 0x4c, 0xc5, + 0x0c, 0xc1, 0x11, 0x1c, 0xc0, 0x26, 0x66, 0x17, + 0x66, 0x88, 0x88, 0x12, 0x22, 0x23, 0xa8, 0x88, + 0x11, 0x13, 0x88, 0x66, 0x17, 0xbb, 0xdd, 0xdd, + 0xd0, 0x8f, 0xff, 0xf4, 0xf4, 0x44, 0xf4, 0x4f, + 0xff, 0x4f, 0x44, 0xf4, 0x4f, 0x44, 0xdd, 0xdd, + 0x00, 0x00, 0x00, 0x05, 0x9d, 0x21, 0x66, 0x27, + 0xa6, 0x65, 0x58, 0x67, 0x22, 0x27, 0x28, 0x88, + 0x11, 0xaa, 0x86, 0x68, 0x1a, 0xbb, 0xdd, 0xdd, + 0xdb, 0x05, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x4f, + 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xdd, 0xdb, + 0x00, 0x00, 0x00, 0x00, 0xdd, 0xda, 0x66, 0x22, + 0x71, 0x15, 0x55, 0x81, 0x22, 0x22, 0x76, 0x88, + 0x11, 0x31, 0x88, 0x88, 0xab, 0xbd, 0xdd, 0xdd, + 0xdd, 0x00, 0x04, 0x44, 0xff, 0xff, 0x4f, 0x4f, + 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0x44, 0xdd, 0xdb, + 0x00, 0x00, 0x00, 0x0b, 0xdd, 0xda, 0x11, 0x22, + 0x23, 0x68, 0x55, 0x86, 0x22, 0x22, 0x7a, 0x88, + 0x1a, 0x71, 0x88, 0x89, 0xbb, 0xdd, 0xdd, 0xdd, + 0xdd, 0xd0, 0x00, 0x4f, 0x44, 0xff, 0x4f, 0x4f, + 0xff, 0x4f, 0x44, 0xf4, 0xff, 0xe2, 0xdd, 0xdb, + 0x90, 0x00, 0x05, 0xbd, 0xdd, 0xb8, 0x63, 0x22, + 0x27, 0xa6, 0x55, 0x88, 0x77, 0x22, 0x22, 0x88, + 0x1a, 0x28, 0xbd, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdb, 0x00, 0x07, 0x44, 0x4f, 0x4f, 0x4f, + 0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x22, 0xdd, 0xdb, + 0xbb, 0x9b, 0xbb, 0xbd, 0xdd, 0xd5, 0x86, 0x22, + 0x22, 0x77, 0x85, 0x88, 0x17, 0x22, 0x22, 0x88, + 0xaa, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0x00, 0x00, 0x54, 0x4f, 0x4f, 0x4f, + 0xff, 0x4f, 0x44, 0xf4, 0x44, 0x22, 0xbd, 0xdd, + 0xbb, 0xbb, 0xbb, 0xdd, 0xdd, 0xdd, 0x88, 0x72, + 0x27, 0x22, 0x88, 0x88, 0x67, 0x72, 0x22, 0x18, + 0x33, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xd0, 0x00, 0x05, 0x4f, 0x4f, 0x4f, + 0xff, 0x4f, 0x44, 0x44, 0x4f, 0x22, 0xbd, 0xdd, + 0xdb, 0xbb, 0xdd, 0xdd, 0xdd, 0xdd, 0x88, 0x17, + 0x27, 0x72, 0x68, 0x88, 0x87, 0x32, 0x22, 0x36, + 0x37, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xd5, 0x00, 0x00, 0x4f, 0x4f, 0x4f, + 0xff, 0xf4, 0xf4, 0xf4, 0xf4, 0x22, 0xbb, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x67, + 0x72, 0x77, 0x38, 0x88, 0x83, 0x37, 0x22, 0x26, + 0x72, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0x00, 0x00, 0x4f, 0x4f, 0x4f, + 0xff, 0xf4, 0xf4, 0xf4, 0x44, 0x25, 0xbb, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd3, + 0x32, 0x73, 0x76, 0x88, 0x81, 0x33, 0x22, 0x2a, + 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xb0, 0x54, 0x4f, 0x4f, 0x4f, + 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x00, 0xbb, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xa7, 0x73, 0x26, 0x88, 0x86, 0x7a, 0x72, 0x27, + 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0xff, 0x4f, 0x4f, + 0xff, 0xf4, 0xf4, 0x44, 0x40, 0x05, 0xbb, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0x13, 0x23, 0x21, 0x68, 0x86, 0x17, 0x72, 0x22, + 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0x4f, 0x4f, 0x4f, + 0xff, 0xff, 0x44, 0x42, 0x00, 0x05, 0xbd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0x87, 0x27, 0x27, 0x16, 0x66, 0x67, 0x22, 0x22, + 0x72, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0x94, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x00, 0x00, 0x05, 0xbb, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb8, + 0x86, 0x22, 0x22, 0x7a, 0x68, 0x81, 0x22, 0x22, + 0x37, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x44, 0x44, 0x44, + 0x44, 0x47, 0x00, 0x00, 0x00, 0x05, 0xbd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x68, + 0x58, 0x72, 0x22, 0x27, 0x18, 0x86, 0x72, 0x22, + 0x1a, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x18, 0x85, + 0x58, 0x12, 0x22, 0x36, 0x18, 0x88, 0x32, 0x22, + 0x61, 0x3b, 0xbb, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x7a, 0x68, 0x85, + 0x88, 0x62, 0x27, 0x16, 0x18, 0x88, 0x12, 0x27, + 0x86, 0x18, 0x9b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbd, + 0xdd, 0xdd, 0xdd, 0xbb, 0xb5, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xbb, 0xbd, + 0xdd, 0xdd, 0xdb, 0xbb, 0x87, 0x31, 0x68, 0x65, + 0x88, 0x82, 0x23, 0x16, 0x18, 0x88, 0x12, 0x23, + 0x88, 0x67, 0x27, 0xa8, 0x9b, 0xbb, 0xbb, 0xbb, + 0xbd, 0xdd, 0xbb, 0xbb, 0x95, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x9b, 0xbb, + 0xbb, 0xbb, 0xbb, 0x96, 0x87, 0x16, 0x68, 0x18, + 0x88, 0x62, 0x31, 0x66, 0x18, 0x88, 0x62, 0x73, + 0x88, 0x63, 0x27, 0x33, 0x65, 0x55, 0x99, 0x9b, + 0xbb, 0xbb, 0xbb, 0x99, 0x55, 0x0a, 0xa1, 0x86, + 0x81, 0x68, 0x88, 0x55, 0x58, 0x85, 0x9b, 0xbb, + 0xbb, 0xbb, 0x95, 0x88, 0x83, 0x66, 0x66, 0x18, + 0x66, 0x82, 0xa1, 0x66, 0x18, 0x88, 0x62, 0x33, + 0x88, 0x81, 0x27, 0x7a, 0x18, 0x58, 0x86, 0x85, + 0x99, 0x99, 0x99, 0x95, 0x53, 0x2a, 0xaa, 0x88, + 0x67, 0x31, 0x68, 0x55, 0x58, 0x85, 0x59, 0xbb, + 0xbb, 0xb9, 0x58, 0x68, 0x83, 0x66, 0x61, 0x16, + 0x66, 0x62, 0x16, 0x66, 0x68, 0x88, 0x62, 0xaa, + 0x88, 0x86, 0x27, 0x77, 0x78, 0x55, 0x88, 0x22, + 0x25, 0x55, 0x95, 0x55, 0x6a, 0xa2, 0x2a, 0x88, + 0x62, 0x27, 0x37, 0x38, 0x88, 0x87, 0x55, 0x59, + 0x95, 0x58, 0x16, 0x88, 0x8a, 0x66, 0x63, 0x68, + 0x86, 0x67, 0x66, 0x66, 0x68, 0x88, 0x12, 0x11, + 0x88, 0x88, 0x72, 0x77, 0x78, 0x85, 0x58, 0x17, + 0x23, 0x32, 0x55, 0x55, 0x81, 0x13, 0x73, 0x66, + 0x62, 0x7a, 0xaa, 0x38, 0x88, 0x58, 0x27, 0x55, + 0x58, 0x32, 0x38, 0x88, 0x81, 0x66, 0xa2, 0x88, + 0x86, 0x61, 0x66, 0x61, 0x66, 0x68, 0x13, 0x11, + 0x88, 0x88, 0x12, 0x22, 0x71, 0x85, 0x58, 0x62, + 0x23, 0xa2, 0x68, 0x88, 0x81, 0x66, 0x88, 0x88, + 0x63, 0x2a, 0xaa, 0x28, 0x88, 0x55, 0x86, 0x61, + 0x66, 0x66, 0x68, 0x88, 0x66, 0x66, 0x77, 0x88, + 0x68, 0x16, 0x66, 0x62, 0x66, 0x68, 0xa1, 0x61, + 0x88, 0x88, 0x62, 0x22, 0x22, 0x85, 0x55, 0x83, + 0x72, 0x37, 0xa8, 0x88, 0x61, 0x66, 0x85, 0x55, + 0x86, 0x23, 0xaa, 0x71, 0x88, 0x85, 0x88, 0x66, + 0x88, 0x86, 0x88, 0x88, 0x16, 0x61, 0x21, 0x88, + 0x66, 0xa6, 0x86, 0x17, 0x66, 0x66, 0x31, 0x61, + 0x88, 0x88, 0x87, 0x72, 0x22, 0x68, 0x55, 0x86, + 0x77, 0x77, 0x36, 0x88, 0x13, 0x68, 0x85, 0x55, + 0x58, 0x12, 0x73, 0x72, 0x76, 0x88, 0x88, 0x68, + 0x88, 0x88, 0x88, 0x66, 0x36, 0x63, 0x26, 0x86, + 0x86, 0x36, 0x86, 0x11, 0x66, 0x66, 0x76, 0x61, + 0x88, 0x88, 0x81, 0x22, 0x22, 0x38, 0x85, 0x58, + 0x37, 0x22, 0x21, 0x68, 0xa2, 0x31, 0x68, 0x55, + 0x55, 0x81, 0x22, 0x22, 0xa8, 0x88, 0x88, 0x68, + 0x86, 0x88, 0x68, 0x81, 0x36, 0x17, 0x21, 0x68, + 0x86, 0x16, 0x66, 0x26, 0x66, 0x61, 0x36, 0x66, + 0x68, 0x88, 0x86, 0x27, 0x22, 0x28, 0x88, 0x88, + 0x17, 0x72, 0x2a, 0x66, 0xa2, 0x22, 0x36, 0x55, + 0x55, 0x58, 0x37, 0x3a, 0x16, 0x66, 0x66, 0x66, + 0x66, 0x18, 0x88, 0x67, 0x16, 0x12, 0x71, 0x68, + 0x81, 0x68, 0x61, 0x76, 0x66, 0x6a, 0x16, 0x66, + 0x88, 0x88, 0x86, 0x77, 0x22, 0x26, 0x88, 0x88, + 0x13, 0x37, 0x71, 0x66, 0xa2, 0x33, 0x2a, 0x85, + 0x55, 0x55, 0x17, 0x73, 0x16, 0x66, 0x66, 0x68, + 0x63, 0x88, 0x88, 0xa2, 0x66, 0xa2, 0xa6, 0x88, + 0x61, 0x68, 0x6a, 0x76, 0x66, 0x6a, 0x66, 0x6a +}; #else diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h index d49f985bfcfa..1dbc17608e77 100644 --- a/include/asm-m68k/pgtable.h +++ b/include/asm-m68k/pgtable.h @@ -16,6 +16,9 @@ /* For virtual address to physical address conversion */ extern unsigned long mm_vtop(unsigned long addr) __attribute__ ((const)); extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const)); + +#include + #define VTOP(addr) (mm_vtop((unsigned long)(addr))) #define PTOV(addr) (mm_ptov((unsigned long)(addr))) @@ -126,7 +129,7 @@ extern inline void flush_page_to_ram (unsigned long address) "cpushp %%dc,(%0)\n\t" "cinvp %%ic,(%0)\n\t" ".chip 68k" - : : "a" (VTOP(address))); + : : "a" (virt_to_phys((void *)address))); } else { unsigned long _tmp; @@ -151,7 +154,7 @@ extern inline void flush_icache_range (unsigned long address, "cpushp %%dc,(%0)\n\t" "cinvp %%ic,(%0)\n\t" ".chip 68k" - : : "a" (VTOP(address))); + : : "a" (virt_to_phys((void *)address))); address += PAGE_SIZE; } } @@ -423,9 +426,9 @@ extern pte_t * __bad_pagetable(void); * and a page entry and page directory to the page they refer to. */ #define mk_pte(page, pgprot) \ -({ pte_t __pte; pte_val(__pte) = VTOP(page) + pgprot_val(pgprot); __pte; }) +({ pte_t __pte; pte_val(__pte) = virt_to_phys((void *)page) + pgprot_val(pgprot); __pte; }) #define mk_pte_phys(physpage, pgprot) \ -({ pte_t __pte; pte_val(__pte) = VTOP(physpage) + pgprot_val(pgprot); __pte; }) +({ pte_t __pte; pte_val(__pte) = virt_to_phys((void *)physpage) + pgprot_val(pgprot); __pte; }) extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } @@ -434,7 +437,7 @@ extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep) { int i; - ptep = (pte_t *) VTOP(ptep); + ptep = (pte_t *) virt_to_phys(ptep); for (i = 0; i < 16; i++, ptep += PTRS_PER_PTE/16) pmdp->pmd[i] = _PAGE_TABLE | _PAGE_ACCESSED | (unsigned long)ptep; } @@ -444,23 +447,23 @@ extern inline void pmd_set_et(pmd_t * pmdp, pte_t * ptep) { int i; - ptep = (pte_t *) VTOP(ptep); + ptep = (pte_t *) virt_to_phys(ptep); for (i = 0; i < 16; i++, ptep += PTRS_PER_PTE/16) pmdp->pmd[i] = _PAGE_PRESENT | _PAGE_ACCESSED | (unsigned long)ptep; } extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp) -{ pgd_val(*pgdp) = _PAGE_TABLE | _PAGE_ACCESSED | VTOP(pmdp); } +{ pgd_val(*pgdp) = _PAGE_TABLE | _PAGE_ACCESSED | virt_to_phys(pmdp); } extern inline unsigned long pte_page(pte_t pte) -{ return PTOV(pte_val(pte) & PAGE_MASK); } +{ return (unsigned long)phys_to_virt((unsigned long)(pte_val(pte) & PAGE_MASK)); } extern inline unsigned long pmd_page2(pmd_t *pmd) -{ return PTOV(pmd_val(*pmd) & _TABLE_MASK); } +{ return (unsigned long)phys_to_virt((unsigned long)(pmd_val(*pmd) & _TABLE_MASK)); } #define pmd_page(pmd) pmd_page2(&(pmd)) extern inline unsigned long pgd_page(pgd_t pgd) -{ return PTOV(pgd_val(pgd) & _TABLE_MASK); } +{ return (unsigned long)phys_to_virt((unsigned long)(pgd_val(pgd) & _TABLE_MASK)); } extern inline int pte_none(pte_t pte) { return !pte_val(pte); } extern inline int pte_present(pte_t pte) { return pte_val(pte) & (_PAGE_PRESENT | _PAGE_FAKE_SUPER); } @@ -517,7 +520,7 @@ extern inline pte_t pte_mkcache(pte_t pte) { pte_val(pte) = (pte_val(pte) & _CAC extern inline void SET_PAGE_DIR(struct task_struct * tsk, pgd_t * pgdir) { tsk->tss.crp[0] = 0x80000000 | _PAGE_TABLE; - tsk->tss.crp[1] = VTOP(pgdir); + tsk->tss.crp[1] = virt_to_phys(pgdir); if (tsk == current) { if (CPU_IS_040_OR_060) __asm__ __volatile__ (".chip 68040\n\t" @@ -632,7 +635,7 @@ extern __inline__ pte_t *get_pte_fast(void) ret = pte_quicklist; if (ret) { pte_quicklist = (unsigned long *)*ret; - ret[0] = ret[1]; + ret[0] = 0; quicklists.pgtable_cache_sz -= 8; } return (pte_t *)ret; @@ -658,7 +661,7 @@ extern __inline__ pmd_t *get_pmd_fast(void) ret = pmd_quicklist; if (ret) { pmd_quicklist = (unsigned long *)*ret; - ret[0] = ret[1]; + ret[0] = 0; quicklists.pgtable_cache_sz--; } return (pmd_t *)ret; @@ -799,7 +802,18 @@ extern inline void set_pgdir(unsigned long address, pgd_t entry) * Check if the addr/len goes up to the end of a physical * memory chunk. Used for DMA functions. */ +#ifdef CONFIG_SINGLE_MEMORY_CHUNK +/* + * It makes no sense to consider whether we cross a memory boundary if + * we support just one physical chunk of memory. + */ +extern inline int mm_end_of_chunk (unsigned long addr, int len) +{ + return 0; +} +#else int mm_end_of_chunk (unsigned long addr, int len); +#endif /* * Map some physical address range into the kernel address space. diff --git a/include/asm-m68k/setup.h b/include/asm-m68k/setup.h index a3084e04d37f..bf3314c2aeaf 100644 --- a/include/asm-m68k/setup.h +++ b/include/asm-m68k/setup.h @@ -43,7 +43,7 @@ #ifdef __KERNEL__ #ifndef __ASSEMBLY__ -extern u_long m68k_machtype; +extern unsigned long m68k_machtype; #endif /* !__ASSEMBLY__ */ #if !defined(CONFIG_AMIGA) @@ -186,9 +186,9 @@ extern u_long m68k_machtype; #ifdef __KERNEL__ #ifndef __ASSEMBLY__ -extern u_long m68k_cputype; -extern u_long m68k_fputype; -extern u_long m68k_mmutype; /* Not really used yet */ +extern unsigned long m68k_cputype; +extern unsigned long m68k_fputype; +extern unsigned long m68k_mmutype; /* Not really used yet */ /* * m68k_is040or060 is != 0 for a '040 or higher; @@ -260,29 +260,23 @@ extern int m68k_is040or060; #define CPU_TYPE (m68k_cputype) -#endif /* __KERNEL__ */ - - /* * Miscellaneous */ -#define NUM_MEMINFO (4) -#define CL_SIZE (256) +#define NUM_MEMINFO 4 +#define CL_SIZE 256 #ifndef __ASSEMBLY__ +extern int m68k_num_memory; /* # of memory blocks found */ +extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */ struct mem_info { unsigned long addr; /* physical address of memory chunk */ unsigned long size; /* length of memory chunk (in bytes) */ }; +#endif -#ifdef __KERNEL__ -extern int m68k_num_memory; /* # of memory blocks found */ -extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */ #endif /* __KERNEL__ */ -#endif /* !__ASSEMBLY__ */ - - #endif /* _M68K_SETUP_H */ diff --git a/include/asm-m68k/softirq.h b/include/asm-m68k/softirq.h index 0798b0d7d45a..89c786665bf4 100644 --- a/include/asm-m68k/softirq.h +++ b/include/asm-m68k/softirq.h @@ -61,6 +61,6 @@ extern inline void end_bh_atomic(void) /* These are for the irq's testing the lock */ #define softirq_trylock(cpu) (local_bh_count[cpu] ? 0 : (local_bh_count[cpu]=1)) #define softirq_endlock(cpu) (local_bh_count[cpu] = 0) -#define synchronize_bh() do { } while (0) +#define synchronize_bh() barrier() #endif diff --git a/include/asm-m68k/spinlock.h b/include/asm-m68k/spinlock.h index 83a04ac7fbd7..6c049a124f78 100644 --- a/include/asm-m68k/spinlock.h +++ b/include/asm-m68k/spinlock.h @@ -5,8 +5,16 @@ * We don't do SMP on the m68k .... at least not yet. */ -typedef struct { int dummy; } spinlock_t; +/* + * Gcc-2.7.x has a nasty bug with empty initializers. + */ +#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) +typedef struct { } spinlock_t; +#define SPIN_LOCK_UNLOCKED { } +#else +typedef struct { int gcc_is_buggy; } spinlock_t; #define SPIN_LOCK_UNLOCKED { 0 } +#endif #define spin_lock_init(lock) do { } while(0) #define spin_lock(lock) do { } while(0) @@ -31,8 +39,8 @@ typedef struct { int dummy; } spinlock_t; * irq-safe write-lock, but readers can get non-irqsafe * read-locks. */ -typedef struct { int dummy; } rwlock_t; -#define RW_LOCK_UNLOCKED { 0 } +typedef struct { } rwlock_t; +#define RW_LOCK_UNLOCKED { } #define read_lock(lock) do { } while(0) #define read_unlock(lock) do { } while(0) diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h index ffd5567b4e10..a477bce011f2 100644 --- a/include/asm-m68k/uaccess.h +++ b/include/asm-m68k/uaccess.h @@ -157,12 +157,24 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n) "6:\n" ".section .fixup,\"ax\"\n" " .even\n" - "7: lsll #2,%2\n" + "7: movel %2,%%d0\n" + "71:clrl (%0)+\n" + " subql #1,%%d0\n" + " jne 71b\n" + " lsll #2,%2\n" " addl %4,%2\n" + " btst #1,%4\n" + " jne 81f\n" + " btst #0,%4\n" + " jne 91f\n" " jra 6b\n" "8: addql #2,%2\n" + "81:clrw (%0)+\n" + " btst #0,%4\n" + " jne 91f\n" " jra 6b\n" "9: addql #1,%2\n" + "91:clrb (%0)+\n" " jra 6b\n" ".previous\n" ".section __ex_table,\"a\"\n" @@ -233,7 +245,11 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n) " jne 10b\n" \ ".section .fixup,\"ax\"\n" \ " .even\n" \ - "11: lsll #2,%2\n" \ + "11: movel %2,%%d0\n" \ + "13: clrl (%0)+\n" \ + " subql #1,%%d0\n" \ + " jne 13b\n" \ + " lsll #2,%2\n" \ fixup "\n" \ " jra 12f\n" \ ".previous\n" \ @@ -261,6 +277,7 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) ".section .fixup,\"ax\"\n" " .even\n" "3: addql #1,%2\n" + " clrb (%0)+\n" " jra 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" @@ -279,6 +296,7 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) ".section .fixup,\"ax\"\n" " .even\n" "3: addql #2,%2\n" + " clrw (%0)+\n" " jra 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" @@ -299,7 +317,9 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) ".section .fixup,\"ax\"\n" " .even\n" "4: addql #2,%2\n" + " clrw (%0)+\n" "5: addql #1,%2\n" + " clrb (%0)+\n" " jra 3b\n" ".previous\n" ".section __ex_table,\"a\"\n" @@ -319,6 +339,7 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) ".section .fixup,\"ax\"\n" " .even\n" "3: addql #4,%2\n" + " clrl (%0)+\n" " jra 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" @@ -339,7 +360,9 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) ".section .fixup,\"ax\"\n" " .even\n" "4: addql #4,%2\n" + " clrl (%0)+\n" "5: addql #4,%2\n" + " clrl (%0)+\n" " jra 3b\n" ".previous\n" ".section __ex_table,\"a\"\n" @@ -363,8 +386,11 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) ".section .fixup,\"ax\"\n" " .even\n" "5: addql #4,%2\n" + " clrl (%0)+\n" "6: addql #4,%2\n" + " clrl (%0)+\n" "7: addql #4,%2\n" + " clrl (%0)+\n" " jra 4b\n" ".previous\n" ".section __ex_table,\"a\"\n" @@ -391,9 +417,13 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) ".section .fixup,\"ax\"\n" " .even\n" "6: addql #4,%2\n" + " clrl (%0)+\n" "7: addql #4,%2\n" + " clrl (%0)+\n" "8: addql #4,%2\n" + " clrl (%0)+\n" "9: addql #4,%2\n" + " clrl (%0)+\n" " jra 5b\n" ".previous\n" ".section __ex_table,\"a\"\n" @@ -415,7 +445,8 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) case 1: __copy_from_user_big(to, from, n, /* fixup */ - "1: addql #1,%2", + "1: addql #1,%2\n" + " clrb (%0)+", /* copy */ "2: movesb (%1)+,%%d0\n" " moveb %%d0,(%0)+\n" @@ -426,7 +457,8 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) case 2: __copy_from_user_big(to, from, n, /* fixup */ - "1: addql #2,%2", + "1: addql #2,%2\n" + " clrw (%0)+", /* copy */ "2: movesw (%1)+,%%d0\n" " movew %%d0,(%0)+\n" @@ -438,7 +470,9 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n) __copy_from_user_big(to, from, n, /* fixup */ "1: addql #2,%2\n" - "2: addql #1,%2", + " clrw (%0)+\n" + "2: addql #1,%2\n" + " clrb (%0)+", /* copy */ "3: movesw (%1)+,%%d0\n" " movew %%d0,(%0)+\n" @@ -712,16 +746,9 @@ __constant_copy_to_user(void *to, const void *from, unsigned long n) } #define copy_from_user(to, from, n) \ -{ void *__to = (to); \ - void *__from = (from); \ - unsigned long __n = (n); \ - char *__end = (char *)__to + __n; \ - unsigned long __res = \ (__builtin_constant_p(n) ? \ __constant_copy_from_user(to, from, n) : \ - __generic_copy_from_user(to, from, n)); \ - if (__res) memset(__end - __res, 0, __res); \ - res; } + __generic_copy_from_user(to, from, n)) #define copy_to_user(to, from, n) \ (__builtin_constant_p(n) ? \ diff --git a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h index 4ed5d9f340a9..2bfda1a3ca22 100644 --- a/include/asm-m68k/unistd.h +++ b/include/asm-m68k/unistd.h @@ -27,7 +27,7 @@ #define __NR_lseek 19 #define __NR_getpid 20 #define __NR_mount 21 -#define __NR_oldumount 22 +#define __NR_umount 22 #define __NR_setuid 23 #define __NR_getuid 24 #define __NR_stime 25 @@ -57,7 +57,7 @@ #define __NR_geteuid 49 #define __NR_getegid 50 #define __NR_acct 51 -#define __NR_umount 52 +#define __NR_umount2 52 #define __NR_lock 53 #define __NR_ioctl 54 #define __NR_fcntl 55 @@ -315,6 +315,8 @@ static inline _syscall1(int,setup,int,magic) static inline _syscall0(int,sync) static inline _syscall0(pid_t,setsid) static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) +static inline _syscall3(int,read,int,fd,char *,buf,off_t,count) +static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) static inline _syscall1(int,dup,int,fd) static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) static inline _syscall3(int,open,const char *,file,int,flag,int,mode) diff --git a/include/asm-m68k/virtconvert.h b/include/asm-m68k/virtconvert.h new file mode 100644 index 000000000000..1e942b9e5fb4 --- /dev/null +++ b/include/asm-m68k/virtconvert.h @@ -0,0 +1,76 @@ +#ifndef __VIRT_CONVERT__ +#define __VIRT_CONVERT__ + +/* + * Macros used for converting between virtual and physical mappings. + */ + +#ifdef __KERNEL__ + +#include +#include + +#ifdef CONFIG_AMIGA +#include +#endif + +/* + * Change virtual addresses to physical addresses and vv. + */ +extern unsigned long mm_vtop(unsigned long addr) __attribute__ ((const)); +extern unsigned long mm_vtop_fallback (unsigned long); +extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const)); + +#ifdef CONFIG_SINGLE_MEMORY_CHUNK +extern inline unsigned long virt_to_phys(volatile void * address) +{ + unsigned long voff = (unsigned long) address; + + if (voff < m68k_memory[0].size) + return m68k_memory[0].addr + voff; + else + return mm_vtop_fallback(voff); +} + +extern inline void * phys_to_virt(unsigned long paddr) +{ + unsigned long base = m68k_memory[0].addr; + + if ((paddr >= base) && (paddr < (base + m68k_memory[0].size))) + return (void *)(paddr - base); +#ifdef CONFIG_AMIGA + /* + * if on an amiga and address is in first 16M, move it + * to the ZTWO_VADDR range + */ + if (MACH_IS_AMIGA && paddr < 16*1024*1024) + return (void *)ZTWO_VADDR(paddr); +#endif + return (void *)paddr; +} +#else +extern inline unsigned long virt_to_phys(volatile void * address) +{ + return mm_vtop((unsigned long)address); +} + +extern inline void * phys_to_virt(unsigned long address) +{ + return (void *) mm_ptov(address); +} +#endif + +/* + * IO bus memory addresses are 1:1 with the physical address, + * except on the PCI bus of the Hades. + */ +#ifdef CONFIG_HADES +#define virt_to_bus(a) (virt_to_phys(a) + (MACH_IS_HADES ? 0x80000000 : 0)) +#define bus_to_virt(a) (phys_to_virt((a) - (MACH_IS_HADES ? 0x80000000 : 0))) +#else +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt +#endif + +#endif +#endif diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h index 5200dc1ad7ba..8fae0f0efcc2 100644 --- a/include/linux/byteorder/generic.h +++ b/include/linux/byteorder/generic.h @@ -5,18 +5,18 @@ * linux/byteorder_generic.h * Generic Byte-reordering support * - * Francois-Rene Rideau 19970707 + * Francois-Rene Rideau 19970707 * gathered all the good ideas from all asm-foo/byteorder.h into one file, * cleaned them up. * I hope it is compliant with non-GCC compilers. * I decided to put __BYTEORDER_HAS_U64__ in byteorder.h, * because I wasn't sure it would be ok to put it in types.h * Upgraded it to 2.1.43 - * Francois-Rene Rideau 19971012 + * Francois-Rene Rideau 19971012 * Upgraded it to 2.1.57 * to please Linus T., replaced huge #ifdef's between little/big endian * by nestedly #include'd files. - * Francois-Rene Rideau 19971205 + * Francois-Rene Rideau 19971205 * Made it to 2.1.71; now a facelift: * Put files under include/linux/byteorder/ * Split swab from generic support. @@ -31,6 +31,11 @@ * nybble swapping support... * = every architecture could add their byteswap macro in asm/byteorder.h * see how some architectures already do (i386, alpha, ppc, etc) + * = cpu_to_beXX and beXX_to_cpu might some day need to be well + * distinguished throughout the kernel. This is not the case currently, + * since little endian, big endian, and pdp endian machines needn't it. + * But this might be the case for, say, a port of Linux to 20/21 bit + * architectures (and F21 Linux addict around?). */ /* diff --git a/include/linux/byteorder/swab.h b/include/linux/byteorder/swab.h index 7c1f5c985ba2..813df46c35ef 100644 --- a/include/linux/byteorder/swab.h +++ b/include/linux/byteorder/swab.h @@ -6,7 +6,7 @@ * Byte-swapping, independently from CPU endianness * swabXX[ps]?(foo) * - * Francois-Rene Rideau 19971205 + * Francois-Rene Rideau 19971205 * separated swab functions from cpu_to_XX, * to clean up support for bizarre-endian architectures. * @@ -15,10 +15,13 @@ * */ +/* casts are necessary for constants, because we never know how for sure + * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. + */ #define ___swab16(x) \ ((__u16)( \ - (((__u16)(x) & 0x00ffU) << 8) | \ - (((__u16)(x) & 0xff00U) >> 8) )) + (((__u16)(x) & (__u16)0x00ffU) << 8) | \ + (((__u16)(x) & (__u16)0xff00U) >> 8) )) #define ___swab32(x) \ ((__u32)( \ (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ diff --git a/include/linux/byteorder/swabb.h b/include/linux/byteorder/swabb.h index 22407afdf875..782db2e8e94e 100644 --- a/include/linux/byteorder/swabb.h +++ b/include/linux/byteorder/swabb.h @@ -8,8 +8,8 @@ * * Support for obNUXIous pdp-endian and other bizarre architectures. * Will Linux ever run on such ancient beasts? if not, this file - * will be but a programming pearl. Still, it's a reminder that - * cpu_to_beXX and beXX_to_cpu should be well distinguished. + * will be but a programming pearl. Still, it's a reminder that we + * shouldn't be making too many assumptions when trying to be portable. * */ diff --git a/include/linux/coda.h b/include/linux/coda.h index 9cdf0d04b8cb..564b3933bb98 100644 --- a/include/linux/coda.h +++ b/include/linux/coda.h @@ -72,6 +72,7 @@ struct timespec { #define C_O_WRITE 0x002 #define C_O_TRUNC 0x010 #define C_O_EXCL 0x100 +#define C_O_CREAT 0x200 /* these are to find mode bits in Venus */ #define C_M_READ 00400 @@ -80,6 +81,7 @@ struct timespec { /* for access Venus will use */ #define C_A_R_OK 4 /* Test for read permission. */ #define C_A_W_OK 2 /* Test for write permission. */ +#define C_A_C_OK 8 /* Test for writing upon create. */ #define C_A_X_OK 1 /* Test for execute permission. */ #define C_A_F_OK 0 /* Test for existence. */ @@ -148,8 +150,8 @@ static inline ino_t coda_f2i(struct ViceFid *fid) #ifndef _VUID_T_ #define _VUID_T_ -typedef unsigned int vuid_t; -typedef unsigned int vgid_t; +typedef u_int32_t vuid_t; +typedef u_int32_t vgid_t; #endif /*_VUID_T_ */ #ifndef _CODACRED_T_ diff --git a/include/linux/coda_fs_i.h b/include/linux/coda_fs_i.h index d312013d5d9c..83980b26ece5 100644 --- a/include/linux/coda_fs_i.h +++ b/include/linux/coda_fs_i.h @@ -43,7 +43,7 @@ struct coda_inode_info { int coda_cnode_make(struct inode **, struct ViceFid *, struct super_block *); int coda_cnode_makectl(struct inode **inode, struct super_block *sb); struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb); - +void coda_replace_fid(struct inode *, ViceFid *, ViceFid *); #endif #endif diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h index e867226ec50b..98407f73bd69 100644 --- a/include/linux/coda_linux.h +++ b/include/linux/coda_linux.h @@ -51,7 +51,6 @@ int coda_fid_is_volroot(struct ViceFid *); int coda_fid_is_weird(struct ViceFid *fid); int coda_iscontrol(const char *name, size_t length); - void coda_load_creds(struct coda_cred *cred); int coda_mycred(struct coda_cred *); void coda_vattr_to_iattr(struct inode *, struct coda_vattr *); @@ -71,6 +70,11 @@ int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind); #define NB_SFS_SIZ 0x895440 +/* cache.c */ +void coda_purge_children(struct inode *); +void coda_purge_dentries(struct inode *); + + /* debugging masks */ #define D_SUPER 1 /* print results returned by Venus */ #define D_INODE 2 /* print entry and exit into procedure */ diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h index 024104c31339..e7c8a38f06fd 100644 --- a/include/linux/cyclades.h +++ b/include/linux/cyclades.h @@ -754,6 +754,13 @@ struct cyclades_port { #define CyTBPR (0x72*2) #define CyTCOR (0x76*2) +/* Custom Registers */ + +#define CyPLX_VER (0x3400) +#define PLX_9050 0x11 +#define PLX_9060 0x12 +#define PLX_9080 0x13 + /***************************************************************************/ #endif /* __KERNEL__ */ diff --git a/include/linux/sched.h b/include/linux/sched.h index b835fc2adea8..7a935394f976 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1,6 +1,8 @@ #ifndef _LINUX_SCHED_H #define _LINUX_SCHED_H +extern void checksignals(void); + #include /* for HZ */ extern unsigned long event; diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h index 70740489c33d..1b8d98b22e5b 100644 --- a/include/linux/ufs_fs.h +++ b/include/linux/ufs_fs.h @@ -6,7 +6,7 @@ * Laboratory for Computer Science Research Computing Facility * Rutgers, The State University of New Jersey * - * Clean swab support by Fare + * Clean swab support by Fare * just hope no one is using NNUUXXI on __?64 structure elements * 64-bit clean thanks to Maciej W. Rozycki * @@ -31,8 +31,8 @@ #define UFS_SBLOCK 8192 #define UFS_SBSIZE 8192 -#define SECTOR_SIZE 512 -#define SECTOR_BITS 9 +#define UFS_SECTOR_SIZE 512 +#define UFS_SECTOR_BITS 9 #define UFS_MAGIC 0x00011954 #define UFS_CIGAM 0x54190100 /* byteswapped MAGIC */ @@ -68,8 +68,15 @@ /* From here to next blank line, s_flags for ufs_sb_info */ /* endianness */ #define UFS_BYTESEX 0x00000001 /* mask; leave room to 0xF */ +#if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN) +/* these are for sane architectures */ +#define UFS_NATIVE_ENDIAN 0x00000000 +#define UFS_SWABBED_ENDIAN 0x00000001 +#else +/* these are for pervert architectures */ #define UFS_LITTLE_ENDIAN 0x00000000 #define UFS_BIG_ENDIAN 0x00000001 +#endif /* directory entry encoding */ #define UFS_DE_MASK 0x00000010 /* mask for the following */ #define UFS_DE_OLD 0x00000000 diff --git a/include/linux/umsdos_fs.h b/include/linux/umsdos_fs.h index c9cfd16e67f9..ef6381579623 100644 --- a/include/linux/umsdos_fs.h +++ b/include/linux/umsdos_fs.h @@ -1,6 +1,8 @@ #ifndef LINUX_UMSDOS_FS_H #define LINUX_UMSDOS_FS_H +#define UMS_DEBUG 1 + #define UMSDOS_VERSION 0 #define UMSDOS_RELEASE 4 @@ -23,6 +25,27 @@ #endif +#ifdef __KERNEL__ +/* #Specification: convention / PRINTK Printk and printk + * Here is the convention for the use of printk inside fs/umsdos + * + * printk carry important message (error or status). + * Printk is for debugging (it is a macro defined at the beginning of + * most source. + * PRINTK is a nulled Printk macro. + * + * This convention makes the source easier to read, and Printk easier + * to shut off. + */ +# define PRINTK(x) +# ifdef UMS_DEBUG +# define Printk(x) printk x +# else +# define Printk(x) +# endif +#endif + + struct umsdos_fake_info { char fname[13]; int len; @@ -93,7 +116,7 @@ struct umsdos_info { #define UMSDOS_READDIR_EMD _IO(0x04,216) /* read the EMD file only. */ #define UMSDOS_GETVERSION _IO(0x04,217) /* Get the release number of UMSDOS */ #define UMSDOS_INIT_EMD _IO(0x04,218) /* Create the EMD file if not there */ -#define UMSDOS_DOS_SETUP _IO(0x04,219) /* Set the defaults of the MsDOS driver */ +#define UMSDOS_DOS_SETUP _IO(0x04,219) /* Set the defaults of the MS-DOS driver. */ #define UMSDOS_RENAME_DOS _IO(0x04,220) /* rename a file/directory in the DOS * directory only */ diff --git a/include/linux/umsdos_fs.p b/include/linux/umsdos_fs.p index 0a7475a1c2cf..ed1c4b47dd30 100644 --- a/include/linux/umsdos_fs.p +++ b/include/linux/umsdos_fs.p @@ -6,7 +6,7 @@ int compat_msdos_create(struct inode *dir, int len, int mode, struct inode **inode); -int UMSDOS_dir_read ( struct file *filp, +int dummy_dir_read ( struct file *filp, char *buf, size_t size, loff_t *count); @@ -24,37 +24,29 @@ int umsdos_lookup_x ( struct dentry *dentry, int nopseudo); int UMSDOS_lookup(struct inode *dir,struct dentry *dentry); - -int umsdos_hlink2inode (struct inode *hlink, struct inode **result); + +struct dentry *umsdos_solve_hlink (struct dentry *hlink); /* emd.c 22/06/95 00.22.04 */ ssize_t umsdos_file_write_kmem_real (struct file *filp, const char *buf, - size_t count, - loff_t *offs); + size_t count); -ssize_t umsdos_file_read_kmem (struct inode *emd_dir, - struct file *filp, +int fix_emd_filp (struct file *filp); + +ssize_t umsdos_file_read_kmem (struct file *filp, char *buf, - size_t count, - loff_t *offs); -ssize_t umsdos_file_write_kmem (struct inode *emd_dir, - struct file *filp, + size_t count); +ssize_t umsdos_file_write_kmem (struct file *filp, const char *buf, - size_t count, - loff_t *offs); -ssize_t umsdos_emd_dir_write (struct inode *emd_dir, - struct file *filp, + size_t count); +ssize_t umsdos_emd_dir_write (struct file *filp, char *buf, - size_t count, - loff_t *offs); -ssize_t umsdos_emd_dir_read (struct inode *emd_dir, - struct file *filp, + size_t count); +ssize_t umsdos_emd_dir_read (struct file *filp, char *buf, - size_t count, - loff_t *loffs); + size_t count); struct inode *umsdos_emd_dir_lookup (struct inode *dir, int creat); -int umsdos_emd_dir_readentry (struct inode *emd_dir, - struct file *filp, +int umsdos_emd_dir_readentry (struct file *filp, struct umsdos_dirent *entry); int umsdos_writeentry (struct inode *dir, struct inode *emd_dir, @@ -72,11 +64,14 @@ int umsdos_findentry (struct inode *dir, /* file.c 25/01/95 02.25.38 */ /* inode.c 12/06/95 09.49.40 */ inline struct dentry *geti_dentry (struct inode *inode); +void checkd_inode (struct inode *inode); inline void inc_count (struct inode *inode); void check_inode (struct inode *inode); void check_dentry (struct dentry *dentry); +void check_dentry_path (struct dentry *dentry, const char *desc); void fill_new_filp (struct file *filp, struct dentry *dentry); void kill_dentry (struct dentry *dentry); +void fin_dentry (struct dentry *dentry); struct dentry *creat_dentry (const char *name, const int len, struct inode *inode, @@ -86,10 +81,9 @@ void UMSDOS_put_super (struct super_block *sb); int UMSDOS_statfs (struct super_block *sb, struct statfs *buf, int bufsiz); -int compat_umsdos_real_lookup (struct inode *dir, +struct dentry *compat_umsdos_real_lookup (struct dentry *d_dir, const char *name, - int len, - struct inode **result); + int len); int umsdos_real_lookup(struct inode *inode,struct dentry *dentry); void umsdos_setup_dir_inode (struct inode *inode); void umsdos_set_dirinfo (struct inode *inode, @@ -121,6 +115,9 @@ void umsdos_startlookup (struct inode *dir); void umsdos_unlockcreate (struct inode *dir); void umsdos_endlookup (struct inode *dir); +int umsdos_readlink_x ( struct dentry *dentry, + char *buffer, + int bufsiz); int UMSDOS_symlink (struct inode *dir, struct dentry *dentry, const char *symname); diff --git a/init/main.c b/init/main.c index d09a1925ed8b..4a6be3b1784a 100644 --- a/init/main.c +++ b/init/main.c @@ -1005,6 +1005,8 @@ int cpu_idle(void *unused) idle(); } +#define smp_init() do { } while (0) + #else /* @@ -1018,20 +1020,10 @@ static void __init smp_init(void) { /* Get other processors into their bootup holding patterns. */ smp_boot_cpus(); -} - -/* - * The autoprobe routines assume CPU#0 on the i386 - * so we don't actually set the game in motion until - * they are finished. - */ - -static void __init smp_begin(void) -{ smp_threads_ready=1; smp_commence(); -} - +} + #endif extern void initialize_secondary(void); @@ -1112,13 +1104,10 @@ asmlinkage void __init start_kernel(void) #if defined(CONFIG_QUOTA) dquot_init_hash(); #endif + check_bugs(); printk("POSIX conformance testing by UNIFIX\n"); -#ifdef __SMP__ smp_init(); -#endif - - check_bugs(); #if defined(CONFIG_MTRR) /* Do this after SMP initialization */ /* @@ -1126,7 +1115,7 @@ asmlinkage void __init start_kernel(void) * everything is up" style function where this would belong better * than in init/main.c.. */ - mtrr_init (); + mtrr_init(); #endif #ifdef CONFIG_SYSCTL @@ -1224,15 +1213,6 @@ static int init(void * unused) #endif setup(0); -#ifdef __SMP__ - /* - * With the devices probed and setup we can - * now enter SMP mode. - */ - - smp_begin(); -#endif - #ifdef CONFIG_UMSDOS_FS { /* diff --git a/ipc/sem.c b/ipc/sem.c index 8e8ce2c44ddd..655047cf2a13 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -466,10 +466,10 @@ asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg) if (ipcperms (ipcp, S_IRUGO)) goto out; switch (cmd) { - case GETVAL : return curr->semval; - case GETPID : return curr->sempid; - case GETNCNT: return count_semncnt(sma,semnum); - case GETZCNT: return count_semzcnt(sma,semnum); + case GETVAL : err = curr->semval; goto out; + case GETPID : err = curr->sempid; goto out; + case GETNCNT: err = count_semncnt(sma,semnum); goto out; + case GETZCNT: err = count_semzcnt(sma,semnum); goto out; case GETALL: array = arg.array; break; diff --git a/kernel/fork.c b/kernel/fork.c index e9508bda979c..856934441b4c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -29,8 +29,10 @@ #include #include -int nr_tasks=1; -int nr_running=1; +/* The idle tasks do not count.. */ +int nr_tasks=0; +int nr_running=0; + unsigned long int total_forks=0; /* Handle normal Linux uptimes. */ int last_pid=0; @@ -556,19 +558,6 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) p->lock_depth = -1; /* -1 = no lock */ p->start_time = jiffies; - { - /* This makes it visible to the rest of the system */ - unsigned long flags; - write_lock_irqsave(&tasklist_lock, flags); - SET_LINKS(p); - hash_pid(p); - write_unlock_irqrestore(&tasklist_lock, flags); - } - - nr_tasks++; - if (p->user) - atomic_inc(&p->user->count); - retval = -ENOMEM; /* copy all the process information */ if (copy_files(clone_flags, p)) @@ -598,9 +587,23 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) current->counter >>= 1; p->counter = current->counter; - /* Ok, add it to the run-queues, let it rip! */ + /* + * Ok, add it to the run-queues and make it + * visible to the rest of the system. + * + * Let it rip! + */ retval = p->pid; if (retval) { + write_lock_irq(&tasklist_lock); + SET_LINKS(p); + hash_pid(p); + write_unlock_irq(&tasklist_lock); + + nr_tasks++; + if (p->user) + atomic_inc(&p->user->count); + p->next_run = NULL; p->prev_run = NULL; wake_up_process(p); /* do this last */ @@ -624,17 +627,6 @@ bad_fork_cleanup: if (p->binfmt && p->binfmt->module) __MOD_DEC_USE_COUNT(p->binfmt->module); - { - unsigned long flags; - write_lock_irqsave(&tasklist_lock, flags); - unhash_pid(p); - REMOVE_LINKS(p); - write_unlock_irqrestore(&tasklist_lock, flags); - } - - if (p->user) - atomic_dec(&p->user->count); - nr_tasks--; add_free_taskslot(p->tarray_ptr); bad_fork_free: free_task_struct(p); diff --git a/kernel/sched.c b/kernel/sched.c index abb4ba695cb9..a9a7a6b64ef7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -844,8 +844,7 @@ static unsigned long count_active_tasks(void) read_lock(&tasklist_lock); for_each_task(p) { - if (p->pid && - (p->state == TASK_RUNNING || + if ((p->state == TASK_RUNNING || p->state == TASK_UNINTERRUPTIBLE || p->state == TASK_SWAPPING)) nr += FIXED_1; diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c index c285b4641fdd..b5d5f071ef1e 100644 --- a/net/ax25/ax25_ip.c +++ b/net/ax25/ax25_ip.c @@ -106,7 +106,7 @@ int ax25_rebuild_header(struct sk_buff *skb) { struct sk_buff *ourskb; unsigned char *bp = skb->data; - struct device *dev = skb->dev; + struct device *dev; ax25_address *src, *dst; ax25_route *route; ax25_dev *ax25_dev; @@ -117,10 +117,14 @@ int ax25_rebuild_header(struct sk_buff *skb) if (arp_find(bp + 1, skb)) return 1; - if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) - return 1; + route = ax25_rt_find_route(dst, NULL); + dev = route->dev; - route = ax25_rt_find_route(dst, dev); + if (dev == NULL) + dev = skb->dev; + + if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) + return 1; if (bp[16] == AX25_P_IP) { if (route->ip_mode == 'V' || (route->ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) { @@ -139,6 +143,10 @@ int ax25_rebuild_header(struct sk_buff *skb) * instead of using skb_clone() unless this * gets fixed. */ + + ax25_address src_c; + ax25_address dst_c; + if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) { kfree_skb(skb); return 1; @@ -149,9 +157,13 @@ int ax25_rebuild_header(struct sk_buff *skb) kfree_skb(skb); + src_c = *src; + dst_c = *dst; + skb_pull(ourskb, AX25_HEADER_LEN - 1); /* Keep PID */ - ax25_send_frame(ourskb, ax25_dev->values[AX25_VALUES_PACLEN], src, dst, route->digipeat, dev); + ax25_send_frame(ourskb, ax25_dev->values[AX25_VALUES_PACLEN], &src_c, +&dst_c, route->digipeat, dev); return 1; } diff --git a/net/ipv4/ip_fw.c b/net/ipv4/ip_fw.c index b8ffe59356e7..b45457c72f44 100644 --- a/net/ipv4/ip_fw.c +++ b/net/ipv4/ip_fw.c @@ -427,18 +427,15 @@ static void dump_packet(const struct iphdr *ip, printk("\n"); } -/* function for checking chain labels for user space. Makes sure that - * there are no special characters in the string */ +/* function for checking chain labels for user space. */ static int check_label(ip_chainlabel label) { unsigned int i; - - for (i = 0; i < IP_FW_MAX_LABEL_LENGTH + 1 && label[i]; i++) - if (label[i] <= ' ') - return 0; - if (i == IP_FW_MAX_LABEL_LENGTH+1) - return 0; - return 1; + /* strlen must be < IP_FW_MAX_LABEL_LENGTH. */ + for (i = 0; i < IP_FW_MAX_LABEL_LENGTH + 1; i++) + if (label[i] == '\0') return 1; + + return 0; } /* This function returns a pointer to the first chain with a label @@ -1098,6 +1095,9 @@ static int create_chain(ip_chainlabel label) { struct ip_chain *tmp; + if (!check_label(label)) + return EINVAL; + FWC_HAVE_LOCK(fwc_wlocks); for (tmp = ip_fw_chains; tmp->next; tmp = tmp->next) if (strcmp(tmp->label,label) == 0) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 9380ff4a45f9..fb0002cb2ad9 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -413,6 +413,7 @@ call_allocate(struct rpc_task *task) return; printk("RPC: buffer allocation failed for task %p\n", task); + checksignals(); if (!signalled()) { xprt_release(task); task->tk_action = call_reserve; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index c2dcac0e9193..a07b7472b53a 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -416,8 +416,11 @@ __rpc_execute(struct rpc_task *task) current->timeout = 0; sleep_on(&task->tk_wait); - /* When the task received a signal, remove from - * any queues etc, and make runnable again. */ + /* + * When the task received a signal, remove from + * any queues etc, and make runnable again. + */ + checksignals(); if (signalled()) __rpc_wake_up(task); @@ -432,6 +435,7 @@ __rpc_execute(struct rpc_task *task) * clean up after sleeping on some queue, we don't * break the loop here, but go around once more. */ + checksignals(); if (!RPC_IS_ASYNC(task) && signalled()) { dprintk("RPC: %4d got signal\n", task->tk_pid); rpc_exit(task, -ERESTARTSYS); @@ -551,6 +555,7 @@ rpc_allocate(unsigned int flags, unsigned int size) if (flags & RPC_TASK_ASYNC) return NULL; current->timeout = jiffies + (HZ >> 4); + checksignals(); current->state = TASK_INTERRUPTIBLE; schedule(); } while (!signalled()); @@ -797,6 +802,7 @@ rpciod(void *ptr) dprintk("RPC: rpciod starting (pid %d)\n", rpciod_pid); while (rpciod_users) { + checksignals(); if (signalled()) { rpciod_killall(); flush_signals(current); @@ -925,6 +931,7 @@ rpciod_down(void) */ while (rpciod_pid) { dprintk("rpciod_down: waiting for pid %d to exit\n", rpciod_pid); + checksignals(); if (signalled()) { dprintk("rpciod_down: caught signal\n"); break; diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index e97d339b3ed0..a60000e14c09 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -736,6 +736,7 @@ again: rqstp->rq_argbuf = rqstp->rq_defbuf; rqstp->rq_resbuf = rqstp->rq_defbuf; + checksignals(); if (signalled()) return -EINTR; @@ -754,6 +755,7 @@ again: * We have to be able to interrupt this wait * to bring down the daemons ... */ + checksignals(); current->state = TASK_INTERRUPTIBLE; add_wait_queue(&rqstp->rq_wait, &wait); end_bh_atomic(); diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index fabe85161349..5dda55a351fc 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -5,7 +5,7 @@ * the following common services for the WAN Link Drivers: * o WAN device managenment (registering, unregistering) * o Network interface management -* o Physical connection management (dial-up, incoming calls) +* o Physical connection management (dial-up, incomming calls) * o Logical connection management (switched virtual circuits) * o Protocol encapsulation/decapsulation * @@ -25,7 +25,6 @@ * Oct 15, 1997 Farhan Thawar changed wan_encapsulate to add a pad byte of 0 * Apr 20, 1998 Alan Cox Fixed 2.1 symbols * May 17, 1998 K. Baranowski Fixed SNAP encapsulation in wan_encapsulate -* Aug 15, 1998 Arnaldo C. Melo Fixed device_setup return value *****************************************************************************/ #include /* offsetof(), etc. */ @@ -373,8 +372,9 @@ int wanrouter_ioctl(struct inode* inode, struct file* file, struct proc_dir_entry* dent; wan_device_t* wandev; - if (!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)){ return -EPERM; + } if ((cmd >> 8) != ROUTER_IOCTL) return -EINVAL; @@ -443,7 +443,7 @@ static int device_setup (wan_device_t* wandev, wandev_conf_t* u_conf) if (wandev->setup == NULL) /* Nothing to do ? */ return 0; - + conf = kmalloc(sizeof(wandev_conf_t), GFP_KERNEL); if (conf == NULL) return -ENOBUFS; @@ -459,15 +459,17 @@ static int device_setup (wan_device_t* wandev, wandev_conf_t* u_conf) if (conf->data_size && conf->data) { - if(conf->data_size > 1024 || conf->data_size < 0) + if(conf->data_size > 64000 || conf->data_size < 0){ goto bail; + } data = kmalloc(conf->data_size, GFP_KERNEL); if (data) { if(!copy_from_user(data, conf->data, conf->data_size)) { conf->data=data; - err = wandev->setup(wandev,conf); + wandev->setup(wandev,conf); + err = 0; } else err = -ENOBUFS; @@ -681,6 +683,7 @@ static int delete_interface (wan_device_t* wandev, char* name, int force) --wandev->ndev; sti(); /****** critical section end ******/ + printk("Unregistering '%s'\n", dev->name); unregister_netdev(dev); kfree(dev); return 0; diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index b619e1daebdc..f92f87e1f45a 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -29,6 +29,7 @@ #include /* kernel <-> user copy */ #include /* htons(), etc. */ #include /* copy_to_user */ +#include #include /* WAN router API definitions */ @@ -243,7 +244,7 @@ static struct proc_dir_entry proc_router_stat = /* Strings */ static char conf_hdr[] = - "Device name | port |IRQ|DMA|mem.addr|mem.size|" + "Device name | port |IRQ|DMA| mem.addr |mem.size|" "option1|option2|option3|option4\n"; static char stat_hdr[] = @@ -386,16 +387,16 @@ static int config_get_info(char* buf, char** start, off_t offs, int len, wan_device_t* wandev; strcpy(buf, conf_hdr); for (wandev = router_devlist; - wandev && (cnt < (PROC_BUFSZ - 80)); + wandev && (cnt < (PROC_BUFSZ - 120)); wandev = wandev->next) { if (wandev->state) cnt += sprintf(&buf[cnt], - "%-15s|0x%-4X|%3u|%3u|0x%-6lX|0x%-6X|%7u|%7u|%7u|%7u\n", + "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n", wandev->name, wandev->ioport, wandev->irq, wandev->dma, - wandev->maddr, + virt_to_phys(wandev->maddr), wandev->msize, wandev->hw_opt[0], wandev->hw_opt[1], -- 2.39.5