]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.89 1.1.89
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:54 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:54 +0000 (15:09 -0500)
110 files changed:
Makefile
arch/alpha/config.in
arch/alpha/kernel/head.S
arch/alpha/kernel/irq.c
arch/alpha/kernel/lca.c [new file with mode: 0644]
arch/alpha/kernel/process.c
arch/alpha/kernel/setup.c
arch/i386/kernel/process.c
arch/i386/kernel/traps.c
arch/i386/kernel/vm86.c
arch/sparc/config.in
arch/sparc/kernel/entry.S
arch/sparc/kernel/head.S
arch/sparc/kernel/ioport.c
arch/sparc/kernel/irq.c
arch/sparc/kernel/probe.c
arch/sparc/kernel/process.c
arch/sparc/kernel/promops.c
arch/sparc/kernel/setup.c
arch/sparc/kernel/traps.c
arch/sparc/mm/fault.c
arch/sparc/mm/init.c
arch/sparc/mm/vac-flush.c
drivers/block/README.aztcd
drivers/block/aztcd.c
drivers/block/floppy.c
drivers/block/mcd.c
drivers/char/ChangeLog
drivers/char/console.c
drivers/char/cyclades.c
drivers/char/kbd_kern.h
drivers/char/keyboard.c
drivers/char/serial.c
drivers/char/tty_io.c
drivers/net/README.wavelan
drivers/net/ni52.c
drivers/net/ni52.h
drivers/net/ppp.c
drivers/net/slip.c
drivers/net/wavelan.h
drivers/scsi/Makefile
drivers/scsi/NCR5380.c
drivers/scsi/NCR5380.h
drivers/scsi/eata.c
drivers/scsi/eata.h
drivers/scsi/eata_dma.c
drivers/scsi/eata_dma.h
drivers/scsi/hosts.c
drivers/scsi/hosts.h
drivers/scsi/qlogic.c
drivers/scsi/scsi.c
drivers/scsi/scsi.h
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/sr_ioctl.c
drivers/scsi/st.c
drivers/scsi/u14-34f.c
drivers/scsi/u14-34f.h
fs/hpfs/Makefile
fs/hpfs/hpfs_caps.c [new file with mode: 0644]
fs/hpfs/hpfs_caps.h [new file with mode: 0644]
fs/hpfs/hpfs_fs.c
fs/proc/inode.c
fs/proc/net.c
include/asm-alpha/io.h
include/asm-alpha/jensen.h [new file with mode: 0644]
include/asm-alpha/lca.h [new file with mode: 0644]
include/asm-alpha/pgtable.h
include/asm-alpha/ptrace.h
include/asm-alpha/system.h
include/asm-i386/ptrace.h
include/asm-i386/system.h
include/asm-sparc/clock.h [new file with mode: 0644]
include/asm-sparc/cprefix.h
include/asm-sparc/head.h
include/asm-sparc/io.h
include/asm-sparc/page.h
include/asm-sparc/pgtable.h [new file with mode: 0644]
include/asm-sparc/ptrace.h
include/asm-sparc/system.h
include/asm-sparc/vaddrs.h [new file with mode: 0644]
include/linux/aztcd.h
include/linux/bios32.h
include/linux/elf.h
include/linux/if_arp.h
include/linux/if_ether.h
include/linux/in.h
include/linux/ip_fw.h
include/linux/mc146818rtc.h
include/linux/mm.h
include/linux/netdevice.h
include/linux/pci.h
include/linux/proc_fs.h
include/linux/sched.h
include/linux/sem.h
include/linux/socket.h
include/linux/time.h
ipc/sem.c
kernel/exit.c
kernel/ksyms.c
kernel/sched.c
kernel/softirq.c
kernel/time.c
mm/kmalloc.c
net/inet/ip.c
net/inet/ip_fw.c
net/inet/rarp.c
net/inet/sock.c
net/inet/tcp.c
net/socket.c

index 30a0d0fbe3328dfeb9a4ad0dd59ba5100f8ae58a..cbe50c984cd2461ef6b0a470fb64c6ea4010149d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 88
+SUBLEVEL = 89
 
 ARCH = i386
 
index 850188e47bf5a76eb391d48759cfb47c5db2140a..c34e6e9242debb314b50059db46c664dec428cd8 100644 (file)
@@ -5,7 +5,7 @@
 
 comment 'General setup'
 
-bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD n
+bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
 bool 'Normal harddisk support' CONFIG_BLK_DEV_HD n
 bool 'XT harddisk support' CONFIG_BLK_DEV_XD n
 bool 'Networking support' CONFIG_NET n
index 9cf6fa2613332fc91a5c74b7d5c35221fc4c968c..898a4f5a7906750c529f60ca6a3246e9eb271e20 100644 (file)
@@ -9,6 +9,7 @@
 
 #define __ASSEMBLY__
 #include <asm/system.h>
+#include <linux/fd.h>
 
 #define halt .long PAL_halt
 
@@ -58,4 +59,7 @@ rdusp:
        ret ($26)
        .end rdusp
 
-
+.align 5
+.globl floppy_track_buffer
+floppy_track_buffer:
+       .space 512*2*MAX_BUFFER_SECTORS,1
index 2fc6e04a14ea9aed5a514ac17fb740d30c3c8c10..63c6bb5aacb1edc9c3412c6e0e88f0af252dde18 100644 (file)
@@ -156,9 +156,11 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
        action->flags = irqflags;
        action->mask = 0;
        action->name = devname;
-       if (irq < 8 && irq) {
-               cache_21 &= ~(1<<irq);
-               outb(cache_21,0x21);
+       if (irq < 8) {
+               if (irq) {
+                       cache_21 &= ~(1<<irq);
+                       outb(cache_21,0x21);
+               }
        } else {
                cache_21 &= ~(1<<2);
                cache_A1 &= ~(1<<(irq-8));
@@ -298,7 +300,6 @@ static void device_interrupt(unsigned long vector, struct pt_regs * regs)
        if (irq == 1)
                irq = 7;
 #endif
-       printk("%d%d", irq, ack);
        kstat.interrupts[irq]++;
        action = irq_action + irq;
        /* quick interrupts get executed with no extra overhead */
diff --git a/arch/alpha/kernel/lca.c b/arch/alpha/kernel/lca.c
new file mode 100644 (file)
index 0000000..7ee9cb2
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Code common to all LCA chips.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/lca.h>
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+/*
+ * PCI BIOS32 interface:
+ */
+#define MAJOR_REV      0
+#define MINOR_REV      0
+
+#ifdef CONFIG_PCI
+
+#define mtpr_mces(v) \
+({ \
+    register unsigned long v0 asm ("0"); \
+    register unsigned long a0 asm ("16"); \
+    a0 = (v); \
+    asm volatile ("call_pal %1 # %0 %2" : "r="(v0) \
+                 : "i"(PAL_mtpr_mces), "r"(a0) \
+                 : "memory", "0", "1", "16", "22", "23", "24", "25"); \
+    v0; \
+})
+
+#define draina()       asm volatile ("call_pal %0" :: "i"(PAL_draina))
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the LCA_IOC_CONF register
+ * accordingly.  It is therefore not safe to have concurrent
+ * invocations to configuration space access routines, but there
+ * really shouldn't be any need for this.
+ */
+static int
+mk_conf_addr(unsigned char bus, unsigned char device_fn,
+           unsigned char where, unsigned long *pci_addr)
+{
+       unsigned long addr;
+
+       if (bus == 0) {
+               int device = device_fn >> 3;
+               int func = device_fn & 0x7;
+
+               /* type 0 configuration cycle: */
+
+               if (device > 12) {
+                       return -1;
+               } /* if */
+
+               *((volatile unsigned long*) LCA_IOC_CONF) = 0;
+               addr = (1 << (11 + device)) | (func << 8) | where;
+       } else {
+               /* type 1 configuration cycle: */
+               *((volatile unsigned long*) LCA_IOC_CONF) = 1;
+               addr = (bus << 16) | (device_fn << 8) | where;
+       } /* if */
+       *pci_addr = addr;
+
+       return 0;
+}
+
+
+static unsigned int
+conf_read(unsigned long addr)
+{
+       unsigned long old_ipl, code, stat0;
+       unsigned int value;
+
+       old_ipl = swpipl(7);    /* avoid getting hit by machine check */
+
+       /* reset status register to avoid loosing errors: */
+       stat0 = *((volatile unsigned long*)LCA_IOC_STAT0);
+       *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
+       mb();
+
+       /* access configuration space: */
+
+       value = *((volatile unsigned int*)addr);
+       draina();
+
+       stat0 = *((unsigned long*)LCA_IOC_STAT0);
+       if (stat0 & LCA_IOC_STAT0_ERR) {
+               code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
+                       & LCA_IOC_STAT0_CODE_MASK);
+               if (code != 1) {
+                       printk("lca.c:conf_read: got stat0=%lx\n", stat0);
+               }
+
+               /* reset error status: */
+               *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
+               mb();
+               mtpr_mces(0x7);                 /* reset machine check */
+
+               value = 0xffffffff;
+       }
+       swpipl(old_ipl);
+
+       return value;
+}
+
+
+static void
+conf_write(unsigned long addr, unsigned int value)
+{
+}
+
+
+int
+pcibios_present (void)
+{
+       return 1;               /* present if configured */
+}
+
+
+int
+pcibios_find_class (unsigned long class_code, unsigned short index,
+                   unsigned char *bus, unsigned char *device_fn)
+{
+       pci_resource_t *dev;
+       unsigned long w;
+
+       for (dev = pci_device_list; dev; dev = dev->next) {
+               pcibios_read_config_dword(dev->bus, dev->dev_fn,
+                                         PCI_CLASS_REVISION, &w);
+               if ((w >> 8) == class_code) {
+                       if (index == 0) {
+                               *bus = dev->bus;
+                               *device_fn = dev->dev_fn;
+                               return PCIBIOS_SUCCESSFUL;
+                       }
+                       --index;
+               }
+       }
+       return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+
+int
+pcibios_find_device (unsigned short vendor, unsigned short device_id,
+                    unsigned short index, unsigned char *bus,
+                    unsigned char *device_fn)
+{
+       unsigned long w, desired = (device_id << 16) | vendor;
+       pci_resource_t *dev;
+
+       if (vendor == 0xffff) {
+               return PCIBIOS_BAD_VENDOR_ID;
+       }
+
+       for (dev = pci_device_list; dev; dev = dev->next) {
+               pcibios_read_config_dword(dev->bus, dev->dev_fn,
+                                         PCI_VENDOR_ID, &w);
+               if (w == desired) {
+                       if (index == 0) {
+                               *bus = dev->bus;
+                               *device_fn = dev->dev_fn;
+                               return PCIBIOS_SUCCESSFUL;
+                       }
+                       --index;
+               }
+       }
+       return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+
+int
+pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
+                         unsigned char where, unsigned char *value)
+{
+       unsigned long addr = LCA_CONF;
+       unsigned long pci_addr;
+
+       *value = 0xff;
+
+       if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
+               return PCIBIOS_SUCCESSFUL;
+       } /* if */
+
+       addr |= (pci_addr << 5) + 0x00;
+
+       *value = conf_read(addr) >> ((where & 3) * 8);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+
+int
+pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
+                         unsigned char where, unsigned short *value)
+{
+       unsigned long addr = LCA_CONF;
+       unsigned long pci_addr;
+
+       *value = 0xffff;
+
+       if (where & 0x1) {
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       } /* if */
+
+       if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
+               return PCIBIOS_SUCCESSFUL;
+       } /* if */
+
+       addr |= (pci_addr << 5) + 0x08;
+
+       *value = conf_read(addr) >> ((where & 3) * 8);
+       return PCIBIOS_SUCCESSFUL;
+}
+
+
+int
+pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
+                          unsigned char where, unsigned long *value)
+{
+       unsigned long addr = LCA_CONF;
+       unsigned long pci_addr;
+
+       *value = 0xffffffff;
+
+       if (where & 0x3) {
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       } /* if */
+
+       if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
+               return PCIBIOS_SUCCESSFUL;
+       } /* if */
+
+       addr |= (pci_addr << 5) + 0x18;
+
+       *value = conf_read(addr);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+
+int
+pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
+                          unsigned char where, unsigned char value)
+{
+       panic("pcibios_write_config_byte");
+}
+
+int
+pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
+                          unsigned char where, unsigned short value)
+{
+       panic("pcibios_write_config_word");
+}
+
+int
+pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
+                           unsigned char where, unsigned long value)
+{
+       panic("pcibios_write_config_dword");
+}
+
+#endif /* CONFIG_PCI */
+
+
+unsigned long
+bios32_init(unsigned long memory_start, unsigned long memory_end)
+{
+#ifdef CONFIG_PCI
+       printk("LCA PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
+
+       probe_pci();
+
+#if 0
+       {
+               char buf[4096];
+
+               get_pci_list(buf);
+               printk("%s", buf);
+       }
+#endif
+
+#if 0
+       {
+               extern void NCR53c810_test(void);
+               NCR53c810_test();
+       }
+#endif
+#endif /* CONFIG_PCI */
+
+    return memory_start;
+} /* bios32_init */
+
+                       /*** end of lca.c ***/
index f511328ad7d960ea7dcab9d2bab0494f19a33caa..800b14dfe4a16afbd141b722fcb74b0681f8e029 100644 (file)
@@ -41,6 +41,11 @@ void hard_reset_now(void)
        halt();
 }
 
+void show_regs(struct pt_regs * regs)
+{
+       printk("\nPS: %04lx PC: %016lx\n", regs->ps, regs->pc);
+}
+
 /*
  * Do necessary setup to start up a newly executed thread.
  */
index 6f745c83de54fe4b5a4c45194c9726d50b95b5e9..2e5ecbe0e22b9a738787554d970d2655e067d9b1 100644 (file)
 
 unsigned char aux_device_present;
 
-/*
- * XXXXX!! Warning Will Robinson.
- * Danger! Danger! This is bogus, I'll get it to link if it kills me
- */
-unsigned char floppy_track_buffer[256];
-
 /*
  * The format of "screen_info" is strange, and due to early
  * i386-setup code. This is just enough to make the console
index b7afb2c8be1174d245dcb89d5bbcbbbb5c952a06..89b1fe89c7aff2307c59cf003bf24f98faecf132 100644 (file)
 
 asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
 
+static int hlt_counter=0;
+
+void disable_hlt(void)
+{
+       hlt_counter++;
+}
+
+void enable_hlt(void)
+{
+       hlt_counter--;
+}
+
 /*
  * The idle loop on a i386..
  */
@@ -44,7 +56,7 @@ asmlinkage int sys_idle(void)
        /* endless idle loop with no priority at all */
        current->counter = -100;
        for (;;) {
-               if (hlt_works_ok && !need_resched)
+               if (hlt_works_ok && !hlt_counter && !need_resched)
                        __asm__("hlt");
                schedule();
        }
@@ -85,6 +97,22 @@ void hard_reset_now(void)
        }
 }
 
+void show_regs(struct pt_regs * regs)
+{
+       printk("\n");
+       printk("EIP: %04x:%08lx",0xffff & regs->cs,regs->eip);
+       if (regs->cs & 3)
+               printk(" ESP: %04x:%08lx",0xffff & regs->ss,regs->esp);
+       printk(" EFLAGS: %08lx\n",regs->eflags);
+       printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+               regs->orig_eax,regs->ebx,regs->ecx,regs->edx);
+       printk("ESI: %08lx EDI: %08lx EBP: %08lx",
+               regs->esi, regs->edi, regs->ebp);
+       printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
+               0xffff & regs->ds,0xffff & regs->es,
+               0xffff & regs->fs,0xffff & regs->gs);
+}
+
 /*
  * Do necessary setup to start up a newly executed thread.
  */
index 5e97595b37b18202640d01e754e3b978b6ef6efc..cd2d25ff0517212b0838742f6fad23988f6dff9d 100644 (file)
@@ -199,8 +199,11 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
 
 asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
 {
+#ifndef CONFIG_IGNORE_NMI
        printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
-       printk("You probably have a hardware problem with your RAM chips\n");
+       printk("You probably have a hardware problem with your RAM chips or a\n");
+       printk("power saving mode enabled.\n");
+#endif 
 }
 
 asmlinkage void do_debug(struct pt_regs * regs, long error_code)
index 94808fb1ddde84bc27d6c3e409d01b642531254e..63692d507192b841ed12ba6a5696b1febcc0fdba 100644 (file)
@@ -366,12 +366,6 @@ void handle_vm86_fault(struct vm86_regs * regs, long error_code)
                set_vflags_short(popw(ssp, sp), regs);
                return;
 
-       /* int 3 */
-       case 0xcc:
-               IP(regs)++;
-               do_int(regs, 3, ssp, sp);
-               return;
-
        /* int xx */
        case 0xcd:
                IP(regs) += 2;
index 58f5837a8057bc09ba691b05daf0fd099769af0f..5fac1cfe5e7204043426c096d6171f7801dcf2eb 100644 (file)
@@ -13,9 +13,10 @@ comment 'Sparc Kernel setup'
 
 bool 'Sparc V8 kernel' CONFIG_SPARC_V8 y
 bool 'Sparc SMP support' CONFIG_LINUX_SMP n
-bool 'Networking support' CONFIG_NET y
+bool 'Networking support' CONFIG_NET n
 bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
 bool 'System V IPC' CONFIG_SYSVIPC y
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y
 
 if [ "$CONFIG_NET" = "y" ]; then
 comment 'Networking options'
@@ -174,16 +175,16 @@ bool 'Aztech/Orchid/Okano/Wearnes (non IDE) CDROM support' CONFIG_AZTCD n
 comment 'Filesystems'
 
 bool 'Standard (minix) fs support' CONFIG_MINIX_FS y
-bool 'Extended fs support' CONFIG_EXT_FS n
+bool 'Extended fs support' CONFIG_EXT_FS y
 bool 'Second extended fs support' CONFIG_EXT2_FS y
-bool 'xiafs filesystem support' CONFIG_XIA_FS n
+bool 'xiafs filesystem support' CONFIG_XIA_FS y
 bool 'msdos fs support' CONFIG_MSDOS_FS y
 if [ "$CONFIG_MSDOS_FS" = "y" ]; then
 bool 'umsdos: Unix like fs on top of std MSDOS FAT fs' CONFIG_UMSDOS_FS n
 fi
-bool '/proc filesystem support' CONFIG_PROC_FS y
+bool '/proc filesystem support' CONFIG_PROC_FS n
 if [ "$CONFIG_INET" = "y" ]; then
-bool 'NFS filesystem support' CONFIG_NFS_FS y
+bool 'NFS filesystem support' CONFIG_NFS_FS n
 fi
 if [ "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_CDU31A" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_BLK_DEV_IDECD" = "y" ]; then
        bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS y
@@ -191,7 +192,7 @@ else
        bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
 fi
 bool 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n
-bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
+bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS y
 
 
 comment 'character devices'
index add72de3581e54755e46ef7c0543f19b4d551a14..2704937bf25ba19bd41a3f95978a2554164263b0 100644 (file)
@@ -8,9 +8,9 @@
  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/cprefix.h>
 #include <asm/head.h>
 #include <asm/asi.h>
+#include <asm/cprefix.h>
 
 /* Here are macros for routines we do often, this allows me to inline this
  * without making the code look real ugly. Well, the macro looks ugly too but
@@ -44,7 +44,7 @@
        sethi   %hi( C_LABEL(current) ), %g6; \
        ld      [%g6 + %lo( C_LABEL(current) )], %g6; \
        ld      [%g6 + THREAD_UWINDOWS], %g7; /* how many user wins are active? */ \
-       subcc   %g7, 0x0, %g0
+       subcc   %g7, 0x0, %g0; \
        bne     2f;                            /* If there are any, branch. */ \
        save    %g0, %g0, %g0;                 /* Save into that window either way. */ \
        std     %l0, [%sp];                    /* If above shows only kernel windows */ \
        or      %g0, %l5, %g5;                  /* Restore the globals. */ \
        or      %g0, %l6, %g6; \
        or      %g0, %l7, %g7; \
-8:                                              /* We are done when we get here. */ \
-
+8:      nop;                                     /* We are done when we get here. */ \
 
 /* As if the last macro wasn't enough, we have to go through a very similar routine
  * upon entry to most traps and interrupts. This is save away the current window
        sub     %fp, 0xb0, %sp; \
 1:     sethi   %hi( C_LABEL(current) ), %l6; \
        ld      [%l6 + %lo( C_LABEL(current) )], %l6; \
-       ld      [%l6 + PCB_WIM], %l5; \
+       ld      [%l6 + THREAD_WIM], %l5; \
        and     %l0, 0x1f, %l7; \
        cmp     %l5, %l7; \
        ble,a   4f; \
        sethi   %hi( C_LABEL(eintstack) ), %l7; \
 2: \
        sub     %l7, 0xb0, %sp; \
-3: \
+3:
 
        .text
        .align 4
 /* Default trap handler */
        .globl my_trap_handler
 my_trap_handler:
+#if 1
+               jmp     %l1
+               rett    %l2
+               nop
+#else
                rd %wim, %l4
                or %g0, 0x1, %l5
                sll %l5, %l0, %l5
@@ -234,7 +238,18 @@ my_trap_handler:
                nop                 ! click our heels three times, "no place like home"
                jmp %l1
                rett %l2
+#endif /* bogon */
        
+       .globl sparc_timer
+sparc_timer:
+       ENTER_IRQ
+       or      %g0, 0x10, %o0  
+       call    C_LABEL(do_IRQ)
+       or      %g0, %g0, %o1
+       jmp     %l1
+       rett    %l2
+       nop     
+
 /* This routine is optimized for kernel window fills. User fills take about two
  * or three extra jumps on the average. We'll see how this works out.
  */
@@ -244,10 +259,11 @@ my_trap_handler:
  * see below.
  */
 
-       .globl fill_window_entry
-fill_window_entry:
+       .align 4
+       .globl spill_window_entry
+spill_window_entry:
        andcc   %l0, 0x40, %g0          ! see if this is a user window fill
-       bz,a    fill_from_user
+       bz,a    spill_from_user
        nop
 
        TRAP_WIN_CLEAN                  /* danger, danger... */
@@ -256,7 +272,7 @@ fill_window_entry:
        jmp     %l1
        rett    %l2
 
-fill_from_user:
+spill_from_user:
        sethi   %hi( C_LABEL(current) ), %l6
        ld      [%l6 + %lo( C_LABEL(current) )], %l6
        ld      [%l6 + THREAD_WIM], %l5
@@ -301,12 +317,13 @@ fill_from_user:
  * it the first time. :>
  */
 
-       .globl spill_window_entry
-spill_window_entry:
+       .align 4
+       .globl fill_window_entry
+fill_window_entry:
        wr      %g0, 0, %wim            ! Can not enter invalid register without this.
        andcc   %l0, 0x40, %g0          ! From user?
        restore                         ! restore to where trap occurred
-       bz      spill_from_user
+       bz      fill_from_user
        restore                         ! enter invalid register, whee...
        restore %g0, 0x1, %l1           ! enter one-past invalid register
        rd      %psr, %l0               ! this is the window we need to save
@@ -332,24 +349,24 @@ spill_window_entry:
        jmp     %l1
        rett    %l2                     ! are you as confused as I am?
 
-spill_from_user:
+fill_from_user:
        andcc   %sp, 0x7, %g0           ! check for alignment of user stack
-       bne     spill_bad_stack
+       bne     fill_bad_stack
        sra     %sp, 0x1e, %l7
        cmp     %l7, 0x0
        be,a    1f
        andn    %sp, 0xfff, %l7
        cmp     %l7, -1
-       bne     spill_bad_stack
+       bne     fill_bad_stack
        andn    %sp, 0xfff, %l7
 1:     lda     [%l7] ASI_PTE, %l7
        srl     %l7, 0x1d, %l7
        andn    %l7, 0x2, %l7
        cmp     %l7, 0x4
-       bne     spill_bad_stack
+       bne     fill_bad_stack
        and     %sp, 0xfff, %l7
        cmp     %l7, 0xfc1
-       bl,a    spill_stack_ok
+       bl,a    fill_stack_ok
        restore %g0, 1, %l1
        add     %sp, 0x38, %l5
        sra     %sp, 0x1e, %l7
@@ -357,16 +374,16 @@ spill_from_user:
        be,a    1f
        andn    %sp, 0xfff, %l7
        cmp     %l7, -1
-       bne     spill_bad_stack
+       bne     fill_bad_stack
        andn    %sp, 0xfff, %l7
 1:     lda     [%l7] ASI_PTE, %l7
        srl     %l7, 0x1d, %l7
        andn    %l7, 0x2, %l7
        cmp     %l7, 0x4
-       be,a    spill_stack_ok
+       be,a    fill_stack_ok
        restore %g0, 0x1, %l1
 
-spill_bad_stack:
+fill_bad_stack:
        save    %g0, %g0, %g0                   ! save to where restore happened
        save    %g0, 0x1, %l4                   ! save is an add remember? to trap window
        sethi   %hi( C_LABEL(current) ), %l6
@@ -450,7 +467,7 @@ spill_bad_stack:
        jmp     %l1
        rett    %l2
 
-spill_stack_ok:
+fill_stack_ok:
        rd      %psr, %l0
        sll     %l1, %l0, %l1
        wr      %l1, 0x0, %wim
@@ -474,24 +491,28 @@ spill_stack_ok:
        jmp     %l1
        rett    %l2
 
+       .align 4
        .globl trap_entry
 trap_entry:
        TRAP_WIN_CLEAN
        jmp     %l1
        rett    %l2
 
+       .align 4
        .globl linux_trap_nmi
 linux_trap_nmi:
        TRAP_WIN_CLEAN
        jmp     %l1
        rett    %l2
 
+       .align 4
        .globl sparc_trap
 sparc_trap:
        TRAP_WIN_CLEAN
        jmp     %l1
        rett    %l2
 
+       .align 4
        .globl leave_trap
 leave_trap:
        jmp     %l1
@@ -655,3 +676,4 @@ C_LABEL(sys_call_table):
        .long C_LABEL(sys_setfsuid)
        .long C_LABEL(sys_setfsgid)
        .long C_LABEL(sys_llseek)               /* 140 */
+       .align 4
index 03e5dde73ccd31f4643b9f90b12f47dd6ff24b64..73f6482522ca113cb4132781afad6c670fc352a7 100644 (file)
@@ -229,13 +229,13 @@ IE_reg_addr = C_LABEL(msgbuf) + msgbufsize   ! this page not used; points to IEr
 _start:   /* danger danger */
 start:
 C_LABEL(trapbase):
-       b gokernel; WRITE_PAUSE         ! we never get trap #0 it is special
+       b gokernel; nop; nop; nop;      ! we never get trap #0 it is special 
 
        TRAP_ENTRY(0x1, my_trap_handler) /* Instruction Access Exception */
        TRAP_ENTRY(0x2, my_trap_handler) /* Illegal Instruction */
        TRAP_ENTRY(0x3, my_trap_handler) /* Privileged Instruction */
        TRAP_ENTRY(0x4, my_trap_handler) /* Floating Point Disabled */
-       TRAP_ENTRY(0x5, spill_window_entry) /* Window Overflow */
+       TRAP_ENTRY(0x5, spill_window_entry)   /* Window Overflow */
        TRAP_ENTRY(0x6, fill_window_entry)  /* Window Underflow */
        TRAP_ENTRY(0x7, my_trap_handler) /* Memory Address Not Aligned */
        TRAP_ENTRY(0x8, my_trap_handler) /* Floating Point Exception */
@@ -263,7 +263,7 @@ C_LABEL(trapbase):
         TRAP_ENTRY_INTERRUPT(11)            /* Interrupt Level 11 */
         TRAP_ENTRY_INTERRUPT(12)            /* Interrupt Level 12 */
         TRAP_ENTRY_INTERRUPT(13)            /* Interrupt Level 13 */
-        TRAP_ENTRY_INTERRUPT(14)            /* Interrupt Level 14 */
+        TRAP_ENTRY(0x27, sparc_timer)       /* Interrupt Level 14 */
         TRAP_ENTRY_INTERRUPT_NMI(15, linux_trap_nmi) /* Level 15 (nmi) */
 
        TRAP_ENTRY(0x20, my_trap_handler)   /* General Register Access Error */
@@ -491,6 +491,8 @@ C_LABEL(trapbase):
        TRAP_ENTRY(0xfe, my_trap_handler)   /* Software Trap                 */
        TRAP_ENTRY(0xff, my_trap_handler)   /* Software Trap                 */ 
 
+       .skip 4096
+
 C_LABEL(msgbufmapped):
         .word   1
 
@@ -712,18 +714,24 @@ rest_of_boot:
  * to all its routines which allows some sanity during bootup.
  */
 
-#if 0 /* paranoid, need to fix this routine now */
                sethi   %hi(IE_reg_addr), %l0
                or      %l0, %lo(IE_reg_addr), %l0
+
+               set     0xf4000000, %l3
                sethi   %hi(INT_ENABLE_REG_PHYSADR), %l2
                or      %l2, %lo(INT_ENABLE_REG_PHYSADR), %l2
-               srl     %l2, %g5, %l1
+               srl     %l2, %g5, %l2
+               or      %l2, %l3, %l1           
 
                sta     %l1, [%l0] ASI_PTE
-               mov     INTS_ALL_ENAB, %l1
+       
+               or      %g0, INTS_ENAB, %l1
+               nop
+               nop
+
                stb     %l1, [%l0]
-#endif /* paranoid, see above */
        
+
 /* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's
  * show-time!
  */
@@ -760,7 +768,6 @@ rest_of_boot:
                wr      %g0, 0x0, %wim          ! magical invalid window reg
                WRITE_PAUSE                     ! see above
 
-       
 /* I keep the timer interrupt on so that BogoMIPS works and the prom
  * keeps updating it's "jiffies" counter. 100HZ clock on sparcstations.
  */    
@@ -769,29 +776,29 @@ rest_of_boot:
  * write. ;-( like this (PSR_PS | PSR_S | PSR_PIL)...
  */
 
-               sethi   %hi(0x1fc0), %g2
-               or      %g2, %lo(0x1fc0), %g2
+               sethi   %hi(PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
+               or      %g2, %lo(PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
                wr      %g2, 0x0, %psr
                WRITE_PAUSE
 
                wr      %g0, 0x2, %wim          ! window 1 invalid
                WRITE_PAUSE
+
                or      %g0, 0x1, %g1
                sethi   %hi( C_LABEL(current) + THREAD_WIM), %g2
                st      %g1, [%g2 + %lo( C_LABEL(current) + THREAD_WIM)]
 
 /* I want a kernel stack NOW! */
 
-               set     ( C_LABEL(init_user_stack) + 4096 - 96), %fp    
-               set     ( C_LABEL(init_user_stack) + 4096), %sp
+               set     ( C_LABEL(init_user_stack) + 4092 - 96 - 80), %fp       
+               set     ( C_LABEL(init_user_stack) + 4092), %sp
 
-       /* now out stack is set up similarly to the way it is on the i386 */
+/* now out stack is set up similarly to the way it is on the i386 */
 
                rd      %psr, %l0
                wr      %l0, PSR_ET, %psr
                WRITE_PAUSE
 
-
 /*
  * Maybe the prom zeroes out our BSS section, maybe it doesn't. I certainly 
  * don't know, do you?
@@ -852,6 +859,11 @@ rest_of_boot:
 
 /* Here we go */
 
+               set     C_LABEL(trapbase), %g3
+               wr      %g3, 0x0, %tbr
+               WRITE_PAUSE
+
+
 /* First we call init_prom() to set up romvec, then off to start_kernel() */
 /* XXX put this in arch_init() */
 
@@ -985,3 +997,6 @@ C_LABEL(empty_bad_page):            .skip 0x1000
 C_LABEL(empty_bad_page_table):         .skip 0x1000
 C_LABEL(empty_zero_page):              .skip 0x1000
 
+               .align 4
+diagstr:       .asciz  "DIAG\n"
+               .align 4
index 1a927deeeeb003fdfa996ac231d727b44107dadd..b70a256ce4c7468aa6f9d7c9d5e60038be942079 100644 (file)
@@ -1,6 +1,6 @@
 /* ioport.c:  I/O access on the Sparc. Work in progress.. Most of the things
  *            in this file are for the sole purpose of getting the kernel
- *           through the compiler. :-)
+ *           throught the compiler. :-)
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
index e6f47f34c86c520decab595698087cb198a76398..a564ab6c08ff99dae09b01d1d1334e8d3095f19a 100644 (file)
  * sa_restorer is the unused
  */
 
-#include <asm/ptrace.h>
-#include <asm/system.h>
+#include <linux/config.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
 #include <linux/linkage.h>
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/psr.h>
 
 void disable_irq(unsigned int irq_nr)
 {
   unsigned long flags;
-
+  unsigned char *int_reg;
+  
   save_flags(flags);
+  cli();
+
+  /* We have mapped the irq enable register in head.S and all we
+   * have to do here is frob the bits.
+   */
+
+  int_reg = (char *) IRQ_ENA_ADR;
+
+  switch(irq_nr)
+    {
+    case 1:
+      *int_reg = ((*int_reg) & (~(0x02)));
+      break;
+    case 4:
+      *int_reg = ((*int_reg) & (~(0x04)));
+      break;
+    case 6:
+      *int_reg = ((*int_reg) & (~(0x08)));
+      break;      
+    case 8:
+      *int_reg = ((*int_reg) & (~(0x10)));
+      break;      
+    case 10:
+      *int_reg = ((*int_reg) & (~(0x20)));
+      break;      
+    case 14:
+      *int_reg = ((*int_reg) & (~(0x80)));
+      break;      
+    default:
+      printk("AIEEE, Illegal interrupt disable requested irq=%d\n", 
+            (int) irq_nr);
+      break;
+    };
+  
   restore_flags(flags);
   return;
 }
@@ -37,19 +78,141 @@ void disable_irq(unsigned int irq_nr)
 void enable_irq(unsigned int irq_nr)
 {
   unsigned long flags;
-
+  unsigned int *int_reg;
+  
   save_flags(flags);
+  cli();
+
+  /* We have mapped the irq enable register in head.S and all we
+   * have to do here is frob the bits.
+   */
+
+  int_reg = (unsigned int *) IRQ_ENA_ADR;
+  
+  switch(irq_nr)
+    {
+    case 1:
+      *int_reg = ((*int_reg) | 0x02);
+      break;
+    case 4:
+      *int_reg = ((*int_reg) | 0x04);
+      break;
+    case 6:
+      *int_reg = ((*int_reg) | 0x08);
+      break;      
+    case 8:
+      *int_reg = ((*int_reg) | 0x10);
+      break;      
+    case 10:
+      *int_reg = ((*int_reg) | 0x20);
+      break;      
+    case 14:
+      *int_reg = ((*int_reg) | 0x80);
+      break;      
+    default:
+      printk("AIEEE, Illegal interrupt enable requested irq=%d\n", 
+            (int) irq_nr);
+      break;
+    };
+
   restore_flags(flags);
   return;
 }
 
+/*
+ * Initial irq handlers.
+ */
+struct irqaction {
+  void (*handler)(int, struct pt_regs *);
+  unsigned long flags;
+  unsigned long mask;
+  const char *name;
+};
+
+static struct irqaction irq_action[16] = {
+  { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+  { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+  { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+  { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+  { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+  { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+  { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+  { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
+};
+
+
 int get_irq_list(char *buf)
 {
-  int len = 0;
-
+  int i, len = 0;
+  struct irqaction * action = irq_action;
+  
+  for (i = 0 ; i < 16 ; i++, action++) {
+    if (!action->handler)
+      continue;
+    len += sprintf(buf+len, "%2d: %8d %c %s\n",
+                  i, kstat.interrupts[i],
+                  (action->flags & SA_INTERRUPT) ? '+' : ' ',
+                  action->name);
+  }
   return len;
 }
 
+void free_irq(unsigned int irq)
+{
+        struct irqaction * action = irq + irq_action;
+        unsigned long flags;
+
+        if (irq > 14) {  /* 14 irq levels on the sparc */
+                printk("Trying to free IRQ%d\n", irq);
+                return;
+        }
+        if (!action->handler) {
+                printk("Trying to free free IRQ%d\n", irq);
+                return;
+        }
+        save_flags(flags);
+        cli();
+        disable_irq(irq);
+        action->handler = NULL;
+        action->flags = 0;
+        action->mask = 0;
+        action->name = NULL;
+        restore_flags(flags);
+}
+
+#if 0
+static void handle_nmi(struct pt_regs * regs)
+{
+  printk("NMI, probably due to bus-parity error.\n");
+  printk("PC=%08lx, SP=%08lx\n", regs->pc, regs->sp);
+}
+#endif
+
+static void unexpected_irq(int irq, struct pt_regs * regs)
+{
+        int i;
+
+        printk("IO device interrupt, irq = %d\n", irq);
+        printk("PC = %08lx NPC = %08lx SP=%08lx\n", regs->pc, 
+              regs->npc, regs->sp);
+        printk("Expecting: ");
+        for (i = 0; i < 16; i++)
+                if (irq_action[i].handler)
+                        printk("[%s:%d] ", irq_action[i].name, i);
+        printk("AIEEE\n");
+}
+
+static inline void handler_irq(int irq, struct pt_regs * regs)
+{
+  struct irqaction * action = irq + irq_action;
+
+  if (!action->handler) {
+    unexpected_irq(irq, regs);
+    return;
+  }
+  action->handler(irq, regs);
+}
+
 /*
  * do_IRQ handles IRQ's that have been installed without the
  * SA_INTERRUPT flag: it uses the full signal-handling return
@@ -59,7 +222,10 @@ int get_irq_list(char *buf)
  */
 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
 {
+  struct irqaction *action = irq + irq_action;
+
   kstat.interrupts[irq]++;
+  action->handler(irq, regs);
   return;
 }
 
@@ -71,37 +237,43 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
 asmlinkage void do_fast_IRQ(int irq)
 {
   kstat.interrupts[irq]++;
+  printk("Got FAST_IRQ number %04lx\n", (long unsigned int) irq);
   return;
 }
 
-#define SA_PROBE SA_ONESHOT
-
-/*
- * Using "struct sigaction" is slightly silly, but there
- * are historical reasons and it works well, so..
- */
-static int irqaction(unsigned int irq, struct sigaction * new_sa)
-{
-       unsigned long flags;
-
-       save_flags(flags);
-       restore_flags(flags);
-       return 0;
-}
                
-int request_irq(unsigned int irq, void (*handler)(int),
-       unsigned long flags, const char * devname)
-{
-       return irqaction(irq, (struct sigaction *) 0);
-}
-
-void free_irq(unsigned int irq)
+int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
+       unsigned long irqflags, const char * devname)
 {
+  struct irqaction *action;
   unsigned long flags;
 
+  if(irq > 14)  /* Only levels 1-14 are valid on the Sparc. */
+    return -EINVAL;
+
+  if(irq == 0)  /* sched_init() requesting the timer IRQ */
+    irq = 14;
+
+  action = irq + irq_action;
+
+  if(action->handler)
+    return -EBUSY;
+
+  if(!handler)
+    return -EINVAL;
+
   save_flags(flags);
+  cli();
+
+  action->handler = handler;
+  action->flags = irqflags;
+  action->mask = 0;
+  action->name = devname;
+
+  enable_irq(irq);
+
   restore_flags(flags);
-  return;
+  return 0;
 }
 
 unsigned int probe_irq_on (void)
@@ -120,10 +292,5 @@ int probe_irq_off (unsigned int irqs)
 
 void init_IRQ(void)
 {
-  int i;
-
-  for (i = 0; i < 16 ; i++)
-    set_intr_gate(0x20+i,bad_interrupt[i]);
-
   return;
 }
index b390736d531ae6bf5e2aa89468d4b4eea743fd32..ddd2c7b88b38f2377a1daccc60bf9f1a695bdd5c 100644 (file)
@@ -5,6 +5,10 @@
 
 #include <linux/kernel.h>
 #include <asm/vac-ops.h>
+#include <asm/io.h>
+#include <asm/vaddrs.h>
+#include <asm/param.h>
+#include <asm/clock.h>
 
 /* #define DEBUG_PROBING */
 
@@ -236,7 +240,49 @@ probe_mmu(void)
 void
 probe_clock(int fchild)
 {
-  /* TODO :> I just can't stomach it right now... */
+  register int node, type;
+  register char *node_str;
+
+  /* This will basically traverse the node-tree of the prom to see
+   * which timer chip is on this machine.
+   */
+
+  printk("Probing timer chip... ");
+
+  type = 0;
+  for(node = fchild ; ; )
+    {
+      node_str = get_str_from_prom(node, "model", promstr_buf);
+      if(strcmp(node_str, "mk48t02") == 0)
+       {
+         type = 2;
+         break;
+       }
+
+      if(strcmp(node_str, "mk48t08") == 0)
+       {
+         type = 8;
+         break;
+       }
+
+      node = node_get_sibling(node);
+      if(node == fchild)
+       {
+         printk("Aieee, could not find timer chip type\n");
+         return;
+       }
+    }
+
+  printk("%s\n", node_str);
+  printk("At OBIO address: 0x%x Virtual address: 0x%x\n",
+        (unsigned int) 0xf3000000, (unsigned int) TIMER_STRUCT);
+
+  mapioaddr((unsigned long) 0xf3000000,
+           (unsigned long) TIMER_STRUCT);
+
+  TIMER_STRUCT->timer_limit14=(((10000) << 10) | 0x80000000);
+  TIMER_STRUCT->timer_limit10=(((10000) << 10) | 0x80000000);
+
   return;
 }
 
index 5d6d38355f757bb3bafc1bff58be34552102c828..fa656e2c04ea2cf5f9a588fcae28af8d25e597e9 100644 (file)
@@ -48,6 +48,12 @@ void hard_reset_now(void)
        halt();
 }
 
+void show_regs(struct pt_regs * regs)
+{
+        printk("\nSP: %08lx PC: %08lx NPC: %08lx\n", regs->sp, regs->pc,
+              regs->npc);
+}
+
 /*
  * Do necessary setup to start up a newly executed thread.
  */
index 7dd07b33a130da7adc4e1ac85ad7b3aefadf3d1a..6f38f5379aa3a279f5e24eb1f3b6608fa7c41cdf 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <asm/openprom.h>
 
-#define DEBUG_PROMOPS
+/* #define DEBUG_PROMOPS */
 #define MAX_PR_LEN   16           /* exotic hardware probably overshoots this */
 
 int prom_node_root;               /* initialized in init_prom */
index 05f0537a278c462bf21b01017575bc3d05311497..d8771f4c62ec8c17238e79165901301f9172b2a2 100644 (file)
@@ -92,6 +92,8 @@ void setup_arch(char **cmdline_p,
        printk("calling probe_devices...\n");
        probe_devices();  /* cpu/fpu, mmu probes */
 
+       swpipl(13);
+
        *memory_start_p = (((unsigned long) &end));
 }
 
index c9abc4f8282b8615eb2a31b7b208f21579f4d1a6..9302191c789e89e5dd8d1465ec46f0cc7ef1bfe7 100644 (file)
@@ -32,9 +32,11 @@ void trap_init(void)
 
   /* load up the trap table */
 
+#if 0 /* not yet */
   __asm__("wr %0, 0x0, %%tbr\n\t"
          "nop; nop; nop\n\t" : :
          "r" (trapbase));
+#endif
 
   return;
 }
index 329e9d0eb3b65a274e13b213f98387a0d693195a..b9791686b2530e69c460836382562885a5364f54 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/segment.h>
 #include <asm/openprom.h>
 #include <asm/page.h>
+#include <asm/pgtable.h>
 
 extern unsigned long pg0[1024];                /* page table for 0-4MB for everybody */
 extern void die_if_kernel(char *,struct pt_regs *,long);
index 1edb0931e763c284a47024d7394199a866ab49b2..23a9afe6feed16b8b17e6d7697a366aef30c9ce7 100644 (file)
@@ -19,6 +19,8 @@
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/vac-ops.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
 
 extern void scsi_mem_init(unsigned long);
 extern void sound_mem_init(void);
@@ -42,16 +44,16 @@ extern int invalid_segment, num_segmaps, num_contexts;
  * ZERO_PAGE is a special page that is used for zero-initialized
  * data and COW.
  */
-unsigned long __bad_pagetable(void)
+pte_t *__bad_pagetable(void)
 {
        memset((void *) EMPTY_PGT, 0, PAGE_SIZE);
-       return EMPTY_PGT;
+       return (pte_t *) EMPTY_PGT;
 }
 
-unsigned long __bad_page(void)
+pte_t __bad_page(void)
 {
        memset((void *) EMPTY_PGE, 0, PAGE_SIZE);
-       return EMPTY_PGE;
+       return pte_mkdirty(mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED));
 }
 
 unsigned long __zero_page(void)
@@ -95,7 +97,7 @@ extern unsigned long free_area_init(unsigned long, unsigned long);
  * unmaps the bootup page table (as we're now in KSEG, so we don't need it).
  *
  * The bootup sequence put the virtual page table into high memory: that
- * means that we can change the L1 page table by just using VL1p below.
+ * means that we cah change the L1 page table by just using VL1p below.
  */
 
 unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
@@ -135,12 +137,12 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
 
        for(a=0; a<b; a++)
          {
-           for(i=1; i<num_contexts; i++)
+           for(i=0; i<num_contexts; i++)
              {
                /* map the kernel virt_addrs */
                (*(romvec->pv_setctxt))(i, (char *) c, a);
-               c += 4096;
              }
+           c += 0x40000;
          }
 
        /* Ok, since now mapped in all contexts, we can free up
@@ -181,9 +183,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
              }
          }
 
-#if 0 /* bogosity */
        invalidate(); /* flush the virtual address cache */
-#endif /* bletcherous */
 
        printk("\nCurrently in context - ");
        for(i=0; i<num_contexts; i++)
index 2d7a5d5589d2ff8da577a142a0d3b86f5cf546b1..796366b5399f0126b7ec114e8c48a959086d6a27 100644 (file)
@@ -5,6 +5,7 @@
 */
 
 #include <asm/vac-ops.h>
+#include <asm/page.h>
 
 /* Flush all VAC entries for the current context */
 
@@ -26,7 +27,7 @@ flush_vac_context()
       while(entries_left-- >=0)
        {
          hw_flush_vac_context_entry(address);
-         address += 4096;
+         address += PAGE_SIZE;
        }
     }
   else
@@ -56,7 +57,7 @@ flush_vac_segment(register unsigned int segment)
       while(entries_left-- >=0)
        {
          hw_flush_vac_segment_entry(address);
-         address += 4096;
+         address += PAGE_SIZE;
        }
     }
   else
index 69f053f7ad8eb609648b8f87a41d55febbe226c5..ee4c3e72193be48925ee3599f9eb5ac37d7cecd1 100644 (file)
@@ -81,6 +81,12 @@ If you still get a different message while Linux boots or when you get the
 message, that the ISO9660-filesystem is not supported by your kernel, when
 you try to mount the CD-ROM drive, you have to recompile your kernel.
 
+If you do *not* have an Aztech/Orchid/Okano/Wearnes drive and want to bypass
+drive detection during Linux boot up, start with boot parameter aztcd=0.
+
+Joe Nardone has compiled a boot disk with the Aztech driver for installing 
+Slackware from CDROM. You can find the disk images at 'sunsite.unc.edu'; 
+see file 'aztech.gz.README' for instructions on how to use it.
 
 4. RECOMPILING YOUR KERNEL
 If your kernel is not yet configured for the AZTECH driver and the ISO9660-
@@ -428,6 +434,7 @@ History:  V0.1  W.Zimmermann: First release. Nov. 8, 1994
           V0.4  W.Zimmermann: fixed some bugs. Dec. 17, 1994
           V0.5  W.Zimmermann: clean 'scanf' commands without compiler warnings
                               Jan. 6, 1995
+          V0.6  W.Zimmermann: volume control (still experimental). Jan. 24, 1995
 */
 
 #include <stdio.h>
@@ -444,7 +451,7 @@ void help(void)
   printf("                     PLAY TRACK   t      PAUSE        p       RESUME       r\n");
   printf("                     NEXT TRACK   n      REPEAT LAST  l       HELP         h\n");
   printf("                     SUB CHANNEL  c      TRACK INFO   i       PLAY AT      a\n");
-  printf("                     READ         d      READ RAW     w                     \n");
+  printf("                     READ         d      READ RAW     w       VOLUME       v\n");
 }
 
 int main(void)
@@ -459,8 +466,9 @@ int main(void)
   union  { struct cdrom_msf msf;
            unsigned char buf[2336];
          } azt;
+  struct cdrom_volctrl  volctrl;
 
-  printf("\nMini-Audio CD-Player V0.5   (C) 1994,1995  W.Zimmermann\n");
+  printf("\nMini-Audio CD-Player V0.6   (C) 1994,1995  W.Zimmermann\n");
   handle=open("/dev/cdrom",O_RDWR);
   ioctl(handle,CDROMRESUME);
   
@@ -580,7 +588,7 @@ int main(void)
                               entry.cdte_track=arg1;
                               if (entry.cdte_track<first) entry.cdte_track=first;
                               if (entry.cdte_track>last)  entry.cdte_track=last;
-                              entry.cdte_format=CDROM_MSF;
+                             entry.cdte_format=CDROM_MSF;
                               if (ioctl(handle,cmd,&entry)) 
                                { printf("Drive error or invalid track no.\n");
                                }
@@ -672,6 +680,19 @@ int main(void)
                            } 
                           break;
 #endif
+              case 'v':   cmd=CDROMVOLCTRL;
+                          printf("--Channel 0 Left  (0-255): ");
+                          scanf("%d",&arg1);
+                          printf("--Channel 1 Right (0-255): ");
+                          scanf("%d",&arg2);
+                          volctrl.channel0=arg1;
+                          volctrl.channel1=arg2;
+                          volctrl.channel2=0;
+                          volctrl.channel3=0;
+                          if (ioctl(handle,cmd,&volctrl)) 
+                           { printf("Drive error or unsupported command\n");
+                           }
+                          break;  
               case 'q':   if (close(handle)) printf("Drive Error: CLOSE\n");
                           exit(0);
               case 'h':   help();
index c023fb1da16d3f122847688f92c64a197214b2a2..47f767c70993c61e4dafc2ec931b5abaffb561d8 100644 (file)
@@ -1,11 +1,12 @@
-#define AZT_VERSION "V0.8"
-/*      $Id: aztcd.c,v 0.80 1995/01/21 19:54:53 root Exp $
+#define AZT_VERSION "V0.9"
+/*      $Id: aztcd.c,v 0.90 1995/02/02 18:14:17 root Exp $
        linux/drivers/block/aztcd.c - AztechCD268 CDROM driver
 
        Copyright (C) 1994,1995 Werner Zimmermann (zimmerma@rz.fht-esslingen.de)
 
        based on Mitsumi CDROM driver by  Martin Hariss and preworks by
-       Eberhard Moenkeberg.
+       Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby 
+       Schirmer.
 
        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
                 Modified the SET_TIMER and CLEAR_TIMER macros to comply with
                 the new timer scheme.
                 W.Zimmermann, Jan. 21, 1995
+        V0.90   Included CDROMVOLCTRL, but with my Aztech drive I can only turn
+                the channels on and off. If it works better with your drive, 
+                please mail me. Also implemented ACMD_CLOSE for CDROMSTART.
+                W.Zimmermann, Jan. 24, 1995
        NOTE: 
        Points marked with ??? are questionable !
 */
@@ -456,6 +461,7 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi
        struct cdrom_tocentry entry;
        struct azt_Toc *tocPtr;            
        struct cdrom_subchnl subchnl;
+        struct cdrom_volctrl volctrl;
 
 #ifdef AZT_DEBUG
        printk("aztcd: starting aztcd_ioctl - Command:%x\n",cmd);
@@ -468,11 +474,12 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi
 
        switch (cmd)
        {
-       case CDROMSTART:     /* Spin up the drive */
-               /* Don't think we can do this.  Even if we could,
-                * I think the drive times out and stops after a while
-                * anyway.  For now, ignore it.
-                */
+       case CDROMSTART:     /* Spin up the drive. Don't know, what to do,
+                               at least close the tray */
+#ifdef AZT_PRIVATE_IOCTLS 
+               if (aztSendCmd(ACMD_CLOSE)) return -1;
+               STEN_LOW_WAIT;
+#endif
                break;
        case CDROMSTOP:      /* Spin down the drive */
                if (aztSendCmd(ACMD_STOP)) return -1;
@@ -481,8 +488,8 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi
                aztAudioStatus = CDROM_AUDIO_NO_STATUS;
                break;
        case CDROMPAUSE:     /* Pause the drive */
-/*              if (aztAudioStatus != CDROM_AUDIO_PLAY) return -EINVAL; 
-*/
+                if (aztAudioStatus != CDROM_AUDIO_PLAY) return -EINVAL; 
+
                if (aztGetQChannelInfo(&qInfo) < 0)
                { /* didn't get q channel info */
                  aztAudioStatus = CDROM_AUDIO_NO_STATUS;
@@ -629,13 +636,22 @@ azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
                  return -EINVAL;
                memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
                break;
-       case CDROMVOLCTRL:   /* Volume control */
-       /*
-        * This is not working yet.  Setting the volume by itself does
-        * nothing.  Following the 'set' by a 'play' results in zero
-        * volume.  Something to work on for the next release.
-        */
-               break;
+       case CDROMVOLCTRL:   /* Volume control 
+        * With my Aztech CD268-01A volume control does not work, I can only
+          turn the cannels on (any value !=0) or off (value==0). Maybe it
+           works better with your drive */
+                st=verify_area(VERIFY_READ,(void *) arg, sizeof(volctrl));
+                if (st) return (st);
+                memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl));
+               azt_Play.start.min = 0x21;
+               azt_Play.start.sec = 0x84;
+               azt_Play.start.frame = volctrl.channel0;
+               azt_Play.end.min =     volctrl.channel1;
+               azt_Play.end.sec =     volctrl.channel2;
+               azt_Play.end.frame =   volctrl.channel3;
+                sendAztCmd(ACMD_SET_VOLUME, &azt_Play);
+                STEN_LOW_WAIT;
+                break;
        case CDROMEJECT:
               /* all drives can at least stop! */
                if (aztAudioStatus == CDROM_AUDIO_PLAY) 
index 3d98ebb133a0a5f40bb2300780bd409ddbde5da6..5be8a9030c133ae747eeda4c722aeaf82a1f3dc8 100644 (file)
@@ -135,6 +135,19 @@ static int FDC2=-1;
 static unsigned int fake_change = 0;
 static int initialising=1;
 
+#define FLOPPY0_TYPE   ((CMOS_READ(0x10) >> 4) & 15)
+#define FLOPPY1_TYPE   (CMOS_READ(0x10) & 15)
+
+/*
+ * Again, the CMOS information doesn't work on the alpha..
+ */
+#ifdef __alpha__
+#undef FLOPPY0_TYPE
+#undef FLOPPY1_TYPE
+#define FLOPPY0_TYPE 6
+#define FLOPPY1_TYPE 0
+#endif
+
 
 #ifdef CONFIG_FLOPPY_2_FDC
 #define N_FDC 2
@@ -551,7 +564,7 @@ static int disk_change(int drive)
                }
                /*USETF(FD_DISK_NEWCHANGE);*/
                return 1;
-       } else if(jiffies >= DRS->select_date+DP->select_delay){
+       } else {
                UDRS->last_checked=jiffies;
                UCLEARF(FD_DISK_NEWCHANGE);
        }
@@ -808,6 +821,36 @@ static int wait_for_completion(int delay, timeout_fn function)
        return 0;
 }
 
+static int hlt_disabled=0;
+static void floppy_disable_hlt(void)
+{
+       unsigned long flags;
+       save_flags(flags);
+       cli();
+       if(!hlt_disabled){
+               hlt_disabled=1;
+#ifdef HAVE_DISABLE_HLT
+               disable_hlt();
+#endif
+       }
+       restore_flags(flags);
+}
+
+static void floppy_enable_hlt(void)
+{
+       unsigned long flags;
+       save_flags(flags);
+       cli();
+       if(hlt_disabled){
+               hlt_disabled=0;
+#ifdef HAVE_DISABLE_HLT
+               enable_hlt();
+#endif
+       }
+       restore_flags(flags);
+}
+               
+
 static void setup_DMA(void)
 {
 #ifdef CONFIG_FLOPPY_SANITY
@@ -854,6 +897,7 @@ static void setup_DMA(void)
        set_dma_count(FLOPPY_DMA, raw_cmd.length);
        enable_dma(FLOPPY_DMA);
        sti();
+       floppy_disable_hlt();
 }
 
 /* sends a command byte to the fdc */
@@ -1418,6 +1462,7 @@ static void floppy_interrupt(int irq, struct pt_regs * regs)
 {
        void (*handler)(void) = DEVICE_INTR;
 
+       floppy_enable_hlt();
        CLEAR_INTR;
        if ( fdc >= N_FDC || FDCS->address == -1){
                /* we don't even know which FDC is the culprit */
@@ -1527,6 +1572,7 @@ static void floppy_shutdown(void)
        floppy_tq.routine = (void *)(void *) empty;
        del_timer( &fd_timer);
 
+       floppy_enable_hlt();
        disable_dma(FLOPPY_DMA);
        /* avoid dma going to a random drive after shutdown */
 
@@ -2877,10 +2923,10 @@ static void config_types(void)
                       sizeof( struct floppy_drive_params ));
        }
        printk("Floppy drive(s): ");
-       set_base_type(0, (CMOS_READ(0x10) >> 4) & 15);
-       if (CMOS_READ(0x10) & 15) {
+       set_base_type(0, FLOPPY0_TYPE);
+       if (FLOPPY1_TYPE) {
                printk(", ");
-               set_base_type(1, CMOS_READ(0x10) & 15);
+               set_base_type(1, FLOPPY1_TYPE);
        }
        printk("\n");
 }
@@ -3157,7 +3203,6 @@ static char get_fdc_version(void)
        return FDC_82077;       /* Revised 82077AA passes all the tests */
 } /* get_fdc_version */
 
-#ifndef FD_MODULE
 /* lilo configuration */
 static void invert_dcl(int *ints)
 {
@@ -3198,6 +3243,8 @@ static struct param_table {
 void floppy_setup(char *str, int *ints)
 {
        int i;
+       if(!str)
+               return;
        for(i=0; i< ARRAY_SIZE(config_params); i++){
                if (strcmp(str,config_params[i].name) == 0 ){
                        config_params[i].fn(ints);
@@ -3206,7 +3253,7 @@ void floppy_setup(char *str, int *ints)
        }
        printk("unknown floppy parameter %s\n", str);
 }
-#endif
+#define FLOPPY_SETUP
 
 #ifdef FD_MODULE
 static
@@ -3372,7 +3419,7 @@ static void floppy_release_irq_and_dma(void)
 #if N_FDC > 1
        set_dor(1, ~8, 0);
 #endif
-
+       floppy_enable_hlt();
 #ifdef CONFIG_FLOPPY_SANITY
        for(drive=0; drive < N_FDC * 4; drive++)
                if( motor_off_timer[drive].next )
index a38b5ff85209c465ec9d8be74a6915d8f8a0f1a5..f20b4d0ab34fce896185d9855cbb8886735096e3 100644 (file)
@@ -248,9 +248,7 @@ mcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
        struct cdrom_tocentry entry;
        struct mcd_Toc *tocPtr;
        struct cdrom_subchnl subchnl;
-#if 0
        struct cdrom_volctrl volctrl;
-#endif
 
        if (!ip)
                return -EINVAL;
@@ -492,42 +490,30 @@ mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
                return 0;
 
        case CDROMVOLCTRL:   /* Volume control */
-       /*
-        * This is not working yet.  Setting the volume by itself does
-        * nothing.  Following the 'set' by a 'play' results in zero
-        * volume.  Something to work on for the next release.
-        */
-#if 0
                st = verify_area(VERIFY_READ, (void *) arg, sizeof(volctrl));
                if (st)
                        return st;
 
                memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
-printk("VOL %d %d\n", volctrl.channel0 & 0xFF, volctrl.channel1 & 0xFF);
                outb(MCMD_SET_VOLUME, MCDPORT(0));
                outb(volctrl.channel0, MCDPORT(0));
-               outb(0, MCDPORT(0));
+               outb(255, MCDPORT(0));
                outb(volctrl.channel1, MCDPORT(0));
-               outb(1, MCDPORT(0));
+               outb(255, MCDPORT(0));
 
                i = getMcdStatus(MCD_STATUS_DELAY);
                if (i < 0)
                        return -EIO;
 
                {
-                       int a, b, c, d;
+                       char a, b, c, d;
 
                        getValue(&a);
                        getValue(&b);
                        getValue(&c);
                        getValue(&d);
-                       printk("%02X %02X %02X %02X\n", a, b, c, d);
                }
 
-               outb(0xF8, MCDPORT(0));
-               i = getMcdStatus(MCD_STATUS_DELAY);
-               printk("F8 -> %02X\n", i & 0xFF);
-#endif
                return 0;
 
        case CDROMEJECT:
index c35442071f38b88600f71bdb7e4be586a69c1478..a746968e3d0c95babdc09e565fa378a544cea3ba 100644 (file)
@@ -16,7 +16,7 @@ Thu Jan 26 09:02:49 1995  Theodore Y. Ts'o  (tytso@rt-11)
                should happen before the receiver is shutdown; this is
                done by reversing the values of close_wait and
                close_wait2.  In the case of a very slow device, the
-               timeouts for close_wait or close_wait2 should be lengthed.
+               timeouts for close_wait or close_wait2 should be lengthened.
                If either value is set to 0, the kernel will wait forever
                for all of the data to be transmitted.  
 
index 6e243d42da00d60a13a4aa9f36ff52fac2514838..a3d31b8ef467a5a44b71bd79e5953481e22c3ca0 100644 (file)
@@ -346,6 +346,16 @@ static void memsetw(void * s, unsigned short c, unsigned int count)
        }
 }
 
+static inline void memcpyw(unsigned short *to, unsigned short *from,
+                          unsigned int count)
+{
+       count /= 2;
+       while (count) {
+               count--;
+               writew(readw(from++), to++);
+       }
+}
+
 int vc_cons_allocated(unsigned int i)
 {
        return (i < MAX_NR_CONSOLES && vc_cons[i].d);
@@ -452,7 +462,7 @@ int vc_resize(unsigned long lines, unsigned long cols)
              ol += (oll - ll) * osr;
 
            while (ol < scr_end) {
-               memcpy((void *) nl, (void *) ol, rlth);
+               memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
                if (rrem)
                  memsetw((void *)(nl + rlth), video_erase_char, rrem);
                ol += osr;
@@ -2036,7 +2046,8 @@ long con_init(long kmem_start)
 
 static void get_scrmem(int currcons)
 {
-       memcpy((void *)vc_scrbuf[currcons], (void *)origin, video_screen_size);
+       memcpyw((unsigned short *)vc_scrbuf[currcons],
+               (unsigned short *)origin, video_screen_size);
        origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
        scr_end = video_mem_end = video_mem_start + video_screen_size;
        pos = origin + y*video_size_row + (x<<1);
@@ -2077,7 +2088,8 @@ static void set_scrmem(int currcons, long offset)
 
        if (video_mem_term - video_mem_base < offset + video_screen_size)
          offset = 0;   /* strange ... */
-       memcpy((void *)(video_mem_base + offset), (void *) origin, video_screen_size);
+       memcpyw((unsigned short *)(video_mem_base + offset),
+               (unsigned short *) origin, video_screen_size);
        video_mem_start = video_mem_base;
        video_mem_end = video_mem_term;
        origin = video_mem_base + offset;
@@ -2235,13 +2247,13 @@ int do_screendump(unsigned long arg, int mode)
                                put_fs_byte(*sptr++,buf++);     
                        break;
            case 1:
-                       put_fs_byte((char)x,buf++); put_fs_byte((char)y,buf++); 
-                       memcpy_tofs(buf,(char *)origin,2*chcount);
+                       put_fs_byte((char)x,buf++); put_fs_byte((char)y,buf++);
+/*XXX*/                        memcpy_tofs(buf,(char *)origin,2*chcount);
                        break;
            case 2:
                        gotoxy(currcons, get_fs_byte(buf+2), get_fs_byte(buf+3));
                        buf+=4; /* ioctl#, console#, x,y */
-                       memcpy_fromfs((char *)origin,buf,2*chcount);
+/*XXX*/                        memcpy_fromfs((char *)origin,buf,2*chcount);
                        break;
            }
        return(0);
index 447c2366429fcb2e6d7b970243442ef409e08be5..db9f36685fb06d1d59f3d9907599522b0cf6b671 100644 (file)
@@ -2501,6 +2501,7 @@ scrn[1] = '\0';
            panic("Couldn't register Cyclom callout driver\n");
 
     bh_base[CYCLADES_BH].routine = do_cyclades_bh;
+    enable_bh(CYCLADES_BH);
 
     for (index = 0; index < 16; index++) {
            IRQ_cards[index] = 0;
index db4a9158a6a751dc1f355cafc03c888e00b2fe3b..09d0b6c17efb35afcca4a14991c9706cc1420930 100644 (file)
@@ -66,10 +66,7 @@ extern void setledstate(struct kbd_struct *kbd, unsigned int led);
 
 extern inline void set_leds(void)
 {
-       /* con_init calls (indirectly) set_leds before kbd_init
-          has been called; ignore these early calls */
-       if (bh_base[KEYBOARD_BH].routine)
-               mark_bh(KEYBOARD_BH);
+       mark_bh(KEYBOARD_BH);
 }
 
 extern inline int vc_kbd_mode(struct kbd_struct * kbd, int flag)
index 22a42a819515d15e1b45abee0c8d4a1350ede112..0a80d7f4dd85c9b64122e1982c3094efb458a019 100644 (file)
@@ -614,22 +614,8 @@ static void caps_on(void)
 
 static void show_ptregs(void)
 {
-#ifdef __i386__
-       if (!pt_regs)
-               return;
-       printk("\n");
-       printk("EIP: %04x:%08lx",0xffff & pt_regs->cs,pt_regs->eip);
-       if (pt_regs->cs & 3)
-               printk(" ESP: %04x:%08lx",0xffff & pt_regs->ss,pt_regs->esp);
-       printk(" EFLAGS: %08lx\n",pt_regs->eflags);
-       printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
-               pt_regs->orig_eax,pt_regs->ebx,pt_regs->ecx,pt_regs->edx);
-       printk("ESI: %08lx EDI: %08lx EBP: %08lx",
-               pt_regs->esi, pt_regs->edi, pt_regs->ebp);
-       printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
-               0xffff & pt_regs->ds,0xffff & pt_regs->es,
-               0xffff & pt_regs->fs,0xffff & pt_regs->gs);
-#endif
+       if (pt_regs)
+               show_regs(pt_regs);
 }
 
 static void hold(void)
@@ -1037,7 +1023,7 @@ static int send_data(unsigned char data)
                resend = 0;
                reply_expected = 1;
                outb_p(data, 0x60);
-               for(i=0; i<0x20000; i++) {
+               for(i=0; i<0x200000; i++) {
                        inb_p(0x64);            /* just as a delay */
                        if (acknowledge)
                                return 1;
@@ -1185,9 +1171,10 @@ unsigned long kbd_init(unsigned long kmem_start)
        outb(0x1,0x60);
        while (inb(0x64) & 2)
                /* nothing */;
-       send_data(0xf0);        /* Select scan code */
-       send_data(0x01);        /* type 1 */
-#endif         
+       if (!send_data(0xf0) || !send_data(0x01))
+               printk("Scanmode 1 change failed\n");
+#endif
        mark_bh(KEYBOARD_BH);
+       enable_bh(KEYBOARD_BH);
        return kmem_start;
 }
index 5db5107b58b2164f9e3460b633d9c4ec1d7ca8f5..468fac11e8e7887c10f166e494906f72a92bd5fd 100644 (file)
@@ -2425,6 +2425,7 @@ long rs_init(long kmem_start)
        struct async_struct * info;
        
        bh_base[SERIAL_BH].routine = do_serial_bh;
+       enable_bh(SERIAL_BH);
        timer_table[RS_TIMER].fn = rs_timer;
        timer_table[RS_TIMER].expires = 0;
 #ifdef CONFIG_AUTO_IRQ
index d5103c61b0f0f1c7660fd92dd28736b13075a603..126081b3860105e621f75358e6e36475da3f5784 100644 (file)
@@ -1443,8 +1443,9 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                        arg = get_fs_long((unsigned long *) arg);
                        return tty_set_ldisc(tty, arg);
                case TIOCLINUX:
-                       if ((current->tty != tty || 
-                            tty->driver.type != TTY_DRIVER_TYPE_CONSOLE) && !suser())
+                       if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
+                               return -EINVAL;
+                       if (current->tty != tty && !suser())
                                return -EPERM;
                        retval = verify_area(VERIFY_READ, (void *) arg, 1);
                        if (retval)
index 2b53f28806f2993cfeabdc359128fd3b0ea87473..f295160a797552fcf9b5c98db8224c268fb364d0 100644 (file)
@@ -38,7 +38,7 @@ Tue Jan 31 10:42:35 EST 1995
    are unique to this package and simply may be moved into place.  The
    others are modified versions of pre-existing files and must
    be incorporated more carefully.  However, the regions of modified code
-   within these files are small and are bracketted by the preprocessor
+   within these files are small and are bracketed by the preprocessor
    symbol CONFIG_WAVELAN, so incorporation should be straightforward.
 
 4. If you encounter any problems send me some email.
index 5b78298a59a75834472e254c79a0b4d54312a8d2..ae233bc2bc8d96ac33e383dbf8e6a1e840d92e95 100644 (file)
@@ -4,14 +4,21 @@
  * This is an extension to the Linux operating system, and is covered by the
  * same Gnu Public License that covers that work.
  * 
- * Alphacode 0.51 (94/08/19) for Linux 1.1.47 (or later)
- * Copyrights (c) 1994 by Michael Hipp (mhipp@student.uni-tuebingen.de)
+ * Alphacode 0.62 (95/01/19) for Linux 1.1.82 (or later)
+ * Copyrights (c) 1994,1995 by M.Hipp (Michael.Hipp@student.uni-tuebingen.de)
  *    [feel free to mail ....]
  *
  * CAN YOU PLEASE REPORT ME YOUR PERFORMANCE EXPERIENCES !!.
+ * 
+ * If you find a bug, please report me:
+ *   The kernelpanic output and any kmsg from the ni52 driver
+ *   the ni5210-driver-version and the linux-kernel version 
+ *   how many shared memory (memsize) on the netcard, 
+ *   bootprom: yes/no, base_addr, mem_start
+ *   maybe the ni5210-card revision and the i82586 version
  *
  * autoprobe for: base_addr: 0x300,0x280,0x360,0x320,0x340
- *                mem_start: 0xd0000,0xd4000,0xd8000 (8K and 16K)
+ *                mem_start: 0xc8000,0xd0000,0xd4000,0xd8000 (8K and 16K)
  *
  * sources:
  *   skeleton.c from Donald Becker
  * I have also done a look in the following sources: (mail me if you need them)
  *   crynwr-packet-driver by Russ Nelson
  *   Garret A. Wollman's (fourth) i82586-driver for BSD
- *   (before getting an i82596 manual, the existing drivers helped
+ *   (before getting an i82596 (yes 596 not 586) manual, the existing drivers helped
  *    me a lot to understand this tricky chip.)
  *
- * Known Bugs:
+ * Known Problems:
  *   The internal sysbus seems to be slow. So we often lose packets because of
  *   overruns while receiving from a fast remote host. 
  *   This can slow down TCP connections. Maybe the newer ni5210 cards are better.
+ * 
+ * IMPORTANT NOTE:
+ *   On fast networks, it's a (very) good idea to have 16K shared memory. With
+ *   8K, we can store only 4 receive frames, so it can (easily) happen that a remote 
+ *   machine 'overruns' our system.
+ *
+ * Known i82586 bugs (I'm sure, there are many more!):
+ *   Running the NOP-mode, the i82586 sometimes seems to forget to report
+ *   every xmit-interrupt until we restart the CU.
+ *   Another MAJOR bug is, that the RU sometimes seems to ignore the EL-Bit 
+ *   in the RBD-Struct which indicates an end of the RBD queue. 
+ *   Instead, the RU fetches another (randomly selected and 
+ *   usually used) RBD and begins to fill it. (Maybe, this happens only if 
+ *   the last buffer from the previous RFD fits exact into the queue and
+ *   the next RFD can't fetch an initial RBD. Anyone knows more? )
  */
 
 /*
+ * 19.Jan.95: verified (MH)
+ *
+ * 19.Sep.94: Added Multicast support (not tested yet) (MH)
+ * 
+ * 18.Sep.94: Workarround for 'EL-Bug'. Removed flexible RBD-handling. 
+ *            Now, every RFD has exact one RBD. (MH)
+ *
+ * 14.Sep.94: added promiscous mode, a few cleanups (MH)
+ *
  * 19.Aug.94: changed request_irq() parameter (MH)
  * 
  * 20.July.94: removed cleanup bugs, removed a 16K-mem-probe-bug (MH)
  * 26.March.94: patches for Linux 1.0 and iomem-auto-probe (MH)
  *
  * 30.Sep.93: Added nop-chain .. driver now runs with only one Xmit-Buff, too (MH)
+ *
+ * < 30.Sep.93: first versions 
  */
  
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 
 #include "ni52.h"
 
-#define DEBUG   /* debug on */
-
-/*
-#define DEBUG1
-#define DEBUG2
-#define DEBUG3
-*/
-
-#define SYSBUSVAL 1
+#define DEBUG       /* debug on */
+#define SYSBUSVAL 1 /* 8 Bit */
 
 #define ni_attn586()  {outb(0,dev->base_addr+NI52_ATTENTION);}
 #define ni_reset586() {outb(0,dev->base_addr+NI52_RESET);}
 #define make24(ptr32) ((char *) (ptr32) - p->base)
 #define make16(ptr32) ((unsigned short) ((unsigned long) (ptr32) - (unsigned long) p->memtop ))
 
-/******************* how to calc the buffers *****************************
-
-IMPORTANT NOTE: if you configure only one NUM_XMIT_BUFFS, do also a 
----------------   #define ONLY_ONE_XMIT_BUF
-                btw: it seems, that only the ONLY_ONE_XMIT_BUF Mode is stable
+/******************* how to calculate the buffers *****************************
 
+  * IMPORTANT NOTE: if you configure only one NUM_XMIT_BUFFS, the driver works
+  * --------------- in a different (more stable?) mode. Only in this mode it's
+  *                 possbile to configure the driver with 'NO_NOPCOMMANDS'
 
 sizeof(scp)=12; sizeof(scb)=16; sizeof(iscp)=8;
 sizeof(scp)+sizeof(iscp)+sizeof(scb) = 36 = INIT
@@ -92,81 +116,16 @@ sizeof(rfd) = 24; sizeof(rbd) = 12;
 sizeof(tbd) = 8; sizeof(transmit_cmd) = 16;
 sizeof(nop_cmd) = 8; 
 
-examples:
----------
-
-->cfg1: NUM_RECV_FRAMES=16, NUM_RECV_BUFFS=48, RECV_BUFF_SIZE=256, 
-        NUM_XMIT_BUFFS=2 ,XMIT_BUFF_SIZE=1514
-
-NUM_RECV_FRAMES * sizeof(rfd) = 384;
-NUM_RECV_BUFFS * ( sizeof(rbd) + RECV_BUFF_SIZE) = 12864
-NUM_XMIT_BUFFS * ( sizeof(tbd+transmit_cmd+nop_cmd) + XMIT_BUFF_SIZE) = 3092
-INIT = 36
---------------------
-16358   (36 bytes left!)
-
-************************
-
-->cfg2: NUM_RECV_FRAMES=9, NUM_RECV_BUFFS=18, RECV_BUFF_SIZE=256, 
-        NUM_XMIT_BUFFS=2 ,XMIT_BUFF_SIZE=1514
-
-NUM_RECV_FRAMES * sizeof(rfd) = 216
-NUM_RECV_BUFFS * ( sizeof(rbd) + RECV_BUFF_SIZE) = 4824
-NUM_XMIT_BUFFS * ( sizeof(tbd+transmit_cmd+nop_cmd) + XMIT_BUFF_SIZE) = 3092
-INIT = 36
-------------------
-8180    (24 bytes left!)
-
-->cfg3: NUM_RECV_FRAMES=7, NUM_RECV_BUFFS=24, RECV_BUFF_SIZE=256, 
-        NUM_XMIT_BUFFS=1, XMIT_BUFF_SIZE=1514
-        168  +  6432  +  1538  +  36  +  16 = 8190 
-
-***************************************************************************/
-
-#if 0
-/* config-1 for 16Kram card */
-#  define NUM_RECV_FRAMES 16   /* number of frames to allow for receive */
-#  define NUM_RECV_BUFFS 48    /* number of buffers to allocate */
-#  define RECV_BUFF_SIZE 256   /* size of each buffer, POWER OF 2 & EVEN*/
-#  define XMIT_BUFF_SIZE 1514  /* length of transmit buffer (EVEN) */
-#  define NUM_XMIT_BUFFS 2     /* number of Xmit-Buffs */
-#elif 0
-/* config-2 for 8Kram card */
-#  define NUM_RECV_FRAMES 9
-#  define NUM_RECV_BUFFS 18
-#  define RECV_BUFF_SIZE 256
-#  define XMIT_BUFF_SIZE 1514
-#  define NUM_XMIT_BUFFS 2
-#elif 1
-/*
- * config-3 for 8Kram card  ___use_this_config____ seems to be stable
- */
-#  define NUM_RECV_FRAMES 7
-#  define NUM_RECV_BUFFS 24
-#  define RECV_BUFF_SIZE 256
-#  define XMIT_BUFF_SIZE 1514
-#  define NUM_XMIT_BUFFS 1
-#  define ONLY_ONE_XMIT_BUF 
-#  define NO_NOPCOMMANDS
-#elif 0
-/*
- * cfg-4 for 16K, ONLY_ONE_XMIT_BUF
- */
-#  define NUM_RECV_FRAMES 20
-#  define NUM_RECV_BUFFS 27
-#  define RECV_BUFF_SIZE 512
-#  define XMIT_BUFF_SIZE 1514
-#  define NUM_XMIT_BUFFS 1
-#  define ONLY_ONE_XMIT_BUF
-#else
-#  define NUM_RECV_FRAMES 4
-#  define NUM_RECV_BUFFS 4
-#  define RECV_BUFF_SIZE 1536
-#  define XMIT_BUFF_SIZE 1536
-#  define NUM_XMIT_BUFFS 1
-#  define ONLY_ONE_XMIT_BUF
-#  define NO_NOPCOMMANDS
-#endif
+  * if you don't know the driver, better do not change this values: */
+
+#define RECV_BUFF_SIZE 1524 /* slightly oversized */
+#define XMIT_BUFF_SIZE 1524 /* slightly oversized */
+#define NUM_XMIT_BUFFS 1    /* config for both, 8K and 16K shmem */
+#define NUM_RECV_BUFFS_8  4 /* config for 8K shared mem */
+#define NUM_RECV_BUFFS_16 9 /* config for 16K shared mem */
+#define NO_NOPCOMMANDS      /* only possible with NUM_XMIT_BUFFS=1 */
+
+/**************************************************************************/
 
 #define DELAY(x) {int i=jiffies; \
                   if(loops_per_sec == 1) \
@@ -175,30 +134,42 @@ INIT = 36
                      __delay((loops_per_sec>>5)*x); \
                  }
 
+/* a much shorter delay: */
+#define DELAY_16(); { __delay( (loops_per_sec>>16)+1 ); }
+
+/* wait for command with timeout: */
+#define WAIT_4_SCB_CMD() { int i; \
+  for(i=0;i<1024;i++) { \
+    if(!p->scb->cmd) break; \
+    DELAY_16(); \
+    if(i == 1023) { \
+      printk("%s: scb_cmd timed out .. resetting i82586\n",dev->name); \
+      ni_reset586(); } } }
+
 extern void autoirq_setup(int waittime);
-extern int autoirq_report(int waittime);
+extern int  autoirq_report(int waittime);
 extern void *irq2dev_map[16];
 
-#ifndef HAVE_PORTRESERVE
-#define check_region(ioaddr, size)             0
-#define        request_region(ioaddr, size,name)       do ; while (0)
-#endif
-
 #define NI52_TOTAL_SIZE 16
 #define NI52_ADDR0 0x02
 #define NI52_ADDR1 0x07
 #define NI52_ADDR2 0x01
 
+#ifndef HAVE_PORTRESERVE
+#define check_region(ioaddr, size)              0
+#define request_region(ioaddr, size,name)    do ; while (0)
+#endif
+
 static int     ni52_probe1(struct device *dev,int ioaddr);
-static void    ni52_interrupt(int irq, struct pt_regs *regs);
+static void    ni52_interrupt(int irq,struct pt_regs *reg_ptr);
 static int     ni52_open(struct device *dev);
 static int     ni52_close(struct device *dev);
 static int     ni52_send_packet(struct sk_buff *,struct device *);
-static struct enet_statistics *ni52_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static struct  enet_statistics *ni52_get_stats(struct device *dev);
+static void    set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 
 /* helper-functions */
-static int     init586(struct device *dev);
+static int     init586(struct device *dev,int num_addrs,void *addrs);
 static int     check586(struct device *dev,char *where,unsigned size);
 static void    alloc586(struct device *dev);
 static void    startrecv586(struct device *dev);
@@ -211,20 +182,19 @@ struct priv
 {
   struct enet_statistics stats;
   unsigned long base;
-  char *memtop,*max_cbuff32,*min_cbuff32,*max_cbuff24;
-  volatile struct rbd_struct  *rbd_last;
+  char *memtop;
   volatile struct rfd_struct  *rfd_last,*rfd_top,*rfd_first;
   volatile struct scp_struct  *scp;  /* volatile is important */
   volatile struct iscp_struct *iscp; /* volatile is important */
   volatile struct scb_struct  *scb;  /* volatile is important */
   volatile struct tbd_struct  *xmit_buffs[NUM_XMIT_BUFFS];
   volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
-#ifdef ONLY_ONE_XMIT_BUF
+#if (NUM_XMIT_BUFFS == 1)
   volatile struct nop_cmd_struct *nop_cmds[2];
 #else
   volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS];
 #endif
-  volatile int    nop_point;
+  volatile int    nop_point,num_recv_buffs;
   volatile char  *xmit_cbuffs[NUM_XMIT_BUFFS];
   volatile int    xmit_count,xmit_last;
 };
@@ -254,7 +224,7 @@ static int ni52_close(struct device *dev)
 static int ni52_open(struct device *dev)
 {
   alloc586(dev);
-  init586(dev);  
+  init586(dev,0,NULL);  
   startrecv586(dev);
 
   if(request_irq(dev->irq, &ni52_interrupt,0,"ni52")) 
@@ -285,7 +255,7 @@ static int check586(struct device *dev,char *where,unsigned size)
   p->memtop = where + size;
   p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
   memset((char *)p->scp,0, sizeof(struct scp_struct));
-  p->scp->sysbus = SYSBUSVAL;        /* 1 = 8Bit-Bus */
+  p->scp->sysbus = SYSBUSVAL;        /* 1 = 8Bit-Bus, 0 = 16 Bit */
   
   iscp_addrs[0] = where;
   iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct);
@@ -302,7 +272,7 @@ static int check586(struct device *dev,char *where,unsigned size)
     ni_attn586();
     DELAY(2);  /* wait a while... */
 
-    if(p->iscp->busy)
+    if(p->iscp->busy) /* i82586 clears 'busy' after succesful init */
       return 0;
   }
   return 1;
@@ -316,6 +286,9 @@ void alloc586(struct device *dev)
 {
   struct priv *p =  (struct priv *) dev->priv; 
 
+  ni_reset586();
+  DELAY(2);
+
   p->scp  = (struct scp_struct *)  (p->base + SCP_DEFAULT_ADDRESS);
   p->scb  = (struct scb_struct *)  (dev->mem_start);
   p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct));
@@ -331,12 +304,10 @@ void alloc586(struct device *dev)
   ni_reset586();
   ni_attn586();
 
-#ifdef DEBUG
   DELAY(2); 
 
   if(p->iscp->busy)
     printk("%s: Init-Problems (alloc).\n",dev->name);
-#endif
 
   memset((char *)p->scb,0,sizeof(struct scb_struct));
 }
@@ -376,7 +347,7 @@ int ni52_probe(struct device *dev)
 
 static int ni52_probe1(struct device *dev,int ioaddr)
 {
-  long memaddrs[] = { 0xd0000,0xd2000,0xd4000,0xd6000,0xd8000, 0 };
+  long memaddrs[] = { 0xd0000,0xd2000,0xc8000,0xca000,0xd4000,0xd6000,0xd8000, 0 };
   int i,size;
 
   for(i=0;i<ETH_ALEN;i++)
@@ -399,9 +370,9 @@ static int ni52_probe1(struct device *dev,int ioaddr)
    */
   if(dev->mem_start != 0) /* no auto-mem-probe */
   {
-    size = 0x4000;
+    size = 0x4000; /* check for 16K mem */
     if(!check586(dev,(char *) dev->mem_start,size)) {
-      size = 0x2000;
+      size = 0x2000; /* check for 8K mem */
       if(!check586(dev,(char *) dev->mem_start,size)) {
         printk("?memprobe, Can't find memory at 0x%lx!\n",dev->mem_start);
         return ENODEV;
@@ -417,18 +388,25 @@ static int ni52_probe1(struct device *dev,int ioaddr)
         return ENODEV;
       }
       dev->mem_start = memaddrs[i];
-      size = 0x2000;
+      size = 0x2000; /* check for 8K mem */
       if(check586(dev,(char *)dev->mem_start,size)) /* 8K-check */
         break;
-      size = 0x4000;
+      size = 0x4000; /* check for 16K mem */
       if(check586(dev,(char *)dev->mem_start,size)) /* 16K-check */
         break;
     }
   }
-
+  dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */
+  
   ((struct priv *) (dev->priv))->base =  dev->mem_start + size - 0x01000000;
   alloc586(dev);
 
+  /* set number of receive-buffs according to memsize */
+  if(size == 0x2000)
+    ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8;
+  else
+    ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
+
   printk("Memaddr: 0x%lx, Memsize: %d, ",dev->mem_start,size);
 
   if(dev->irq < 2)
@@ -469,7 +447,7 @@ static int ni52_probe1(struct device *dev,int ioaddr)
  * needs a correct 'allocated' memory
  */
 
-static int init586(struct device *dev)
+static int init586(struct device *dev,int num_addrs,void *addrs)
 {
   void *ptr;
   unsigned long s;
@@ -478,19 +456,26 @@ static int init586(struct device *dev)
   volatile struct configure_cmd_struct  *cfg_cmd;
   volatile struct iasetup_cmd_struct *ias_cmd;
   volatile struct tdr_cmd_struct *tdr_cmd;
+  volatile struct mcsetup_cmd_struct *mc_cmd;
 
   ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));
 
   cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */
-  cfg_cmd->byte_cnt     = 0x04; /* number of cfg bytes */
-  cfg_cmd->fifo         = 0xc8;    /* fifo-limit (8=tx:32/rx:64) | monitor */
-  cfg_cmd->sav_bf       = 0x40; /* hold or discard bad recv frames (bit 7) */
-  cfg_cmd->adr_len      = 0x2e; /* addr_len |!src_insert |pre-len |loopback */
-  cfg_cmd->cmd_status   = 0;
-  cfg_cmd->cmd_cmd      = CMD_CONFIGURE | CMD_LAST;
-  cfg_cmd->cmd_link     = 0xffff;
+  cfg_cmd->cmd_status = 0;
+  cfg_cmd->cmd_cmd    = CMD_CONFIGURE | CMD_LAST;
+  cfg_cmd->cmd_link   = 0xffff;
 
+  cfg_cmd->byte_cnt   = 0x0a; /* number of cfg bytes */
+  cfg_cmd->fifo       = 0x08; /* fifo-limit (8=tx:32/rx:64) */
+  cfg_cmd->sav_bf     = 0x40; /* hold or discard bad recv frames (bit 7) */
+  cfg_cmd->adr_len    = 0x2e; /* addr_len |!src_insert |pre-len |loopback */
+  cfg_cmd->priority   = 0x00;
+  cfg_cmd->ifs        = 0x60;
+  cfg_cmd->time_low   = 0x00;
+  cfg_cmd->time_high  = 0xf2;
+  cfg_cmd->promisc    = (num_addrs < 0) ? 1 : 0;  /* promisc on/off */
+  cfg_cmd->carr_coll  = 0x00;
   p->scb->cbl_offset = make16(cfg_cmd);
 
   p->scb->cmd = CUC_START; /* cmd.-unit start */
@@ -584,41 +569,78 @@ static int init586(struct device *dev)
    /*
     * alloc nop/xmit-cmds
     */
-#ifdef ONLY_ONE_XMIT_BUF
+#if (NUM_XMIT_BUFFS == 1)
   for(i=0;i<2;i++)
   {
     p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
-    p->nop_cmds[i]->cmd_cmd    = 0;
+    p->nop_cmds[i]->cmd_cmd    = CMD_NOP;
     p->nop_cmds[i]->cmd_status = 0;
     p->nop_cmds[i]->cmd_link   = make16((p->nop_cmds[i]));
-    ptr += sizeof(struct nop_cmd_struct);
+    ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
   }
   p->xmit_cmds[0] = (struct transmit_cmd_struct *)ptr; /* transmit cmd/buff 0 */
-  ptr += sizeof(struct transmit_cmd_struct);
+  ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
 #else
   for(i=0;i<NUM_XMIT_BUFFS;i++)
   {
     p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
-    p->nop_cmds[i]->cmd_cmd    = 0;
+    p->nop_cmds[i]->cmd_cmd    = CMD_NOP;
     p->nop_cmds[i]->cmd_status = 0;
     p->nop_cmds[i]->cmd_link   = make16((p->nop_cmds[i]));
-    ptr += sizeof(struct nop_cmd_struct);
-    p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /* transmit cmd/buff 0 */
-    ptr += sizeof(struct transmit_cmd_struct);
+    ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
+    p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/
+    ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
   }
 #endif
 
   ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */ 
 
-   /*
-    * alloc xmit-buffs 
-    */
+  /* 
+   * Multicast setup
+   */
+  
+  if(num_addrs > 0)
+  { /* I don't understand this: do we really need memory after the init? */
+    int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
+    if(len <= 0)
+    {
+      printk("%s: Ooooops, no memory for MC-Setup!\n",dev->name);
+    }
+    else
+    {
+      if(len < num_addrs)
+      {
+        num_addrs = len;
+        printk("%s: Sorry, can only apply %d MC-Addresse(s).\n",dev->name,num_addrs);
+      }
+      mc_cmd = (struct mcsetup_cmd_struct *) ptr;
+      mc_cmd->cmd_status = 0;
+      mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST;
+      mc_cmd->cmd_link = 0xffff;
+      mc_cmd->mc_cnt = num_addrs * 6;
+      for(i=0;i<num_addrs;i++)
+        memcpy((char *) mc_cmd->mc_list[i],((char (*)[6]) addrs)[i],6);
+      p->scb->cbl_offset = make16(mc_cmd);
+      p->scb->cmd = CUC_START;
+      ni_attn586();
+      s = jiffies;
+      while(!(mc_cmd->cmd_status & STAT_COMPL))
+        if(jiffies - s > 30)
+          break;
+      if(!(mc_cmd->cmd_status & STAT_COMPL))
+        printk("%s: Can't apply multicast-address-list.\n",dev->name);
+    }
+  }
+
+  /*
+   * alloc xmit-buffs / init xmit_cmds
+   */
   for(i=0;i<NUM_XMIT_BUFFS;i++)
   {
     p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */
-    ptr += XMIT_BUFF_SIZE;
+    ptr = (char *) ptr + XMIT_BUFF_SIZE;
     p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */
-    ptr += sizeof(struct tbd_struct);
+    ptr = (char *) ptr + sizeof(struct tbd_struct);
     if((void *)ptr > (void *)p->iscp) 
     {
       printk("%s: not enough shared-mem for your configuration!\n",dev->name);
@@ -627,11 +649,12 @@ static int init586(struct device *dev)
     memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct));
     memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct));
     p->xmit_cmds[i]->cmd_status = STAT_COMPL;
+    p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT;
     p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i]));
     p->xmit_buffs[i]->next = 0xffff;
     p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i]));
   }
-  
+
   p->xmit_count = 0; 
   p->xmit_last  = 0;
 #ifndef NO_NOPCOMMANDS
@@ -645,12 +668,8 @@ static int init586(struct device *dev)
   p->scb->cbl_offset = make16(p->nop_cmds[0]);
   p->scb->cmd = CUC_START;
   ni_attn586();
-  while(p->scb->cmd);
+  WAIT_4_SCB_CMD();
 #else
-/*
-  p->nop_cmds[0]->cmd_link = make16(p->nop_cmds[1]);
-  p->nop_cmds[1]->cmd_link = make16(p->xmit_cmds[0]);
-*/
   p->xmit_cmds[0]->cmd_link = 0xffff;
   p->xmit_cmds[0]->cmd_cmd  = CMD_XMIT | CMD_LAST | CMD_INT;
 #endif
@@ -659,7 +678,7 @@ static int init586(struct device *dev)
 }
 
 /******************************************************
- * This is a helper routine for ni52_nr_int() and init586(). 
+ * This is a helper routine for ni52_rnr_int() and init586(). 
  * It sets up the Receive Frame Area (RFA).
  */
 
@@ -670,38 +689,32 @@ static void *alloc_rfa(struct device *dev,void *ptr)
   int i;
   struct priv *p = (struct priv *) dev->priv;
 
-  memset((char *) rfd,0,sizeof(struct rfd_struct)*NUM_RECV_FRAMES);
+  memset((char *) rfd,0,sizeof(struct rfd_struct)*p->num_recv_buffs);
   p->rfd_first = rfd;
 
-  for(i = 0; i < NUM_RECV_FRAMES; i++)
-    rfd[i].next = make16(rfd + (i+1) % NUM_RECV_FRAMES);
-  rfd[NUM_RECV_FRAMES-1].last = RFD_LAST; /* set EOL (no RU suspend) */
+  for(i = 0; i < p->num_recv_buffs; i++)
+    rfd[i].next = make16(rfd + (i+1) % p->num_recv_buffs);
+  rfd[p->num_recv_buffs-1].last = RFD_SUSP;   /* RU suspend */
 
-  ptr = (char *) (rfd + NUM_RECV_FRAMES);
+  ptr = (void *) (rfd + p->num_recv_buffs);
 
   rbd = (struct rbd_struct *) ptr;
-  ptr += sizeof(struct rbd_struct)*NUM_RECV_BUFFS;
+  ptr = (void *) (rbd + p->num_recv_buffs);
 
    /* clr descriptors */
-  memset((char *) rbd,0,sizeof(struct rbd_struct)*NUM_RECV_BUFFS);
+  memset((char *) rbd,0,sizeof(struct rbd_struct)*p->num_recv_buffs);
 
-  p->min_cbuff32 = ptr;
-  for(i=0;i<NUM_RECV_BUFFS;i++)
+  for(i=0;i<p->num_recv_buffs;i++)
   {
-    rbd[i].next = make16((rbd + (i+1) % NUM_RECV_BUFFS));
+    rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs));
     rbd[i].size = RECV_BUFF_SIZE;
     rbd[i].buffer = make24(ptr);
-    ptr += RECV_BUFF_SIZE;
+    ptr = (char *) ptr + RECV_BUFF_SIZE;
   }
-  rbd[NUM_RECV_BUFFS-1].size |= RBD_LAST; /* set eol */
-  p->max_cbuff32 = ptr;
-  p->max_cbuff24 = make24(p->max_cbuff32);
+
   p->rfd_top  = p->rfd_first;
-  p->rfd_last = p->rfd_first + NUM_RECV_FRAMES - 1;
+  p->rfd_last = p->rfd_first + p->num_recv_buffs - 1;
 
-  p->rbd_last = rbd + NUM_RECV_BUFFS - 1;
   p->scb->rfa_offset           = make16(p->rfd_first);
   p->rfd_first->rbd_offset     = make16(rbd);
 
@@ -713,29 +726,18 @@ static void *alloc_rfa(struct device *dev,void *ptr)
  * Interrupt Handler ...
  */
 
-static void ni52_interrupt(int irq, struct pt_regs *regs)
+static void ni52_interrupt(int irq,struct pt_regs *reg_ptr)
 {
   struct device *dev = (struct device *) irq2dev_map[irq];
   unsigned short stat;
-  int pd = 0;
   struct priv *p;
 
-#ifdef DEBUG2
-  printk("(1)");
-#endif
-
   if (dev == NULL) {
-    printk ("ni52-interrupt: irq %d for unknown device.\n", irq);
+    printk ("ni52-interrupt: irq %d for unknown device.\n",(int) -(((struct pt_regs *)reg_ptr)->orig_eax+2));
     return;
   }
   p = (struct priv *) dev->priv;
 
-  if(dev->interrupt)
-  {
-    printk("(ni52-I)");
-    return;
-  }
-
   dev->interrupt = 1;
 
   while((stat=p->scb->status & STAT_MASK))
@@ -743,57 +745,38 @@ static void ni52_interrupt(int irq, struct pt_regs *regs)
     p->scb->cmd = stat;
     ni_attn586(); /* ack inter. */
 
-    if(pd) 
-      printk("ni52-%04x/%04x-",(int) stat,(int) p->scb->status); /* debug */
+   if(stat & STAT_CX)    /* command with I-bit set complete */
+      ni52_xmt_int(dev);
 
-    if(stat & (STAT_FR | STAT_RNR)) 
+    if(stat & STAT_FR)   /* received a frame */
       ni52_rcv_int(dev);
 
-    if(stat & STAT_CX) 
-      ni52_xmt_int(dev);
-
 #ifndef NO_NOPCOMMANDS
-    if(stat & STAT_CNA)
-#else
-    if( (stat & STAT_CNA) && !(stat & STAT_CX) )
-#endif
-      printk("%s: oops! CU has left active state. stat: %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status);
-
-    if(stat & STAT_RNR)
+    if(stat & STAT_CNA)  /* CU went 'not ready' */
     {
-      printk("%s: rnr: %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status);
-      ni52_rnr_int(dev); 
-      pd = 1; /* local debug on */
+      if(dev->start)
+        printk("%s: oops! CU has left active state. stat: %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status);
     }
-
-#ifdef DEBUG2
-    pd++;
 #endif
 
-    while(p->scb->cmd)
-    {
-      int i; /* wait for ack. (ni52_xmt_int can be faster than ack!!) */
-      for(i=0;i<200;i++);
-    }
-  }
-
-#ifdef DEBUG
-  {
-    static int old_ovr=0;
-    int l;
-    if((l = p->scb->ovrn_errs - old_ovr))
+    if(stat & STAT_RNR) /* RU went 'not ready' */
     {
-      if(l > 0)
-        p->stats.rx_over_errors += l;
+      if(p->scb->status & RU_SUSPEND) /* special case: RU_SUSPEND */
+      {
+        WAIT_4_SCB_CMD();
+        p->scb->cmd = RUC_RESUME;
+        ni_attn586();
+      }
       else
-        old_ovr=0;
+      {
+        printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status);
+        ni52_rnr_int(dev); 
+      }
     }
+    WAIT_4_SCB_CMD(); /* wait for ack. (ni52_xmt_int can be faster than ack!!) */
+    if(p->scb->cmd)   /* timed out? */
+      break;
   }
-#endif
-
-#ifdef DEBUG2
-  printk("(2)");
-#endif
 
   dev->interrupt = 0;
 }
@@ -805,92 +788,37 @@ static void ni52_interrupt(int irq, struct pt_regs *regs)
 static void ni52_rcv_int(struct device *dev)
 {
   int status;
-  unsigned short totlen,pnt;
+  unsigned short totlen;
   struct sk_buff *skb;
-  struct rbd_struct *rbd,*rbd_first;
+  struct rbd_struct *rbd;
   struct priv *p = (struct priv *) dev->priv;
 
   for(;(status = p->rfd_top->status) & STAT_COMPL;)
   {
-      rbd = rbd_first = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
+      rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
 
-#ifdef DEBUG1
-      {
-        struct rbd_struct *rbd1 = rbd;
-        if(rbd1==p->rbd_last)
-          printk("L");
-        printk("S:%04x/%x/%02x >",(int) rbd1->status,(int) rbd1->size>>12,(int)((unsigned long) rbd1 & 0xff));
-        rbd1 = (struct rbd_struct *) make32(rbd1->next);
-        for(;rbd1 != rbd_first;rbd1 = (struct rbd_struct *)  make32(rbd1->next))
-        {
-          if(rbd1 == p->rbd_last)
-            printk("L:");
-          printk("%04x/%x-",(int) rbd1->status>>12,(int) rbd1->size>>12);
-        }
-        printk("< ");
-      }
+      if(status & STAT_OK) /* frame received without error? */
       {
-        struct rfd_struct *rfd1 = p->rfd_top;
-        if(rfd1==p->rfd_last)
-          printk("L");
-        printk("S:%04x/%x/%02x >",(int) rfd1->status,(int) rfd1->last>>12,(int)((unsigned long) rfd1 & 0xff));
-        rfd1 = (struct rfd_struct *) make32(rfd1->next);
-        for(;rfd1 != p->rfd_top;rfd1 = (struct rfd_struct *)  make32(rfd1->next))
+        if( (totlen = rbd->status) & RBD_LAST) /* the first and the last buffer? */
         {
-          if(rfd1 == p->rfd_last)
-            printk("L:");
-          printk("%x/%x-",(int) rfd1->status>>12,(int) rfd1->last>>12);
-        }
-        printk("<\n");
-      }
-#endif
-
-      p->rfd_top->status = 0;
-      p->rfd_top->last = RFD_LAST;
-      p->rfd_last->last = 0;        /* delete RFD_LAST, no RU suspend */
-      p->rfd_last = p->rfd_top;
-      p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next);
-
-      if(status & RFD_ERRMASK)
-        printk("%s: RFD-Error ... status: %04x.\n",dev->name,status);
-
-      if(status & STAT_OK)
-      {
-        for(totlen=0; !(rbd->status & RBD_LAST); rbd=(struct rbd_struct *) make32(rbd->next)) {
-          totlen += RECV_BUFF_SIZE;
+          totlen &= RBD_MASK; /* length of this frame */
           rbd->status = 0;
-        }
-        totlen += rbd->status & RBD_MASK;
-        rbd->status = 0;
-        
-        skb = (struct sk_buff *) alloc_skb(totlen, GFP_ATOMIC);
-
-        if (skb != NULL) /* copy header */
-        {
-          skb->len = totlen;
-          skb->dev = dev;
-
-          if(rbd->buffer < rbd_first->buffer)
+          skb = (struct sk_buff *) alloc_skb(totlen, GFP_ATOMIC);
+          if(skb != NULL)
           {
-            pnt = p->max_cbuff24 - rbd_first->buffer;
-            memcpy( (char *) skb->data,p->max_cbuff32-pnt,pnt);
-            memcpy( (char *) skb->data+pnt,p->min_cbuff32,totlen-pnt);
+            skb->len = totlen;
+            skb->dev = dev;
+            memcpy( (char *) skb->data,(char *) p->base+(unsigned long) rbd->buffer, totlen);
+            netif_rx(skb);
+            p->stats.rx_packets++;
           }
           else
-            memcpy( (char *) skb->data,(char *) p->base+(unsigned long) rbd_first->buffer, totlen);
-
-          rbd->size |= RBD_LAST;
-          p->rbd_last->size &= ~RBD_LAST;
-          p->rbd_last = rbd;
-
-          netif_rx(skb);
-          p->stats.rx_packets++;
+            p->stats.rx_dropped++;
         }
         else
         {
-          rbd->size |= RBD_LAST;
-          p->rbd_last->size &= ~RBD_LAST;
-          p->rbd_last = rbd;
+          printk("%s: received oversized frame.\n",dev->name);
+          p->stats.rx_dropped++;
         }
       }
       else /* frame !(ok), only with 'save-bad-frames' */
@@ -898,13 +826,16 @@ static void ni52_rcv_int(struct device *dev)
         printk("%s: oops! rfd-error-status: %04x\n",dev->name,status);
         p->stats.rx_errors++;
       }
+      p->rfd_top->status = 0;
+      p->rfd_top->last = RFD_SUSP;
+      p->rfd_last->last = 0;        /* delete RU_SUSP  */
+      p->rfd_last = p->rfd_top;
+      p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */
   }
 }
 
 /**********************************************************
- * I never got this error , (which should occur if someone 
- * wants to blast your machine) so I couldn't debug it for now.
- * but we _try_ to fix the receiver not ready int.
+ * handle 'Receiver went not ready'. 
  */
 
 static void ni52_rnr_int(struct device *dev)
@@ -913,13 +844,16 @@ static void ni52_rnr_int(struct device *dev)
 
   p->stats.rx_errors++;
 
-  while(p->scb->cmd);    /* wait for the last cmd */
-  p->scb->cmd = RUC_ABORT;
+  WAIT_4_SCB_CMD();    /* wait for the last cmd */
+  p->scb->cmd = RUC_ABORT; /* usually the RU is in the 'no ressource'-state .. abort it now. */
   ni_attn586(); 
-  while(p->scb->cmd);    /* wait for accept cmd. */
+  WAIT_4_SCB_CMD();    /* wait for accept cmd. */
 
   alloc_rfa(dev,(char *)p->rfd_first);
-  startrecv586(dev); /* restart */
+  startrecv586(dev); /* restart RU */
+
+  printk("%s: Receive-Unit restarted. Status: %04x\n",dev->name,p->scb->status);
+
 }
 
 /**********************************************************
@@ -931,17 +865,14 @@ static void ni52_xmt_int(struct device *dev)
   int status;
   struct priv *p = (struct priv *) dev->priv;
 
-/*
-  if(!(p->xmit_cmds[0]->cmd_status & STAT_COMPL))
-    return;
-*/
+  status = p->xmit_cmds[p->xmit_last]->cmd_status;
+  if(!(status & STAT_COMPL))
+    printk("%s: strange .. xmit-int without a 'COMPLETE'\n",dev->name);
 
-  if( (status=p->xmit_cmds[p->xmit_last]->cmd_status) & STAT_OK)
+  if(status & STAT_OK)
   {
     p->stats.tx_packets++;
     p->stats.collisions += (status & TCMD_MAXCOLLMASK);
-    dev->tbusy = 0;
-    mark_bh(NET_BH);
   }
   else 
   {
@@ -957,6 +888,7 @@ static void ni52_xmt_int(struct device *dev)
     else if(status & TCMD_LOSTCTS) 
       printk("%s: loss of CTS detected.\n",dev->name);
     else if(status & TCMD_UNDERRUN) {
+      p->stats.tx_fifo_errors++;
       printk("%s: DMA underrun detected.\n",dev->name);
     }
     else if(status & TCMD_MAXCOLL) {
@@ -965,11 +897,13 @@ static void ni52_xmt_int(struct device *dev)
     } 
   }
 
-#ifndef ONLY_ONE_XMIT_BUF
+#if (NUM_XMIT_BUFFS != 1)
   if( (++p->xmit_last) == NUM_XMIT_BUFFS) 
     p->xmit_last = 0;
 #endif
 
+  dev->tbusy = 0;
+  mark_bh(NET_BH);
 }
 
 /***********************************************************
@@ -982,13 +916,8 @@ static void startrecv586(struct device *dev)
 
   p->scb->rfa_offset = make16(p->rfd_first);
   p->scb->cmd = RUC_START;
-  ni_attn586(); /* start cmd. */
-  while(p->scb->cmd); /* wait for accept cmd. (no timeout!!) */
-
-  DELAY(2); /* isn't necess. */
-
-  p->scb->cmd = p->scb->status & STAT_MASK;
-  ni_attn586(); /* ack interr */
+  ni_attn586();                /* start cmd. */
+  WAIT_4_SCB_CMD();    /* wait for accept cmd. (no timeout!!) */
 }
 
 /******************************************************
@@ -997,7 +926,7 @@ static void startrecv586(struct device *dev)
 
 static int ni52_send_packet(struct sk_buff *skb, struct device *dev)
 {
-  int len;
+  int len,i;
 #ifndef NO_NOPCOMMANDS
   int next_nop;
 #endif
@@ -1006,18 +935,37 @@ static int ni52_send_packet(struct sk_buff *skb, struct device *dev)
   if(dev->tbusy)
   {
     int tickssofar = jiffies - dev->trans_start;
-
-    if (tickssofar < 30)
+    if (tickssofar < 5)
       return 1;
 
+    if(p->scb->status & CU_ACTIVE) /* COMMAND-UNIT active? */
+    {
+      dev->tbusy = 0;
 #ifdef DEBUG
-    printk("%s: xmitter timed out, try to restart! stat: %04x\n",dev->name,p->scb->status);
-    printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status);
+      printk("%s: strange ... timeout with CU active?!?\n",dev->name);
+      printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point);
 #endif
-
-    ni52_close(dev);
-    ni52_open(dev);
+      p->scb->cmd = CUC_ABORT;
+      ni_attn586();
+      WAIT_4_SCB_CMD();
+      p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
+      p->scb->cmd = CUC_START;
+      ni_attn586();
+      WAIT_4_SCB_CMD();
+      dev->trans_start = jiffies;
+      return 0;
+    }
+    else
+    {
+#ifdef DEBUG
+      printk("%s: xmitter timed out, try to restart! stat: %04x\n",dev->name,p->scb->status);
+      printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status);
+#endif
+      ni52_close(dev);
+      ni52_open(dev);
+    }
     dev->trans_start = jiffies;
+    return 0;
   }
 
   if(skb == NULL)
@@ -1028,6 +976,11 @@ static int ni52_send_packet(struct sk_buff *skb, struct device *dev)
 
   if (skb->len <= 0)
     return 0;
+  if(skb->len > XMIT_BUFF_SIZE)
+  {
+    printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %ld bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
+    return 0;
+  }
 
   if (set_bit(0, (void*)&dev->tbusy) != 0)
      printk("%s: Transmitter access conflict.\n", dev->name);
@@ -1036,39 +989,45 @@ static int ni52_send_packet(struct sk_buff *skb, struct device *dev)
     memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len);
     len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 
-#ifdef ONLY_ONE_XMIT_BUF  
+#if (NUM_XMIT_BUFFS == 1)
 #  ifdef NO_NOPCOMMANDS
     p->xmit_buffs[0]->size = TBD_LAST | len;
-    p->xmit_cmds[0]->cmd_status = 0;
-    p->scb->cbl_offset = make16(p->xmit_cmds[0]);
-    p->scb->cmd = CUC_START;
-
-    dev->trans_start = jiffies;
-    ni_attn586();
-    while(p->scb->cmd)
-      for(len=0;len<256;len++);
-
-  /*  DELAY(1); */ /* TEST;TEST;TEST */
+    for(i=0;i<16;i++)
+    {
+      p->scb->cbl_offset = make16(p->xmit_cmds[0]);
+      p->scb->cmd = CUC_START;
+      p->xmit_cmds[0]->cmd_status = 0;
+
+      ni_attn586();
+      dev->trans_start = jiffies;
+      if(!i)
+        dev_kfree_skb(skb,FREE_WRITE);
+      WAIT_4_SCB_CMD();
+      if( (p->scb->status & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */
+        break;
+      if(p->xmit_cmds[0]->cmd_status)
+        break;
+      if(i==15)
+        printk("%s: Can't start transmit-command.\n",dev->name);
+    }
 #  else
     next_nop = (p->nop_point + 1) & 0x1;
     p->xmit_buffs[0]->size = TBD_LAST | len;
 
-    p->xmit_cmds[0]->cmd_cmd    = CMD_XMIT | CMD_INT;
-    p->xmit_cmds[0]->cmd_status = 0;
     p->xmit_cmds[0]->cmd_link   = p->nop_cmds[next_nop]->cmd_link 
                                 = make16((p->nop_cmds[next_nop]));
-    p->nop_cmds[next_nop]->cmd_status = 0;
+    p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
 
     p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
     dev->trans_start = jiffies;
     p->nop_point = next_nop;
+    dev_kfree_skb(skb,FREE_WRITE);
 #  endif
 #else
     p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
     if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) 
       next_nop = 0;
 
-    p->xmit_cmds[p->xmit_count]->cmd_cmd  = CMD_XMIT | CMD_INT;
     p->xmit_cmds[p->xmit_count]->cmd_status  = 0;
     p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link 
                                           = make16((p->nop_cmds[next_nop]));
@@ -1082,71 +1041,57 @@ static int ni52_send_packet(struct sk_buff *skb, struct device *dev)
     if(p->xmit_count != p->xmit_last)
       dev->tbusy = 0;
     sti();
+    dev_kfree_skb(skb,FREE_WRITE);
 #endif
   }
-
-  dev_kfree_skb(skb,FREE_WRITE);
-
   return 0;
 }
 
+/*******************************************
+ * Someone wanna have the statistics 
+ */
+
 static struct enet_statistics *ni52_get_stats(struct device *dev)
 {
   struct priv *p = (struct priv *) dev->priv;
-#ifdef DEBUG3
-  printk("ni52: errs, crc %d, align %d, resource %d, ovrn %d.\n",(int) p->scb->crc_errs,(int) p->scb->aln_errs,(int) p->scb->rsc_errs,(int) p->scb->ovrn_errs); 
-#endif
+  unsigned short crc,aln,rsc,ovrn;
+
+  crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */
+  p->scb->crc_errs -= crc;
+  aln = p->scb->aln_errs;
+  p->scb->aln_errs -= aln;
+  rsc = p->scb->rsc_errs;
+  p->scb->rsc_errs -= rsc;
+  ovrn = p->scb->ovrn_errs;
+  p->scb->ovrn_errs -= ovrn;
+
+  p->stats.rx_crc_errors += crc;
+  p->stats.rx_fifo_errors += ovrn;
+  p->stats.rx_frame_errors += aln;
+  p->stats.rx_dropped += rsc;
+
   return &p->stats;
 }
 
+/********************************************************
+ * Set MC list ..  
+ */
+
 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 {
-/*
-  struct priv *p = (struct priv *) dev->priv;
-  volatile struct configure_cmd_struct  *cfg_cmd;
-*/
-
-  if(!num_addrs)
-    printk("%s: Currently, the Ni52 driver doesn't support promiscuous or multicast mode.\n",dev->name);
-
-#if 0
-  p->scb->cmd = CUC_SUSPEND;
-  ni_attn586();
-  while(p->scb->cmd);
-  p->scb->cmd = RUC_SUSPEND; 
-  ni_attn586();
-  while(p->scb->cmd);
-
-  cfg_cmd = (struct configure_cmd_struct *) p->xmit_cbuffs[0]; /* we're using a transmitcommand */
-  cfg_cmd->cmd_status = 0;
-  cfg_cmd->cmd_cmd    = CMD_CONFIGURE | CMD_LAST;
-  cfg_cmd->cmd_link   = 0xffff;
-
-  cfg_cmd->byte_cnt   = 0x0a; /* number of cfg bytes */
-  cfg_cmd->fifo       = 0x08; /* fifo-limit (8=tx:32/rx:64) */
-  cfg_cmd->sav_bf     = 0x40; /* hold or discard bad recv frames (bit 7) */
-  cfg_cmd->adr_len    = 0x2e; /* addr_len |!src_insert |pre-len |loopback */
-  cfg_cmd->priority   = 0x00;
-  cfg_cmd->ifd        = 0x60;
-  cfg_cmd->time_low   = 0x00;
-  cfg_cmd->time_high  = 0xf2;
-  cfg_cmd->promisc    = 0x01; /* promisc on */
-  cfg_cmd->carr_coll  = 0x00;
-
-  p->scb->cbl_offset = make16(cfg_cmd);
-
-  p->scb->cmd = CUC_START; /* cmd.-unit start */
-  ni_attn586();
-  while(p->scb->cmd);
-
-  p->scb->cbl_offset = p->nop_cmds[0]->cmd_link = make16(p->nop_cmds[0]);
-  p->scb->cmd = CUC_START;
-  ni_atthn586();
-  while(p->scb->cmd);
-  p->scb->cmd = RUC_RESUME;
-  ni_atthn586();
-  while(p->scb->cmd);
-#endif
+  if(!dev->start && !num_addrs)
+  {
+    printk("%s: Can't apply promiscous/multicastmode to a not running interface.\n",dev->name);
+    return;
+  }
 
+  dev->start = 0;
+  alloc586(dev);
+  init586(dev,num_addrs,addrs);  
+  startrecv586(dev);
+  dev->start = 1;
 }
+
+/*
+ * END: linux/drivers/net/ni52.c 
+ */
index 652da6eaca3d45448b40f085e8f74ef6c8d4865d..23b0a0e89d69dcddd8ef05d68a4e581a40621fab 100644 (file)
@@ -227,7 +227,7 @@ struct mcsetup_cmd_struct
   unsigned short cmd_cmd;
   unsigned short cmd_link;
   unsigned short mc_cnt;               /* number of bytes in the MC-List */
-  unsigned char  mc_list[16][6];       /* the list for 16 entries */
+  unsigned char  mc_list[0][6];        /* pointer to 6 bytes entries */
 };
 
 /*
index 421cd8216737a317c454fd0849103b1587fcc91e..1100ad5c78b36277103a2b274622372fcee85ca3 100644 (file)
 #define NEW_TTY_DRIVERS                                /* */
 #define OPTIMIZE_FLAG_TIME  ((HZ * 3)/2)       /* */
 
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#endif
+
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -63,8 +68,8 @@
 
 #include <linux/ppp.h>
 
-#include <ip.h>
-#include <tcp.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
 
 #include "slhc.h"
 
@@ -563,6 +568,10 @@ ppp_open(struct tty_struct *tty)
 
   PRINTKN (2,(KERN_INFO "ppp: channel %s open\n", ppp->dev->name));
 
+#ifdef MODULE
+  MOD_INC_USE_COUNT;
+#endif
+
   return (ppp->line);
 }
 
@@ -603,6 +612,9 @@ ppp_dev_close(struct device *dev)
   PRINTKN (2,(KERN_INFO "ppp: channel %s going down for IP packets!\n",
              dev->name));
   CHECK_PPP(-ENXIO);
+#ifdef MODULE
+  MOD_DEC_USE_COUNT;
+#endif
   return 0;
 }
 
@@ -2034,3 +2046,54 @@ static void ppp_print_buffer(const char *name, char *buf, int count, int seg)
 
   set_fs (old_fs);
 }
+
+#ifdef MODULE
+char kernel_version[] = UTS_RELEASE;
+
+static struct device dev_ppp[PPP_NRUNIT] = {
+       {
+               "ppp0",         /* ppp */
+               0, 0, 0, 0,     /* memory */
+               0, 0,           /* base, irq */
+               0, 0, 0, NULL, ppp_init,
+       },
+       { "ppp1" , 0, 0, 0, 0,  1, 0, 0, 0, 0, NULL, ppp_init },
+       { "ppp2" , 0, 0, 0, 0,  2, 0, 0, 0, 0, NULL, ppp_init },
+       { "ppp3" , 0, 0, 0, 0,  3, 0, 0, 0, 0, NULL, ppp_init },
+};
+
+int
+init_module(void)
+{
+       int err;
+       int i;
+
+       for (i = 0; i < PPP_NRUNIT; i++)  {
+               if ((err = register_netdev(&dev_ppp[i])))  {
+                       if (err == -EEXIST)  {
+                               printk("PPP: devices already present. Module not loaded.\n");
+                       }
+                       return err;
+               }
+       }
+       return 0;
+}
+
+void
+cleanup_module(void)
+{
+       int i;
+
+       if (MOD_IN_USE)  {
+               printk("PPP: device busy, remove delayed\n");
+               return;
+       }
+       for (i = 0; i < PPP_NRUNIT; i++)  {
+               unregister_netdev(&dev_ppp[i]);
+       }
+       if ((i = tty_register_ldisc(N_PPP, NULL)))  {
+               printk("PPP: can't unregister line discipline (err = %d)\n", i);
+       }
+}
+
+#endif
index ea20e0332df9e0b7273ad60b3a256474f6457f38..af6be9df9b398df5c330d615aecaefe12e2f6893 100644 (file)
@@ -71,8 +71,8 @@
 #include <linux/if_arp.h>
 #include "slip.h"
 #ifdef CONFIG_INET
-#include "ip.h"
-#include "tcp.h"
+#include <linux/ip.h>
+#include <linux/tcp.h>
 #include "slhc.h"
 #endif
 
index 203949e6f9230518d295bff8c06d4ee329dd6676..4e1f514fff63059f36244eea9e7c38a75ff80783 100644 (file)
@@ -26,7 +26,7 @@ struct psa_t
        unsigned char   psa_univ_local_sel;     /* Universal Local Selection */
 #define                PSA_UNIVERSAL   0               /* Universal (factory) */
 #define                PSA_LOCAL       1               /* Local */
-       unsigned char   psa_comp_number;        /* Compatability Number: */
+       unsigned char   psa_comp_number;        /* Compatibility Number: */
 #define                PSA_COMP_PC_AT_915      0       /* PC-AT 915 MHz        */
 #define                PSA_COMP_PC_MC_915      1       /* PC-MC 915 MHz        */
 #define                PSA_COMP_PC_AT_2400     2       /* PC-AT 2.4 GHz        */
@@ -94,7 +94,7 @@ struct mmw_t
 #define                MMW_LOOPT_SEL_LT3C      0x02    /* looptest 3c */
 #define                MMW_LOOPT_SEL_LT3D      0x01    /* looptest 3d */
        unsigned char   mmw_jabber_enable;      /* jabber timer enable */
-       unsigned char   mmw_freeze;             /* freeze / unfreeeze signal level */
+       unsigned char   mmw_freeze;             /* freeze / unfreeze signal level */
        unsigned char   mmw_anten_sel;          /* antenna selection */
 #define                MMW_ANTEN_SEL_SEL       0x01    /* direct antenna selection */
 #define                MMW_ANTEN_SEL_ALG_EN    0x02    /* antenna selection algorithm enable */
@@ -104,7 +104,7 @@ struct mmw_t
        unsigned char   mmw_unused2[1];         /* unused */
        unsigned char   mmw_thr_pre_set;        /* level threshold preset */
        unsigned char   mmw_decay_prm;          /* decay parameters */
-       unsigned char   mmw_decay_updat_prm;    /* decay update parameterz */
+       unsigned char   mmw_decay_updat_prm;    /* decay update parameters */
        unsigned char   mmw_quality_thr;        /* quality (z-quotient) threshold */
        unsigned char   mmw_netw_id_l;          /* NWID low order byte */
        unsigned char   mmw_netw_id_h;          /* NWID high order byte */
index 6532842df05b2004d987cfcd16a0b984210c4e8a..9935e60a0cf6ab4f14166a14adf4528842099227 100644 (file)
@@ -94,6 +94,8 @@ endif
 ifdef CONFIG_SCSI_U14_34F
 SCSI_OBJS := $(SCSI_OBJS) u14-34f.o
 SCSI_SRCS := $(SCSI_SRCS) u14-34f.c
+else
+SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) u14-34f.o
 endif
 
 ifdef CONFIG_SCSI_DEBUG
@@ -158,6 +160,8 @@ endif
 ifdef CONFIG_SCSI_EATA
 SCSI_OBJS := $(SCSI_OBJS) eata.o
 SCSI_SRCS := $(SCSI_SRCS) eata.c
+else
+SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) eata.o
 endif
 
 
index fbd4244d629789675859fa5f9519fdce75b0d0ea..40aa25dc65475c8dc95de2b4b4389f019d4aa1ff 100644 (file)
@@ -1030,7 +1030,7 @@ static void NCR5380_main (void) {
  *
  */
 
-static void NCR5380_intr (int irq) {
+static void NCR5380_intr (int irq, struct pt_regs * regs) {
     NCR5380_local_declare(); 
     struct Scsi_Host *instance;
     int done;
@@ -1912,7 +1912,10 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) {
        instance->hostdata;
     unsigned char msgout = NOP;
     int sink = 0;
-    int len, transfersize;
+    int len;
+#if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL)
+    int transfersize;
+#endif
     unsigned char *data;
     unsigned char phase, tmp, extended_msg[10], old_phase=0xff;
     Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
@@ -2014,7 +2017,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) {
                    } else
                        cmd->SCp.this_residual -= transfersize - len;
                } else
-#endif /* defined(REAL_DMA) || defined(REAL_DMA_POLL) */
+#endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */
                  NCR5380_transfer_pio(instance, &phase, 
                    (int *) &cmd->SCp.this_residual, (unsigned char **)
                    &cmd->SCp.ptr);
index e0a21dc33097756e6c31cbede02a2eb29cdf4fa7..7d80697fe5358ef7d4d637bbb197f8d7568ef0f6 100644 (file)
@@ -272,7 +272,7 @@ static int NCR5380_probe_irq (struct Scsi_Host *instance, int possible);
 #endif
 static void NCR5380_init (struct Scsi_Host *instance, int flags);
 static void NCR5380_information_transfer (struct Scsi_Host *instance);
-static void NCR5380_intr (int irq);
+static void NCR5380_intr (int irq, struct pt_regs * regs);
 static void NCR5380_main (void);
 static void NCR5380_print_options (struct Scsi_Host *instance);
 #ifndef NCR5380_abort
index ebe7fa7afafcd80a22c8e3d294f00a7443d68504..d33f396e80e9472381966d04ee136f3dc025da3e 100644 (file)
@@ -1,6 +1,15 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *      28 Jan 1995 rev. 1.14 for linux 1.1.86
+ *          Added module support.
+ *          Log and do a retry when a disk drive returns a target status 
+ *          different from zero on a recovered error.
+ *
+ *      24 Jan 1995 rev. 1.13 for linux 1.1.85
+ *          Use optimized board configuration, with a measured performance
+ *          increase in the range 10%-20% on i/o throughput.
+ *
  *      16 Jan 1995 rev. 1.12 for linux 1.1.81
  *          Fix mscp structure comments (no functional change).
  *          Display a message if check_region detects a port address
@@ -18,7 +27,7 @@
  *          for EISA boards, it just prints a warning message.
  *
  *      30 Nov 1994 rev. 1.09 for linux 1.1.68
- *          Redo i/o on target status CONDITION_GOOD for TYPE_DISK only.
+ *          Redo i/o on target status CHECK_CONDITION for TYPE_DISK only.
  *          Added optional support for using a single board at a time.
  *
  *      18 Nov 1994 rev. 1.08 for linux 1.1.64
  *  the driver sets host->block = TRUE for all ISA boards.
  */
 
+#if defined(MODULE)
+#include <linux/module.h>
+#endif
+
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #define ISA  0
 #define ESA 1
 
+#undef FORCE_CONFIG
+
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
 #define IN_USE   1
 #define LOCKED   2
 #define IN_RESET 3
+#define IGNORE   4
 #define NO_IRQ  0xff
-#define MAXLOOP 20000
+#define NO_DMA  0xff
+#define MAXLOOP 200000
 
 #define REG_CMD         7
 #define REG_STATUS      7
 #define REG_LM          3
 #define REG_MID         4
 #define REG_MSB         5
-#define REG_REGION      9
+#define REGION_SIZE     9
 #define EISA_RANGE      0xf000
 #define BSY_ASSERTED      0x80
 #define DRQ_ASSERTED      0x08
 #define ABSY_ASSERTED     0x01
 #define IRQ_ASSERTED      0x02
-#define READ_CONFIG_PIO   0xF0
-#define SET_CONFIG_PIO    0xF1
-#define SEND_CP_PIO       0xF2
-#define RECEIVE_SP_PIO    0xF3
-#define TRUNCATE_XFR_PIO  0xF4
-#define RESET_PIO         0xF9
-#define READ_CONFIG_DMA   0xFD
-#define SET_CONFIG_DMA    0xFE
-#define SEND_CP_DMA       0xFF
+#define READ_CONFIG_PIO   0xf0
+#define SET_CONFIG_PIO    0xf1
+#define SEND_CP_PIO       0xf2
+#define RECEIVE_SP_PIO    0xf3
+#define TRUNCATE_XFR_PIO  0xf4
+#define RESET_PIO         0xf9
+#define READ_CONFIG_DMA   0xfd
+#define SET_CONFIG_DMA    0xfe
+#define SEND_CP_DMA       0xff
 #define ASOK              0x00
 #define ASST              0x01
 
 /* "EATA", in Big Endian format */
 #define EATA_SIGNATURE 0x41544145
 
+/* Number of valid bytes in the board config structure for EATA 2.0x */
+#define EATA_2_0A_SIZE 28
+#define EATA_2_0B_SIZE 30
+
 /* Board info structure */
 struct eata_info {
-   ulong  data_len;     /* Number of valid bytes after this field (30) */
+   ulong  data_len;     /* Number of valid bytes after this field */
    ulong  sign;         /* ASCII "EATA" signature */
    unchar        :4,    /* unused low nibble */
-          version:4;    /* EATA version */
+          version:4;    /* EATA version, should be 0x1 */
    unchar  ocsena:1,    /* Overlap Command Support Enabled */
            tarsup:1,    /* Target Mode Supported */
                  :2,
@@ -162,7 +183,8 @@ struct eata_info {
               ata:1,    /* This is an ATA device */
            haaval:1;    /* Host Adapter Address Valid */
    ushort cp_pad_len;   /* Number of pad bytes after cp_len */
-   ulong  host_addr;    /* Host Adapter SCSI ID */
+   unchar host_addr[3]; /* Host Adapter SCSI ID for channels 2, 1, 0 */
+   unchar reserved;
    ulong  cp_len;       /* Number of valid bytes in cp */
    ulong  sp_len;       /* Number of valid bytes in sp */
    ushort queue_size;   /* Max number of cp that can be queued */
@@ -173,7 +195,15 @@ struct eata_info {
            second:1,    /* 1 if this is a secondary (not primary) controller */
              drqx:2;    /* DRQ Index (0=DMA0, 1=DMA7, 2=DMA6, 3=DMA5) */
    unchar  sync;        /* 1 if scsi target id 7...0 is running sync scsi */
-   ushort ipad[250];
+
+   /* Structure extension defined in EATA 2.0B */
+   unchar  isaena:1,    /* ISA i/o addressing is disabled/enabled */
+         forcaddr:1,    /* Port address has been forced */
+                 :6;
+   unchar  max_id:5,    /* Max number of SCSI target IDs */
+         max_chan:3;    /* Max SCSI channel number on this board */
+
+   ushort ipad[249];
    };
 
 /* Board config structure */
@@ -242,10 +272,12 @@ struct hostdata {
    unsigned int multicount;             /* Total ... in second ihdlr loop */
    int board_number;                    /* Number of this board */
    char board_name[16];                 /* Name of this board */
+   char board_id[256];                  /* data from INQUIRY on this board */
    int in_reset;                        /* True if board is doing a reset */
    int target_time_out[MAX_TARGET];     /* N. of timeout errors on target */
    int target_reset[MAX_TARGET];        /* If TRUE redo operation on target */
    unsigned char subversion;            /* Bus type, either ISA or ESA */
+   unsigned char protocol_rev;          /* EATA 2.0 rev., 'A' or 'B' or 'C' */
    struct mssp sp[MAX_MAILBOXES];       /* Returned status for this board */
    };
 
@@ -302,8 +334,8 @@ static inline unchar read_pio (ushort iobase, ushort *start, ushort *end) {
 static inline int port_detect(ushort *port_base, unsigned int j, 
                               Scsi_Host_Template * tpnt) {
    unsigned char irq, dma_channel, subversion;
+   unsigned char protocol_rev;
    struct eata_info info;
-   struct eata_config config;
    char *board_status;
 
    /* Allowed DMA channels for ISA (0 indicates reserved) */
@@ -313,8 +345,8 @@ static inline int port_detect(ushort *port_base, unsigned int j,
 
    sprintf(name, "%s%d", driver_name, j);
 
-   if(check_region(*port_base, REG_REGION)) {
-      printk("%s: address 0x%03x already in use, detaching.\n", 
+   if(check_region(*port_base, REGION_SIZE)) {
+      printk("%s: address 0x%03x in use, skipping probe.\n", 
              name, *port_base);
       return FALSE;
       }
@@ -325,25 +357,42 @@ static inline int port_detect(ushort *port_base, unsigned int j,
    if (read_pio(*port_base, (ushort *)&info, (ushort *)&info.ipad[0])) 
       return FALSE;
 
-   /* check the controller "EATA" signature */
+   /* Check the controller "EATA" signature */
    if (info.sign != EATA_SIGNATURE) return FALSE;
 
+   if (ntohl(info.data_len) < EATA_2_0A_SIZE) {
+      printk("%s: config structure size (%ld bytes) too short, detaching.\n", 
+             name, ntohl(info.data_len));
+      return FALSE;
+      }
+   else if (ntohl(info.data_len) == EATA_2_0A_SIZE)
+      protocol_rev = 'A';
+   else if (ntohl(info.data_len) == EATA_2_0B_SIZE)
+      protocol_rev = 'B';
+   else
+      protocol_rev = 'C';
+
+   if (protocol_rev != 'A' && info.max_chan > 0)
+      printk("%s: warning, only scsi channel 0 is supported.\n", name);
+
    irq = info.irq;
 
    if (*port_base & EISA_RANGE) {
 
       if (!info.haaval || info.ata || info.drqvld || !info.dmasup) {
-         printk("%s: unusable EISA board found, detaching.\n", name);
+         printk("%s: unusable EISA board found (%d%d%d%d), detaching.\n", 
+                name, info.haaval, info.ata, info.drqvld, info.dmasup);
          return FALSE;
          }
 
       subversion = ESA;
-      dma_channel = 0;
+      dma_channel = NO_DMA;
       }
    else {
 
       if (!info.haaval || info.ata || !info.drqvld || !info.dmasup) {
-         printk("%s: unusable ISA board found, detaching.\n", name);
+         printk("%s: unusable ISA board found (%d%d%d%d), detaching.\n",
+                name, info.haaval, info.ata, info.drqvld, info.dmasup);
          return FALSE;
          }
 
@@ -374,6 +423,10 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       return FALSE;
       }
 
+#if defined (FORCE_CONFIG)
+   {
+   struct eata_config config;
+
    /* Set board configuration */
    memset((char *)&config, 0, sizeof(struct eata_config));
    config.len = (ushort) htons((ushort)510);
@@ -383,28 +436,37 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       printk("%s: busy timeout sending configuration, detaching.\n", name);
       return FALSE;
       }
+   }
+#endif
 
    sh[j] = scsi_register(tpnt, sizeof(struct hostdata));
    sh[j]->io_port = *port_base;
+   sh[j]->n_io_port = REGION_SIZE;
    sh[j]->dma_channel = dma_channel;
    sh[j]->irq = irq;
    sh[j]->sg_tablesize = (ushort) ntohs(info.scatt_size);
-   sh[j]->this_id = (ushort) ntohl(info.host_addr);
+   sh[j]->this_id = (ushort) info.host_addr[3];
    sh[j]->can_queue = (ushort) ntohs(info.queue_size);
    sh[j]->cmd_per_lun = MAX_CMD_PER_LUN;
 
    /* Register the I/O space that we use */
-   request_region(sh[j]->io_port, REG_REGION, driver_name);
+   request_region(sh[j]->io_port, REGION_SIZE, driver_name);
 
    memset(HD(j), 0, sizeof(struct hostdata));
    HD(j)->subversion = subversion;
+   HD(j)->protocol_rev = protocol_rev;
    HD(j)->board_number = j;
    irqlist[irq] = j;
 
    if (HD(j)->subversion == ESA)
       sh[j]->unchecked_isa_dma = FALSE;
    else {
+
+#if !defined(MODULE)
+      /* The module code does not checkin/checkout in the blocking list yet */
       sh[j]->block = sh[j];
+#endif
+
       sh[j]->unchecked_isa_dma = TRUE;
       disable_dma(dma_channel);
       clear_dma_ff(dma_channel);
@@ -414,11 +476,10 @@ static inline int port_detect(ushort *port_base, unsigned int j,
 
    strcpy(BN(j), name);
 
-   printk("%s: %s, ID %d, PORT 0x%03x, IRQ %u, DMA %u, SG %d, "\
-          "Mbox %d, CmdLun %d.\n", BN(j), board_status, sh[j]->this_id, 
-           sh[j]->io_port, sh[j]->irq, 
-           sh[j]->dma_channel, sh[j]->sg_tablesize, 
-           sh[j]->can_queue, sh[j]->cmd_per_lun);
+   printk("%s: 2.0%c, %s, ID %d, PORT 0x%03x, IRQ %u, DMA %u, SG %d, "\
+          "Mbox %d, CmdLun %d.\n", BN(j), HD(j)->protocol_rev, board_status, 
+           sh[j]->this_id, sh[j]->io_port, sh[j]->irq, sh[j]->dma_channel,
+           sh[j]->sg_tablesize, sh[j]->can_queue, sh[j]->cmd_per_lun);
 
    /* DPT PM2012 does not allow to detect sg_tablesize correctly */
    if (sh[j]->sg_tablesize > MAX_SGLIST || sh[j]->sg_tablesize < 2) {
@@ -433,6 +494,11 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       }
 
 #if defined (DEBUG_DETECT)
+   if (protocol_rev != 'A')
+      printk("%s: EATA 2.0%c, isaena %u, forcaddr %u, max_id %u,"\
+             " max_chan %u.\n", name, protocol_rev, info.isaena, 
+             info.forcaddr, info.max_id, info.max_chan);
+
    printk("%s: Version 0x%x, SYNC 0x%x, infol %ld, cpl %ld spl %ld.\n", 
           name, info.version, info.sync, ntohl(info.data_len), 
           ntohl(info.cp_len), ntohl(info.sp_len));
@@ -447,7 +513,7 @@ int eata_detect (Scsi_Host_Template * tpnt) {
    ushort io_port[] = { 
       0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88,
       0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, 
-      0x330,  0x230,  0x1f0,  0x170,  0x0
+      0x1f0,  0x170,  0x330,  0x230,  0x0
       };
 
    ushort *port_base = io_port;
@@ -757,7 +823,7 @@ int eata_reset (Scsi_Cmnd *SCarg) {
 
 static void eata_interrupt_handler(int irq, struct pt_regs * regs) {
    Scsi_Cmnd *SCpnt;
-   unsigned int i, j, k, flags, status, loops, total_loops = 0;
+   unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0;
    struct mssp *spp;
    struct mscp *cpp;
 
@@ -800,7 +866,11 @@ static void eata_interrupt_handler(int irq, struct pt_regs * regs) {
    
             spp->eoc = FALSE;
    
-            if (HD(j)->cp_stat[i] == LOCKED) {
+            if (HD(j)->cp_stat[i] == IGNORE) {
+               HD(j)->cp_stat[i] = FREE;
+               continue;
+               }
+            else if (HD(j)->cp_stat[i] == LOCKED) {
                HD(j)->cp_stat[i] = FREE;
                printk("%s: ihdlr, mbox %d unlocked, count %d.\n",
                       BN(j), i, HD(j)->iocount);
@@ -836,30 +906,51 @@ static void eata_interrupt_handler(int irq, struct pt_regs * regs) {
                      " irq %d.\n", BN(j), i, SCpnt->pid, 
                      *(unsigned int *)SCpnt->host_scribble, irq);
    
+            tstatus = status_byte(spp->target_status);
+   
             switch (spp->adapter_status) {
-               case ASOK:          /* status OK */
+               case ASOK:     /* status OK */
    
-                  /* Fix a "READ CAPACITY failed" error on some disk drives */
-                  if (spp->target_status == INTERMEDIATE_GOOD
-                                        && SCpnt->device->type != TYPE_TAPE) 
+                  /* Forces a reset if a disk drive keeps returning BUSY */
+                  if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
                      status = DID_ERROR << 16;
    
                   /* If there was a bus reset, redo operation on each target */
-                  else if (spp->target_status == CONDITION_GOOD
-                                        && SCpnt->device->type == TYPE_DISK
-                                        && HD(j)->target_reset[SCpnt->target])
+                  else if (tstatus != GOOD
+                           && SCpnt->device->type == TYPE_DISK
+                           && HD(j)->target_reset[SCpnt->target])
                      status = DID_BUS_BUSY << 16;
+   
+                  /* Works around a flaw in scsi.c */
+                  else if (tstatus == CHECK_CONDITION
+                           && SCpnt->device->type == TYPE_DISK
+                           && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
+                     status = DID_BUS_BUSY << 16;
+
+                  else if (tstatus == CHECK_CONDITION
+                           && (SCpnt->device->type == TYPE_DISK
+                            || SCpnt->device->type == TYPE_ROM)
+                           && (SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION)
+                     status = DID_ERROR << 16;
+   
                   else
                      status = DID_OK << 16;
    
-                  if (spp->target_status == 0)
+                  if (tstatus == GOOD)
                      HD(j)->target_reset[SCpnt->target] = FALSE;
    
+                  if (spp->target_status && (SCpnt->device->type == TYPE_DISK
+                                          || SCpnt->device->type == TYPE_ROM))
+                     printk("%s: ihdlr, target %d:%d, pid %ld, target_status "\
+                            "0x%x, sense key 0x%x.\n", BN(j), 
+                            SCpnt->target, SCpnt->lun, SCpnt->pid,
+                            spp->target_status, SCpnt->sense_buffer[2]);
+   
                   HD(j)->target_time_out[SCpnt->target] = 0;
    
                   break;
-               case ASST:          /* Selection Time Out */
-               case 0x02:          /* Command Time Out   */
+               case ASST:     /* Selection Time Out */
+               case 0x02:     /* Command Time Out   */
    
                   if (HD(j)->target_time_out[SCpnt->target] > 1)
                      status = DID_ERROR << 16;
@@ -869,7 +960,8 @@ static void eata_interrupt_handler(int irq, struct pt_regs * regs) {
                      }
    
                   break;
-               case 0x03:          /* SCSI Bus Reset Received */
+               case 0x03:     /* SCSI Bus Reset Received */
+               case 0x04:     /* Initial Controller Power-up */
    
                   if (SCpnt->device->type != TYPE_TAPE)
                      status = DID_BUS_BUSY << 16;
@@ -880,15 +972,14 @@ static void eata_interrupt_handler(int irq, struct pt_regs * regs) {
                      HD(j)->target_reset[k] = TRUE;
    
                   break;
-               case 0x07:          /* Bus Parity Error */
-               case 0x0c:          /* Controller Ram Parity */
-               case 0x04:          /* Initial Controller Power-up */
-               case 0x05:          /* Unexpected Bus Phase */
-               case 0x06:          /* Unexpected Bus Free */
-               case 0x08:          /* SCSI Hung */
-               case 0x09:          /* Unexpected Message Reject */
-               case 0x0a:          /* SCSI Bus Reset Stuck */
-               case 0x0b:          /* Auto Request-Sense Failed */
+               case 0x07:     /* Bus Parity Error */
+               case 0x0c:     /* Controller Ram Parity */
+               case 0x05:     /* Unexpected Bus Phase */
+               case 0x06:     /* Unexpected Bus Free */
+               case 0x08:     /* SCSI Hung */
+               case 0x09:     /* Unexpected Message Reject */
+               case 0x0a:     /* SCSI Bus Reset Stuck */
+               case 0x0b:     /* Auto Request-Sense Failed */
                default:
                   status = DID_ERROR << 16;
                   break;
@@ -944,3 +1035,9 @@ static void eata_interrupt_handler(int irq, struct pt_regs * regs) {
    restore_flags(flags);
    return;
 }
+
+#if defined(MODULE)
+Scsi_Host_Template driver_template = EATA;
+
+#include "scsi_module.c"
+#endif
index 5169d4bf027598d78d68551b759ba996ff3c1052..518e9f2c68067bfc6f1f1ab0bf70a1f8552e0613 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <linux/scsicam.h>
 
-#define EATA_VERSION "1.12.00"
+#define EATA_VERSION "1.14.03"
 
 int eata_detect(Scsi_Host_Template *);
 int eata_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
@@ -16,7 +16,7 @@ int eata_reset(Scsi_Cmnd *);
 
 #define EATA {  NULL, /* Ptr for modules */                    \
                 NULL, /* usage count for modules */           \
-                "EATA/DMA 2.0A rev. " EATA_VERSION " by "      \
+                "EATA/DMA 2.0 rev. " EATA_VERSION " by "       \
                 "Dario_Ballabio@milano.europe.dg.com.",        \
                 eata_detect,                                  \
                 NULL, /* Release */                           \
@@ -32,7 +32,7 @@ int eata_reset(Scsi_Cmnd *);
                 0,   /* sg_tablesize, reset by detect */       \
                 0,   /* cmd_per_lun, reset by detect */        \
                0,   /* number of boards present */            \
-                0,   /* unchecked isa dma, reset by detect */  \
+                1,   /* unchecked isa dma, reset by detect */  \
                 ENABLE_CLUSTERING                              \
                 }
 #endif
index 4554ab363d9f3b0e221e8e17567258c0a2f0d7ca..af754f4f03b101d90ee3b4270e4a3a8dfac6e86b 100644 (file)
@@ -12,6 +12,8 @@
  *      -supports all PCI based EATA-DMA boards             *
  *      -supports multiple HBAs with & without IRQ sharing  *
  *      -supports all SCSI channels on multi channel boards *
+ *      -displays (more or less useful) infos in /proc/scsi *
+ *      -can be loaded as module                            *
  *                                                          *
  *  (c)1993,94,95 Michael Neuffer                           *
  *                neuffer@goofy.zdv.uni-mainz.de            *
  * very helpful and tried to give me all the infos and      *
  * support I need.                                          *
  *                                                          *
- *  Thanks also to Greg Hosler who did a lot of testing and *
- *  found quite a number of bugs during the development.    *
+ * Thanks also to Greg Hosler who did a lot of testing and  *
+ * found quite a number of bugs during the development.     *
  ************************************************************
- *  last change: 95/01/24                                   *
+ *  last change: 95/01/30                                   *
  ************************************************************/
 
 /* Look in eata_dma.h for configuration information */
 
+#ifdef MODULE
+#include <linux/module.h>
+#endif
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include "scsi.h"
 #include "sd.h"
 
+#if 0
+#include "eata_dma_proc.c"
+#endif
+
 static uint ISAbases[] =
 {0x1F0, 0x170, 0x330, 0x230};
 static unchar EISAbases[] =
 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
 static uint registered_HBAs = 0;
 static struct Scsi_Host *last_HBA = NULL;
+static struct Scsi_Host *first_HBA = NULL;
 static unchar reg_IRQ[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 static unchar reg_IRQL[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
 static struct eata_sp status[MAXIRQ];  /* Statuspacket array   */
 
+static uint internal_command_finished = TRUE;
+
 static struct geom_emul geometry;      /* Drive 1 & 2 geometry */
 
-#if DEBUG_EATA
 static ulong int_counter = 0;
 static ulong queue_counter = 0;
-#endif
+
+void eata_scsi_done (Scsi_Cmnd * SCpnt)
+{
+    return;
+}      
+
+int eata_release(struct Scsi_Host *sh)
+{
+  if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq);
+  else reg_IRQ[sh->irq]--;
+  if (SD(sh)->channel == 0) {
+      if (sh->dma_channel != 0xff) free_dma(sh->dma_channel);
+      if (sh->io_port && sh->n_io_port)
+         release_region(sh->io_port, sh->n_io_port);
+  }
+  return(TRUE);
+}
 
 const char *eata_info(struct Scsi_Host *host)
 {
@@ -102,13 +129,13 @@ void eata_int_handler(int irq, struct pt_regs * regs)
     save_flags(flags);
     cli();
 
-    for (x = 1, sh = last_HBA; x <= registered_HBAs; x++, sh = SD(sh)->next) {
+    for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev) {
         if (sh->irq != irq)
            continue;
         if (!(inb((uint)sh->base + HA_RAUXSTAT) & HA_AIRQ))
            continue;
 
-       DBG(DEBUG_EATA, int_counter++);
+       int_counter++;
 
        sp=&SD(sh)->sp;
 
@@ -192,14 +219,14 @@ void eata_int_handler(int irq, struct pt_regs * regs)
            break;
        }
        cmd->result = result | scsi_stat; 
-        if (scsi_stat == CHECK_CONDITION && 
+        if (in_scan_scsis && scsi_stat == CHECK_CONDITION && 
            (cmd->sense_buffer[2] & 0xf) == UNIT_ATTENTION) 
            cmd->result |= (DRIVER_SENSE << 24);
 
 #if DBG_INTR2
        if (scsi_stat || result || hba_stat || eata_stat != 0x50) 
-         printk("eata_stat: %#x hba_stat: %#.2x,scsi_stat: %#.2x, sense_key: %#x, "
-                "result: %#.8x\n", eata_stat, hba_stat, 
+           printk("eata_stat: %#x hba_stat: %#.2x,scsi_stat: %#.2x, "
+                  "sense_key: %#x, result: %#.8x\n", eata_stat, hba_stat, 
                 scsi_stat,cmd->sense_buffer[2] & 0xf, cmd->result); 
        DBG(DBG_INTR&&DBG_DELAY,DEL2(800));
 #endif
@@ -207,9 +234,8 @@ void eata_int_handler(int irq, struct pt_regs * regs)
        cp->status = FREE;   /* now we can release the slot  */
  
        restore_flags(flags);
-   
-       cmd->scsi_done(cmd);
+       if(cmd->scsi_done != eata_scsi_done) cmd->scsi_done(cmd);
+       else internal_command_finished = TRUE;
        save_flags(flags);
        cli();
     }
@@ -247,8 +273,15 @@ int eata_queue(Scsi_Cmnd * cmd, void *(done) (Scsi_Cmnd *))
     save_flags(flags);
     cli();
 
-    DBG(DEBUG_EATA, queue_counter++);
+    queue_counter++;
 
+    if (done == (void *)eata_scsi_done) { 
+        if (internal_command_finished == TRUE)
+           internal_command_finished = FALSE;
+        else 
+           cmd->result = (DID_ERROR << 16) + QUEUE_FULL;
+    }
+    
     hd = HD(cmd);
     sh = cmd->host;
  
@@ -285,11 +318,28 @@ int eata_queue(Scsi_Cmnd * cmd, void *(done) (Scsi_Cmnd *))
  
     cmd->scsi_done = (void *)done;
 
-    if (cmd->cmnd[0] == WRITE_6 || cmd->cmnd[0] == WRITE_10)
+    switch (cmd->cmnd[0]) {
+    case CHANGE_DEFINITION: case COMPARE:         case COPY:
+    case COPY_VERIFY:       case LOG_SELECT:      case MODE_SELECT:
+    case MODE_SELECT_10:    case SEND_DIAGNOSTIC: case WRITE_BUFFER:
+    case FORMAT_UNIT:       case REASSIGN_BLOCKS: case RESERVE:
+    case SEARCH_EQUAL:      case SEARCH_HIGH:     case SEARCH_LOW:
+    case WRITE_6:           case WRITE_10:        case WRITE_VERIFY:
+    case 0x3f:              case 0x41:            case 0xb1:
+    case 0xb0:              case 0xb2:            case 0xaa:
+    case 0xae:              case 0x24:            case 0x38:
+    case 0x3d:              case 0xb6:            
+    case 0xea:         /* alternate number for WRITE LONG */
        cp->DataOut = TRUE;     /* Output mode */
-    else
+        break;
+    case 0x00:
+    default:
        cp->DataIn = TRUE;      /* Input mode  */
+    }
 
+    if (done == (void *) eata_scsi_done) 
+        cp->Interpret = TRUE;   /* Interpret command */
+   
     if (cmd->use_sg) {
        cp->scatter = TRUE;     /* SG mode     */
        cp->cp_dataDMA = htonl((long)&cp->sg_list);
@@ -303,7 +353,7 @@ int eata_queue(Scsi_Cmnd * cmd, void *(done) (Scsi_Cmnd *))
     } else {
         cp->scatter = FALSE;
        cp->cp_datalen = htonl(cmd->request_bufflen);
-       cp->cp_dataDMA = htonl((int)cmd->request_buffer);
+       cp->cp_dataDMA = htonl((ulong)cmd->request_buffer);
     }
 
     cp->Auto_Req_Sen = TRUE;
@@ -327,7 +377,7 @@ int eata_queue(Scsi_Cmnd * cmd, void *(done) (Scsi_Cmnd *))
       printk("eata_queue target %d, pid %ld, HBA busy, returning DID_ERROR, done.\n",
               cmd->target, cmd->pid);
       restore_flags(flags);
-      done(cmd);
+      if(done != (void *)eata_scsi_done) done(cmd);
       return (0);
     }
     DBG(DBG_QUEUE,printk("Queued base %#.4lx pid: %ld target: %x lun: %x slot %d irq %d\n",
@@ -460,7 +510,7 @@ int eata_reset(Scsi_Cmnd * cmd)
     }
 
     /* hard reset the HBA  */
-    inb((uint) (cmd->host->base) + HA_RSTATUS);   /* This might cause trouble */
+    inb((uint) (cmd->host->base) + HA_RSTATUS);  /* This might cause trouble */
     eata_send_command(0, (uint) cmd->host->base, EATA_CMD_RESET);
 
     DBG(DBG_ABNORM, printk("eata_reset: board reset done, enabling interrupts.\n"));
@@ -511,7 +561,6 @@ int eata_reset(Scsi_Cmnd * cmd)
     }
 }
 
-
 char * get_board_data(ulong base, uint irq, uint id)
 {
     struct eata_ccb cp;
@@ -580,7 +629,7 @@ int get_conf_PIO(struct eata_register *base, struct get_conf *buf)
        if (--loop == 0) 
            return (FALSE);
        
-    DBG(DBG_PIO && DBG_PROBE, printk("Issuing PIO READ CONFIG to HBA at %lx\n", 
+    DBG(DBG_PIO && DBG_PROBE,printk("Issuing PIO READ CONFIG to HBA at %lx\n", 
                                   (long)base));
     eata_send_command(0, (uint) base, EATA_CMD_PIO_READ_CONFIG);
     loop = R_LIMIT;
@@ -645,19 +694,31 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
        return (FALSE);
     }
 
+    if ((buff = get_board_data((uint)base, gc->IRQ, gc->scsi_id[3])) == NULL){
+        printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (ulong) base);
+       return (FALSE);
+    }
+
+    if(gc->HAA_valid == FALSE || ntohl(gc->len) == 0x1c || ntohl(gc->len) == 0x1e) 
+        gc->MAX_CHAN = 0;
+
+    if(strncmp("PM2322", &buff[16], 6) && strncmp("PM3021", &buff[16], 6)
+         && strncmp("PM3222", &buff[16], 6) && strncmp("PM3224", &buff[16], 6))
+        gc->MAX_CHAN = 0;
+
     /* if gc->DMA_valid it must be a PM2011 and we have to register it */
-    dma_channel = (8 - gc->DMA_channel) & 7;
+    dma_channel = 0xff;
     if (gc->DMA_valid) {
-       if (request_dma(dma_channel, "DPT_PM2011")) {
+       if (request_dma(dma_channel = (8 - gc->DMA_channel) & 7, "DPT_PM2011")) {
            printk("Unable to allocate DMA channel %d for HBA PM2011.\n",
                dma_channel);
            return (FALSE);
        }
-    }
-
+    } 
+    
     if (!reg_IRQ[gc->IRQ]) {   /* Interrupt already registered ? */
        if (!request_irq(gc->IRQ, eata_int_handler, SA_INTERRUPT, "EATA-DMA")){
-           reg_IRQ[gc->IRQ]++;
+           reg_IRQ[gc->IRQ] += (gc->MAX_CHAN+1);
            if (!gc->IRQ_TR)
                reg_IRQL[gc->IRQ] = TRUE;       /* IRQ is edge triggered */
 
@@ -674,28 +735,17 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
                   "  if the IRQ is edge triggered. Sorry.\n");
            return (FALSE);
        } else
-           reg_IRQ[gc->IRQ]++;
+           reg_IRQ[gc->IRQ] += (gc->MAX_CHAN+1);
     }
 
     request_region(base, 9, "eata_dma");
 
-    if ((buff = get_board_data((uint)base, gc->IRQ, gc->scsi_id[3])) == NULL){
-        printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (ulong) base);
-       return (FALSE);
-    }
-
     if(ntohs(gc->queuesiz) == 0) {
         gc->queuesiz = ntohs(64);
            printk("Warning: Queue size had to be corrected.\n"
                   "This might be a PM2012 with a defective Firmware\n");
     }
 
-    if(gc->HAA_valid == FALSE || ntohl(gc->len) == 0x1c || ntohl(gc->len) == 0x1e) 
-        gc->MAX_CHAN = 0;
-
-    if(strncmp("PM2322", &buff[16], 6) && strncmp("PM3021", &buff[16], 6)
-         && strncmp("PM3222", &buff[16], 6) && strncmp("PM3224", &buff[16], 6))
-        gc->MAX_CHAN = 0;
     
     size = sizeof(hostdata) + ((sizeof(struct eata_ccb) * ntohs(gc->queuesiz))/
                               (gc->MAX_CHAN + 1));
@@ -712,7 +762,8 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
 
        memset(hd->ccb, 0, (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)) / 
               (gc->MAX_CHAN + 1));
-
+        memset(hd->reads, 0, sizeof(ulong) * 26); 
        strncpy(SD(sh)->vendor, &buff[8], 8);
        SD(sh)->vendor[8] = 0;
        strncpy(SD(sh)->name, &buff[16], 17);
@@ -737,14 +788,11 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
            SD(sh)->EATA_revision = '?';
        }
        sh->base = (char *) base;
-       sh->irq = gc->IRQ;
-       if (gc->DMA_valid) 
-         sh->dma_channel = dma_channel;
-       else 
-         sh->dma_channel = 0;
-
+       sh->io_port = (ushort) base;
+       sh->n_io_port = 9;
+       sh->irq = gc->IRQ;
+       sh->dma_channel = dma_channel;
        sh->this_id = gc->scsi_id[3 - i];
-
        sh->can_queue = ntohs(gc->queuesiz) / (gc->MAX_CHAN + 1);
 
        if (gc->OCS_enabled == TRUE) {
@@ -761,7 +809,6 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
                printk("Warning: SG size had to be corrected.\n"
                       "This might be a PM2012 with a defective Firmware\n");
        }
-       sh->loaded_as_module = 0;       /* Not yet supported */
 
        hd->channel = i;
 
@@ -803,7 +850,8 @@ int register_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
        if(hd->prev != NULL)
            SD(hd->prev)->next = sh;
        last_HBA = sh;
-       
+       if (first_HBA == NULL)
+           first_HBA = sh;
        registered_HBAs++;
     }
     return (1);
@@ -863,7 +911,7 @@ long find_ISA(struct get_conf *buf)
 
     for (l = 0; l < MAXISA; l++) {     
         if (ISAbases[l]) {     
-           if (get_conf_PIO((struct eata_register *)ISAbases[l], buf) == TRUE){
+           if (get_conf_PIO((struct eata_register *)ISAbases[l],buf) == TRUE){
                ret = ISAbases[l];
                ISAbases[l] = 0;
                return (ret);
@@ -920,7 +968,7 @@ void find_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt)
            }
 
            if (!(error = pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                                 PCI_BASE_ADDRESS_0, &base))) {
+                                                 PCI_BASE_ADDRESS_0, &base))){
 
                /* Check if the address is valid */
                if (base & 0x01) {
@@ -1005,23 +1053,18 @@ int eata_detect(Scsi_Host_Template * tpnt)
        if (reg_IRQ[i])
            request_irq(i, eata_int_handler, SA_INTERRUPT, "EATA-DMA");
 
-    HBA_ptr = last_HBA;
-    for (i = 1; i < registered_HBAs; i++)
-        HBA_ptr = SD(HBA_ptr)->prev;
+    HBA_ptr = first_HBA;
 
     printk("Registered HBAs:\n");
     printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: DMA: Ch: ID: Pr: QS: SG: CPL:\n");
     for (i = 1; i <= registered_HBAs; i++) {
-        printk("scsi%-2d: %.10s v%s 2.0%c  ", HBA_ptr->host_no, 
-              SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
-              SD(HBA_ptr)->EATA_revision);
-       if(SD(HBA_ptr)->bustype == 'P') printk("PCI "); 
-       else if(SD(HBA_ptr)->bustype == 'E') printk("EISA"); 
-       else printk("ISA ");
-       printk(" %#.4x   %2d   %2d   %d   %d   %d  %2d  %2d   %2d\n", 
-              (uint) HBA_ptr->base, HBA_ptr->irq, HBA_ptr->dma_channel, SD(HBA_ptr)->channel, 
-              HBA_ptr->this_id, SD(HBA_ptr)->primary, HBA_ptr->can_queue, 
-              HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun);
+        printk("scsi%-2d: %.10s v%s 2.0%c  %s %#.4x   %2d   %2x   %d   %d   %d  %2d  %2d   %2d\n", 
+              HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
+              SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')? 
+              "PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ",
+              (uint) HBA_ptr->base, HBA_ptr->irq, HBA_ptr->dma_channel, 
+              SD(HBA_ptr)->channel, HBA_ptr->this_id, SD(HBA_ptr)->primary, 
+              HBA_ptr->can_queue, HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun);
         HBA_ptr = SD(HBA_ptr)->next;
     }
     DBG(DPT_DEBUG,DELAY(1200));
@@ -1029,5 +1072,11 @@ int eata_detect(Scsi_Host_Template * tpnt)
     return (registered_HBAs);
 }
 
+#ifdef MODULE
+/* Eventually this will go into an include file, but this will be later */
+Scsi_Host_Template driver_template = EATA_DMA;
 
+#include "scsi_module.c"
+#endif
 
index 5dbded492ea887e774f8fb48cf9722de04e7ff58..367672cc7aca3f1ed6913968b8ba9f53b14511a9 100644 (file)
@@ -2,7 +2,7 @@
 * Header file for eata_dma.c Linux EATA-DMA SCSI driver *
 * (c) 1993,94,95 Michael Neuffer                        *
 *********************************************************
-* last change: 95/01/16                                 *
+* last change: 95/01/30                                 *
 ********************************************************/
 
 
@@ -15,8 +15,8 @@
 #include <linux/scsicam.h>
 
 #define VER_MAJOR 2
-#define VER_MINOR 1
-#define VER_SUB   "0i"
+#define VER_MINOR 3
+#define VER_SUB   "0a"
 
 /************************************************************************
  * Here you can configure your drives that are using a non-standard     *
@@ -65,6 +65,7 @@
 #define DBG_QUEUE      0       /* Trace command queueing.              */
 #define DBG_INTR       0       /* Trace interrupt service routine.     */
 #define DBG_INTR2      0       /* Trace interrupt service routine.     */
+#define DBG_PROC        0       /* Debug proc-fs related statistics     */
 #define DBG_REGISTER    0       /* */
 #define DBG_ABNORM     1       /* Debug abnormal actions (reset, abort)*/
 
@@ -79,7 +80,7 @@
        NULL, NULL,                  \
         "EATA (Extended Attachment) driver", \
         eata_detect,                 \
-        NULL,                        \
+        eata_release,                \
         eata_info,                   \
         eata_command,                \
         eata_queue,                  \
@@ -101,7 +102,7 @@ int eata_command(Scsi_Cmnd *);
 int eata_queue(Scsi_Cmnd *, void *(done)(Scsi_Cmnd *));
 int eata_abort(Scsi_Cmnd *);
 int eata_reset(Scsi_Cmnd *);
-
+int eata_release(struct Scsi_Host *);
 
 /*********************************************
  * Misc. definitions                         *
@@ -127,8 +128,24 @@ int eata_reset(Scsi_Cmnd *);
 #define MAX_PCI_BUS       16             /* Maximum # Of Busses Allowed    */
 
 #define SG_SIZE           64 
-#define C_P_L_DIV          8             /* 1 <= C_P_L_DIV <= 8            */
-#define C_P_L_CURRENT_MAX  2             /* Until this limit is removed    */
+
+#define C_P_L_CURRENT_MAX 10  /* Until this limit in the mm is removed    
+                              * Kernels < 1.1.86 died horrible deaths
+                              * if you used values >2. The memory management
+                              * of pl.86 seems to cope with 10. 
+                              */
+#define C_P_L_DIV          4  /* 1 <= C_P_L_DIV <= 8            
+                              * You can use this parameter to fine-tune
+                              * the driver. Depending on the number of 
+                              * devices and their ablilty to queue commands
+                              * you will get the best results with a value
+                              * ~= numdevices-(devices_unable_to_queue_commands/2)
+                              * The reason for this is that the disk driver tents 
+                              * to flood the queue, so that other drivers have 
+                              * problems to queue commands themselves. This can 
+                              * for example result in the effect that the tape
+                              * stops during disk accesses. 
+                              */
 
 #define FREE       0
 #define USED       1
@@ -210,7 +227,7 @@ struct eata_register {                  /* EATA register set */
   unchar data_reg[2];          /* R, couldn't figure this one out          */
   unchar cp_addr[4];           /* W, CP address register                   */
   union { 
-    unchar command;                    /* W, command code: [read|set] conf, send CP*/
+    unchar command;            /* W, command code: [read|set] conf, send CP*/
     struct reg_bit status;     /* R, see register_bit1                     */
     unchar statusunchar;
   } ovr;   
@@ -319,8 +336,7 @@ struct eata_ccb {             /* Send Command Packet structure      */
 };
 
 
-struct eata_sp
-{
+struct eata_sp {
   unchar hba_stat:7,          /* HBA status                     */
               EOC:1;          /* True if command finished       */
   unchar scsi_stat;           /* Target SCSI status             */       
@@ -330,7 +346,7 @@ struct eata_sp
   unchar msg[12];
 };
 
-typedef struct hstd{
+typedef struct hstd {
   char   vendor[9];
   char   name[18];
   char   revision[6];
@@ -338,9 +354,11 @@ typedef struct hstd{
   unchar bustype;              /* bustype of HBA             */
   unchar channel;              /* no. of scsi channel        */
   unchar state;                /* state of HBA               */
+  unchar primary;              /* true if primary            */
+  ulong  reads[13];
+  ulong  writes[13];
   unchar t_state[MAXTARGET];   /* state of Target (RESET,..) */
   uint   t_timeout[MAXTARGET]; /* timeouts on target         */
-  unchar primary;              /* true if primary            */
   uint   last_ccb;             /* Last used ccb              */
   struct Scsi_Host *next;         
   struct Scsi_Host *prev;
@@ -367,27 +385,4 @@ struct geom_emul {
   struct drive_geom_emul drv[2]; /* drive structures          */
 };
 
-struct lun_map {
-  unchar   id:5,
-         chan:3;
-  unchar lun;
-};
-
-typedef struct emul_pp {
-  unchar p_code:6,
-           null:1,
-         p_save:1;
-  unchar p_length;
-  ushort cylinder;
-  unchar heads;
-  unchar sectors;
-  unchar null2;
-  unchar s_lunmap:4,
-              ems:1;
-  ushort drive_type;   /* In Little Endian ! */
-  struct lun_map lunmap[4];
-}emulpp;
-
-
-
 #endif /* _EATA_H */
index 7b3732196f58b6abd020c773c6b57a80fc725c17..93b470894f973e0e7db866e3d9f159cc97061b50 100644 (file)
@@ -249,6 +249,8 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){
        retval->host_wait = NULL;
        retval->last_reset = 0;
        retval->irq = 0;
+       retval->dma_channel = 0xff;
+       retval->io_port = 0;
        retval->forbidden_addr = 0;
        retval->forbidden_size = 0;
        retval->hostt = tpnt;
index de93c5fac4e085979d3ce55503a751e8e5e184e2..69041d57c9d1a849f00ed15be67c33623a0ebcb7 100644 (file)
@@ -303,6 +303,7 @@ extern int scsi_loadable_module_flag;
 unsigned int scsi_init(void);
 extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int j);
 extern void scsi_unregister(struct Scsi_Host * i);
+extern int scsicam_bios_param (Disk *, int, int *);
 
 #define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 
index b5ab6835cc1cdd570ad8da8ec15c3e7b8d8f61ee..3755063f6015bfaf517319bbdd52012eb92f634b 100644 (file)
@@ -4,32 +4,35 @@
    Use at your own risk.  Support Tort Reform so you won't have to read all
    these silly disclaimers.
 
-   Copyright 1994, Tom Zerucha.
+   Copyright 1994, Tom Zerucha.   
    zerucha@shell.portal.com
 
    Additional Code, and much appreciated help by
    Michael A. Griffith
    grif@cs.ucr.edu
 
+   Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA
+   help respectively, and for suffering through my foolishness during the
+   debugging process.
+
    Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994
    (you can reference it, but it is incomplete and inaccurate in places)
 
-   Version 0.38b
+   Version 0.39a
 
-   This also works with loadable SCSI as a module.  Check configuration
-   options QL_INT_ACTIVE_HIGH and QL_TURBO_PDMA for PCMCIA usage (which
-   also requires an enabler).
+   Functions as standalone, loadable, and PCMCIA driver, the latter from
+   Dave Hind's PCMCIA package.
 
    Redistributable under terms of the GNU Public License
 
 */
 /*----------------------------------------------------------------*/
 /* Configuration */
-/* Set this if you are using the PCMCIA adapter - it will automatically
-   take care of several settings */
-#define QL_PCMCIA 0
 
-/* Set the following to 2 to use normal interrupt (active high/totempole-
+/* The following option is normally left alone.  PCMCIA support needs to
+   change this to adapt to the different way the interrupt pin works.
+   
+   Set the following to 2 to use normal interrupt (active high/totempole-
    tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open
    drain */
 #define QL_INT_ACTIVE_HIGH 2
 #define QL_USE_IRQ 1
 
 /* Set the following to max out the speed of the PIO PseudoDMA transfers,
-   again, 0 tends to be slower, but more stable.  THIS SHOULD BE ZERO FOR
-   PCMCIA */
+   again, 0 tends to be slower, but more stable.  */
 #define QL_TURBO_PDMA 1
 
 /* This will reset all devices when the driver is initialized (during bootup).
    The other linux drivers don't do this, but the DOS drivers do, and after
-   using DOS or some kind of crash or lockup this will bring things back */
+   using DOS or some kind of crash or lockup this will bring things back
+   without requiring a cold boot.  It does take some time to recover from a
+   reset, so it is slower, and I have seen timeouts so that devices weren't
+   recognized when this was set. */
 #define QL_RESET_AT_START 1
 
-/* This will set fast (10Mhz) synchronous timing, FASTCLK must also be 1*/
+/* This will set fast (10Mhz) synchronous timing, FASTCLK must also be 1 */
 #define FASTSCSI  0
 
 /* This will set a faster sync transfer rate */
        cause the deassertion to be early by 1/2 clock.  Bits 5&4 control
        the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */
 
-/* Option Synchronization */
-       
-#if QL_PCMCIA
+/* PCMCIA option adjustment */
+#ifdef PCMCIA
 #undef QL_INT_ACTIVE_HIGH
-#undef QL_TURBO_PDMA
 #define QL_INT_ACTIVE_HIGH 0
-#define QL_TURBO_PDMA 0
 #endif
 
 /*----------------------------------------------------------------*/
@@ -109,11 +111,11 @@ static char           qinfo[80];  /* description */
 static Scsi_Cmnd   *qlcmd;     /* current command being processed */
 
 /*----------------------------------------------------------------*/
-
+/* The qlogic card uses two register maps - These macros select which one */
 #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
 #define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd ))
 
-/* following is watchdog timeout */
+/* following is watchdog timeout in microseconds */
 #define WATCHDOG 5000000
 
 /*----------------------------------------------------------------*/
@@ -414,7 +416,9 @@ Scsi_Cmnd      *icmd;
        if (!(inb(qbase + 4) & 0x80))   /* false alarm? */
                return;
        if (qlcmd == NULL) {            /* no command to process? */
-               while (inb(qbase + 5)); /* maybe also ql_zap() */
+               int     i;
+               i = 16;
+               while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */
                return;
        }
        icmd = qlcmd;
@@ -489,22 +493,15 @@ unsigned long     flags;
 
 /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the
    address - I check 230 first since MIDI cards are typically at 330
-   Note that this will not work for 2 Qlogic cards in 1 system.  The
-   easiest way to do that is to create 2 versions of this file, one for
-   230 and one for 330.
-
-   Alternately, the Scsi_Host structure now stores the i/o port and can
-   be used to set the port (go through and replace qbase with
-   (struct Scsi_Cmnd *) cmd->host->io_port, or for efficiency, set a local
-   copy of qbase.  There will also need to be something similar within the
-   IRQ handlers to sort out which board it came from and thus which port.
+
+   Theoretically, two Qlogic cards can coexist in the same system.  This
+   should work by simply using this as a loadable module for the second
+   card, but I haven't tested this.
 */
 
        for (qbase = 0x230; qbase < 0x430; qbase += 0x100) {
-#ifndef PCMCIA
                if( check_region( qbase , 0x10 ) )
                        continue;
-#endif                 
                REG1;
                if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
                  && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
@@ -548,20 +545,19 @@ unsigned long     flags;
        while (inb(qbase + 5));                         /* purge int */
        while (i)                                       /* find on bit */
                i >>= 1, qlirq++;       /* should check for exactly 1 on */
-       if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, SA_INTERRUPT, "qlogic"))
+       if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic"))
                host->can_queue = 1;
        restore_flags( flags );
 #endif
-#ifndef PCMCIA
        request_region( qbase , 0x10 ,"qlogic");
-#endif
        hreg = scsi_register( host , 0 );       /* no host data */
        hreg->io_port = qbase;
        hreg->n_io_port = 16;
+       hreg->dma_channel = -1;
        if( qlirq != -1 )
                hreg->irq = qlirq;
 
-       sprintf(qinfo, "Qlogic Driver version 0.38b, chip %02X at %03X, IRQ %d, Opts:%d%d",
+       sprintf(qinfo, "Qlogic Driver version 0.39a, chip %02X at %03X, IRQ %d, Opts:%d%d",
            qltyp, qbase, qlirq, QL_INT_ACTIVE_HIGH, QL_TURBO_PDMA );
        host->name = qinfo;
 
index 705d43b7d0b4117757ab62d6d6b331037fd85254..c1cdfd0b4227b7877c1af7c6d2613dbd164a07d6 100644 (file)
@@ -145,6 +145,7 @@ static struct blist blacklist[] =
    {"CHINON","CD-ROM CDS-431","H42"},  /* Locks up if polled for lun != 0 */
    {"CHINON","CD-ROM CDS-535","Q14"}, /* Lockup if polled for lun != 0 */
    {"DENON","DRD-25X","V"},   /* A cdrom that locks up when probed at lun != 0 */
+   {"HITACHI","DK314C","CR21" }, /* responds to all lun */
    {"IMS", "CDD521/10","2.06"},   /* Locks-up when LUN>0 polled. */
    {"MAXTOR","XT-3280","PR02"},   /* Locks-up when LUN>0 polled. */
    {"MAXTOR","XT-4380S","B3C"},   /* Locks-up when LUN>0 polled. */
@@ -227,10 +228,10 @@ static void scan_scsis_done (Scsi_Cmnd * SCpnt)
          up(SCpnt->request.sem);
        }
 
-#ifdef NO_MULTI_LUN
-static int max_scsi_luns = 1;
-#else
+#ifdef CONFIG_SCSI_MULTI_LUN
 static int max_scsi_luns = 8;
+#else
+static int max_scsi_luns = 1;
 #endif
 
 void scsi_luns_setup(char *str, int *ints) {
index 8841cdf9e0aed82143ae52c910931a92a51c23b9..e47383ec0b7bf13f1fa41cabd87b45b58d4b83cb 100644 (file)
@@ -126,6 +126,7 @@ extern const unsigned char scsi_command_size[8];
 #define INTERMEDIATE_GOOD      0x08
 #define INTERMEDIATE_C_GOOD    0x0a
 #define RESERVATION_CONFLICT   0x0c
+#define QUEUE_FULL              0x1a
 
 #define STATUS_MASK            0x1e
        
index f54dd7ade054f2db37ccffc0fdf7525cf3a6b5a6..f43443862f1122d67082b5e0d9db9dc8ba563fb6 100644 (file)
@@ -86,12 +86,6 @@ static int sd_open(struct inode * inode, struct file * filp)
        if(target >= sd_template.dev_max || !rscsi_disks[target].device)
          return -ENXIO;   /* No such device */
        
-       /*
-        * See if we are requesting a non-existent partition.
-        */
-       if(sd_sizes[MINOR(inode->i_rdev)] == 0)
-         return -ENXIO;
-
 /* Make sure that only one process can do a check_change_disk at one time.
  This is also used to lock out further access when the partition table is being re-read. */
 
@@ -103,6 +97,13 @@ static int sd_open(struct inode * inode, struct file * filp)
          if(!rscsi_disks[target].device->access_count)
            sd_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
        };
+       /*
+        * See if we are requesting a non-existent partition.  Do this
+        * after checking for disk change.
+        */
+       if(sd_sizes[MINOR(inode->i_rdev)] == 0)
+         return -ENXIO;
+
        rscsi_disks[target].device->access_count++;
        if (rscsi_disks[target].device->host->hostt->usage_count)
          (*rscsi_disks[target].device->host->hostt->usage_count)++;
index 159473fdd2e4603f42c2df3efd8e869346cf0830..84039c885b4c77aadca223909569806d661127fa 100644 (file)
@@ -313,7 +313,7 @@ static int sg_write(struct inode *inode,struct file *filp,char *buf,int count)
   printk("do cmd\n");
 #endif
   scsi_do_cmd (SCpnt,(void *) cmnd,
-               (void *) device->buff,device->header.pack_len-size-sizeof(struct sg_header),
+               (void *) device->buff,amt,
               sg_command_done,device->timeout,SG_DEFAULT_RETRIES);
 #ifdef DEBUG
   printk("done cmd\n");
index 037a6f9d1f6b30c9d3a60989b21228f5774ae9ba..4e317c5556f85193a6a8b0c0ccaddf7532fe7e14 100644 (file)
@@ -15,7 +15,7 @@
 
 #define IOCTL_RETRIES 3
 /* The CDROM is fairly slow, so we need a little extra time */
-#define IOCTL_TIMEOUT 200
+#define IOCTL_TIMEOUT 2000
 
 extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
 
index 429d981ad16c9eea3bc1183bfff6c40827f02f25..3f5d07a6df5bdc83284150ece43f34cf7e6fce53 100644 (file)
@@ -11,7 +11,7 @@
   Copyright 1992, 1993, 1994, 1995 Kai Makisara
                 email Kai.Makisara@metla.fi
 
-  Last modified: Thu Jan 19 23:28:05 1995 by makisara@kai.home
+  Last modified: Mon Jan 30 23:20:07 1995 by root@kai.home
 */
 
 #include <linux/fs.h>
@@ -894,7 +894,8 @@ st_write(struct inode * inode, struct file * filp, char * buf, int count)
       else
        (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
          STp->block_size) * STp->block_size;
-      STp->dirty = 0;
+      STp->dirty = !((STp->buffer)->writing ==
+                    (STp->buffer)->buffer_bytes);
 
       if (STp->block_size == 0)
        blks = (STp->buffer)->writing;
@@ -1612,18 +1613,30 @@ st_int_ioctl(struct inode * inode,struct file * file,
        STp->drv_block = 0;
      }
      else if (cmd_in == MTFSR) {
-       if (blkno >= undone)
-        STp->drv_block = blkno - undone;
-       else
-        STp->drv_block = (-1);
+       if (SCpnt->sense_buffer[2] & 0x80) { /* Hit filemark */
+        (STp->mt_status)->mt_fileno++;
+        STp->drv_block = 0;
+       }
+       else {
+        if (blkno >= undone)
+          STp->drv_block = blkno - undone;
+        else
+          STp->drv_block = (-1);
+       }
      }
      else if (cmd_in == MTBSR) {
-       if (blkno >= 0)
-        STp->drv_block = blkno + undone;
-       else
+       if (SCpnt->sense_buffer[2] & 0x80) { /* Hit filemark */
+        (STp->mt_status)->mt_fileno--;
         STp->drv_block = (-1);
+       }
+       else {
+        if (blkno >= 0)
+          STp->drv_block = blkno + undone;
+        else
+          STp->drv_block = (-1);
+       }
      }
-     else if (cmd_in == MTEOM) {
+     else if (cmd_in == MTEOM || cmd_in == MTSEEK) {
        (STp->mt_status)->mt_fileno = (-1);
        STp->drv_block = (-1);
      }
index f8b4f6af3f7dda7b8eea9631544ca0119849ebfb..c5f1ae7a77e64a1f069c9d24e93a123635a598ab 100644 (file)
@@ -1,6 +1,15 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      28 Jan 1995 rev. 1.14 for linux 1.1.86
+ *          Added module support.
+ *          Log and do a retry when a disk drive returns a target status
+ *          different from zero on a recovered error.
+ *          Auto detects if U14F boards have an old firmware revision.
+ *          Max number of scatter/gather lists set to 16 for all boards
+ *          (most installation run fine using 33 sglists, while other
+ *          has problems when using more then 16).
+ *
  *      16 Jan 1995 rev. 1.13 for linux 1.1.81
  *          Display a message if check_region detects a port address
  *          already in use.
@@ -9,7 +18,7 @@
  *          The host->block flag is set for all the detected ISA boards.
  *
  *      30 Nov 1994 rev. 1.11 for linux 1.1.68
- *          Redo i/o on target status CONDITION_GOOD for TYPE_DISK only.
+ *          Redo i/o on target status CHECK_CONDITION for TYPE_DISK only.
  *          Added optional support for using a single board at a time.
  *
  *      14 Nov 1994 rev. 1.10 for linux 1.1.63
@@ -54,8 +63,8 @@
  *
  *  Here a sample configuration using two U14F boards:
  *
- U14F0: PORT 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 33, Mbox 16, CmdLun 2, C1.
- U14F1: PORT 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 33, Mbox 16, CmdLun 2, C1.
+ U14F0: PORT 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 16, Mbox 16, CmdLun 2, C1.
+ U14F1: PORT 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 16, Mbox 16, CmdLun 2, C1.
  *
  *  The boot controller must have its BIOS enabled, while other boards can
  *  have their BIOS disabled, or enabled to an higher address.
  *    when DISABLE_CLUSTERING is in effect, but unscattered requests could be
  *    larger than 16Kbyte.
  *
- *    The new firmware has fixed all the above problems and has been tested 
- *    with up to 33 scatter/gather lists.
+ *    The new firmware has fixed all the above problems.
  *
  *  In order to support multiple ISA boards in a reliable way,
  *  the driver sets host->block = TRUE for all ISA boards.
  */
 
+#if defined(MODULE)
+#include <linux/module.h>
+#endif
+
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #define HA_CMD_READ_BUFF  0x3
 #define HA_CMD_WRITE_BUFF 0x4
 
-#if defined (HAVE_OLD_U14F_FIRMWARE)
-#define U14F_MAX_SGLIST 16
-#define U14F_CLUSTERING DISABLE_CLUSTERING
-#else
-#define U14F_MAX_SGLIST 33
-#define U14F_CLUSTERING ENABLE_CLUSTERING
-#endif
-
-#define U34F_MAX_SGLIST 33
-#define U34F_CLUSTERING ENABLE_CLUSTERING
-
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_STATISTICS
 #define MAX_IRQ 16
 #define MAX_BOARDS 4
 #define MAX_MAILBOXES 16
-#define MAX_SGLIST 33
+#define MAX_SGLIST 16
 #define MAX_CMD_PER_LUN 2
 
 #define FALSE 0
 #define IN_USE   1
 #define LOCKED   2
 #define IN_RESET 3
+#define IGNORE   4
 #define NO_IRQ  0xff
-#define MAXLOOP 20000
+#define NO_DMA  0xff
+#define MAXLOOP 200000
 
 #define REG_LCL_MASK      0
 #define REG_LCL_INTR      1
 #define REG_CONFIG2       7
 #define REG_OGM           8
 #define REG_ICM           12
-#define REG_REGION        0x0c
+#define REGION_SIZE       13
 #define BSY_ASSERTED      0x01
-#define INTR_ASSERTED     0x01
+#define IRQ_ASSERTED      0x01
 #define CMD_RESET         0xc0
 #define CMD_OGM_INTR      0x01
 #define CMD_CLR_INTR      0x01
@@ -230,13 +233,13 @@ struct hostdata {
    unsigned int multicount;             /* Total ... in second ihdlr loop */
    int board_number;                    /* Number of this board */
    char board_name[16];                 /* Name of this board */
+   char board_id[256];                  /* data from INQUIRY on this board */
    int in_reset;                        /* True if board is doing a reset */
    int target_time_out[MAX_TARGET];     /* N. of timeout errors on target */
    int target_reset[MAX_TARGET];        /* If TRUE redo operation on target */
-   unsigned char bios_drive_number: 1;
+   unsigned char subversion;            /* Bus type, either ISA or ESA */
    unsigned char heads;
    unsigned char sectors;
-   unsigned char subversion: 4;         /* Bus type, either ISA or ESA */
 
    /* slot != 0 for the U24F, slot == 0 for both the U14F and U34F */
    unsigned char slot;
@@ -261,6 +264,49 @@ static inline unchar wait_on_busy(ushort iobase) {
    return FALSE;
 }
 
+static int board_inquiry(unsigned int j) {
+   struct mscp *cpp;
+   unsigned int time, limit = 0;
+
+   cpp = &HD(j)->cp[0];
+   memset(cpp, 0, sizeof(struct mscp));
+   cpp->opcode = OP_HOST_ADAPTER;
+   cpp->xdir = DTD_IN;
+   cpp->data_address = (unsigned int) HD(j)->board_id;
+   cpp->data_len = sizeof(HD(j)->board_id);
+   cpp->scsi_cdbs_len = 6;
+   cpp->scsi_cdbs[0] = HA_CMD_INQUIRY;
+
+   if (wait_on_busy(sh[j]->io_port)) {
+      printk("%s: board_inquiry, adapter busy.\n", BN(j));
+      return TRUE;
+      }
+
+   HD(j)->cp_stat[0] = IGNORE;
+
+   /* Clear the interrupt indication */
+   outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
+
+   /* Store pointer in OGM address bytes */
+   outl((unsigned int)cpp, sh[j]->io_port + REG_OGM);
+
+   /* Issue OGM interrupt */
+   outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
+
+   sti();
+   time = jiffies;
+   while (jiffies < (time + 100) && limit++ < 100000000) sti();
+   cli();
+
+   if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) {
+      HD(j)->cp_stat[0] = FREE;
+      printk("%s: board_inquiry, err 0x%x.\n", BN(j), cpp->adapter_status);
+      return TRUE;
+      }
+
+   return FALSE;
+}
+
 static inline int port_detect(ushort *port_base, unsigned int j, 
                               Scsi_Host_Template * tpnt) {
    unsigned char irq, dma_channel, subversion;
@@ -305,8 +351,8 @@ static inline int port_detect(ushort *port_base, unsigned int j,
 
    sprintf(name, "%s%d", driver_name, j);
 
-   if(check_region(*port_base, REG_REGION)) {
-      printk("%s: address 0x%03x already in use, detaching.\n", 
+   if(check_region(*port_base, REGION_SIZE)) {
+      printk("%s: address 0x%03x in use, skipping probe.\n", 
              name, *port_base);
       return FALSE;
       }
@@ -340,8 +386,10 @@ static inline int port_detect(ushort *port_base, unsigned int j,
 
    sh[j] = scsi_register(tpnt, sizeof(struct hostdata));
    sh[j]->io_port = *port_base;
+   sh[j]->n_io_port = REGION_SIZE;
    sh[j]->base = bios_segment_table[config_1.bios_segment];
    sh[j]->irq = irq;
+   sh[j]->sg_tablesize = MAX_SGLIST;
    sh[j]->this_id = config_2.ha_scsi_id;
    sh[j]->can_queue = MAX_MAILBOXES;
    sh[j]->cmd_per_lun = MAX_CMD_PER_LUN;
@@ -360,29 +408,36 @@ static inline int port_detect(ushort *port_base, unsigned int j,
    if (sh[j]->base == 0) outb(CMD_ENA_INTR, sh[j]->io_port + REG_SYS_MASK);
 
    /* Register the I/O space that we use */
-   request_region(sh[j]->io_port, REG_REGION, driver_name);
+   request_region(sh[j]->io_port, REGION_SIZE, driver_name);
 
    memset(HD(j), 0, sizeof(struct hostdata));
    HD(j)->heads = mapping_table[config_2.mapping_mode].heads;
    HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors;
-   HD(j)->bios_drive_number = config_2.bios_drive_number;
    HD(j)->subversion = subversion;
    HD(j)->board_number = j;
    irqlist[irq] = j;
 
    if (HD(j)->subversion == ESA) {
-      sh[j]->dma_channel = 0;
+      sh[j]->dma_channel = NO_DMA;
       sh[j]->unchecked_isa_dma = FALSE;
-      sh[j]->sg_tablesize = U34F_MAX_SGLIST;
-      sh[j]->hostt->use_clustering = U34F_CLUSTERING;
+      sh[j]->hostt->use_clustering = ENABLE_CLUSTERING;
       sprintf(BN(j), "U34F%d", j);
       }
    else {
-      sh[j]->dma_channel = dma_channel;
+
+#if !defined(MODULE)
+      /* The module code does not checkin/checkout in the blocking list yet */
       sh[j]->block = sh[j];
+#endif
+
+#if defined (HAVE_OLD_U14F_FIRMWARE)
+      sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
+#else
+      sh[j]->hostt->use_clustering = ENABLE_CLUSTERING;
+#endif
+
+      sh[j]->dma_channel = dma_channel;
       sh[j]->unchecked_isa_dma = TRUE;
-      sh[j]->sg_tablesize = U14F_MAX_SGLIST;
-      sh[j]->hostt->use_clustering = U14F_CLUSTERING;
       sprintf(BN(j), "U14F%d", j);
       disable_dma(dma_channel);
       clear_dma_ff(dma_channel);
@@ -390,6 +445,17 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       enable_dma(dma_channel);
       }
 
+   if (HD(j)->subversion == ISA && !board_inquiry(j)) {
+      HD(j)->board_id[40] = 0;
+
+      if (strcmp(&HD(j)->board_id[32], "06000600")) {
+         printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]);
+         printk("%s: firmware %s is outdated, BIOS rev. should be 2.01.\n", 
+                BN(j), &HD(j)->board_id[32]);
+         sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
+         }
+      }
+
    printk("%s: PORT 0x%03x, BIOS 0x%05x, IRQ %u, DMA %u, SG %d, "\
           "Mbox %d, CmdLun %d, C%d.\n", BN(j), sh[j]->io_port, 
           (int)sh[j]->base, sh[j]->irq, 
@@ -716,7 +782,7 @@ int u14_34f_biosparam(Disk * disk, int dev, int * dkinfo) {
 
 static void u14_34f_interrupt_handler(int irq, struct pt_regs * regs) {
    Scsi_Cmnd *SCpnt;
-   unsigned int i, j, k, flags, status, loops, total_loops = 0;
+   unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0;
    struct mscp *spp;
 
    save_flags(flags);
@@ -739,7 +805,7 @@ static void u14_34f_interrupt_handler(int irq, struct pt_regs * regs) {
       loops = 0;
 
       /* Loop until all interrupts for a board are serviced */
-      while (inb(sh[j]->io_port + REG_SYS_INTR) & INTR_ASSERTED) {
+      while (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED) {
          total_loops++;
          loops++;
 
@@ -756,7 +822,11 @@ static void u14_34f_interrupt_handler(int irq, struct pt_regs * regs) {
          if (i >= sh[j]->can_queue)
             panic("%s: ihdlr, invalid mscp address.\n", BN(j));
 
-         if (HD(j)->cp_stat[i] == LOCKED) {
+         if (HD(j)->cp_stat[i] == IGNORE) {
+            HD(j)->cp_stat[i] = FREE;
+            continue;
+            }
+         else if (HD(j)->cp_stat[i] == LOCKED) {
             HD(j)->cp_stat[i] = FREE;
             printk("%s: ihdlr, mbox %d unlocked, count %d.\n",
                    BN(j), i, HD(j)->iocount);
@@ -787,29 +857,50 @@ static void u14_34f_interrupt_handler(int irq, struct pt_regs * regs) {
                   " irq %d.\n", BN(j), i, SCpnt->pid, 
                   *(unsigned int *)SCpnt->host_scribble, irq);
 
+         tstatus = status_byte(spp->target_status);
+
          switch (spp->adapter_status) {
             case ASOK:     /* status OK */
 
-               /* Fix a "READ CAPACITY failed" error on some disk drives */
-               if (spp->target_status == INTERMEDIATE_GOOD
-                                     && SCpnt->device->type != TYPE_TAPE) 
+               /* Forces a reset if a disk drive keeps returning BUSY */
+               if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
                   status = DID_ERROR << 16;
 
                /* If there was a bus reset, redo operation on each target */
-               else if (spp->target_status == CONDITION_GOOD
-                                     && SCpnt->device->type == TYPE_DISK
-                                     && HD(j)->target_reset[SCpnt->target])
+               else if (tstatus != GOOD
+                        && SCpnt->device->type == TYPE_DISK
+                        && HD(j)->target_reset[SCpnt->target])
+                  status = DID_BUS_BUSY << 16;
+
+               /* Works around a flaw in scsi.c */
+               else if (tstatus == CHECK_CONDITION
+                        && SCpnt->device->type == TYPE_DISK
+                        && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
                   status = DID_BUS_BUSY << 16;
+
+               else if (tstatus == CHECK_CONDITION
+                        && (SCpnt->device->type == TYPE_DISK
+                         || SCpnt->device->type == TYPE_ROM)
+                        && (SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION)
+                  status = DID_ERROR << 16;
+   
                else
                   status = DID_OK << 16;
 
-               if (spp->target_status == 0)
+               if (tstatus == GOOD)
                   HD(j)->target_reset[SCpnt->target] = FALSE;
 
+               if (spp->target_status && (SCpnt->device->type == TYPE_DISK
+                                       || SCpnt->device->type == TYPE_ROM))
+                  printk("%s: ihdlr, target %d:%d, pid %ld, target_status "\
+                         "0x%x, sense key 0x%x.\n", BN(j), 
+                         SCpnt->target, SCpnt->lun, SCpnt->pid,
+                         spp->target_status, SCpnt->sense_buffer[2]);
+
                HD(j)->target_time_out[SCpnt->target] = 0;
 
                break;
-            case ASST:     /* SCSI bus selection time out */
+            case ASST:     /* Selection Time Out */
 
                if (HD(j)->target_time_out[SCpnt->target] > 1)
                   status = DID_ERROR << 16;
@@ -894,3 +985,9 @@ static void u14_34f_interrupt_handler(int irq, struct pt_regs * regs) {
    restore_flags(flags);
    return;
 }
+
+#if defined(MODULE)
+Scsi_Host_Template driver_template = ULTRASTOR_14_34F;
+
+#include "scsi_module.c"
+#endif
index c2615a14f0bc3b97f18e0e8648bf0070924180e6..041d1f81f6bdc61fde8f8c4bd2b3a794908d825b 100644 (file)
@@ -10,7 +10,7 @@ int u14_34f_abort(Scsi_Cmnd *);
 int u14_34f_reset(Scsi_Cmnd *);
 int u14_34f_biosparam(Disk *, int, int *);
 
-#define U14_34F_VERSION "1.13.00"
+#define U14_34F_VERSION "1.14.05"
 
 #define ULTRASTOR_14_34F {                                            \
                 NULL,                                                 \
@@ -31,7 +31,7 @@ int u14_34f_biosparam(Disk *, int, int *);
                 0,   /* sg_tablesize, reset by detect */              \
                 0,   /* cmd_per_lun, reset by detect */               \
                0,   /* number of boards present */                   \
-                0,   /* unchecked isa dma, reset by detect */         \
+                1,   /* unchecked isa dma, reset by detect */         \
                 0,   /* use_clustering, reset by detect */            \
                 }
 #endif
index 94ab74d5d64d28620031b96d6a23d0af6aa9e437..fec1d65f41d69dee3db3e15eaa12ed2e58468eaa 100644 (file)
 .s.o:
        $(AS) -o $*.o $<
 
-OBJS=  hpfs_fs.o
+OBJS=  hpfs_fs.o hpfs_caps.o
 
 hpfs.o: $(OBJS)
-       ln -f hpfs_fs.o hpfs.o
+       $(LD) -r -o hpfs.o $(OBJS)
 
 dep:
        $(CPP) -M *.c > .depend
diff --git a/fs/hpfs/hpfs_caps.c b/fs/hpfs/hpfs_caps.c
new file mode 100644 (file)
index 0000000..64dbf66
--- /dev/null
@@ -0,0 +1,161 @@
+/* Capitalization rules for HPFS */
+
+/* In OS/2, HPFS filenames preserve upper and lower case letter distinctions
+   but filename matching ignores case.  That is, creating a file "Foo"
+   actually creates a file named "Foo" which can be looked up as "Foo",
+   "foo", or "FOO", among other possibilities.
+
+   Also, HPFS is internationalized -- a table giving the uppercase
+   equivalent of every character is stored in the filesystem, so that
+   any national character set may be used.  If several different
+   national character sets are in use, several tables are stored
+   in the filesystem.
+
+   It would be perfectly reasonable for Linux HPFS to act as a Unix
+   filesystem and match "Foo" only if asked for "Foo" exactly.  But
+   the sort order of HPFS directories is case-insensitive, so Linux
+   still has to know the capitalization rules used by OS/2.  Because
+   of this, it turns out to be more natural for us to be case-insensitive
+   than not.
+
+   Currently the standard character set used by Linux is Latin-1.
+   Work is underway to permit people to use UTF-8 instead, therefore
+   all code that depends on the character set is segregated here.
+
+   (It would be wonderful if Linux HPFS could be independent of what
+   character set is in use on the Linux side, but because of the
+   necessary case folding this is impossible.)
+
+   There is a map from Latin-1 into code page 850 for every printing
+   character in Latin-1.  Most, maybe all, OS/2 installations have code
+   page 850 available, and surely all (on PC hardware) have 437 available.
+
+   It is not clear exactly how HPFS.IFS handles the situation when
+   multiple code pages are in use.  Experiments show that
+
+   - tables on the disk give uppercasing rules for the installed code pages
+
+   - each directory entry is tagged with what code page was current
+     when that name was created
+
+   - doing just CHCP, without changing what's on the disk in any way,
+     can change what DIR reports, and what name a case-folded match
+     will match.
+
+   This means, I think, that HPFS.IFS operates in the current code
+   page, without regard to the uppercasing information recorded in
+   the tables on the disk.  It does record the uppercasing rules
+   it used, perhaps for alien operating systems such as us, but it
+   does not appear to use them itself.
+
+   So: Linux, a Latin-1 system, will operate in code page 850.  We
+   recode between 850 and Latin-1 when dealing with the names actually
+   on the disk.  We don't use the uppercasing tables either.
+
+   In a hypothetical UTF-8 implementation, one reasonable way to
+   proceed that matches OS/2 (for least surprise) is: do case
+   translation in UTF-8, and recode to/from one of the code pages
+   available on the mounted filesystem.  Reject as invalid any name
+   containing chars that can't be represented on disk by one of the
+   code pages OS/2 is using.  Recoding from on-disk names to UTF-8
+   could use the code page tags, though this is not what OS/2 does. */
+
+static const unsigned char tb_cp850_to_latin1[128] =
+{
+  199, 252, 233, 226, 228, 224, 229, 231,
+  234, 235, 232, 239, 238, 236, 196, 197,
+  201, 230, 198, 244, 246, 242, 251, 249,
+  255, 214, 220, 248, 163, 216, 215, 159,
+  225, 237, 243, 250, 241, 209, 170, 186,
+  191, 174, 172, 189, 188, 161, 171, 187,
+  155, 156, 157, 144, 151, 193, 194, 192,
+  169, 135, 128, 131, 133, 162, 165, 147,
+  148, 153, 152, 150, 145, 154, 227, 195,
+  132, 130, 137, 136, 134, 129, 138, 164,
+  240, 208, 202, 203, 200, 158, 205, 206,
+  207, 149, 146, 141, 140, 166, 204, 139,
+  211, 223, 212, 210, 245, 213, 181, 254,
+  222, 218, 219, 217, 253, 221, 175, 180,
+  173, 177, 143, 190, 182, 167, 247, 184,
+  176, 168, 183, 185, 179, 178, 142, 160,
+};
+
+#if 0
+static const unsigned char tb_latin1_to_cp850[128] =
+{
+  186, 205, 201, 187, 200, 188, 204, 185,
+  203, 202, 206, 223, 220, 219, 254, 242,
+  179, 196, 218, 191, 192, 217, 195, 180,
+  194, 193, 197, 176, 177, 178, 213, 159,
+  255, 173, 189, 156, 207, 190, 221, 245,
+  249, 184, 166, 174, 170, 240, 169, 238,
+  248, 241, 253, 252, 239, 230, 244, 250,
+  247, 251, 167, 175, 172, 171, 243, 168,
+  183, 181, 182, 199, 142, 143, 146, 128,
+  212, 144, 210, 211, 222, 214, 215, 216,
+  209, 165, 227, 224, 226, 229, 153, 158,
+  157, 235, 233, 234, 154, 237, 232, 225,
+  133, 160, 131, 198, 132, 134, 145, 135,
+  138, 130, 136, 137, 141, 161, 140, 139,
+  208, 164, 149, 162, 147, 228, 148, 246,
+  155, 151, 163, 150, 129, 236, 231, 152,
+};
+#endif
+
+static inline unsigned latin1_upcase (unsigned c)
+{
+  if (c - (unsigned char) 'a' <= (unsigned char) 'z' - (unsigned char) 'a'
+      || (c - (unsigned char) '`' <= (unsigned char) '~' - (unsigned char) '`'
+         && c != (unsigned char) 'w'))
+    return c - (unsigned char) 'a' + (unsigned char) 'A';
+  else
+    return c;
+}
+
+static inline unsigned latin1_downcase (unsigned c)
+{
+  if (c - (unsigned char) 'A' <= (unsigned char) 'Z' - (unsigned char) 'A'
+      || (c - (unsigned char) '@' <= (unsigned char) '^' - (unsigned char) '@'
+         && c != (unsigned char) 'W'))
+    return c + (unsigned char) 'a' - (unsigned char) 'A';
+  else
+    return c;
+}
+
+#if 0
+static inline unsigned latin1_to_cp850 (unsigned c)
+{
+  if ((signed) c - 128 >= 0)
+    return tb_latin1_to_cp850[c - 128];
+  else
+    return c;
+}
+#endif
+
+static inline unsigned cp850_to_latin1 (unsigned c)
+{
+  if ((signed) c - 128 >= 0)
+    return tb_cp850_to_latin1[c - 128];
+  else
+    return c;
+}
+
+unsigned hpfs_char_to_upper_linux (unsigned c)
+{
+  return latin1_upcase (cp850_to_latin1 (c));
+}
+
+unsigned linux_char_to_upper_linux (unsigned c)
+{
+  return latin1_upcase (c);
+}
+
+unsigned hpfs_char_to_lower_linux (unsigned c)
+{
+  return latin1_downcase (cp850_to_latin1 (c));
+}
+
+unsigned hpfs_char_to_linux (unsigned c)
+{
+  return cp850_to_latin1 (c);
+}
diff --git a/fs/hpfs/hpfs_caps.h b/fs/hpfs/hpfs_caps.h
new file mode 100644 (file)
index 0000000..c4e49e9
--- /dev/null
@@ -0,0 +1,4 @@
+unsigned hpfs_char_to_linux (unsigned c);
+unsigned hpfs_char_to_lower_linux (unsigned c);
+unsigned hpfs_char_to_upper_linux (unsigned c);
+unsigned linux_char_to_upper_linux (unsigned c);
index c05cf56ab9efbe536d0b70db6a31d16042197ea1..13ad5ae327db36a99305afa083ca59dea5095974 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/segment.h>
 
 #include "hpfs.h"
+#include "hpfs_caps.h"
 
 /* 
  * HPFS is a mixture of 512-byte blocks and 2048-byte blocks.  The 2k blocks
@@ -1209,12 +1210,8 @@ static inline int memcasecmp(const unsigned char *s1, const unsigned char *s2,
 
        if (n != 0)
                do {
-                       unsigned c1 = *s1++;
-                       unsigned c2 = *s2++;
-                       if (c1 - 'a' < 26)
-                               c1 -= 040;
-                       if (c2 - 'a' < 26)
-                               c2 -= 040;
+                       unsigned c1 = linux_char_to_upper_linux (*s1++);
+                       unsigned c2 = hpfs_char_to_upper_linux (*s2++);
                        if ((t = c1 - c2) != 0)
                                return t;
                } while (--n != 0);
@@ -1394,15 +1391,14 @@ static void write_one_dirent(struct dirent *dirent, const unsigned char *name,
        put_fs_long(ino, &dirent->d_ino);
        put_fs_word(namelen, &dirent->d_reclen);
 
-       if (lowercase)
-               for (n = namelen; n != 0;) {
-                       unsigned t = name[--n];
-                       if (t - 'A' < 26)
-                               t += 040;
-                       put_fs_byte(t, &dirent->d_name[n]);
-               }
-       else
-               memcpy_tofs(dirent->d_name, name, namelen);
+       for (n = namelen; n != 0;) {
+               unsigned t = name[--n];
+               if (lowercase)
+                       t = hpfs_char_to_lower_linux (t);
+               else
+                       t = hpfs_char_to_linux (t);
+               put_fs_byte(t, &dirent->d_name[n]);
+       }
 
        put_fs_byte(0, &dirent->d_name[namelen]);
 }
index 79d07cb77dd56fae617da22a29917bc6b39ced2c..b298cd8dfbca4dd01df0feee13cf13aaa99e468b 100644 (file)
@@ -139,7 +139,24 @@ void proc_read_inode(struct inode * inode)
                return;
        }
 
-       /* files within /proc/net */
+#ifdef CONFIG_IP_ACCT
+       /* be careful: /proc/net/ip_acct_0 resets IP accounting */
+       if (ino == PROC_NET_IPACCT0) {
+               inode->i_mode = S_IFREG | S_IRUSR;
+               inode->i_op = &proc_net_inode_operations;
+               return;
+       }
+#endif
+#ifdef CONFIG_IP_FIREWALL
+       /* /proc/net/ip_forward_0 and /proc/net/ip_block_0 reset counters */
+       if ((ino == PROC_NET_IPFWFWD0) || (ino == PROC_NET_IPFWBLK0)) {
+               inode->i_mode = S_IFREG | S_IRUSR;
+               inode->i_op = &proc_net_inode_operations;
+               return;
+       }
+#endif
+
+       /* other files within /proc/net */
        if ((ino >= PROC_NET_UNIX) && (ino < PROC_NET_LAST)) {
                inode->i_mode = S_IFREG | S_IRUGO;
                inode->i_op = &proc_net_inode_operations;
index f972ceea8f2fec66e4f1dbe4d463c10b51192ee8..f9c4b384f3159669c025bea739450701a2988390 100644 (file)
@@ -58,9 +58,16 @@ extern int afinet_get_info(char *, char **, off_t, int);
 #if    defined(CONFIG_WAVELAN)
 extern int wavelan_get_info(char *, char **, off_t, int);
 #endif /* defined(CONFIG_WAVELAN) */
+#ifdef CONFIG_IP_ACCT
 extern int ip_acct_procinfo(char *, char **, off_t, int);
+extern int ip_acct0_procinfo(char *, char **, off_t, int);
+#endif /* CONFIG_IP_ACCT */
+#ifdef CONFIG_IP_FIREWALL
 extern int ip_fw_blk_procinfo(char *, char **, off_t, int);
+extern int ip_fw_blk0_procinfo(char *, char **, off_t, int);
 extern int ip_fw_fwd_procinfo(char *, char **, off_t, int);
+extern int ip_fw_fwd0_procinfo(char *, char **, off_t, int);
+#endif /* CONFIG_IP_FIREWALL */
 extern int ip_msqhst_procinfo(char *, char **, off_t, int);
 extern int ip_mc_procinfo(char *, char **, off_t, int);
 #endif /* CONFIG_INET */
@@ -140,13 +147,16 @@ static struct proc_dir_entry net_dir[] = {
 #endif
 #ifdef CONFIG_IP_FIREWALL
        { PROC_NET_IPFWFWD,     10, "ip_forward"},
-       { PROC_NET_IPBLFWD,     8,  "ip_block"},
+       { PROC_NET_IPFWFWD0,    12, "ip_forward_0"},
+       { PROC_NET_IPFWBLK,     8,  "ip_block"},
+       { PROC_NET_IPFWBLK0,    10, "ip_block_0"},
 #endif
 #ifdef CONFIG_IP_MASQUERADE
        { PROC_NET_IPMSQHST,    13, "ip_masquerade"},
 #endif
 #ifdef CONFIG_IP_ACCT
        { PROC_NET_IPACCT,      7,  "ip_acct"},
+       { PROC_NET_IPACCT0,     9,  "ip_acct_0"},
 #endif
 #if    defined(CONFIG_WAVELAN)
        { PROC_NET_WAVELAN,     7, "wavelan" },
@@ -292,14 +302,23 @@ static int proc_readnet(struct inode * inode, struct file * file,
                        case PROC_NET_IPFWFWD:
                                length = ip_fw_fwd_procinfo(page, &start, file->f_pos,thistime);
                                break;
-                       case PROC_NET_IPBLFWD:
+                       case PROC_NET_IPFWFWD0:
+                               length = ip_fw_fwd0_procinfo(page, &start, file->f_pos,thistime);
+                               break;
+                       case PROC_NET_IPFWBLK:
                                length = ip_fw_blk_procinfo(page, &start, file->f_pos,thistime);
                                break;
+                       case PROC_NET_IPFWBLK0:
+                               length = ip_fw_blk0_procinfo(page, &start, file->f_pos,thistime);
+                               break;
 #endif
 #ifdef CONFIG_IP_ACCT
                        case PROC_NET_IPACCT:
                                length = ip_acct_procinfo(page, &start, file->f_pos,thistime);
                                break;
+                       case PROC_NET_IPACCT0:
+                               length = ip_acct0_procinfo(page, &start, file->f_pos,thistime);
+                               break;
 #endif
 #ifdef CONFIG_IP_MASQUERADE
                        case PROC_NET_IPMSQHST:
index 92276914146ff329fb33380640f94393cbe44b42..011a1ad2a7352f8f9203d12ae0020a04c0c46c1c 100644 (file)
 #ifndef __ALPHA_IO_H
 #define __ALPHA_IO_H
 
-/*
- * Defines for the AlphaPC EISA IO and memory address space.
- */
+#include <linux/config.h>
 
 #ifndef mb
 #define mb() __asm__ __volatile__("mb": : :"memory")
 #endif
 
 /*
- * NOTE! Currently it never uses the HAE register, so these work only
- * for the low 25 bits of EISA addressing.  That covers all of the IO
- * address space (16 bits), and most of the "normal" EISA memory space.
- * I'll fix it eventually, but I'll need to come up with a clean way
- * to handle races with interrupt services wanting to change HAE...
- */
-
-/*
- * NOTE 2! The memory operations do not set any memory barriers, as it's
- * not needed for cases like a frame buffer that is essentially memory-like.
- * You need to do them by hand if the operations depend on ordering.
- *
- * Similarly, the port IO operations do a "mb" only after a write operation:
- * if an mb is needed before (as in the case of doing memory mapped IO
- * first, and then a port IO operation to the same device), it needs to be
- * done by hand.
- *
- * After the above has bitten me 100 times, I'll give up and just do the
- * mb all the time, but right now I'm hoping this will work out.  Avoiding
- * mb's may potentially be a noticeable speed improvement, but I can't
- * honestly say I've tested it.
- *
- * Handling interrupts that need to do mb's to synchronize to non-interrupts
- * is another fun race area.  Don't do it (because if you do, I'll have to
- * do *everything* with interrupts disabled, ugh).
- */
-
-/*
- * Virtual -> physical identity mapping starts at this offset
- */
-#define IDENT_ADDR     (0xfffffc0000000000UL)
-
-/*
- * EISA Interrupt Acknowledge address
- */
-#define EISA_INTA              (IDENT_ADDR + 0x100000000UL)
-
-/*
- * FEPROM addresses
- */
-#define EISA_FEPROM0           (IDENT_ADDR + 0x180000000UL)
-#define EISA_FEPROM1           (IDENT_ADDR + 0x1A0000000UL)
-
-/*
- * VL82C106 base address
- */
-#define EISA_VL82C106          (IDENT_ADDR + 0x1C0000000UL)
-
-/*
- * EISA "Host Address Extension" address (bits 25-31 of the EISA address)
- */
-#define EISA_HAE               (IDENT_ADDR + 0x1D0000000UL)
-
-/*
- * "SYSCTL" register address
- */
-#define EISA_SYSCTL            (IDENT_ADDR + 0x1E0000000UL)
-
-/*
- * "spare" register address
- */
-#define EISA_SPARE             (IDENT_ADDR + 0x1F0000000UL)
-
-/*
- * EISA memory address offset
- */
-#define EISA_MEM               (IDENT_ADDR + 0x200000000UL)
-
-/*
- * EISA IO address offset
- */
-#define EISA_IO                        (IDENT_ADDR + 0x300000000UL)
-
-/*
- * IO functions
- *
- * The "local" functions are those that don't go out to the EISA bus,
- * but instead act on the VL82C106 chip directly.. This is mainly the
- * keyboard, RTC,  printer and first two serial lines..
- *
- * The local stuff makes for some complications, but it seems to be
- * gone in the PCI version. I hope I can get DEC suckered^H^H^H^H^H^H^H^H
- * convinced that I need one of the newer machines.
- */
-extern inline unsigned int __local_inb(unsigned long addr)
-{
-       long result = *(volatile int *) ((addr << 9) + EISA_VL82C106);
-       return 0xffUL & result;
-}
-
-extern inline void __local_outb(unsigned char b, unsigned long addr)
-{
-       *(volatile unsigned int *) ((addr << 9) + EISA_VL82C106) = b;
-       mb();
-}
-
-extern inline unsigned int __inb(unsigned long addr)
-{
-       long result = *(volatile int *) ((addr << 7) + EISA_IO + 0x00);
-       result >>= (addr & 3) * 8;
-       return 0xffUL & result;
-}
-
-extern inline void __outb(unsigned char b, unsigned long addr)
-{
-       *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x00) = b * 0x01010101;
-       mb();
-}
-
-/*
- * This is a stupid one: I'll make it a bitmap soon, promise..
- *
- * On the other hand: this allows gcc to optimize. Hmm. I'll
- * have to use the __constant_p() stuff here.
- *
- * The PCI version just returns zero all the time, I do believe..
+ * There are different version of the alpha motherboards: the
+ * "interesting" (read: slightly braindead) Jensen type hardware
+ * and the PCI version
  */
-extern inline int __is_local(unsigned long addr)
-{
-       /* keyboard */
-       if (addr == 0x60 || addr == 0x64)
-               return 1;
-
-       /* RTC */
-       if (addr == 0x170 || addr == 0x171)
-               return 1;
-
-       /* motherboard COM2 */
-       if (addr >= 0x2f8 && addr <= 0x2ff)
-               return 1;
-
-       /* motherboard LPT1 */
-       if (addr >= 0x3bc && addr <= 0x3be)
-               return 1;
-
-       /* motherboard COM2 */
-       if (addr >= 0x3f8 && addr <= 0x3ff)
-               return 1;
-
-       return 0;
-}
-
-extern inline unsigned int inb(unsigned long addr)
-{
-       if (__is_local(addr))
-               return __local_inb(addr);
-       return __inb(addr);
-}
-
-extern inline void outb(unsigned char b, unsigned long addr)
-{
-       if (__is_local(addr))
-               __local_outb(b, addr);
-       else
-               __outb(b, addr);
-}
-
-extern inline unsigned int inw(unsigned long addr)
-{
-       long result = *(volatile int *) ((addr << 7) + EISA_IO + 0x20);
-       result >>= (addr & 3) * 8;
-       return 0xffffUL & result;
-}
-
-extern inline unsigned int inl(unsigned long addr)
-{
-       return *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x60);
-}
-
-extern inline void outw(unsigned short b, unsigned long addr)
-{
-       *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x20) = b * 0x00010001;
-       mb();
-}
-
-extern inline void outl(unsigned int b, unsigned long addr)
-{
-       *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x60) = b;
-       mb();
-}
-
-/*
- * Memory functions
- */
-extern inline unsigned long readb(unsigned long addr)
-{
-       long result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x00);
-       result >>= (addr & 3) * 8;
-       return 0xffUL & result;
-}
-
-extern inline unsigned long readw(unsigned long addr)
-{
-       long result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x20);
-       result >>= (addr & 3) * 8;
-       return 0xffffUL & result;
-}
-
-extern inline unsigned long readl(unsigned long addr)
-{
-       return *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60);
-}
-
-extern inline void writeb(unsigned short b, unsigned long addr)
-{
-       *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101;
-}
-
-extern inline void writew(unsigned short b, unsigned long addr)
-{
-       *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001;
-}
-
-extern inline void writel(unsigned int b, unsigned long addr)
-{
-       *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60) = b;
-}
-
-#define inb_p inb
-#define outb_p outb
+#ifdef CONFIG_PCI
+#include <asm/lca.h>           /* get chip-specific definitions */
+#else
+#include <asm/jensen.h>
+#endif
 
 #endif
diff --git a/include/asm-alpha/jensen.h b/include/asm-alpha/jensen.h
new file mode 100644 (file)
index 0000000..f100c2b
--- /dev/null
@@ -0,0 +1,239 @@
+#ifndef __ALPHA_JENSEN_H
+#define __ALPHA_JENSEN_H
+
+/*
+ * Defines for the AlphaPC EISA IO and memory address space.
+ */
+
+/*
+ * NOTE! Currently it never uses the HAE register, so these work only
+ * for the low 25 bits of EISA addressing.  That covers all of the IO
+ * address space (16 bits), and most of the "normal" EISA memory space.
+ * I'll fix it eventually, but I'll need to come up with a clean way
+ * to handle races with interrupt services wanting to change HAE...
+ */
+
+/*
+ * NOTE 2! The memory operations do not set any memory barriers, as it's
+ * not needed for cases like a frame buffer that is essentially memory-like.
+ * You need to do them by hand if the operations depend on ordering.
+ *
+ * Similarly, the port IO operations do a "mb" only after a write operation:
+ * if an mb is needed before (as in the case of doing memory mapped IO
+ * first, and then a port IO operation to the same device), it needs to be
+ * done by hand.
+ *
+ * After the above has bitten me 100 times, I'll give up and just do the
+ * mb all the time, but right now I'm hoping this will work out.  Avoiding
+ * mb's may potentially be a noticeable speed improvement, but I can't
+ * honestly say I've tested it.
+ *
+ * Handling interrupts that need to do mb's to synchronize to non-interrupts
+ * is another fun race area.  Don't do it (because if you do, I'll have to
+ * do *everything* with interrupts disabled, ugh).
+ */
+
+/*
+ * Virtual -> physical identity mapping starts at this offset
+ */
+#define IDENT_ADDR     (0xfffffc0000000000UL)
+
+/*
+ * EISA Interrupt Acknowledge address
+ */
+#define EISA_INTA              (IDENT_ADDR + 0x100000000UL)
+
+/*
+ * FEPROM addresses
+ */
+#define EISA_FEPROM0           (IDENT_ADDR + 0x180000000UL)
+#define EISA_FEPROM1           (IDENT_ADDR + 0x1A0000000UL)
+
+/*
+ * VL82C106 base address
+ */
+#define EISA_VL82C106          (IDENT_ADDR + 0x1C0000000UL)
+
+/*
+ * EISA "Host Address Extension" address (bits 25-31 of the EISA address)
+ */
+#define EISA_HAE               (IDENT_ADDR + 0x1D0000000UL)
+
+/*
+ * "SYSCTL" register address
+ */
+#define EISA_SYSCTL            (IDENT_ADDR + 0x1E0000000UL)
+
+/*
+ * "spare" register address
+ */
+#define EISA_SPARE             (IDENT_ADDR + 0x1F0000000UL)
+
+/*
+ * EISA memory address offset
+ */
+#define EISA_MEM               (IDENT_ADDR + 0x200000000UL)
+
+/*
+ * EISA IO address offset
+ */
+#define EISA_IO                        (IDENT_ADDR + 0x300000000UL)
+
+/*
+ * IO functions
+ *
+ * The "local" functions are those that don't go out to the EISA bus,
+ * but instead act on the VL82C106 chip directly.. This is mainly the
+ * keyboard, RTC,  printer and first two serial lines..
+ *
+ * The local stuff makes for some complications, but it seems to be
+ * gone in the PCI version. I hope I can get DEC suckered^H^H^H^H^H^H^H^H
+ * convinced that I need one of the newer machines.
+ */
+extern inline unsigned int __local_inb(unsigned long addr)
+{
+       long result = *(volatile int *) ((addr << 9) + EISA_VL82C106);
+       return 0xffUL & result;
+}
+
+extern inline void __local_outb(unsigned char b, unsigned long addr)
+{
+       *(volatile unsigned int *) ((addr << 9) + EISA_VL82C106) = b;
+       mb();
+}
+
+extern inline unsigned int __inb(unsigned long addr)
+{
+       long result = *(volatile int *) ((addr << 7) + EISA_IO + 0x00);
+       result >>= (addr & 3) * 8;
+       return 0xffUL & result;
+}
+
+extern inline void __outb(unsigned char b, unsigned long addr)
+{
+       *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x00) = b * 0x01010101;
+       mb();
+}
+
+/*
+ * This is a stupid one: I'll make it a bitmap soon, promise..
+ *
+ * On the other hand: this allows gcc to optimize. Hmm. I'll
+ * have to use the __constant_p() stuff here.
+ */
+extern inline int __is_local(unsigned long addr)
+{
+       /* keyboard */
+       if (addr == 0x60 || addr == 0x64)
+               return 1;
+
+       /* RTC */
+       if (addr == 0x170 || addr == 0x171)
+               return 1;
+
+       /* motherboard COM2 */
+       if (addr >= 0x2f8 && addr <= 0x2ff)
+               return 1;
+
+       /* motherboard LPT1 */
+       if (addr >= 0x3bc && addr <= 0x3be)
+               return 1;
+
+       /* motherboard COM2 */
+       if (addr >= 0x3f8 && addr <= 0x3ff)
+               return 1;
+
+       return 0;
+}
+
+extern inline unsigned int inb(unsigned long addr)
+{
+       if (__is_local(addr))
+               return __local_inb(addr);
+       return __inb(addr);
+}
+
+extern inline void outb(unsigned char b, unsigned long addr)
+{
+       if (__is_local(addr))
+               __local_outb(b, addr);
+       else
+               __outb(b, addr);
+}
+
+extern inline unsigned int inw(unsigned long addr)
+{
+       long result = *(volatile int *) ((addr << 7) + EISA_IO + 0x20);
+       result >>= (addr & 3) * 8;
+       return 0xffffUL & result;
+}
+
+extern inline unsigned int inl(unsigned long addr)
+{
+       return *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x60);
+}
+
+extern inline void outw(unsigned short b, unsigned long addr)
+{
+       *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x20) = b * 0x00010001;
+       mb();
+}
+
+extern inline void outl(unsigned int b, unsigned long addr)
+{
+       *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x60) = b;
+       mb();
+}
+
+/*
+ * Memory functions
+ */
+extern inline unsigned long readb(unsigned long addr)
+{
+       long result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x00);
+       result >>= (addr & 3) * 8;
+       return 0xffUL & result;
+}
+
+extern inline unsigned long readw(unsigned long addr)
+{
+       long result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x20);
+       result >>= (addr & 3) * 8;
+       return 0xffffUL & result;
+}
+
+extern inline unsigned long readl(unsigned long addr)
+{
+       return *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60);
+}
+
+extern inline void writeb(unsigned short b, unsigned long addr)
+{
+       *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101;
+}
+
+extern inline void writew(unsigned short b, unsigned long addr)
+{
+       *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001;
+}
+
+extern inline void writel(unsigned int b, unsigned long addr)
+{
+       *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60) = b;
+}
+
+#define inb_p inb
+#define outb_p outb
+
+/*
+ * The Alpha Jensen hardware for some rather strange reason puts
+ * the RTC clock at 0x170 instead of 0x70. Probably due to some
+ * misguided idea about using 0x70 for NMI stuff.
+ *
+ * These defines will override the defaults when doing RTC queries
+ */
+#define RTC_PORT(x)    (0x170+(x))
+#define RTC_ADDR(x)    (x)
+#define RTC_ALWAYS_BCD 0
+
+#endif
diff --git a/include/asm-alpha/lca.h b/include/asm-alpha/lca.h
new file mode 100644 (file)
index 0000000..61a88c2
--- /dev/null
@@ -0,0 +1,207 @@
+#ifndef __ALPHA_LCA__H
+#define __ALPHA_LCA__H
+
+/*
+ * Low Cost Alpha (LCA) definitions (these apply to 21066 and 21068,
+ * for example).
+ *
+ * This file is based on:
+ *
+ *     DECchip 21066 and DECchip 21068 Alpha AXP Microprocessors
+ *     Hardware Reference Manual; Digital Equipment Corp.; May 1994;
+ *     Maynard, MA; Order Number: EC-N2681-71.
+ */
+
+/*
+ * NOTE! Currently, this never uses the HAE register, so it works only
+ * for the low 27 bits of the PCI sparse memory address space.  Dense
+ * memory space doesn't require the HAE, but is restricted to aligned
+ * 32 and 64 bit accesses.  Special Cycle and Interrupt Acknowledge
+ * cycles may also require the use of the HAE.  The LCA limits I/O
+ * address space to the bottom 24 bits of address space, but this
+ * easily covers the 16 bit ISA I/O address space.
+ */
+
+/*
+ * NOTE 2! The memory operations do not set any memory barriers, as
+ * it's not needed for cases like a frame buffer that is essentially
+ * memory-like.  You need to do them by hand if the operations depend
+ * on ordering.
+ *
+ * Similarly, the port I/O operations do a "mb" only after a write
+ * operation: if an mb is needed before (as in the case of doing
+ * memory mapped I/O first, and then a port I/O operation to the same
+ * device), it needs to be done by hand.
+ *
+ * After the above has bitten me 100 times, I'll give up and just do
+ * the mb all the time, but right now I'm hoping this will work out.
+ * Avoiding mb's may potentially be a noticeable speed improvement,
+ * but I can't honestly say I've tested it.
+ *
+ * Handling interrupts that need to do mb's to synchronize to
+ * non-interrupts is another fun race area.  Don't do it (because if
+ * you do, I'll have to do *everything* with interrupts disabled,
+ * ugh).
+ */
+
+/*
+ * Virtual -> physical identity mapping starts at this offset.
+ */
+#define IDENT_ADDR     (0xfffffc0000000000UL)
+
+/*
+ * I/O Controller registers:
+ */
+#define LCA_IOC_HAE            (IDENT_ADDR + 0x180000000UL)
+#define LCA_IOC_CONF           (IDENT_ADDR + 0x180000020UL)
+#define LCA_IOC_STAT0          (IDENT_ADDR + 0x180000040UL)
+#define LCA_IOC_STAT1          (IDENT_ADDR + 0x180000060UL)
+#define LCA_IOC_TBIA           (IDENT_ADDR + 0x180000080UL)
+#define LCA_IOC_TB_ENA         (IDENT_ADDR + 0x1800000a0UL)
+#define LCA_IOC_SFT_RST                (IDENT_ADDR + 0x1800000c0UL)
+#define LCA_IOC_PAR_DIS                (IDENT_ADDR + 0x1800000e0UL)
+#define LCA_IOC_W_BASE0                (IDENT_ADDR + 0x180000100UL)
+#define LCA_IOC_W_BASE1                (IDENT_ADDR + 0x180000120UL)
+#define LCA_IOC_W_MASK0                (IDENT_ADDR + 0x180000140UL)
+#define LCA_IOC_W_MASK1                (IDENT_ADDR + 0x180000160UL)
+#define LCA_IOC_T_BASE0                (IDENT_ADDR + 0x180000180UL)
+#define LCA_IOC_T_BASE1                (IDENT_ADDR + 0x1800001a0UL)
+#define LCA_IOC_TB_TAG0                (IDENT_ADDR + 0x188000000UL)
+#define LCA_IOC_TB_TAG1                (IDENT_ADDR + 0x188000020UL)
+#define LCA_IOC_TB_TAG2                (IDENT_ADDR + 0x188000040UL)
+#define LCA_IOC_TB_TAG3                (IDENT_ADDR + 0x188000060UL)
+#define LCA_IOC_TB_TAG4                (IDENT_ADDR + 0x188000070UL)
+#define LCA_IOC_TB_TAG5                (IDENT_ADDR + 0x1880000a0UL)
+#define LCA_IOC_TB_TAG6                (IDENT_ADDR + 0x1880000c0UL)
+#define LCA_IOC_TB_TAG7                (IDENT_ADDR + 0x1880000e0UL)
+
+/*
+ * Memory spaces:
+ */
+#define LCA_IACK_SC            (IDENT_ADDR + 0x1a0000000UL)
+#define LCA_CONF               (IDENT_ADDR + 0x1e0000000UL)
+#define LCA_IO                 (IDENT_ADDR + 0x1c0000000UL)
+#define LCA_SPARSE_MEM         (IDENT_ADDR + 0x200000000UL)
+#define LCA_DENSE_MEM          (IDENT_ADDR + 0x300000000UL)
+
+/*
+ * Bit definitions for I/O Controller status register 0:
+ */
+#define LCA_IOC_STAT0_CMD              0xf
+#define LCA_IOC_STAT0_ERR              (1<<4)
+#define LCA_IOC_STAT0_LOST             (1<<5)
+#define LCA_IOC_STAT0_THIT             (1<<6)
+#define LCA_IOC_STAT0_TREF             (1<<7)
+#define LCA_IOC_STAT0_CODE_SHIFT       8
+#define LCA_IOC_STAT0_CODE_MASK                0x7
+#define LCA_IOC_STAT0_P_NBR_SHIFT      13
+#define LCA_IOC_STAT0_P_NBR_MASK       0x7ffff
+
+/*
+ * I/O functions:
+ *
+ * Unlike Jensen, the Noname machines have no concept of local
+ * I/O---everything goes over the PCI bus.
+ *
+ * There is plenty room for optimization here.  In particular,
+ * the Alpha's insb/insw/extb/extw should be useful in moving
+ * data to/from the right byte-lanes.
+ */
+
+extern inline unsigned int
+inb(unsigned long addr)
+{
+    long result = *(volatile int *) ((addr << 5) + LCA_IO + 0x00);
+    result >>= (addr & 3) * 8;
+    return 0xffUL & result;
+}
+
+extern inline unsigned int
+inw(unsigned long addr)
+{
+    long result = *(volatile int *) ((addr << 5) + LCA_IO + 0x08);
+    result >>= (addr & 3) * 8;
+    return 0xffffUL & result;
+}
+
+extern inline unsigned int
+inl(unsigned long addr)
+{
+    return *(volatile unsigned int *) ((addr << 5) + LCA_IO + 0x18);
+}
+
+extern inline void
+outb(unsigned char b, unsigned long addr)
+{
+    *(volatile unsigned int *) ((addr << 5) + LCA_IO + 0x00) = b * 0x01010101;
+    mb();
+}
+
+extern inline void
+outw(unsigned char b, unsigned long addr)
+{
+    *(volatile unsigned int *) ((addr << 5) + LCA_IO + 0x08) = b * 0x00010001;
+    mb();
+}
+
+extern inline void
+outl(unsigned char b, unsigned long addr)
+{
+    *(volatile unsigned int *) ((addr << 5) + LCA_IO + 0x18) = b;
+    mb();
+}
+
+
+/*
+ * Memory functions.  64-bit and 32-bit accesses are done through
+ * dense memory space, everything else through sparse space.
+ */
+
+extern inline unsigned long
+readb(unsigned long addr)
+{
+    long result = *(volatile int *) ((addr << 5) + LCA_SPARSE_MEM + 0x00);
+    result >>= (addr & 3) * 8;
+    return 0xffUL & result;
+}
+
+extern inline unsigned long
+readw(unsigned long addr)
+{
+    long result = *(volatile int *) ((addr << 5) + LCA_SPARSE_MEM + 0x08);
+    result >>= (addr & 3) * 8;
+    return 0xffffUL & result;
+}
+
+extern inline unsigned long
+readl(unsigned long addr)
+{
+    return *(volatile int *) (addr + LCA_DENSE_MEM);
+}
+
+extern inline void
+writeb(unsigned short b, unsigned long addr)
+{
+    *(volatile unsigned int *) ((addr << 5) + LCA_SPARSE_MEM + 0x00) =
+      b * 0x01010101;
+}
+
+extern inline void
+writew(unsigned short b, unsigned long addr)
+{
+    *(volatile unsigned int *) ((addr << 5) + LCA_SPARSE_MEM + 0x08) =
+      b * 0x00010001;
+}
+
+extern inline void
+writel(unsigned short b, unsigned long addr)
+{
+    *(volatile unsigned int *) (addr + LCA_DENSE_MEM) = b;
+}
+
+#define inb_local inb
+#define outb_local outb
+#define inb_p inb
+#define outb_p outb
+
+#endif
index d0502a3e20416dacae2591bc2f9dd895f4f05b45..f3158661f37b9fe83168d8c608d3bd5ae508f7ae 100644 (file)
@@ -53,7 +53,7 @@
 
 /*
  * NOTE! The "accessed" bit isn't necessarily exact: it can be kept exactly
- * by software (use the KRE/URE/KWE/UWE bits appropritely), but I'll fake it.
+ * by software (use the KRE/URE/KWE/UWE bits appropriately), but I'll fake it.
  * Under Linux/AXP, the "accessed" bit just means "read", and I'll just use
  * the KRE/URE bits to watch for it. That way we don't need to overload the
  * KWE/UWE bits with both handling dirty and accessed.
index cc5c4f3adecfd224cb7b7f59adc61975c63b6937..9941f6b628798da35ee7b1362cb3ecaa537d45c6 100644 (file)
@@ -46,6 +46,9 @@ struct pt_regs {
        unsigned long r18;
 };
 
+#ifdef __KERNEL__
 #define user_mode(regs) ((regs)->ps & 8)
+extern void show_regs(struct pt_regs *);
+#endif
 
 #endif
index 6c6f55766fb3bc9d8656821cc1531071937d226c..902e0679661d933b0ed710ec573b7f196fa6b715 100644 (file)
@@ -80,8 +80,9 @@ extern void wrusp(unsigned long);
 extern unsigned long rdusp(void);
 
 #define halt() __asm__ __volatile__(".long 0");
-#define move_to_user_mode() halt()
-#define switch_to(x) halt()
+
+#define move_to_user_mode()    printk("Null move_to_user_mode\n")
+#define switch_to(x)           panic("switch_to() not yet done")
 
 #ifndef mb
 #define mb() __asm__ __volatile__("mb": : :"memory")
index 78f66abf6e7877f28f2d15d6749b6c5f7125ba4e..e379542cf7f1d259dcaedc847a6a0e525c84741c 100644 (file)
@@ -45,6 +45,7 @@ struct pt_regs {
 
 #ifdef __KERNEL__
 #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->cs))
+extern void show_regs(struct pt_regs *);
 #endif
 
 #endif
index 9e1f6c5dcb6cc3859a68256b77f1e31744e93ea2..df01e6cc81d3db237f2a7f963c76b08d1744a5b3 100644 (file)
@@ -249,4 +249,11 @@ __asm__ __volatile__ ("movw $" #limit ",%1\n\t" \
  */
 extern struct desc_struct default_ldt;
 
+/*
+ * disable hlt during certain critical i/o operations
+ */
+#define HAVE_DISABLE_HLT
+void disable_hlt(void);
+void enable_hlt(void);
+
 #endif
diff --git a/include/asm-sparc/clock.h b/include/asm-sparc/clock.h
new file mode 100644 (file)
index 0000000..6029236
--- /dev/null
@@ -0,0 +1,51 @@
+/* clock.h:  Definitions for the clock/timer chips on the Sparc.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* Clock timer structures. The interrupt timer has two properties which
+ * are the counter (which is handled in do_timer in sched.c) and the limit.
+ * This limit is where the timer's counter 'wraps' around. Oddly enough,
+ * the sun4c timer when it hits the limit wraps back to 1 and not zero
+ * thus when calculating the value at which it will fire a microsecond you
+ * must adjust by one.  Thanks SUN for designing such great hardware ;(
+ */
+
+/* Note that I am only going to use the timer that interrupts at
+ * Sparc IRQ 10.  There is another one available that can fire at
+ * IRQ 14. If I can think of some creative uses for it this may
+ * change. It might make a nice kernel/user profiler etc.
+ */
+
+struct sparc_timer_info {
+  unsigned int cur_count10;
+  unsigned int timer_limit10;
+  unsigned int cur_count14;
+  unsigned int timer_limit14;
+};
+
+struct sparc_clock_info {
+  unsigned char hsec;
+  unsigned char hr;
+  unsigned char min;
+  unsigned char sec;
+  unsigned char mon;
+  unsigned char day;
+  unsigned char yr;
+  unsigned char wkday;
+  unsigned char ram_hsec;
+  unsigned char ram_hr;
+  unsigned char ram_min;
+  unsigned char ram_sec;
+  unsigned char ram_mon;
+  unsigned char ram_day;
+  unsigned char ram_year;
+  unsigned char ram_wkday;
+  unsigned char intr_reg;
+  unsigned char cmd_reg;
+  unsigned char foo[14];
+};
+
+/* YUCK YUCK YUCK, grrr... */
+#define  TIMER_STRUCT  ((struct sparc_timer_info *)((struct sparc_clock_info *) TIMER_VADDR))
+
index 439c7c67124a53db90da8d29c9e984bdf8102efc..20fbbf531c3841aa560f063ec0c4c594a9271fc6 100644 (file)
@@ -1,7 +1,7 @@
 /* cprefix.h:  This file is included by assembly source which needs
  *             to know what the c-label prefixes are. The newer versions
  *            of cpp that come with gcc predefine such things to help
- *            us out. The reason this stuff is needed is to make
+ *            us out. The reason this stuff is neaded is to make
  *            solaris compiles of the kernel work.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
index b9e41109bdd71d74b2a526e608645340cc1306af..fea56964851863644749b40d6233ea7668204eae 100644 (file)
 #define SUN4C_SEGSZ     (1 << 18)
 #define USRSTACK        0x0         /* no joke, this is temporary, trust me */
 #define INT_ENABLE_REG_PHYSADR      0xf5000000
-#define INTS_ALL_ENAB   0x01
+#define INTS_ENAB   0x01
 
 #define WRITE_PAUSE     nop; nop; nop;
 
+#define PAGE_SIZE       4096
+
 /* Here are some trap goodies */
 
 
index 144cf4c80d22528934402168827ffe46f84b7d2f..13f93c6b6838c6df47dd221ce042aa3c52b7b1b7 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __SPARC_IO_H
 #define __SPARC_IO_H
 
+#include <asm/page.h>      /* IO address mapping routines need this */
+
 /*
  * Defines for io operations on the Sparc. Whether a memory access is going
  * to i/o sparc is encoded in the pte. The type bits determine whether this
@@ -84,4 +86,15 @@ extern inline void writel(unsigned int b, unsigned long addr)
 #define inb_p inb
 #define outb_p outb
 
+extern inline void mapioaddr(unsigned long physaddr, unsigned long virt_addr)
+{
+  unsigned long page_entry;
+
+  page_entry = physaddr >> PAGE_SHIFT;
+  page_entry |= (PTE_V | PTE_ACC | PTE_W | PTE_P | PTE_IO);  /* kernel io addr */
+
+  put_pte(page_entry, virt_addr);
+  return;
+}
+
 #endif /* !(__SPARC_IO_H) */
index cd0bbb84b4e60e38e2cc8c317c9ac259dd908e7e..34dfffd2f8594603c6af572b25301b9067c845ba 100644 (file)
 #include <asm/asi.h>        /* for get/set segmap/pte routines */
 #include <asm/contregs.h>   /* for switch_to_context */
 
-/* The current va context is global and known, so all that is needed to
- * do an invalidate is flush the VAC.
- */
-
-#define invalidate() flush_vac_context()  /* how conveeeiiiiinnnient :> */
-
-
 #define PAGE_SHIFT   12             /* This is the virtual page... */
-#define PGDIR_SHIFT  18             /* This is the virtual segment */
-#define PAGE_SIZE    4096
-#define PGDIR_SIZE   (1UL << PGDIR_SHIFT)
 
-#define PAGE_OFFSET    0
-#define MAP_NR(addr) (((addr)) >> PAGE_SHIFT)
-#define MAP_PAGE_RESERVED (1<<31)
+#ifndef __ASSEMBLY__
+#define PAGE_SIZE    (1UL << PAGE_SHIFT)
 
+/* to mask away the intra-page address bits */
+#define PAGE_MASK         (~(PAGE_SIZE-1))
 
+#ifdef __KERNEL__
 
-#define PAGE_PRESENT   0x001
-#define PAGE_RW                0x002
-#define PAGE_USER      0x004
-#define PAGE_ACCESSED  0x020
-#define PAGE_DIRTY     0x040
-#define PAGE_COW       0x200   /* implemented in software (one of the AVL bits) */
+#define CONFIG_STRICT_MM_TYPECHECKS
 
-#define PAGE_PRIVATE   (PAGE_PRESENT | PAGE_RW | PAGE_USER | PAGE_ACCESSED | PAGE_COW)
-#define PAGE_SHARED    (PAGE_PRESENT | PAGE_RW | PAGE_USER | PAGE_ACCESSED)
-#define PAGE_COPY      (PAGE_PRESENT | PAGE_USER | PAGE_ACCESSED | PAGE_COW)
-#define PAGE_READONLY  (PAGE_PRESENT | PAGE_USER | PAGE_ACCESSED)
-#define PAGE_EXECONLY  (PAGE_PRESENT | PAGE_USER | PAGE_ACCESSED)
-#define PAGE_TABLE     (PAGE_PRESENT | PAGE_RW | PAGE_USER | PAGE_ACCESSED)
+#ifdef CONFIG_STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)     ((x).pte)
+#define pmd_val(x)      ((x).pmd)
+#define pgd_val(x)     ((x).pgd)
+#define pgprot_val(x)  ((x).pgprot)
+
+#define __pte(x)       ((pte_t) { (x) } )
+#define __pmd(x)        ((pmd_t) { (x) } )
+#define __pgd(x)       ((pgd_t) { (x) } )
+#define __pgprot(x)    ((pgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
 
-#define PAGE_CHG_MASK (PAGE_MASK | PAGE_ACCESSED | PAGE_DIRTY)
+#define pte_val(x)     (x)
+#define pmd_val(x)      (x)
+#define pgd_val(x)     (x)
+#define pgprot_val(x)  (x)
 
-#ifdef __KERNEL__
+#define __pte(x)       (x)
+#define __pmd(x)        (x)
+#define __pgd(x)       (x)
+#define __pgprot(x)    (x)
 
-/* number of bits that fit into a memory pointer */
-#define BITS_PER_PTR      (8*sizeof(unsigned long))   /* better check this stuff */
+#endif
 
-/* to mask away the intra-page address bits */
-#define PAGE_MASK         (~(PAGE_SIZE-1))
+/* The current va context is global and known, so all that is needed to
+ * do an invalidate is flush the VAC.
+ */
 
-/* to mask away the intra-page address bits */
-#define PGDIR_MASK        (~(PGDIR_SIZE-1))
+#define invalidate() flush_vac_context()  /* how conveeeiiiiinnnient :> */
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-#define PGDIR_ALIGN(addr) (((addr)+PGDIR_SIZE-1)&PGDIR_MASK)
 
-/* to align the pointer to a pointer address */
-#define PTR_MASK          (~(sizeof(void*)-1))
+#define PAGE_OFFSET    0
+#define MAP_NR(addr) (((unsigned long)(addr)) >> PAGE_SHIFT)
+#define MAP_PAGE_RESERVED (1<<15)
 
 
-#define SIZEOF_PTR_LOG2   2
+#endif /* !(__ASSEMBLY__) */
 
 /* The rest is kind of funky because on the sparc, the offsets into the mmu 
  * entries are encoded in magic alternate address space tables. I will 
  * Much thought must go into this code.   (davem@caip.rutgers.edu)
  */
 
-#define PAGE_DIR_OFFSET(base, address)   ((unsigned long *) 0)
-#define PAGE_PTR(address)                ((unsigned long) 0)
-#define PTRS_PER_PAGE                    (64)  /* 64 pte's per phys_seg */
-
 /* Bitfields within a Sparc sun4c PTE (page table entry). */
 
 #define PTE_V     0x80000000   /* valid bit */
 #define PTE_RESV  0x00f80000   /* reserved bits */
 #define PTE_PHYPG 0x0007ffff   /* phys pg number, sun4c only uses 16bits */
 
-/* termed a 'page table' in the linux kernel, a segmap entry is obtained
- * with the following macro
- */
-
-#ifndef __ASSEMBLY__ /* for head.S */
-/*
- * BAD_PAGETABLE is used when we need a bogus page-table, while
- * BAD_PAGE is used for a bogus page.
- *
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long __bad_page(void);
-extern unsigned long __bad_pagetable(void);
-extern unsigned long __zero_page(void);
-
-typedef unsigned int mem_map_t;
-
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE __zero_page()
-
 extern __inline__ unsigned long get_segmap(unsigned long addr)
 {
   register unsigned long entry;
@@ -172,16 +159,7 @@ extern __inline__ int get_context(void)
   return ctx;
 }
 
-/* to set the page-dir
- *
- * On the Sparc this is a nop for now. It will set the proper segmap
- * in the real implementation.
- */
-
-#define SET_PAGE_DIR(tsk,pgdir)
-
-
-#endif /* !(__ASSEMBLY__) */
+typedef unsigned short mem_map_t;
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
new file mode 100644 (file)
index 0000000..b4dbd13
--- /dev/null
@@ -0,0 +1,317 @@
+#ifndef _SPARC_PGTABLE_H
+#define _SPARC_PGTABLE_H
+
+/*  asm-sparc/pgtable.h:  Defines and functions used to work
+ *                        with Sparc page tables.
+ *
+ *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* PMD_SHIFT determines the size of the area a second-level page table can map */
+#define PMD_SHIFT       22
+#define PMD_SIZE        (1UL << PMD_SHIFT)
+#define PMD_MASK        (~(PMD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT       22
+#define PGDIR_SIZE        (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK        (~(PGDIR_SIZE-1))
+#define PGDIR_ALIGN(addr) (((addr)+PGDIR_SIZE-1)&PGDIR_MASK)
+
+/*
+ * Just following the i386 lead, because it works on the Sparc sun4c
+ * machines.  Two-level, therefore there is no real PMD.
+ */
+
+#define PTRS_PER_PTE    1024
+#define PTRS_PER_PMD    1
+#define PTRS_PER_PGD    1024
+
+/* the no. of pointers that fit on a page: this will go away */
+#define PTRS_PER_PAGE   (PAGE_SIZE/sizeof(void*))
+
+/* Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET  (8*1024*1024)
+#define VMALLOC_START ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) (TASK_SIZE + (unsigned long)(x))
+
+/*
+ * Sparc page table fields.
+ */
+
+#define _PAGE_VALID     0x80000000   /* valid page */
+#define _PAGE_WRITE     0x40000000   /* can be written to */
+#define _PAGE_PRIV      0x20000000   /* bit to signify privileged page */
+#define _PAGE_REF       0x02000000   /* Page had been accessed/referenced */
+#define _PAGE_DIRTY     0x01000000   /* Page has been modified, is dirty */
+#define _PAGE_COW       0x00800000   /* COW page, hardware ignores this bit (untested) */
+
+
+/* Sparc sun4c mmu has only a writable bit. Thus if a page is valid it can be
+ * read in a load, and executed as code automatically. Although, the memory fault
+ * hardware does make a distinction between date-read faults and insn-read faults
+ * which is determined by which trap happened plus magic sync/async fault register
+ * values which must be checked in the actual fault handler.
+ */
+
+/* We want the swapper not to swap out page tables, thus dirty and writable
+ * so that the kernel can change the entries as needed. Also valid for
+ * obvious reasons.
+ */
+#define _PAGE_TABLE     (_PAGE_VALID | _PAGE_WRITE | _PAGE_DIRTY)
+#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_REF | _PAGE_DIRTY)
+
+#define PAGE_NONE       __pgprot(_PAGE_VALID | _PAGE_REF)
+#define PAGE_SHARED     __pgprot(_PAGE_VALID | _PAGE_WRITE | _PAGE_REF)
+#define PAGE_COPY       __pgprot(_PAGE_VALID | _PAGE_REF | _PAGE_COW)
+#define PAGE_READONLY   __pgprot(_PAGE_VALID | _PAGE_REF)
+#define PAGE_KERNEL     __pgprot(_PAGE_VALID | _PAGE_PRIV)
+
+#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | _PAGE_REF | (x))
+
+/* I define these like the i386 does because the check for text or data fault
+ * is done at trap time by the low level handler. Maybe I can set these bits
+ * then once determined. I leave them like this for now though.
+ */
+#define __P000  PAGE_NONE
+#define __P001  PAGE_READONLY
+#define __P010  PAGE_COPY
+#define __P011  PAGE_COPY
+#define __P100  PAGE_READONLY
+#define __P101  PAGE_READONLY
+#define __P110  PAGE_COPY
+#define __P111  PAGE_COPY
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED
+#define __S100 PAGE_READONLY
+#define __S101 PAGE_READONLY
+#define __S110 PAGE_SHARED
+#define __S111 PAGE_SHARED
+
+
+extern unsigned long pg0[1024];
+
+/*
+ * BAD_PAGETABLE is used when we need a bogus page-table, while
+ * BAD_PAGE is used for a bogus page.
+ *
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern pte_t __bad_page(void);
+extern pte_t * __bad_pagetable(void);
+
+extern unsigned long __zero_page(void);
+
+
+#define BAD_PAGETABLE __bad_pagetable()
+#define BAD_PAGE __bad_page()
+#define ZERO_PAGE __zero_page()
+
+/* number of bits that fit into a memory pointer */
+#define BITS_PER_PTR      (8*sizeof(unsigned long))   /* better check this stuff */
+
+/* to align the pointer to a pointer address */
+#define PTR_MASK          (~(sizeof(void*)-1))
+
+
+#define SIZEOF_PTR_LOG2   2
+
+
+/* to set the page-dir
+ *
+ * On the Sparc the page segments hold 64 pte's which means 256k/segment.
+ * Therefore there is no global idea of 'the' page directory, although we
+ * make a virtual one in kernel memory so that we can keep the stats on
+ * all the pages since not all can be loaded at once in the mmu.
+ */
+
+#define SET_PAGE_DIR(tsk,pgdir)
+
+/* to find an entry in a page-table */
+#define PAGE_PTR(address) \
+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+
+extern unsigned long high_memory;
+
+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_VALID; }
+extern inline void pte_clear(pte_t *ptep)      { pte_val(*ptep) = 0; }
+
+extern inline int pmd_none(pmd_t pmd)          { return !pmd_val(pmd); }
+extern inline int pmd_bad(pmd_t pmd)           { return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE || pmd_val(pmd) > high_memory; }
+extern inline int pmd_present(pmd_t pmd)       { return pmd_val(pmd) & _PAGE_VALID; }
+extern inline void pmd_clear(pmd_t * pmdp)     { pmd_val(*pmdp) = 0; }
+
+extern inline int pgd_none(pgd_t pgd)          { return !pgd_val(pgd); }
+extern inline int pgd_bad(pgd_t pgd)           { return (pgd_val(pgd) & ~PAGE_MASK) != _PAGE_TABLE || pgd_val(pgd) > high_memory; }
+extern inline int pgd_present(pgd_t pgd)       { return pgd_val(pgd) & _PAGE_VALID; }
+extern inline void pgd_clear(pgd_t * pgdp)     { pgd_val(*pgdp) = 0; }
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+extern inline int pte_read(pte_t pte)          { return pte_val(pte) & _PAGE_VALID; }
+extern inline int pte_write(pte_t pte)         { return pte_val(pte) & _PAGE_WRITE; }
+extern inline int pte_exec(pte_t pte)          { return pte_val(pte) & _PAGE_VALID; }
+extern inline int pte_dirty(pte_t pte)         { return pte_val(pte) & _PAGE_REF; }
+extern inline int pte_young(pte_t pte)         { return pte_val(pte) & _PAGE_REF; }
+extern inline int pte_cow(pte_t pte)           { return pte_val(pte) & _PAGE_COW; }
+
+extern inline pte_t pte_wrprotect(pte_t pte)   { pte_val(pte) &= ~_PAGE_WRITE; return pte; }
+extern inline pte_t pte_rdprotect(pte_t pte)   { pte_val(pte) &= ~_PAGE_VALID; return pte; }
+extern inline pte_t pte_exprotect(pte_t pte)   { pte_val(pte) &= ~_PAGE_VALID; return pte; }
+extern inline pte_t pte_mkclean(pte_t pte)     { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkold(pte_t pte)       { pte_val(pte) &= ~_PAGE_REF; return pte; }
+extern inline pte_t pte_uncow(pte_t pte)       { pte_val(pte) &= ~_PAGE_COW; return pte; }
+extern inline pte_t pte_mkwrite(pte_t pte)     { pte_val(pte) |= _PAGE_WRITE; return pte; }
+extern inline pte_t pte_mkread(pte_t pte)      { pte_val(pte) |= _PAGE_VALID; return pte; }
+extern inline pte_t pte_mkexec(pte_t pte)      { pte_val(pte) |= _PAGE_VALID; return pte; }
+extern inline pte_t pte_mkdirty(pte_t pte)     { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkyoung(pte_t pte)     { pte_val(pte) |= _PAGE_REF; return pte; }
+extern inline pte_t pte_mkcow(pte_t pte)       { pte_val(pte) |= _PAGE_COW; return pte; }
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
+{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return 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; }
+
+extern inline unsigned long pte_page(pte_t pte)        { return pte_val(pte) & PAGE_MASK; }
+
+extern inline unsigned long pmd_page(pmd_t pmd) { return pmd_val(pmd) & PAGE_MASK; }
+
+extern inline unsigned long pgd_page(pgd_t pgd)        { return pgd_val(pgd) & PAGE_MASK; }
+
+extern inline void pgd_set(pgd_t * pgdp, pte_t * ptep)
+{ pgd_val(*pgdp) = _PAGE_TABLE | (unsigned long) ptep; }
+
+/* to find an entry in a page-table-directory */
+#define PAGE_DIR_OFFSET(tsk,address) \
+((((unsigned long)(address)) >> 22) + (pgd_t *) (tsk)->tss.cr3)
+
+/* to find an entry in a page-table-directory */
+extern inline pgd_t * pgd_offset(struct task_struct * tsk, unsigned long address)
+{
+       return (pgd_t *) tsk->tss.cr3 + (address >> PGDIR_SHIFT);
+}
+
+/* Find an entry in the second-level page table.. */
+extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+{
+       return (pmd_t *) dir;
+}
+
+/* Find an entry in the third-level page table.. */ 
+extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
+{
+       return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+}
+
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any, and marks the page tables reserved.
+ */
+extern inline void pte_free_kernel(pte_t * pte)
+{
+       mem_map[MAP_NR(pte)] = 1;
+       free_page((unsigned long) pte);
+}
+
+extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
+{
+       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+       if (pmd_none(*pmd)) {
+               pte_t * page = (pte_t *) get_free_page(GFP_KERNEL);
+               if (pmd_none(*pmd)) {
+                       if (page) {
+                               pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) page;
+                               mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED;
+                               return page + address;
+                       }
+                       pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE;
+                       return NULL;
+               }
+               free_page((unsigned long) page);
+       }
+       if (pmd_bad(*pmd)) {
+               printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+               pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE;
+               return NULL;
+       }
+       return (pte_t *) pmd_page(*pmd) + address;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free_kernel(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
+{
+       return (pmd_t *) pgd;
+}
+
+extern inline void pte_free(pte_t * pte)
+{
+       free_page((unsigned long) pte);
+}
+
+extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+{
+       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+       if (pmd_none(*pmd)) {
+               pte_t * page = (pte_t *) get_free_page(GFP_KERNEL);
+               if (pmd_none(*pmd)) {
+                       if (page) {
+                               pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) page;
+                               return page + address;
+                       }
+                       pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE;
+                       return NULL;
+               }
+               free_page((unsigned long) page);
+       }
+       if (pmd_bad(*pmd)) {
+               printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+               pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE;
+               return NULL;
+       }
+       return (pte_t *) pmd_page(*pmd) + address;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+{
+       return (pmd_t *) pgd;
+}
+
+extern pgd_t swapper_pg_dir[1024];
+
+#endif /* !(_SPARC_PGTABLE_H) */
index a6da4551c6d5f4ffd4443a20dab2a4aeb3f47238..70fb8d5df9f38111dcd0359f6e3cf171d711d1b2 100644 (file)
@@ -24,6 +24,9 @@ struct pt_regs {
        unsigned long f_regs[64];    /* yuck yuck yuck */
 };
 
-#define user_mode(regs) (~((regs)->ps&0x1))  /* if previous supervisor is 0, came from user */
+#ifdef __KERNEL__
+#define user_mode(regs) (0x0)  /* if previous supervisor is 0, came from user */
+extern void show_regs(struct pt_regs *);
+#endif
 
 #endif
index 9baf1eb37954371bede4fa6a7b0545c5daf685cb..039039d76b34e60a80e36b80366da97e8e087c15 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <asm/openprom.h>
+#include <asm/psr.h>
 
 #define INIT_PCB       0x00011fe0
 #define INIT_STACK     0x00013fe0
 #define EMPTY_PGE      0x00001000
 #define ZERO_PGE       0x00001000
 
+#define IRQ_ENA_ADR     0x2000        /* This is a bitmap of all activated IRQ's
+                                      * which is mapped in head.S during boot.
+                                      */
+
 #ifndef __ASSEMBLY__
 
 extern void wrent(void *, unsigned long);
@@ -46,18 +51,17 @@ extern struct linux_romvec *romvec;
  */
 
 #define swpipl(__new_ipl) \
-({ unsigned long __old_ipl, psr; \
+({ unsigned long psr, retval; \
 __asm__ __volatile__( \
-        "rd %%psr, %0\n\t" : "=&r" (__old_ipl)); \
+        "rd %%psr, %0\n\t" : "=&r" (psr)); \
+retval = psr; \
+psr = (psr & ~(PSR_PIL)); \
+psr |= ((__new_ipl << 8) & PSR_PIL); \
 __asm__ __volatile__( \
-       "and %1, 15, %0\n\t" \
-       "sll %0, 8, %0\n\t" \
-       "or  %0, %2, %0\n\t" \
        "wr  %0, 0x0, %%psr\n\t" \
-       : "=&r" (psr) \
-       : "r" (__new_ipl), "r" (__old_ipl)); \
-__old_ipl = ((__old_ipl>>8)&15); \
-__old_ipl; })
+       : : "r" (psr)); \
+retval = ((retval>>8)&15); \
+retval; })
 
 #define cli()                  swpipl(15)  /* 15 = no int's except nmi's */
 #define sti()                  swpipl(0)   /* same as alpha */
@@ -83,6 +87,20 @@ __asm__ __volatile__ ("nop\n\t")
        _set_gate(a,12,3,addr)
 
 
+extern inline unsigned int get_psr(void)
+{
+  unsigned int ret_val;
+  __asm__("rd %%psr, %0\n\t" :
+         "=r" (ret_val));
+  return ret_val;
+}
+
+extern inline void put_psr(unsigned int new_psr)
+{
+  __asm__("wr %0, 0x0, %%psr\n\t" : :
+         "r" (new_psr));
+}
+
 /* Must this be atomic? */
 
 extern inline void *xchg_u32(int * m, unsigned long val)
diff --git a/include/asm-sparc/vaddrs.h b/include/asm-sparc/vaddrs.h
new file mode 100644 (file)
index 0000000..7df4431
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _SPARC_VADDRS_H
+#define _SPARC_VADDRS_H
+
+/* asm-sparc/vaddrs.h:  Here will be define the virtual addresses at
+ *                      which important I/O addresses will be mapped.
+ *                      For instance the timer register virtual address
+ *                      is defined here.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#define  TIMER_VADDR    0x3000   /* Next page after where the interrupt enable
+                                 * register gets mapped at boot.
+                                 */
+
+#endif /* !(_SPARC_VADDRS_H) */
index b9ba44119ba93b32fdcce26ec5bf0746ddf1fd97..4983ecf484f9d1153b41af304489d7f3716a34ce 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: aztcd.h,v 0.80 1995/01/21 19:55:04 root Exp $
+/* $Id: aztcd.h,v 0.90 1995/02/02 18:14:28 root Exp $
  * Definitions for a AztechCD268 CD-ROM interface
  *     Copyright (C) 1994, 1995  Werner Zimmermann
  *
 #define ACMD_GET_ERROR         0x40            /* get error code */
 #define ACMD_GET_STATUS                0x41            /* get status */
 #define ACMD_GET_Q_CHANNEL      0x50           /* read info from q channel */
-#define ACMD_EJECT             0x60            /* eject/open */
+#define ACMD_EJECT             0x60            /* eject/open tray */
+#define ACMD_CLOSE              0x61            /* close tray */
 #define ACMD_PAUSE             0x80            /* pause */
 #define ACMD_STOP              0x81            /* stop play */
 #define ACMD_PLAY_AUDIO                0x90            /* play audio track */
+#define ACMD_SET_VOLUME                0x93            /* set audio level */
 #define ACMD_GET_VERSION       0xA0            /* get firmware version */
 #define ACMD_SET_MODE          0xA1            /* set drive mode */
-#define ACMD_SET_VOLUME                0xAE            /* set audio level */
 
 #define SET_TIMER(func, jifs) \
         delay_timer.expires = jifs; \
index 4684186e56bb97e8a086773b692c0d029cc64e83..69f83e6fd75ee190f8e366380b9f38eb77f25e16 100644 (file)
 #ifndef BIOS32_H
 #define BIOS32_H
 
+extern int pcibios_present (void);
 unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end);
 
+#define PCIBIOS_SUCCESSFUL             0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED     0x81
+#define PCIBIOS_BAD_VENDOR_ID          0x83
+#define PCIBIOS_DEVICE_NOT_FOUND       0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER    0x87
+
 extern int pcibios_find_class (unsigned long class_code, unsigned short index, 
     unsigned char *bus, unsigned char *device_fn);
 extern int pcibios_find_device (unsigned short vendor, unsigned short device_id, 
index 7e4912304cf9f073dfcfba83e2e308c78395a995..36a80ca40fb35c5fc6ed647daf95fac48010322b 100644 (file)
@@ -206,6 +206,27 @@ typedef struct {
   Elf32_Word   sh_entsize;
 } Elf32_Shdr;
 
+#define        EI_MAG0         0               /* e_ident[] indexes */
+#define        EI_MAG1         1
+#define        EI_MAG2         2
+#define        EI_MAG3         3
+#define        EI_CLASS        4
+#define        EI_DATA         5
+#define        EI_VERSION      6
+#define        EI_PAD          7
+
+#define        ELFMAG0         0x7f            /* EI_MAG */
+#define        ELFMAG1         'E'
+#define        ELFMAG2         'L'
+#define        ELFMAG3         'F'
+#define        ELFMAG          "\177ELF"
+#define        SELFMAG         4
+
+#define        ELFCLASSNONE    0               /* EI_CLASS */
+#define        ELFCLASS32      1
+#define        ELFCLASS64      2
+#define        ELFCLASSNUM     3
+
 #define ELF_START_MMAP 0x80000000
 
 #endif /* _LINUX_ELF_H */
index 78b09a6e2db35e409f613cf63d7dd03403ce370c..75f86b6163007ffc992530cb18822ca22ce56450 100644 (file)
@@ -39,6 +39,7 @@
 #define ARPHRD_RSRVD   260             /* Notional KISS type           */
 #define ARPHRD_ADAPT   264
 #define ARPHRD_PPP     512
+#define ARPHRD_TUNNEL  768             /* IPIP tunnel                  */
 
 /* ARP protocol opcodes. */
 #define        ARPOP_REQUEST   1               /* ARP request                  */
index 5c4122d6d0699138b45ec1bbe6e09731d39fddd7..b87b1785406de44657f8944e520326d635e57f32 100644 (file)
@@ -36,6 +36,7 @@
 #define ETH_P_ARP      0x0806          /* Address Resolution packet    */
 #define ETH_P_RARP      0x8035         /* Reverse Addr Res packet      */
 #define ETH_P_X25      0x0805          /* CCITT X.25                   */
+#define ETH_P_ATALK    0x809B          /* Appletalk DDP                */
 #define ETH_P_IPX      0x8137          /* IPX over DIX                 */
 #define ETH_P_802_3    0x0001          /* Dummy type for 802.3 frames  */
 #define ETH_P_AX25     0x0002          /* Dummy protocol id for AX.25  */
index 241d35f12708edd5e986e2e120497bb4ab0d48d4..1c80fa6dee189a3e9fb3e1806bcadbe4f50d64c8 100644 (file)
@@ -24,6 +24,7 @@ enum {
   IPPROTO_IP = 0,              /* Dummy protocol for TCP               */
   IPPROTO_ICMP = 1,            /* Internet Control Message Protocol    */
   IPPROTO_IGMP = 2,            /* Internet Gateway Management Protocol */
+  IPPROTO_IPIP = 4,            /* IPIP tunnels (older KA9Q tunnels use 94) */
   IPPROTO_TCP = 6,             /* Transmission Control Protocol        */
   IPPROTO_EGP = 8,             /* Exterior Gateway Protocol            */
   IPPROTO_PUP = 12,            /* PUP protocol                         */
index 57a9a447c6e5ab45f7ef47217677a2fe3a9da984..c9d3f49f2b468182277ba0a22787a52c1e6c49ee 100644 (file)
@@ -82,21 +82,25 @@ struct ip_fw
  *     a raw socket for this. Instead we check rights in the calls.
  */     
 
-#define IP_FW_BASE_CTL 64
+#define IP_FW_BASE_CTL   64
 
-#define IP_FW_ADD_BLK (IP_FW_BASE_CTL)
-#define IP_FW_ADD_FWD (IP_FW_BASE_CTL+1)   
-#define IP_FW_CHK_BLK (IP_FW_BASE_CTL+2)
-#define IP_FW_CHK_FWD (IP_FW_BASE_CTL+3)
-#define IP_FW_DEL_BLK (IP_FW_BASE_CTL+4)
-#define IP_FW_DEL_FWD (IP_FW_BASE_CTL+5)
-#define IP_FW_FLUSH   (IP_FW_BASE_CTL+6)
-#define IP_FW_POLICY  (IP_FW_BASE_CTL+7) 
+#define IP_FW_ADD_BLK    (IP_FW_BASE_CTL)
+#define IP_FW_ADD_FWD    (IP_FW_BASE_CTL+1)   
+#define IP_FW_CHK_BLK    (IP_FW_BASE_CTL+2)
+#define IP_FW_CHK_FWD    (IP_FW_BASE_CTL+3)
+#define IP_FW_DEL_BLK    (IP_FW_BASE_CTL+4)
+#define IP_FW_DEL_FWD    (IP_FW_BASE_CTL+5)
+#define IP_FW_FLUSH_BLK  (IP_FW_BASE_CTL+6)
+#define IP_FW_FLUSH_FWD  (IP_FW_BASE_CTL+7)
+#define IP_FW_ZERO_BLK   (IP_FW_BASE_CTL+8)
+#define IP_FW_ZERO_FWD   (IP_FW_BASE_CTL+9)
+#define IP_FW_POLICY_BLK (IP_FW_BASE_CTL+10)
+#define IP_FW_POLICY_FWD (IP_FW_BASE_CTL+11)
 
-#define IP_ACCT_ADD   (IP_FW_BASE_CTL+10)
-#define IP_ACCT_DEL   (IP_FW_BASE_CTL+11)
-#define IP_ACCT_FLUSH (IP_FW_BASE_CTL+12)
-#define IP_ACCT_ZERO  (IP_FW_BASE_CTL+13)
+#define IP_ACCT_ADD      (IP_FW_BASE_CTL+16)
+#define IP_ACCT_DEL      (IP_FW_BASE_CTL+17)
+#define IP_ACCT_FLUSH    (IP_FW_BASE_CTL+18)
+#define IP_ACCT_ZERO     (IP_FW_BASE_CTL+19)
 
 
 /*
@@ -110,13 +114,14 @@ struct ip_fw
 #ifdef CONFIG_IP_FIREWALL
 extern struct ip_fw *ip_fw_blk_chain;
 extern struct ip_fw *ip_fw_fwd_chain;
-extern int ip_fw_policy;
-extern int ip_fw_chk(struct iphdr *, struct ip_fw *);
+extern int ip_fw_blk_policy;
+extern int ip_fw_fwd_policy;
+extern int ip_fw_chk(struct iphdr *, struct ip_fw *, int);
 extern int ip_fw_ctl(int, void *, int);
 #endif
 #ifdef CONFIG_IP_ACCT
 extern struct ip_fw *ip_acct_chain;
-extern void ip_acct_cnt(struct iphdr *, struct ip_fw *, int);
+extern void ip_acct_cnt(struct iphdr *, struct ip_fw *);
 extern int ip_acct_ctl(int, void *, int);
 #endif
 #endif /* KERNEL */
index 7b9c267d0bd4c07a36b6ed04d9fd08281e74113a..5f22761fdd8f1eaaf279476fd7f506f937c8ff24 100644 (file)
 #define _MC146818RTC_H
 #include <asm/io.h>
 
+#ifndef RTC_PORT
 #define RTC_PORT(x)    (0x70 + (x))
 #define RTC_ADDR(x)    (0x80 | (x))
 #define RTC_ALWAYS_BCD 1
-
-/*
- * The Alpha Jensen hardware for some rather strange reason puts
- * the RTC clock at 0x170 instead of 0x70. Probably due to some
- * misguided idea about using 0x70 for NMI stuff.
- */
-#ifdef __alpha__
-#undef RTC_PORT
-#undef RTC_ADDR
-#undef RTC_ALWAYS_BCD
-#define RTC_PORT(x)    (0x170+(x))
-#define RTC_ADDR(x)    (x)
-#define RTC_ALWAYS_BCD 0
 #endif
 
 #define CMOS_READ(addr) ({ \
index 3368924ece864ad4b9a935bf2ce7d990eb1abf58..43ac7c16d2feb38055afa2f699b00f2ac2daf483 100644 (file)
@@ -10,6 +10,8 @@ extern unsigned long high_memory;
 
 #include <asm/page.h>
 
+#ifdef __KERNEL__
+
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
 
@@ -124,8 +126,6 @@ struct page_info {
 };
 /* end of planning stage */
 
-#ifdef __KERNEL__
-
 /*
  * Free area management
  */
index 45bbbd7e16463f127cbc42597f8b93277302f1f1..dcca542df4167168d95e36c7a20d4816b8a36007 100644 (file)
@@ -72,7 +72,7 @@ struct device
   unsigned long                  rmem_start;           /* shmem "recv" start   */
   unsigned long                  mem_end;              /* sahared mem end      */
   unsigned long                  mem_start;            /* shared mem start     */
-  unsigned short         base_addr;            /* device I/O address   */
+  unsigned long                  base_addr;            /* device I/O address   */
   unsigned char                  irq;                  /* device IRQ number    */
 
   /* Low-level status flags. */
index 09067d9c70bee781d4c8b9fb77f75b4f6d5c1429..2b2c84f6287c6ea906796a5c2253c47f7f637eee 100644 (file)
@@ -489,38 +489,6 @@ struct bridge_mapping_type {
        {0x0    ,0x0    ,0x0    }  \
 }
 
+#include <linux/bios32.h>
 
-/* PCI BIOS */
-
-extern int pcibios_present (void);
-
-#define PCIBIOS_SUCCESSFUL             0x00
-#define PCIBIOS_FUNC_NOT_SUPPORTED     0x81
-#define PCIBIOS_BAD_VENDOR_ID          0x83
-#define PCIBIOS_DEVICE_NOT_FOUND       0x86
-#define PCIBIOS_BAD_REGISTER_NUMBER    0x87
-
-/*
- * The PCIBIOS calls all bit-field the device_function variable such that 
- * the bit fielding matches that of the bl register used in the actual
- * calls.
- */
-
-extern int pcibios_find_class (unsigned long class_code, unsigned short index, 
-    unsigned char *bus, unsigned char *device_fn);
-extern int pcibios_find_device (unsigned short vendor, unsigned short device_id, 
-    unsigned short index, unsigned char *bus, unsigned char *device_fn);
-extern int pcibios_read_config_byte (unsigned char bus,
-    unsigned char device_fn, unsigned char where, unsigned char *value);
-extern int pcibios_read_config_word (unsigned char bus,
-    unsigned char device_fn, unsigned char where, unsigned short *value);
-extern int pcibios_read_config_dword (unsigned char bus,
-    unsigned char device_fn, unsigned char where, unsigned long *value);
-extern char *pcibios_strerror (int error);
-extern int pcibios_write_config_byte (unsigned char bus,
-    unsigned char device_fn, unsigned char where, unsigned char value);
-extern int pcibios_write_config_word (unsigned char bus,
-    unsigned char device_fn, unsigned char where, unsigned short value);
-extern pcibios_write_config_dword (unsigned char bus,
-    unsigned char device_fn, unsigned char where, unsigned long value);
 #endif /* ndef PCI_H */
index a58153576fddcedc7abe1bb890cea5f93c7b4c83..5e7847002fc7cb83d32e74ed398c5058c7c02da7 100644 (file)
@@ -69,10 +69,13 @@ enum net_directory_inos {
 #endif
 #ifdef CONFIG_IP_FIREWALL
        PROC_NET_IPFWFWD,
-       PROC_NET_IPBLFWD,
+       PROC_NET_IPFWFWD0,
+       PROC_NET_IPFWBLK,
+       PROC_NET_IPFWBLK0,
 #endif
 #ifdef CONFIG_IP_ACCT
        PROC_NET_IPACCT,
+       PROC_NET_IPACCT0,
 #endif
 #if    defined(CONFIG_WAVELAN)
        PROC_NET_WAVELAN,
index 0028bc0925d6d2a95634ec8071f0d87f8fc8bf79..ff6f46a786b27e35fc0d4aa58984458dfbfa2f63 100644 (file)
@@ -180,6 +180,7 @@ struct task_struct {
        struct tty_struct *tty; /* NULL if no tty */
 /* ipc stuff */
        struct sem_undo *semundo;
+       struct sem_queue *semsleeping;
 /* ldt for this task - used by Wine.  If NULL, default_ldt is used */
        struct desc_struct *ldt;
 /* tss for this task */
@@ -232,7 +233,7 @@ struct task_struct {
 /* math */     0, \
 /* comm */     "swapper", \
 /* fs info */  0,NULL, \
-/* ipc */      NULL, \
+/* ipc */      NULL, NULL, \
 /* ldt */      NULL, \
 /* tss */      INIT_TSS, \
 /* fs */       { INIT_FS }, \
index 52189879b822c3fdcf9a98ca8e8df5a1d9258339..9484d233ea326af461dfb36ee3324cdf35e69a27 100644 (file)
@@ -3,7 +3,7 @@
 #include <linux/ipc.h>
 
 /* semop flags */
-#define SEM_UNDO        010000  /* undo the operation on exit */
+#define SEM_UNDO        0x1000  /* undo the operation on exit */
 
 /* semctl Command Definitions. */
 #define GETPID  11       /* get sempid */
 
 /* One semid data structure for each set of semaphores in the system. */
 struct semid_ds {
-  struct ipc_perm sem_perm;       /* permissions .. see ipc.h */
-  time_t          sem_otime;      /* last semop time */
-  time_t          sem_ctime;      /* last change time */
-  struct sem      *sem_base;      /* ptr to first semaphore in array */
-  struct wait_queue *eventn;
-  struct wait_queue *eventz;
-  struct sem_undo  *undo;        /* undo requests on this array */
-  ushort          sem_nsems;      /* no. of semaphores in array */
+  struct ipc_perm sem_perm;            /* permissions .. see ipc.h */
+  time_t          sem_otime;           /* last semop time */
+  time_t          sem_ctime;           /* last change time */
+  struct sem      *sem_base;           /* ptr to first semaphore in array */
+  struct sem_queue *sem_pending;       /* pending operations to be processed */
+  struct sem_queue **sem_pending_last; /* last pending operation */
+  struct sem_undo *undo;              /* undo requests on this array */
+  ushort          sem_nsems;           /* no. of semaphores in array */
 };
 
 /* semop system calls takes an array of these. */
@@ -43,16 +43,16 @@ union semun {
 };
 
 struct  seminfo {
-    int semmap; 
-    int semmni; 
-    int semmns; 
-    int semmnu; 
-    int semmsl; 
-    int semopm; 
-    int semume; 
-    int semusz; 
-    int semvmx; 
-    int semaem; 
+    int semmap;
+    int semmni;
+    int semmns;
+    int semmnu;
+    int semmsl;
+    int semopm;
+    int semume;
+    int semusz;
+    int semvmx;
+    int semaem;
 };
 
 #define SEMMNI  128             /* ?  max # of semaphore identifiers */
@@ -66,31 +66,42 @@ struct  seminfo {
 #define SEMMNU  SEMMNS          /* num of undo structures system wide */
 #define SEMAEM  (SEMVMX >> 1)   /* adjust on exit max value */
 #define SEMMAP  SEMMNS          /* # of entries in semaphore map */
-#define SEMUSZ  20             /* sizeof struct sem_undo */ 
+#define SEMUSZ  20             /* sizeof struct sem_undo */
 
 #ifdef __KERNEL__
 
 /* One semaphore structure for each semaphore in the system. */
 struct sem {
+  short   semval;         /* current value */
   short   sempid;         /* pid of last operation */
-  ushort  semval;         /* current value */
-  ushort  semncnt;        /* num procs awaiting increase in semval */
-  ushort  semzcnt;        /* num procs awaiting semval = 0 */
 };
 
 /* ipcs ctl cmds */
-#define SEM_STAT 18    
+#define SEM_STAT 18
 #define SEM_INFO 19
 
-/* per process undo requests */
-/* this gets linked into the task_struct */
+/* One queue for each semaphore set in the system. */
+struct sem_queue {
+    struct sem_queue * next;    /* next entry in the queue */
+    struct sem_queue **        prev;    /* previous entry in the queue, *(q->prev) == q */
+    struct wait_queue *        sleeper; /* sleeping process */
+    struct sem_undo *  undo;    /* undo structure */
+    int                pid;     /* process id of requesting process */
+    int                status;  /* completion status of operation */
+    struct semid_ds *  sma;     /* semaphore array for operations */
+    struct sembuf *    sops;    /* array of pending operations */
+    int                        nsops;   /* number of operations */
+};
+
+/* Each task has a list of undo requests. They are executed automatically
+ * when the process exits.
+ */
 struct sem_undo {
-    struct sem_undo *proc_next;
-    struct sem_undo *id_next;
-    int    semid;
-    short  semadj;             /* semval adjusted by exit */
-    ushort sem_num;            /* semaphore index in array semid */
-};      
+    struct sem_undo *  proc_next; /* next entry on this process */
+    struct sem_undo *  id_next;          /* next entry on this semaphore set */
+    int                       semid;     /* semaphore set identifier */
+    short *           semadj;    /* array of adjustments, one per semaphore */
+};
 
 #endif /* __KERNEL__ */
 
index 5c2080bb2737fff2c84e404128f1a2225f900a6c..f7d26723040ca4936001eb6990cb6fba3faa45a0 100644 (file)
@@ -56,6 +56,7 @@ struct linger {
 #define SOL_IP         0
 #define SOL_IPX                256
 #define SOL_AX25       257
+#define SOL_ATALK      258
 #define SOL_TCP                6
 #define SOL_UDP                17
 
index 8dca3f48556607cf717e06e68b712db26ccfd1a5..31f50669d89e4c43c8d81b71622e63d9979bf041 100644 (file)
@@ -14,6 +14,7 @@ struct timezone {
 #define NFDBITS                        __NFDBITS
 
 #ifdef __KERNEL__
+void do_gettimeofday(struct timeval *tv);
 #include <asm/bitops.h>
 #include <linux/string.h>
 #define FD_SETSIZE             __FD_SETSIZE
index 8a98e93e9778e1c7aa2c9455e6cb5d5dbdc18342..fa3700824509f3fb96065a15177671df47dc3f30 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1,6 +1,34 @@
 /*
  * linux/ipc/sem.c
- * Copyright (C) 1992 Krishna Balasubramanian 
+ * Copyright (C) 1992 Krishna Balasubramanian
+ * Copyright (C) 1995 Eric Schenk, Bruno Haible
+ *
+ * IMPLEMENTATION NOTES ON CODE REWRITE (Eric Schenk, January 1995):
+ * This code underwent a massive rewrite in order to solve some problems
+ * with the original code. In particular the original code failed to
+ * wake up processes that were waiting for semval to go to 0 if the
+ * value went to 0 and was then incremented rapidly enough. In solving
+ * this problem I have also modified the implementation so that it
+ * processes pending operations in a FIFO manner, thus give a guarentee
+ * that processes waiting for a lock on the semaphore won't starve
+ * unless another locking process fails to unlock.
+ * In addition the following two changes in behavior have been introduced:
+ * - The original implementation of semop returned the value
+ *   last semaphore element examined on success. This does not
+ *   match the manual page specifications, and effectively
+ *   allows the user to read the semaphore even if they do not
+ *   have read permissions. The implementation now returns 0
+ *   on success as stated in the manual page.
+ * - There is some confusion over whether the set of undo adjustments
+ *   to be peformed at exit should be done in an atomic manner.
+ *   That is, if we are attempting to decrement the semval should we queue
+ *   up and wait until we can do so legally?
+ *   The original implementation attempted to do this.
+ *   The current implementation does not do so. This is because I don't
+ *   think it is the right thing (TM) to do, and because I couldn't
+ *   see a clean way to get the old behavior with the new design.
+ *   The POSIX standard and SVID should be consulted to determine
+ *   what behavior is mandated.
  */
 
 #include <linux/errno.h>
@@ -18,7 +46,7 @@ static int findkey (key_t key);
 static void freeary (int id);
 
 static struct semid_ds *semary[SEMMNI];
-static int used_sems = 0, used_semids = 0;                    
+static int used_sems = 0, used_semids = 0;
 static struct wait_queue *sem_lock = NULL;
 static int max_semid = 0;
 
@@ -27,7 +55,7 @@ static unsigned short sem_seq = 0;
 void sem_init (void)
 {
        int i;
-       
+
        sem_lock = NULL;
        used_sems = used_semids = max_semid = sem_seq = 0;
        for (i = 0; i < SEMMNI; i++)
@@ -39,9 +67,9 @@ static int findkey (key_t key)
 {
        int id;
        struct semid_ds *sma;
-       
+
        for (id = 0; id <= max_semid; id++) {
-               while ((sma = semary[id]) == IPC_NOID) 
+               while ((sma = semary[id]) == IPC_NOID)
                        interruptible_sleep_on (&sem_lock);
                if (sma == IPC_UNUSED)
                        continue;
@@ -62,7 +90,7 @@ static int newary (key_t key, int nsems, int semflg)
                return -EINVAL;
        if (used_sems + nsems > SEMMNS)
                return -ENOSPC;
-       for (id = 0; id < SEMMNI; id++) 
+       for (id = 0; id < SEMMNI; id++)
                if (semary[id] == IPC_UNUSED) {
                        semary[id] = (struct semid_ds *) IPC_NOID;
                        goto found;
@@ -87,10 +115,12 @@ found:
        ipcp->cuid = ipcp->uid = current->euid;
        ipcp->gid = ipcp->cgid = current->egid;
        sma->sem_perm.seq = sem_seq;
-       sma->eventn = sma->eventz = NULL;
+       /* sma->sem_pending = NULL; */
+       sma->sem_pending_last = &sma->sem_pending;
+       /* sma->undo = NULL; */
        sma->sem_nsems = nsems;
        sma->sem_ctime = CURRENT_TIME;
-        if (id > max_semid)
+       if (id > max_semid)
                max_semid = id;
        used_semids++;
        semary[id] = sma;
@@ -103,10 +133,10 @@ int sys_semget (key_t key, int nsems, int semflg)
 {
        int id;
        struct semid_ds *sma;
-       
-       if (nsems < 0  || nsems > SEMMSL)
+
+       if (nsems < 0 || nsems > SEMMSL)
                return -EINVAL;
-       if (key == IPC_PRIVATE) 
+       if (key == IPC_PRIVATE)
                return newary(key, nsems, semflg);
        if ((id = findkey (key)) == -1) {  /* key not used */
                if (!(semflg & IPC_CREAT))
@@ -121,13 +151,188 @@ int sys_semget (key_t key, int nsems, int semflg)
        if (ipcperms(&sma->sem_perm, semflg))
                return -EACCES;
        return (unsigned int) sma->sem_perm.seq * SEMMNI + id;
-} 
+}
+
+/* Manage the doubly linked list sma->sem_pending as a FIFO:
+ * insert new queue elements at the tail sma->sem_pending_last.
+ */
+static inline void insert_into_queue (struct semid_ds * sma, struct sem_queue * q)
+{
+       *(q->prev = sma->sem_pending_last) = q;
+       *(sma->sem_pending_last = &q->next) = NULL;
+}
+static inline void remove_from_queue (struct semid_ds * sma, struct sem_queue * q)
+{
+       *(q->prev) = q->next;
+       if (q->next)
+               q->next->prev = q->prev;
+       else /* sma->sem_pending_last == &q->next */
+               sma->sem_pending_last = q->prev;
+       q->prev = NULL; /* mark as removed */
+}
+
+/* Determine whether a sequence of semaphore operations would succeed
+ * all at once. Return 0 if yes, 1 if need to sleep, else return error code.
+ */
+static int try_semop (struct semid_ds * sma, struct sembuf * sops, int nsops)
+{
+       int result = 0;
+       int i = 0;
+
+       while (i < nsops) {
+               struct sembuf * sop = &sops[i];
+               struct sem * curr = &sma->sem_base[sop->sem_num];
+               if (sop->sem_op + curr->semval > SEMVMX) {
+                       result = -ERANGE;
+                       break;
+               }
+               if (!sop->sem_op && curr->semval) {
+                       if (sop->sem_flg & IPC_NOWAIT)
+                               result = -EAGAIN;
+                       else
+                               result = 1;
+                       break;
+               }
+               i++;
+               curr->semval += sop->sem_op;
+               if (curr->semval < 0) {
+                       if (sop->sem_flg & IPC_NOWAIT)
+                               result = -EAGAIN;
+                       else
+                               result = 1;
+                       break;
+               }
+       }
+       while (--i >= 0) {
+               struct sembuf * sop = &sops[i];
+               struct sem * curr = &sma->sem_base[sop->sem_num];
+               curr->semval -= sop->sem_op;
+       }
+       return result;
+}
+
+/* Actually perform a sequence of semaphore operations. Atomically. */
+/* This assumes that try_semop() already returned 0. */
+static int do_semop (struct semid_ds * sma, struct sembuf * sops, int nsops,
+                    struct sem_undo * un, int pid)
+{
+       int i;
+
+       for (i = 0; i < nsops; i++) {
+               struct sembuf * sop = &sops[i];
+               struct sem * curr = &sma->sem_base[sop->sem_num];
+               if (sop->sem_op + curr->semval > SEMVMX) {
+                       printk("do_semop: race\n");
+                       break;
+               }
+               if (!sop->sem_op) {
+                       if (curr->semval) {
+                               printk("do_semop: race\n");
+                               break;
+                       }
+               } else {
+                       curr->semval += sop->sem_op;
+                       if (curr->semval < 0) {
+                               printk("do_semop: race\n");
+                               break;
+                       }
+                       if (sop->sem_flg & SEM_UNDO)
+                               un->semadj[sop->sem_num] -= sop->sem_op;
+               }
+               curr->sempid = pid;
+       }
+       sma->sem_otime = CURRENT_TIME;
+
+       /* Previous implementation returned the last semaphore's semval.
+        * This is wrong because we may not have checked read permission,
+        * only write permission.
+        */
+       return 0;
+}
+
+/* Go through the pending queue for the indicated semaphore
+ * looking for tasks that can be completed. Keep cycling through
+ * the queue until a pass is made in which no process is woken up.
+ */
+static void update_queue (struct semid_ds * sma)
+{
+       int wokeup, error;
+       struct sem_queue * q;
+
+       do {
+               wokeup = 0;
+               for (q = sma->sem_pending; q; q = q->next) {
+                       error = try_semop(sma, q->sops, q->nsops);
+                       /* Does q->sleeper still need to sleep? */
+                       if (error > 0)
+                               continue;
+                       /* Perform the operations the sleeper was waiting for */
+                       if (!error)
+                               error = do_semop(sma, q->sops, q->nsops, q->undo, q->pid);
+                       q->status = error;
+                       /* Remove it from the queue */
+                       remove_from_queue(sma,q);
+                       /* Wake it up */
+                       wake_up_interruptible(&q->sleeper); /* doesn't sleep! */
+                       wokeup++;
+               }
+       } while (wokeup);
+}
+
+/* The following counts are associated to each semaphore:
+ *   semncnt        number of tasks waiting on semval being nonzero
+ *   semzcnt        number of tasks waiting on semval being zero
+ * This model assumes that a task waits on exactly one semaphore.
+ * Since semaphore operations are to be performed atomically, tasks actually
+ * wait on a whole sequence of semaphores simultaneously.
+ * The counts we return here are a rough approximation, but still
+ * warrant that semncnt+semzcnt>0 if the task is on the pending queue.
+ */
+static int count_semncnt (struct semid_ds * sma, ushort semnum)
+{
+       int semncnt;
+       struct sem_queue * q;
+
+       semncnt = 0;
+       for (q = sma->sem_pending; q; q = q->next) {
+               struct sembuf * sops = q->sops;
+               int nsops = q->nsops;
+               int i;
+               for (i = 0; i < nsops; i++)
+                       if (sops[i].sem_num == semnum
+                           && (sops[i].sem_op < 0)
+                           && !(sops[i].sem_flg & IPC_NOWAIT))
+                               semncnt++;
+       }
+       return semncnt;
+}
+static int count_semzcnt (struct semid_ds * sma, ushort semnum)
+{
+       int semzcnt;
+       struct sem_queue * q;
+
+       semzcnt = 0;
+       for (q = sma->sem_pending; q; q = q->next) {
+               struct sembuf * sops = q->sops;
+               int nsops = q->nsops;
+               int i;
+               for (i = 0; i < nsops; i++)
+                       if (sops[i].sem_num == semnum
+                           && (sops[i].sem_op == 0)
+                           && !(sops[i].sem_flg & IPC_NOWAIT))
+                               semzcnt++;
+       }
+       return semzcnt;
+}
 
+/* Free a semaphore set. */
 static void freeary (int id)
 {
        struct semid_ds *sma = semary[id];
        struct sem_undo *un;
+       struct sem_queue *q;
 
+       /* Invalidate this semaphore set */
        sma->sem_perm.seq++;
        sem_seq = (sem_seq+1) % ((unsigned)(1<<31)/SEMMNI); /* increment, but avoid overflow */
        used_sems -= sma->sem_nsems;
@@ -135,17 +340,21 @@ static void freeary (int id)
                while (max_semid && (semary[--max_semid] == IPC_UNUSED));
        semary[id] = (struct semid_ds *) IPC_UNUSED;
        used_semids--;
+
+       /* Invalidate the existing undo structures for this semaphore set.
+        * (They will be freed without any further action in sem_exit().)
+        */
        for (un = sma->undo; un; un = un->id_next)
-               un->semadj = 0;
-       while (sma->eventz || sma->eventn) {
-               if (sma->eventz)
-                       wake_up (&sma->eventz);
-               if (sma->eventn)
-                       wake_up (&sma->eventn);
-               schedule();
+               un->semid = -1;
+
+       /* Wake up all pending processes and let them fail with EIDRM. */
+       for (q = sma->sem_pending; q; q = q->next) {
+               q->status = -EIDRM;
+               q->prev = NULL;
+               wake_up_interruptible(&q->sleeper); /* doesn't sleep! */
        }
+
        kfree(sma);
-       return;
 }
 
 int sys_semctl (int semid, int semnum, int cmd, union semun arg)
@@ -165,8 +374,8 @@ int sys_semctl (int semid, int semnum, int cmd, union semun arg)
                return -EINVAL;
 
        switch (cmd) {
-       case IPC_INFO: 
-       case SEM_INFO: 
+       case IPC_INFO:
+       case SEM_INFO:
        {
                struct seminfo seminfo, *tmp = arg.__buf;
                seminfo.semmni = SEMMNI;
@@ -174,8 +383,8 @@ int sys_semctl (int semid, int semnum, int cmd, union semun arg)
                seminfo.semmsl = SEMMSL;
                seminfo.semopm = SEMOPM;
                seminfo.semvmx = SEMVMX;
-               seminfo.semmnu = SEMMNU; 
-               seminfo.semmap = SEMMAP; 
+               seminfo.semmnu = SEMMNU;
+               seminfo.semmap = SEMMAP;
                seminfo.semume = SEMUME;
                seminfo.semusz = SEMUSZ;
                seminfo.semaem = SEMAEM;
@@ -241,10 +450,10 @@ int sys_semctl (int semid, int semnum, int cmd, union semun arg)
                if (ipcperms (ipcp, S_IRUGO))
                        return -EACCES;
                switch (cmd) {
-               case GETVAL : return curr->semval; 
+               case GETVAL : return curr->semval;
                case GETPID : return curr->sempid;
-               case GETNCNT: return curr->semncnt;
-               case GETZCNT: return curr->semzcnt;
+               case GETNCNT: return count_semncnt(sma,semnum);
+               case GETZCNT: return count_semzcnt(sma,semnum);
                case GETALL:
                        array = arg.array;
                        i = verify_area (VERIFY_WRITE, array, nsems*sizeof(ushort));
@@ -254,13 +463,12 @@ int sys_semctl (int semid, int semnum, int cmd, union semun arg)
                break;
        case SETVAL:
                val = arg.val;
-               if (val > SEMVMX || val < 0) 
+               if (val > SEMVMX || val < 0)
                        return -ERANGE;
                break;
        case IPC_RMID:
-               if (suser() || current->euid == ipcp->cuid || 
-                   current->euid == ipcp->uid) {
-                       freeary (id); 
+               if (suser() || current->euid == ipcp->cuid || current->euid == ipcp->uid) {
+                       freeary (id);
                        return 0;
                }
                return -EPERM;
@@ -285,12 +493,12 @@ int sys_semctl (int semid, int semnum, int cmd, union semun arg)
                memcpy_fromfs (&tbuf, buf, sizeof (*buf));
                break;
        }
-       
+
        if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)
                return -EIDRM;
        if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
                return -EIDRM;
-       
+
        switch (cmd) {
        case GETALL:
                if (ipcperms (ipcp, S_IRUGO))
@@ -303,18 +511,14 @@ int sys_semctl (int semid, int semnum, int cmd, union semun arg)
                if (ipcperms (ipcp, S_IWUGO))
                        return -EACCES;
                for (un = sma->undo; un; un = un->id_next)
-                       if (semnum == un->sem_num)
-                               un->semadj = 0;
-               sma->sem_ctime = CURRENT_TIME;
+                       un->semadj[semnum] = 0;
                curr->semval = val;
-               if (sma->eventn)
-                       wake_up (&sma->eventn);
-               if (sma->eventz)
-                       wake_up (&sma->eventz);
+               sma->sem_ctime = CURRENT_TIME;
+               /* maybe some queued-up processes were waiting for this */
+               update_queue(sma);
                break;
        case IPC_SET:
-               if (suser() || current->euid == ipcp->cuid || 
-                   current->euid == ipcp->uid) {
+               if (suser() || current->euid == ipcp->cuid || current->euid == ipcp->uid) {
                        ipcp->uid = tbuf.sem_perm.uid;
                        ipcp->gid = tbuf.sem_perm.gid;
                        ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
@@ -335,15 +539,14 @@ int sys_semctl (int semid, int semnum, int cmd, union semun arg)
        case SETALL:
                if (ipcperms (ipcp, S_IWUGO))
                        return -EACCES;
-               for (i = 0; i < nsems; i++) 
+               for (i = 0; i < nsems; i++)
                        sma->sem_base[i].semval = sem_io[i];
                for (un = sma->undo; un; un = un->id_next)
-                       un->semadj = 0;
-               if (sma->eventn)
-                       wake_up (&sma->eventn);
-               if (sma->eventz)
-                       wake_up (&sma->eventz);
+                       for (i = 0; i < nsems; i++)
+                               un->semadj[i] = 0;
                sma->sem_ctime = CURRENT_TIME;
+               /* maybe some queued-up processes were waiting for this */
+               update_queue(sma);
                break;
        default:
                return -EINVAL;
@@ -353,170 +556,155 @@ int sys_semctl (int semid, int semnum, int cmd, union semun arg)
 
 int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
 {
-       int i, id;
+       int i, id, size, error;
        struct semid_ds *sma;
-       struct sem *curr = NULL;
        struct sembuf sops[SEMOPM], *sop;
        struct sem_undo *un;
-       int undos = 0, alter = 0, semncnt = 0, semzcnt = 0;
-       
+       int undos = 0, alter = 0;
+
        if (nsops < 1 || semid < 0)
                return -EINVAL;
        if (nsops > SEMOPM)
                return -E2BIG;
-       if (!tsops) 
+       if (!tsops)
                return -EFAULT;
        if ((i = verify_area (VERIFY_READ, tsops, nsops * sizeof(*tsops))))
                return i;
-       memcpy_fromfs (sops, tsops, nsops * sizeof(*tsops));  
+       memcpy_fromfs (sops, tsops, nsops * sizeof(*tsops));
        id = (unsigned int) semid % SEMMNI;
        if ((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)
                return -EINVAL;
-       for (i = 0; i < nsops; i++) { 
+       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+               return -EIDRM;
+       for (i = 0; i < nsops; i++) {
                sop = &sops[i];
-               if (sop->sem_num > sma->sem_nsems)
+               if (sop->sem_num >= sma->sem_nsems)
                        return -EFBIG;
                if (sop->sem_flg & SEM_UNDO)
                        undos++;
-               if (sop->sem_op) {
+               if (sop->sem_op)
                        alter++;
-                       if (sop->sem_op > 0)
-                               semncnt ++;
-               }
        }
        if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
                return -EACCES;
-       /* 
-        * ensure every sop with undo gets an undo structure 
-        */
+       error = try_semop(sma, sops, nsops);
+       if (error < 0)
+               return error;
        if (undos) {
-               for (i = 0; i < nsops; i++) {
-                       if (!(sops[i].sem_flg & SEM_UNDO))
-                               continue;
-                       for (un = current->semundo; un; un = un->proc_next) 
-                               if ((un->semid == semid) && 
-                                   (un->sem_num == sops[i].sem_num))
-                                       break;
-                       if (un)
-                               continue;
-                       un = (struct sem_undo *) 
-                               kmalloc (sizeof(*un), GFP_ATOMIC);
+               /* Make sure we have an undo structure
+                * for this process and this semaphore set.
+                */
+               for (un = current->semundo; un; un = un->proc_next)
+                       if (un->semid == semid)
+                               break;
+               if (!un) {
+                       size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
+                       un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);
                        if (!un)
-                               return -ENOMEM; /* freed on exit */
+                               return -ENOMEM;
+                       memset(un, 0, size);
+                       un->semadj = (short *) &un[1];
                        un->semid = semid;
-                       un->semadj = 0;
-                       un->sem_num = sops[i].sem_num;
                        un->proc_next = current->semundo;
                        current->semundo = un;
                        un->id_next = sma->undo;
                        sma->undo = un;
                }
-       }
-       
- slept:
-       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI) 
-               return -EIDRM;
-       for (i = 0; i < nsops; i++) {
-               sop = &sops[i];
-               curr = &sma->sem_base[sop->sem_num];
-               if (sop->sem_op + curr->semval > SEMVMX)
-                       return -ERANGE;
-               if (!sop->sem_op && curr->semval) { 
-                       if (sop->sem_flg & IPC_NOWAIT)
-                               return -EAGAIN;
-                       if (current->signal & ~current->blocked) 
-                               return -EINTR;
-                       curr->semzcnt++;
-                       interruptible_sleep_on (&sma->eventz);
-                       curr->semzcnt--;
-                       goto slept;
-               }
-               if ((sop->sem_op + curr->semval < 0) ) { 
-                       if (sop->sem_flg & IPC_NOWAIT)
-                               return -EAGAIN;
-                       if (current->signal & ~current->blocked)
-                               return -EINTR;
-                       curr->semncnt++;
-                       interruptible_sleep_on (&sma->eventn);
-                       curr->semncnt--;
-                       goto slept;
-               }
-       }
-       
-       for (i = 0; i < nsops; i++) {
-               sop = &sops[i];
-               curr = &sma->sem_base[sop->sem_num];
-               curr->sempid = current->pid;
-               if (!(curr->semval += sop->sem_op))
-                       semzcnt++;
-               if (!(sop->sem_flg & SEM_UNDO))
-                       continue;
-               for (un = current->semundo; un; un = un->proc_next) 
-                       if ((un->semid == semid) && 
-                           (un->sem_num == sop->sem_num))
-                               break;
-               if (!un) {
-                       printk ("semop : no undo for op %d\n", i);
-                       continue;
+       } else
+               un = NULL;
+       if (error == 0) {
+               /* the operations go through immediately */
+               error = do_semop(sma, sops, nsops, un, current->pid);
+               /* maybe some queued-up processes were waiting for this */
+               update_queue(sma);
+               return error;
+       } else {
+               /* We need to sleep on this operation, so we put the current
+                * task into the pending queue and go to sleep.
+                */
+               struct sem_queue queue;
+
+               queue.sma = sma;
+               queue.sops = sops;
+               queue.nsops = nsops;
+               queue.undo = un;
+               queue.pid = current->pid;
+               queue.status = 0;
+               insert_into_queue(sma,&queue);
+               queue.sleeper = NULL;
+               current->semsleeping = &queue;
+               interruptible_sleep_on(&queue.sleeper);
+               current->semsleeping = NULL;
+               /* When we wake up, either the operation is finished,
+                * or some kind of error happened.
+                */
+               if (!queue.prev) {
+                       /* operation is finished, update_queue() removed us */
+                       return queue.status;
+               } else {
+                       remove_from_queue(sma,&queue);
+                       return -EINTR;
                }
-               un->semadj -= sop->sem_op;
        }
-       sma->sem_otime = CURRENT_TIME; 
-               if (semncnt && sma->eventn)
-               wake_up(&sma->eventn);
-       if (semzcnt && sma->eventz)
-               wake_up(&sma->eventz);
-       return curr->semval;
 }
 
 /*
  * add semadj values to semaphores, free undo structures.
  * undo structures are not freed when semaphore arrays are destroyed
  * so some of them may be out of date.
+ * IMPLEMENTATION NOTE: There is some confusion over whether the
+ * set of adjustments that needs to be done should be done in an atomic
+ * manner or not. That is, if we are attempting to decrement the semval
+ * should we queue up and wait until we can do so legally?
+ * The original implementation attempted to do this (queue and wait).
+ * The current implementation does not do so. The POSIX standard
+ * and SVID should be consulted to determine what behavior is mandated.
  */
 void sem_exit (void)
 {
+       struct sem_queue *q;
        struct sem_undo *u, *un = NULL, **up, **unp;
        struct semid_ds *sma;
-       struct sem *sem = NULL;
-       
+       int nsems, i;
+
+       /* If the current process was sleeping for a semaphore,
+        * remove it from the queue.
+        */
+       if ((q = current->semsleeping)) {
+               if (q->prev)
+                       remove_from_queue(q->sma,q);
+               current->semsleeping = NULL;
+       }
+
        for (up = &current->semundo; (u = *up); *up = u->proc_next, kfree(u)) {
+               if (u->semid == -1)
+                       continue;
                sma = semary[(unsigned int) u->semid % SEMMNI];
-               if (sma == IPC_UNUSED || sma == IPC_NOID) 
+               if (sma == IPC_UNUSED || sma == IPC_NOID)
                        continue;
                if (sma->sem_perm.seq != (unsigned int) u->semid / SEMMNI)
                        continue;
+               /* remove u from the sma->undo list */
                for (unp = &sma->undo; (un = *unp); unp = &un->id_next) {
-                       if (u == un) 
+                       if (u == un)
                                goto found;
                }
                printk ("sem_exit undo list error id=%d\n", u->semid);
                break;
 found:
                *unp = un->id_next;
-               if (!un->semadj)
-                       continue;
-               while (1) {
-                       if (sma->sem_perm.seq != (unsigned int) un->semid / SEMMNI)
-                               break;
-                       sem = &sma->sem_base[un->sem_num];
-                       if (sem->semval + un->semadj >= 0) {
-                               sem->semval += un->semadj;
-                               sem->sempid = current->pid;
-                               sma->sem_otime = CURRENT_TIME;
-                               if (un->semadj > 0 && sma->eventn)
-                                       wake_up (&sma->eventn);
-                               if (!sem->semval && sma->eventz)
-                                       wake_up (&sma->eventz);
-                               break;
-                       } 
-                       if (current->signal & ~current->blocked)
-                               break;
-                       sem->semncnt++;
-                       interruptible_sleep_on (&sma->eventn);
-                       sem->semncnt--;
+               /* perform adjustments registered in u */
+               nsems = sma->sem_nsems;
+               for (i = 0; i < nsems; i++) {
+                       struct sem * sem = &sma->sem_base[i];
+                       sem->semval += u->semadj[i];
+                       if (sem->semval < 0)
+                               sem->semval = 0; /* shouldn't happen */
+                       sem->sempid = current->pid;
                }
+               sma->sem_otime = CURRENT_TIME;
+               /* maybe some queued-up processes were waiting for this */
+               update_queue(sma);
        }
        current->semundo = NULL;
-       return;
 }
index 39892ae5f062e6f776cd68c9fb62bcecef5ffef4..0eee68060d6ad8fd1039968786b87b711e86fc7c 100644 (file)
@@ -380,8 +380,7 @@ NORET_TYPE void do_exit(long code)
                intr_count = 0;
        }
 fake_volatile:
-       if (current->semundo)
-               sem_exit();
+       sem_exit();
        exit_mmap(current);
        free_page_tables(current);
        exit_files();
index 4a9967eb78e1b8162f514a6a3dea7bdd3cc54ae5..a01a982b8c2ceab42d2c2b0c499da09664c89f2c 100644 (file)
@@ -37,6 +37,8 @@
 #ifdef CONFIG_INET
 #include <linux/net.h>
 #include <linux/netdevice.h>
+#include <linux/ip.h>
+#include "../net/inet/protocol.h"
 #endif
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
@@ -202,6 +204,10 @@ struct symbol_table symbol_table = {
        /* dma handling */
        X(request_dma),
        X(free_dma),
+#ifdef HAVE_DISABLE_HLT
+       X(disable_hlt),
+       X(enable_hlt),
+#endif
 
        /* IO port handling */
        X(check_region),
@@ -247,10 +253,19 @@ struct symbol_table symbol_table = {
 
        /* Miscellaneous access points */
        X(si_meminfo),
-
+#ifdef CONFIG_NET
        /* socket layer registration */
        X(sock_register),
        X(sock_unregister),
+       /* Internet layer registration */
+#ifdef CONFIG_INET     
+       X(inet_add_protocol),
+       X(inet_del_protocol),
+#endif
+       /* Device callback registration */
+       X(register_netdevice_notifier),
+       X(unregister_netdevice_notifier),
+#endif
 
 #ifdef CONFIG_FTAPE
        /* The next labels are needed for ftape driver.  */
@@ -275,6 +290,11 @@ struct symbol_table symbol_table = {
        X(dev_ioctl),
        X(dev_queue_xmit),
        X(dev_base),
+       X(dev_close),
+       X(n_tty_ioctl),
+       X(tty_register_ldisc),
+       X(kill_fasync),
+       X(tty_hung_up_p),
 #endif
 #ifdef CONFIG_SCSI
        /* Supports loadable scsi drivers */
@@ -284,6 +304,7 @@ struct symbol_table symbol_table = {
        X(scsi_malloc),
        X(scsi_register),
        X(scsi_unregister),
+       X(scsicam_bios_param),
 #endif
        /* Added to make file system as module */
        X(set_writetime),
index f8b340584ab4b38fdcc1ccb929a672c6a41e9535..adda39857b9b6bc271345fe710996f0b4dc15654 100644 (file)
@@ -770,4 +770,7 @@ void sched_init(void)
        bh_base[IMMEDIATE_BH].routine = immediate_bh;
        if (request_irq(TIMER_IRQ, do_timer, 0, "timer") != 0)
                panic("Could not allocate timer IRQ!");
+       enable_bh(TIMER_BH);
+       enable_bh(TQUEUE_BH);
+       enable_bh(IMMEDIATE_BH);
 }
index 709e64b5d905b014d5adf7b4c070ce80ce0a1b47..7d919272bbab31c9da3aacd980bad4a19cebe8d6 100644 (file)
@@ -27,7 +27,7 @@
 unsigned long intr_count = 0;
 
 unsigned long bh_active = 0;
-unsigned long bh_mask = ~0UL;
+unsigned long bh_mask = 0;
 struct bh_struct bh_base[32];
 
 
index a28598e18167113ac853aed26266afcdc1a8729d..d29cb2fe39f07a07cbc663b608ba50313a94e71d 100644 (file)
@@ -202,18 +202,13 @@ void do_gettimeofday(struct timeval *tv)
 
        save_flags(flags);
        cli();
-#if defined (__i386__) || defined (__mips__)
        *tv = xtime;
+#if defined (__i386__) || defined (__mips__)
        tv->tv_usec += do_gettimeoffset();
        if (tv->tv_usec >= 1000000) {
                tv->tv_usec -= 1000000;
                tv->tv_sec++;
        }
-       sti();
-#else /* !defined (__i386__) && !defined (__mips__) */
-       cli();
-       *tv = xtime;
-       sti();
 #endif /* !defined (__i386__) && !defined (__mips__) */
        restore_flags(flags);
 }
index 96d527c9e04f47a00af5dd0b89c2550a41af9222..c69ae21072bca153c2c6595508dcd62aa9f6d7cf 100644 (file)
@@ -270,11 +270,13 @@ while (tries --)
      * sizes[order].firstfree used to be NULL, otherwise we wouldn't be
      * here, but you never know.... 
      */
-    page->next = sizes[order].firstfree;
-    if (dma_flag)
+    if (dma_flag) {
+      page->next = sizes[order].dmafree;
       sizes[order].dmafree = page;
-    else
+    } else {
+      page->next = sizes[order].firstfree;
       sizes[order].firstfree = page;
+    }
     restore_flags(flags);
     }
 
index b94319401b347da51f69b6dcf90944062a9017df..20496b28e6f1bd093e715e578abded3db38d4fca 100644 (file)
@@ -1268,7 +1268,7 @@ static void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag)
         */
 
 #ifdef CONFIG_IP_FIREWALL
-       if(!ip_fw_chk(skb->h.iph, ip_fw_fwd_chain))
+       if(!ip_fw_chk(skb->h.iph, ip_fw_fwd_chain, ip_fw_fwd_policy))
        {
                return;
        }
@@ -1425,7 +1425,7 @@ static void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag)
                         *      Count mapping we shortcut
                         */
                         
-                       ip_acct_cnt(iph,ip_acct_chain,1);
+                       ip_acct_cnt(iph,ip_acct_chain);
 #endif                 
                        
                        /*
@@ -1493,7 +1493,8 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 
 #ifdef CONFIG_IP_FIREWALL
        
-       if(!LOOPBACK(iph->daddr) && !ip_fw_chk(iph,ip_fw_blk_chain))
+       if(!LOOPBACK(iph->daddr) && !ip_fw_chk(iph,ip_fw_blk_chain,
+                       ip_fw_blk_policy))
        {
                kfree_skb(skb, FREE_WRITE);
                return 0;       
@@ -1608,7 +1609,7 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
         */
         
 #ifdef CONFIG_IP_ACCT
-       ip_acct_cnt(iph,ip_acct_chain,1);
+       ip_acct_cnt(iph,ip_acct_chain);
 #endif 
 
        /*
@@ -1905,7 +1906,7 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
         
        ip_statistics.IpOutRequests++;
 #ifdef CONFIG_IP_ACCT
-       ip_acct_cnt(iph,ip_acct_chain,1);
+       ip_acct_cnt(iph,ip_acct_chain);
 #endif 
        
 #ifdef CONFIG_IP_MULTICAST     
@@ -2280,8 +2281,12 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                case IP_FW_DEL_FWD:
                case IP_FW_CHK_BLK:
                case IP_FW_CHK_FWD:
-               case IP_FW_FLUSH:
-               case IP_FW_POLICY:
+               case IP_FW_FLUSH_BLK:
+               case IP_FW_FLUSH_FWD:
+               case IP_FW_ZERO_BLK:
+               case IP_FW_ZERO_FWD:
+               case IP_FW_POLICY_BLK:
+               case IP_FW_POLICY_FWD:
                        if(!suser())
                                return -EPERM;
                        if(optlen>sizeof(tmp_fw) || optlen<1)
index 1227a8f21172e4c7b901f0dace28a400c32c5209..fbbdb6da7e438e0a69bab10600a520eab5066585 100644 (file)
 #ifdef CONFIG_IP_FIREWALL
 struct ip_fw *ip_fw_fwd_chain;
 struct ip_fw *ip_fw_blk_chain;
-static int ip_fw_policy=1;
+int ip_fw_blk_policy=1;
+int ip_fw_fwd_policy=1;
 #endif
 #ifdef CONFIG_IP_ACCT
 struct ip_fw *ip_acct_chain;
 #endif
 
+#define IP_INFO_BLK    0
+#define IP_INFO_FWD    1
+#define IP_INFO_ACCT   2
+
 
 extern inline void print_ip(unsigned long xaddr)
 {
@@ -106,7 +111,7 @@ extern inline int port_match(unsigned short *portptr,int nports,unsigned short p
 
 #ifdef CONFIG_IP_FIREWALL
 
-int ip_fw_chk(struct iphdr *ip, struct ip_fw *chain)
+int ip_fw_chk(struct iphdr *ip, struct ip_fw *chain, int policy)
 {
        unsigned long src, dst;
        char got_proto=0;
@@ -116,7 +121,7 @@ int ip_fw_chk(struct iphdr *ip, struct ip_fw *chain)
        unsigned short *portptr=(unsigned short *)&(((u_int *)ip)[ip->ihl]);
 
        if (!chain) 
-               return(1);     /* If no chain , always say Ok to packet */
+               return(policy);  /* If no chain, use your policy. */
 
        src = ip->saddr;
        dst = ip->daddr;
@@ -166,6 +171,8 @@ int ip_fw_chk(struct iphdr *ip, struct ip_fw *chain)
 #ifdef DEBUG_CONFIG_IP_FIREWALL
                                printf("universal frwl match\n");
 #endif
+                               f->p_cnt++;
+                               f->b_cnt+=ntohs(ip->tot_len);
 #ifdef CONFIG_IP_FIREWALL_VERBOSE
                                if (!(f->flags & IP_FW_F_ACCEPT))
                                        goto bad_packet;
@@ -226,6 +233,9 @@ int ip_fw_chk(struct iphdr *ip, struct ip_fw *chain)
                                                port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port,
                                                f->flags&IP_FW_F_DRNG))) 
                                        {
+                                       /* We've got a match! */
+                                       f->p_cnt++;
+                                       f->b_cnt+=ntohs(ip->tot_len);
 #ifdef CONFIG_IP_FIREWALL_VERBOSE
                                                if (!(f->flags & IP_FW_F_ACCEPT))
                                                        goto bad_packet;
@@ -246,11 +256,11 @@ int ip_fw_chk(struct iphdr *ip, struct ip_fw *chain)
         */
 
 #ifdef CONFIG_IP_FIREWALL_VERBOSE
-       if (!(ip_fw_policy))
+       if (!(policy))
                goto bad_packet;
        return 1;
 #else
-       return(ip_fw_policy);
+       return(policy);
 #endif
 
 #ifdef CONFIG_IP_FIREWALL_VERBOSE
@@ -302,7 +312,7 @@ bad_packet:
 
 
 #ifdef CONFIG_IP_ACCT
-void ip_acct_cnt(struct iphdr *ip,struct ip_fw *chain,int nh_conv)
+void ip_acct_cnt(struct iphdr *ip,struct ip_fw *chain)
 {
        unsigned long src, dst;
        char got_proto=0,rev=0;
@@ -341,13 +351,10 @@ addr_match:
                        f->p_cnt++;     /*      Rise packet count */
 
                        /*
-                        *      Rise byte count, if need to convert from host to network byte order,do it.
+                        *      Rise byte count, convert from host to network byte order.
                         */
                         
-                       if (nh_conv)                
-                               f->b_cnt+=ntohs(ip->tot_len);
-                       else
-                               f->b_cnt+=ip->tot_len;
+                       f->b_cnt+=ntohs(ip->tot_len);
                }
                else
                {
@@ -407,12 +414,9 @@ addr_match:
                                {
                                        f->p_cnt++;                   /* Rise packet count */
                                        /*
-                                        * Rise byte count, if need to convert from host to network byte order,do it.
+                                        * Rise byte count, convert from host to network byte order.
                                         */
-                                       if (nh_conv)                
-                                               f->b_cnt+=ntohs(ip->tot_len);
-                                       else
-                                               f->b_cnt+=ip->tot_len;
+                                       f->b_cnt+=ntohs(ip->tot_len);
                                } /* Ports match */
                        } /* Proto matches */
                }  /* ALL/Specific */
@@ -811,25 +815,44 @@ int ip_acct_ctl(int stage, void *m, int len)
 #ifdef CONFIG_IP_FIREWALL
 int ip_fw_ctl(int stage, void *m, int len)
 {
-       if ( stage == IP_FW_FLUSH )
+       if ( stage == IP_FW_FLUSH_BLK )
        {
                free_fw_chain(&ip_fw_blk_chain);
+               return(0);
+       }  
+
+       if ( stage == IP_FW_FLUSH_FWD )
+       {
                free_fw_chain(&ip_fw_fwd_chain);
                return(0);
        }  
 
-       if ( stage == IP_FW_POLICY )
+       if ( stage == IP_FW_ZERO_BLK )
+       {
+               zero_fw_chain(ip_fw_blk_chain);
+               return(0);
+       }  
+
+       if ( stage == IP_FW_ZERO_FWD )
+       {
+               zero_fw_chain(ip_fw_fwd_chain);
+               return(0);
+       }  
+
+       if ( stage == IP_FW_POLICY_BLK || stage == IP_FW_POLICY_FWD )
        {
                int *tmp_policy_ptr;
                tmp_policy_ptr=(int *)m;
                if ((*tmp_policy_ptr)!=1 && (*tmp_policy_ptr)!=0)
                        return (EINVAL);
-               ip_fw_policy=*tmp_policy_ptr;
+               if ( stage == IP_FW_POLICY_BLK )
+                       ip_fw_blk_policy=*tmp_policy_ptr;
+               else
+                       ip_fw_fwd_policy=*tmp_policy_ptr;
                return 0;
        }
 
-       if ( stage == IP_FW_CHK_BLK 
-               || stage == IP_FW_CHK_FWD )
+       if ( stage == IP_FW_CHK_BLK || stage == IP_FW_CHK_FWD )
        {
                struct iphdr *ip;
 
@@ -855,7 +878,9 @@ int ip_fw_ctl(int stage, void *m, int len)
 
                if ( ip_fw_chk(ip,
                        stage == IP_FW_CHK_BLK ?
-                       ip_fw_blk_chain : ip_fw_fwd_chain )
+                       ip_fw_blk_chain : ip_fw_fwd_chain,
+                       stage == IP_FW_CHK_BLK ?
+                       ip_fw_blk_policy : ip_fw_fwd_policy )
                       ) 
                        return(0);
                else    
@@ -906,20 +931,45 @@ int ip_fw_ctl(int stage, void *m, int len)
 
 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
 
-static int ip_chain_procinfo(struct ip_fw *chain, char *buffer, char **start, off_t offset, int length)
+static int ip_chain_procinfo(int stage, char *buffer, char **start,
+               off_t offset, int length, int reset)
 {
        off_t pos=0, begin=0;
        struct ip_fw *i;
        unsigned long flags;
-       int len=0;
-       
+       int len;
        
-       len=sprintf(buffer,"Firewall Rules\n");  
+
+       switch(stage)
+       {
+#ifdef CONFIG_IP_FIREWALL
+               case IP_INFO_BLK:
+                       i = ip_fw_blk_chain;
+                       len=sprintf(buffer, "IP firewall block rules, policy = %d\n",
+                               ip_fw_blk_policy);
+                       break;
+               case IP_INFO_FWD:
+                       i = ip_fw_fwd_chain;
+                       len=sprintf(buffer, "IP firewall forward rules, policy = %d\n",
+                               ip_fw_fwd_policy);
+                       break;
+#endif
+#ifdef CONFIG_IP_ACCT
+               case IP_INFO_ACCT:
+                       i = ip_acct_chain;
+                       len=sprintf(buffer,"IP accounting rules\n");
+                       break;
+#endif
+               default:
+                       /* this should never be reached, but safety first... */
+                       i = NULL;
+                       len=0;
+                       break;
+       }
+
        save_flags(flags);
        cli();
        
-       i=chain;
-       
        while(i!=NULL)
        {
                len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %X ",
@@ -938,6 +988,12 @@ static int ip_chain_procinfo(struct ip_fw *chain, char *buffer, char **start, of
                        len=0;
                        begin=pos;
                }
+               else if(reset)
+               {
+                       /* This needs to be done at this specific place! */
+                       i->p_cnt=0L;
+                       i->b_cnt=0L;
+               }
                if(pos>offset+length)
                        break;
                i=i->next;
@@ -955,7 +1011,12 @@ static int ip_chain_procinfo(struct ip_fw *chain, char *buffer, char **start, of
 
 int ip_acct_procinfo(char *buffer, char **start, off_t offset, int length)
 {
-       return ip_chain_procinfo(ip_acct_chain, buffer,start,offset,length);
+       return ip_chain_procinfo(IP_INFO_ACCT, buffer,start,offset,length,0);
+}
+
+int ip_acct0_procinfo(char *buffer, char **start, off_t offset, int length)
+{
+       return ip_chain_procinfo(IP_INFO_ACCT, buffer,start,offset,length,1);
 }
 
 #endif
@@ -964,12 +1025,22 @@ int ip_acct_procinfo(char *buffer, char **start, off_t offset, int length)
 
 int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset, int length)
 {
-       return ip_chain_procinfo(ip_fw_blk_chain, buffer,start,offset,length);
+       return ip_chain_procinfo(IP_INFO_BLK, buffer,start,offset,length,0);
+}
+
+int ip_fw_blk0_procinfo(char *buffer, char **start, off_t offset, int length)
+{
+       return ip_chain_procinfo(IP_INFO_BLK, buffer,start,offset,length,1);
 }
 
 int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset, int length)
 {
-       return ip_chain_procinfo(ip_fw_fwd_chain, buffer,start,offset,length);
+       return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,0);
+}
+
+int ip_fw_fwd0_procinfo(char *buffer, char **start, off_t offset, int length)
+{
+       return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,1);
 }
 
 #endif
index 5d2c8c04170b0e6b2105f2392e9a414ef27b22d2..778e1cd5305a4a11992bc48420ba9ad50051daad 100644 (file)
@@ -202,13 +202,13 @@ int rarp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        memcpy(&tip,rarp_ptr,4);
 
 /*
- *     Process entry
+ *     Process entry. Use tha for table lookup according to RFC903.
  */
   
        cli();
        for (entry = rarp_tables; entry != NULL; entry = entry->next)
-       if (!memcmp(entry->ha, sha, rarp->ar_hln))
-               break;
+               if (!memcmp(entry->ha, tha, rarp->ar_hln))
+                       break;
   
        if (entry != NULL)
        {
index 14bda90cd35c8089aed2a8cca98be6f4b8b412fa..40d4a8f407b9fcc9b66556529c09b8662b955d30 100644 (file)
@@ -62,6 +62,8 @@
  *             Alan Cox        :       Split IP from generic code
  *             Alan Cox        :       New kfree_skbmem()
  *             Alan Cox        :       Make SO_DEBUG superuser only.
+ *             Alan Cox        :       Allow anyone to clear SO_DEBUG
+ *                                     (compatibility fix)
  *
  * To Fix:
  *
@@ -134,7 +136,7 @@ int sock_setsockopt(struct sock *sk, int level, int optname,
                        return(-ENOPROTOOPT);
 
                case SO_DEBUG:  
-                       if(!suser())
+                       if(val && !suser())
                                return(-EPERM);
                        sk->debug=val?1:0;
                        return 0;
index 19fc51dfa94807dbd3a59873cdf9e8cba944ca72..4ae85af0a25670996f5f78bccf4ac4eaa206d78a 100644 (file)
@@ -2642,11 +2642,18 @@ static inline unsigned long default_mask(unsigned long dst)
 
 /*
  *     Default sequence number picking algorithm.
+ *     As close as possible to RFC 793, which
+ *     suggests using a 250kHz clock.
+ *     Further reading shows this assumes 2MB/s networks.
+ *     For 10MB/s ethernet, a 1MHz clock is appropriate.
+ *     That's funny, Linux has one built in!  Use it!
  */
 
-extern inline long tcp_init_seq(void)
+extern inline unsigned long tcp_init_seq(void)
 {
-       return jiffies * SEQ_TICK - seq_offset; 
+       struct timeval tv;
+       do_gettimeofday(&tv);
+       return tv.tv_usec+tv.tv_sec*1000000;
 }
 
 /*
@@ -4276,7 +4283,7 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
   
        sk->inuse = 1;
        sk->daddr = usin->sin_addr.s_addr;
-       sk->write_seq = jiffies * SEQ_TICK - seq_offset;
+       sk->write_seq = tcp_init_seq();
        sk->window_seq = sk->write_seq;
        sk->rcv_ack_seq = sk->write_seq -1;
        sk->err = 0;
index ef241aa2e2e3df9fba59c93ff8b14feaee8dea21..d8a34d12ecdb837c02113526012db1d522c72b71 100644 (file)
@@ -1370,6 +1370,7 @@ void sock_init(void)
         */
 
        bh_base[NET_BH].routine= net_bh;
+       enable_bh(NET_BH);
 #endif  
 }