@@ -478,6+478,10 @@ N: Kai M"akisara E: Kai.Makisara@vtt.fi
D: SCSI Tape Driver
+N: Peter MacDonald
+D: SLS distribution
+D: Initial implementation of VC's, pty's and select()
+
N: James B. MacLean
E: jmaclean@fox.nstn.ns.ca
D: Coordinator of DOSEMU releases
VERSION = 1
PATCHLEVEL = 1
-SUBLEVEL = 77
+SUBLEVEL = 78
ARCH = i386
@@ -193,7+193,7 @@ net: dummy $(MAKE) linuxsubdirs SUBDIRS=net
modules: dummy
- @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i modules; done
+ @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i CFLAGS="$(CFLAGS) -DMODULE" modules; done
clean: archclean
@@ -13,8+13,9 @@ CFLAGS := $(CFLAGS) -mno-fp-regs
HEAD := arch/alpha/kernel/head.o
-SUBDIRS := $(SUBDIRS) arch/alpha/kernel
+SUBDIRS := $(SUBDIRS) arch/alpha/kernel arch/alpha/lib
ARCHIVES := arch/alpha/kernel/kernel.o $(ARCHIVES)
+LIBS := arch/alpha/lib/lib.a $(LIBS)
archclean:
@@ -14,7+14,7 @@ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y
if [ "$CONFIG_NET" = "y" ]; then
comment 'Networking options'
-bool 'TCP/IP networking' CONFIG_INET y
+bool 'TCP/IP networking' CONFIG_INET n
if [ "$CONFIG_INET" "=" "y" ]; then
bool 'IP forwarding/gatewaying' CONFIG_IP_FORWARD n
bool 'IP multicasting (ALPHA)' CONFIG_IP_MULTICAST n
comment 'SCSI support'
-bool 'SCSI support?' CONFIG_SCSI y
+bool 'SCSI support?' CONFIG_SCSI n
if [ "$CONFIG_SCSI" = "n" ]; then
@@ -109,7+109,7 @@ if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then fi
bool '3c509/3c579 support' CONFIG_EL3 y
fi
-bool 'Other ISA cards' CONFIG_NET_ISA y
+bool 'Other ISA cards' CONFIG_NET_ISA n
if [ "$CONFIG_NET_ISA" = "y" ]; then
bool 'Cabletron E21xx support' CONFIG_E2100 n
bool 'DEPCA support' CONFIG_DEPCA y
#include <asm/system.h>
#define halt .long PAL_halt
-#define rti .long RAL_rti
+#define rti .long PAL_rti
.text
.set noat
--- /dev/null
+#
+# Makefile for alpha-specific library files..
+#
+
+.c.s:
+ $(CC) $(CFLAGS) -S $<
+.s.o:
+ $(AS) -c -o $*.o $<
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+OBJS = __divqu.o __remqu.o __divlu.o __remlu.o
+
+lib.a: $(OBJS)
+ $(AR) rcs lib.a $(OBJS)
+ sync
+
+__divqu.o: divide.S
+ $(CC) -DDIV -c -o __divqu.o divide.S
+
+__remqu.o: divide.S
+ $(CC) -DREM -c -o __remqu.o divide.S
+
+__divlu.o: divide.S
+ $(CC) -DDIV -DINTSIZE -c -o __divlu.o divide.S
+
+__remlu.o: divide.S
+ $(CC) -DREM -DINTSIZE -c -o __remlu.o divide.S
+
+dep:
+ $(CPP) -M *.c > .depend
+
+#
+# include a dependency file if one exists
+#
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
+
--- /dev/null
+/*
+ * arch/alpha/lib/divide.S
+ *
+ * (C) 1995 Linus Torvalds
+ *
+ * Alpha division..
+ */
+
+/*
+ * The alpha chip doesn't provide hardware division, so we have to do it
+ * by hand. The compiler expects the functions
+ *
+ * __divqu: 64-bit unsigned long divide
+ * __remqu: 64-bit unsigned long reminder
+ * __divqs/__remqs: signed 64-bit
+ * __divlu/__remlu: unsigned 32-bit
+ * __divls/__remls: signed 32-bit
+ *
+ * These are not normal C functions: instead of the normal
+ * calling sequence, these expect their arguments in registers
+ * $24 and $25, and return the result in $27. Register $28 may
+ * be clobbered (assembly temprary), anything else must be saved.
+ *
+ * In short: painful. I'm not going to try to be clever about it:
+ * let somebody else optimize it if they will.
+ */
+
+/*
+ * My temporaries:
+ * $0 - current bit
+ * $1 - shifted divisor
+ * $2 - rest
+ * $3 - compare status
+ *
+ * $23 - return address
+ * $24 - dividend
+ * $25 - divisor
+ */
+
+/*
+ * Select function type and registers
+ */
+#ifdef DIV
+#define func(x) __div##x
+#define modulus $2
+#define quotient $27
+#else
+#define func(x) __rem##x
+#define modulus $27
+#define quotient $2
+#endif
+
+/*
+ * For 32-bit operations, we need to extend to 64-bit
+ */
+#ifdef INTSIZE
+#define function func(lu)
+#define LONGIFY(x) zapnot x,15,x
+#else
+#define function func(qu)
+#define LONGIFY(x)
+#endif
+
+.globl function
+.ent function
+function:
+ lda $30,-32($30)
+ stq $0, 0($30)
+ stq $1, 8($30)
+ stq $2,16($30)
+ stq $3,24($30)
+ bis $25,$25,$1
+ bis $24,$24,modulus
+ bis $31,$31,quotient
+ LONGIFY($1)
+ LONGIFY(modulus)
+ beq $1, 9f /* div by zero */
+ bis $31,1,$0
+ blt $1, 2f /* high bit set */
+1: cmpult modulus,$1,$3
+ bne $3,3f
+ addq $1,$1,$1
+ addq $0,$0,$0
+ bge $1,1b
+2: cmpult modulus,$1,$3
+ bne $3,3f
+ subq modulus,$1,modulus
+ addq $0,quotient,quotient
+3: srl $0,1,$0
+ srl $1,1,$1
+ bne $0,2b
+9: ldq $0, 0($30)
+ ldq $1, 8($30)
+ ldq $2, 16($30)
+ ldq $3, 32($30)
+ lda $30,32($30)
+ ret $31,($23),1
+ .end function
@@ -34,6+34,8 @@ kernel.o: $(OBJS) dep:
$(CPP) -M *.c > .depend
+modules:
+
dummy:
#
@@ -451,7+451,7 @@ int revision_decode(unsigned char bus,unsigned char dev_fn) unsigned char revision;
pcibios_read_config_byte(
bus, dev_fn, (unsigned char) PCI_CLASS_REVISION, &revision);
- return revision;
+ return (int) revision;
}
@@ -484,7+484,8 @@ int device_decode(unsigned char bus,unsigned char dev_fn,unsigned short vendor) bus, dev_fn, (unsigned char) PCI_DEVICE_ID, &device);
for (i=0;i<PCI_DEVICE_NUM;i++)
if ((device==pci_device[i].device_id)
- && (vendor==pci_device[i].vendor_id)) break;
+ && (vendor==pci_device[i].vendor_id)) return i;
+ printk("Device id=%x ",device);
return i;
}
@@ -503,6+504,7 @@ int vendor_decode(unsigned char bus,unsigned char dev_fn) bus, dev_fn, (unsigned char) PCI_VENDOR_ID, &vendor);
for (i=0;i<PCI_VENDOR_NUM;i++)
if (vendor==pci_vendor[i].vendor_id) return i;
+ printk("Vendor id=%x ",vendor);
return i;
}
#include <linux/types.h>
#include <linux/ioport.h>
-static unsigned long ioport_registrar[IO_BITMAP_SIZE] = {0, /* ... */};
-#define IOPORTNAMES_NUM 32
-#define IOPORTNAMES_LEN 26
-struct { int from;
- int num;
- int flags;
- char name[IOPORTNAMES_LEN];
- } ioportnames[IOPORTNAMES_NUM];
+#define IOTABLE_SIZE 32
+#define STR(x) #x
+
+typedef struct resource_entry_t {
+ u_long from, num;
+ const char *name;
+ struct resource_entry_t *next;
+} resource_entry_t;
+
+static resource_entry_t iolist = { 0, 0, "", NULL };
+
+static resource_entry_t iotable[IOTABLE_SIZE];
#define _IODEBUG
@@ -84,52+88,20 @@ asmlinkage void set_bitmap(unsigned long *bitmap, short base, short extent, int }
}
-/* Check for set bits in BITMAP starting at BASE, going to EXTENT. */
-asmlinkage int check_bitmap(unsigned long *bitmap, short base, short extent)
-{
- int mask;
- unsigned long *bitmap_base = bitmap + (base >> 5);
- unsigned short low_index = base & 0x1f;
- int length = low_index + extent;
-
- if (low_index != 0) {
- mask = (~0 << low_index);
- if (length < 32)
- mask &= ~(~0 << length);
- if (*bitmap_base++ & mask)
- return 1;
- length -= 32;
- }
- while (length >= 32) {
- if (*bitmap_base++ != 0)
- return 1;
- length -= 32;
- }
-
- if (length > 0) {
- mask = ~(~0 << length);
- if (*bitmap_base++ & mask)
- return 1;
- }
- return 0;
-}
-
/*
* This generates the report for /proc/ioports
*/
int get_ioport_list(char *buf)
-{ int i=0,len=0;
- while(i<IOPORTNAMES_LEN && len<4000)
- { if(ioportnames[i].flags)
- len+=sprintf(buf+len,"%04x-%04x : %s\n",
- ioportnames[i].from,
- ioportnames[i].from+ioportnames[i].num-1,
- ioportnames[i].name);
- i++;
- }
- if(len>=4000)
- len+=sprintf(buf+len,"4k-Limit reached!\n");
- return len;
+{
+ resource_entry_t *p;
+ int len = 0;
+
+ for (p = iolist.next; (p) && (len < 4000); p = p->next)
+ len += sprintf(buf+len, "%04lx-%04lx : %s\n",
+ p->from, p->from+p->num-1, p->name);
+ if (p)
+ len += sprintf(buf+len, "4K limit reached!\n");
+ return len;
}
/*
@@ -179,37+151,54 @@ asmlinkage int sys_iopl(long ebx,long ecx,long edx, }
/*
- * This is the 'old' snarfing worker function
+ * The workhorse function: find where to put a new entry
*/
-void do_snarf_region(unsigned int from, unsigned int num)
+static resource_entry_t *find_gap(resource_entry_t *root,
+ u_long from, u_long num)
{
- if (from > IO_BITMAP_SIZE*32)
- return;
- if (from + num > IO_BITMAP_SIZE*32)
- num = IO_BITMAP_SIZE*32 - from;
- set_bitmap(ioport_registrar, from, num, 1);
- return;
+ unsigned long flags;
+ resource_entry_t *p;
+
+ if (from > from+num-1)
+ return NULL;
+ save_flags(flags);
+ cli();
+ for (p = root; ; p = p->next) {
+ if ((p != root) && (p->from+p->num-1 >= from)) {
+ p = NULL;
+ break;
+ }
+ if ((p->next == NULL) || (p->next->from > from+num-1))
+ break;
+ }
+ restore_flags(flags);
+ return p;
}
/*
* Call this from the device driver to register the ioport region.
*/
-void register_iomem(unsigned int from, unsigned int num, char *name)
-{
- int i=0;
- while(ioportnames[i].flags && i<IOPORTNAMES_NUM)
- i++;
- if(i==IOPORTNAMES_NUM)
- printk("warning:ioportname-table is full");
- else
- {
- strncpy(ioportnames[i].name,name,IOPORTNAMES_LEN);
- ioportnames[i].name[IOPORTNAMES_LEN-1]=(char)0;
- ioportnames[i].from=from;
- ioportnames[i].num=num;
- ioportnames[i].flags=1;
+void request_region(unsigned int from, unsigned int num, const char *name)
+{
+ resource_entry_t *p;
+ int i;
+
+ for (i = 0; i < IOTABLE_SIZE; i++)
+ if (iotable[i].num == 0)
+ break;
+ if (i == IOTABLE_SIZE)
+ printk("warning: ioport table is full\n");
+ else {
+ p = find_gap(&iolist, from, num);
+ if (p == NULL)
+ return;
+ iotable[i].name = name;
+ iotable[i].from = from;
+ iotable[i].num = num;
+ iotable[i].next = p->next;
+ p->next = &iotable[i];
+ return;
}
- do_snarf_region(from,num);
}
/*
@@ -217,33+206,27 @@ void register_iomem(unsigned int from, unsigned int num, char *name) * It can be removed when all driver call the new function.
*/
void snarf_region(unsigned int from, unsigned int num)
-{ register_iomem(from,num,"No name given.");
-}
-
-/*
- * The worker for releasing
- */
-void do_release_region(unsigned int from, unsigned int num)
{
- if (from > IO_BITMAP_SIZE*32)
- return;
- if (from + num > IO_BITMAP_SIZE*32)
- num = IO_BITMAP_SIZE*32 - from;
- set_bitmap(ioport_registrar, from, num, 0);
- return;
+ request_region(from,num,"No name given.");
}
/*
* Call this when the device driver is unloaded
*/
void release_region(unsigned int from, unsigned int num)
-{ int i=0;
- while(i<IOPORTNAMES_NUM)
- { if(ioportnames[i].from==from && ioportnames[i].num==num)
- ioportnames[i].flags=0;
- i++;
+{
+ resource_entry_t *p, *q;
+
+ for (p = &iolist; ; p = q) {
+ q = p->next;
+ if (q == NULL)
+ break;
+ if ((q->from == from) && (q->num == num)) {
+ q->num = 0;
+ p->next = q->next;
+ return;
+ }
}
- do_release_region(from,num);
}
/*
@@ -251,11+234,7 @@ void release_region(unsigned int from, unsigned int num) */
int check_region(unsigned int from, unsigned int num)
{
- if (from > IO_BITMAP_SIZE*32)
- return 0;
- if (from + num > IO_BITMAP_SIZE*32)
- num = IO_BITMAP_SIZE*32 - from;
- return check_bitmap(ioport_registrar, from, num);
+ return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
}
/* Called from init/main.c to reserve IO ports. */
@@ -264,5+243,5 @@ void reserve_setup(char *str, int *ints) int i;
for (i = 1; i < ints[0]; i += 2)
- register_iomem(ints[i], ints[i+1],"reserved");
+ request_region(ints[i], ints[i+1], "reserved");
}
proto:
cproto -e -DMAKING_PROTO *.c >fpu_proto.h
+modules:
+
dummy:
#
.S.o:
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
-OBJS = entry.o traps.o
+OBJS = entry.o traps.o irq.o process.o
all: kernel.o head.o
-/* arch/sparc/kernel/entry.S: Sparc trap low-level entry points.
- *
- * Sparc traps are so ugly, this code is going to go through a lot
- * of changes as I find out more interesting things. See head.S for
- * the trap table and how it works, this will show you how we get
- * to these routines.
- *
- * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <asm/head.h>
-
- .text
- .align 4
-
-/* Default trap handler */
- .globl my_trap_handler
-my_trap_handler:
- rd %wim, %l4
- or %g0, 0x1, %l5
- sll %l5, %l0, %l5
- cmp %l4, %l5 ! are we in the invalid register?
-
-#if 0 /* work in progress */
- be wash_trap_win
-#endif
-
- nop
- or %%g0, %l3, %o0
- call _do_hw_interrupt
- or %%g0, %%g0, %o1
- wr %l0, 0x20, %psr ! re-enable traps and reset the condition codes
- nop
- nop
- nop ! click our heels three times, "no place like home"
- jmp %l1
- rett %l2
-
-/* This is cheese and only works reliably if not coming from userland. */
- .globl fill_window_entry
-fill_window_entry:
- wr %g0, 0, %wim ! let us into the invalid window
- ! without inducing another trap
- restore
- nop
- nop ! no guarentees until 3 insns later
- restore
- restore %g0, 1, %l1
- rd %psr, %l0
- sll %l1, %l0, %l0
- wr %l0, 0, %wim
- save %g0, %g0, %g0
-
-/* load up the window */
- ldd [%sp], %l0
- ldd [%sp + 8], %l2
- ldd [%sp + 16], %l4
- ldd [%sp + 24], %l6
- ldd [%sp + 32], %i0
- ldd [%sp + 40], %i2
- ldd [%sp + 48], %i4
- ldd [%sp + 56], %i6
-
- save %g0, %g0, %g0
- save %g0, %g0, %g0
- jmp %l1
- rett %l2
-
-/* Cheese number two, give this a bad stack pointer and get scared. */
- .globl spill_window_entry
-spill_window_entry:
- save %g0, %g0, %g0 ! save into next 'valid' window
- std %l0, [%sp] ! acquire some scratch registers
- rd %psr, %l0
- or %g0, 0x1, %l1
- sll %l1, %l0, %l0
- wr %l0, 0, %wim ! make window we are saving the 'invalid' one
- std %l2, [%sp + 8]
- std %l4, [%sp + 16]
- std %l6, [%sp + 24]
- std %i0, [%sp + 32]
- std %i2, [%sp + 40]
- std %i4, [%sp + 48]
- std %i6, [%sp + 56]
- restore ! restore back into the window we want to use
- jmp %l1
- rett %l2 ! return from spill handler
-
-
-/* This is where most generic traps enter, the registers should be:
- %l0 == %psr
- %l1 == %pc
- %l2 == %npc
- %l4 == trap_type
- %l7 == trap_handler
-*/
-
-trap_entry:
- srl %l0, 0x6, %l5 ! shift over to previous priv bit
- andcc %l5, 0x1, %g0 ! 1 == from kernel 0 == from user
- bz 2f
- nop ! we dont handle users yet ;-(
-
- or %g0, 0x1, %l5
- sll %l5, %l0, %l5 ! a trick, only least 5 bits are
- ! significant in a register shift
- ! count.
- rd %wim, %l6
- andcc %l6, %l5, %g0 ! if (((1<<CWP)&(%wim))==1) we are
- ! in an 'invalid' window
- bz,a 3f
- sub %fp, C_STACK+80, %sp ! cool, just set stack and go
- ! this window is valid to use
-
-/* we aparently need to clean the trap window, inline this for speed */
- or %g0, %g7, %l7 ! set up g6 and g7 for scratch
- or %g0, %g6, %l6
-
- save %g0, %g0, %g0 ! enter next window after the invalid one
- std %l0, [%sp] ! and store it on the stack for later
- std %l2, [%sp + 8] ! retrieval
- std %l4, [%sp + 16]
- std %l6, [%sp + 24]
- std %i0, [%sp + 32]
- std %i2, [%sp + 40]
- std %i4, [%sp + 48]
- std %i6, [%sp + 56]
-
- rd %psr, %g7 ! read the current window pointer
- or %g0, 0x1, %g6 ! and mask it over into the %wim
- sll %g6, %g7, %g6 ! value
- wr %g6, 0, %wim ! make this window the now 'invalid' one
- and %g6, 31, %g6
- restore ! re-enter the trap window, it is ok now
-
- or %g0, %l6, %g6 ! bring back in the old temporaries
- or %g0, %l7, %g7 ! to the locals they were in
-
- b 3f
- sub %fp, C_STACK+80, %sp ! fix stack pointer
-
-
-/* for now if we get a from-user trap you lose... */
-
- .data
- .align 4
-
-tfu_youlose: .asciz "trap from userland, you lose...\n"
-
- .align 4
- .text
-
-2:
- sethi %hi(tfu_youlose), %o0
- sethi %hi(prom_printf), %o1
- ld [%o1 + %lo(prom_printf)], %o1
- call %o1
- or %o0, %lo(tfu_youlose), %o0
-
- sethi %hi(prom_halt), %o1
- ld [%o1 + %lo(prom_halt)], %o1
- call %o1 ! its over
- nop
-
-/* nop and just return, here is where I would jump to the
- * appropriate handler.
- */
-
- jmp %1
- rett %l2
- nop
+/* arch/sparc/kernel/entry.S: Sparc trap low-level entry points.
+ *
+ * Sparc traps are so ugly, this code is going to go through a lot
+ * of changes as I find out more interesting things. See head.S for
+ * the trap table and how it works, this will show you how we get
+ * to these routines.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/head.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
+ * makes the trap entry code easier to understand.
+ */
+
+/* I really don't like synthetic instructions. So I avoid them like the
+ * plague.
+ */
+
+/* Note that when I have to write a window out, and it is a user's window, I
+ * have to check that the pages of memory that I am going to throw the window(s)
+ * onto are valid and are writable by the user (this is %sp to %sp + 64) before
+ * I start dumping stuff there. We always assume that kernels stack is ok.
+ *
+ * If we have to save a kernel window, only one branch is taken. This should
+ * make trap handlers quicker in this scenario.
+ *
+ * Once 'current' is loaded into %g6, it stays there until we leave
+ * this macro.
+ *
+ * XXX must do some checking on the assumption that kernel stack is always ok
+ */
+
+/* I will document how this works real soon. TODO */
+
+#define TRAP_WIN_CLEAN \
+ or %g0, %g5, %l5; /* we need the globals to do our work */ \
+ or %g0, %g6, %l6; /* and %l0 to %l4 are loaded with important */ \
+ or %g0, %g7, %l7; /* information like the psr and pc's to return to */ \
+ sethi %hi(_current), %g6; \
+ ld [%g6 + %lo(_current)], %g6; \
+ ld [%g6 + THREAD_UWINDOWS], %g7; /* how many user wins are active? */ \
+ 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 */ \
+1: std %l2, [%sp + 0x8]; /* then we get here. */ \
+ std %l4, [%sp + 0x10]; \
+ std %l6, [%sp + 0x18]; \
+ std %i0, [%sp + 0x20]; \
+ std %i2, [%sp + 0x28]; \
+ std %i4, [%sp + 0x30]; \
+ std %i6, [%sp + 0x38]; \
+ or %g0, 0x1, %g5; \
+ rd %psr, %g7; \
+ sll %g5, %g7, %g5; \
+ wr %g5, 0x0, %wim; /* update %wim to 'now' invalid */ \
+ and %g7, 0x1f, %g7; \
+ st %g7, [%g6 + THREAD_WIM]; /* save 'this' threads mask */ \
+ restore %g0, %g0, %g0; \
+ or %g0, %l5, %g5; /* restore the globals we used */ \
+ or %g0, %l6, %g6; \
+ b 8f; /* we are done */ \
+ or %g0, %l7, %g7; \
+2: sub %g7, 0x1, %g7; \
+ st %g7, [%g6 + THREAD_UWINDOWS]; /* There are user windows if we */ \
+ andcc %sp, 0x7, %g0; /* get here. Check for stack alignment. */ \
+ bne 5f; /* Stack is unaligned, yuck. */ \
+ sra %sp, 0x1e, %g7; /* This stuff checks to see if top 3-bits */ \
+ subcc %g7, 0x0, %g0; /* of stack pointer address are ok. */ \
+ be,a 3f; \
+ andn %sp, 0xfff, %g7; \
+ subcc %g7, -1, %g0; \
+ bne 5f; /* bad stack pointer, ugh */ \
+ andn %sp, 0xfff, %g7; \
+3: lda [%g7] ASI_PTE, %g7; /* Ok, user stack is a valid address */ \
+ srl %g7, 0x1d, %g7; \
+ subcc %g7, 0x6, %g0; /* Can the user write to it? */ \
+ bne 5f; \
+ and %sp, 0xfff, %g7; \
+ subcc %g7, 0xfc1, %g0; /* Is our save area on one page? */ \
+ bl,a 1b; \
+ std %l0, [%sp]; \
+ add %sp, 0x38, %g5; /* Nope, have to check both pages */ \
+ sra %g5, 0x1e, %g7; \
+ subcc %g7, 0x0, %g0; \
+ be,a 4f; \
+ andn %g5, 0xfff, %g7; \
+ subcc %g7, -1, %g0; \
+ bne 5f; \
+ andn %g5, 0xfff, %g7; \
+4: lda [%g7] ASI_PTE, %g7; /* Stack space in 2nd page is valid */ \
+ srl %g7, 0x1d, %g7; \
+ subcc %g7, 0x6, %g0; /* Can user write here too? */ \
+ be,a 1b; \
+ std %l0, [%sp]; \
+5: ld [%g6 + THREAD_UWINDOWS], %g7; /* This is due to either bad page perms */ \
+ add %g6, THREAD_REG_WINDOW, %g5; /* for the users stack area, or the stack */ \
+6: std %l0, [%g5]; /* pointer is misaligned. See above. */ \
+ std %l2, [%g5 + 0x8]; \
+ std %l4, [%g5 + 0x10]; \
+ std %l6, [%g5 + 0x18]; \
+ std %i0, [%g5 + 0x20]; \
+ std %i2, [%g5 + 0x28]; \
+ std %i4, [%g5 + 0x30]; \
+ std %i6, [%g5 + 0x38]; \
+ subcc %g7, 0x1, %g7; \
+ bge,a 6b; /* while(uwindows>=0) { write_win(); */ \
+ save %g5, 0x40, %g5; /* uwindows--; } */ \
+ st %sp, [%g6 + THREAD_USP]; \
+ or %g0, 0x1, %g5; \
+ rd %psr, %g7; \
+ sll %g5, %g7, %g5; \
+ wr %g5, 0x0, %wim; \
+ and %g7, 0x1f, %g7; \
+ st %g7, [%g6 + THREAD_WIM]; /* Update thread_struct fields */ \
+ ld [%g6 + THREAD_UWINDOWS], %g7; \
+ add %g7, 0x1, %g5; \
+ st %g5, [%g6 + THREAD_W_SAVED]; \
+ st %g0, [%g6 + THREAD_UWINDOWS]; \
+7: subcc %g7, 0x1, %g7; /* Restore back to where we started. */ \
+ bge 7b; \
+ restore %g0, %g0, %g0; \
+ or %g0, %l5, %g5; /* Restore the globals. */ \
+ or %g0, %l6, %g6; \
+ or %g0, %l7, %g7; \
+8: /* 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
+ * if it is the trap window, clean it, and adjust the stack for the handler c-code
+ * to work.
+ */
+
+#define ENTER_TRAP \
+ rd %wim, %l4; \
+ or %g0, 0x1, %l5; \
+ sll %l5, %l0, %l5; \
+ andcc %l0, 0x40, %g0; \
+ bz 1f; \
+ andcc %l4, %l5, %g0; \
+ bz,a 3f; \
+ sub %fp, 0xb0, %sp; \
+ TRAP_WIN_CLEAN \
+ b 3f; \
+ sub %fp, 0xb0, %sp; \
+1: sethi %hi(_current), %l6; \
+ ld [%l6 + %lo(_current)], %l6; \
+ ld [%l6 + THREAD_WIM], %l5; \
+ and %l0, 0x1f, %l4; \
+ cmp %l5, %l3; \
+ ble,a 4f; \
+ sethi %hi(_nwindowsm1), %l4; \
+ sub %l5, %l3, %l3; \
+ b 5f; \
+ sub %l3, 0x1, %l5; \
+4: ld [%l4 + %lo(_nwindowsm1)], %l4; \
+ sub %l4, %l3, %l4; \
+ add %l5, %l4, %l5; \
+5: st %l5, [%l6 + THREAD_UWINDOWS]; \
+ bz,a 2f; \
+ sethi %hi(TASK_SIZE-176), %l5; \
+ TRAP_WIN_CLEAN; \
+ sethi %hi(_current), %l6; \
+ ld [%l6 + %lo(_current)], %l6; \
+ sethi %hi(TASK_SIZE-176), %l5; \
+2: or %l5, %lo(TASK_SIZE-176), %l5; \
+ add %l6, %l5, %sp; \
+3: \
+
+#define ENTER_IRQ \
+ rd %wim, %l4; \
+ or %g0, 0x1, %l5; \
+ sll %l5, %l0, %l5; \
+ andcc %l0, 0x40, %g0; \
+ bz 1f; \
+ andcc %l4, %l5, %g0; \
+ bz,a 0f; \
+ sethi %hi(_eintstack), %l7; \
+ TRAP_WIN_CLEAN \
+ sethi %hi(_eintstack), %l7; \
+0: cmp %fp, %l7; \
+ bge,a 3f; \
+ sub %l7, 0xb0, %sp; \
+ b 3f; \
+ sub %fp, 0xb0, %sp; \
+1: sethi %hi(_current), %l6; \
+ ld [%l6 + %lo(_current)], %l6; \
+ ld [%l6 + PCB_WIM], %l5; \
+ and %l0, 0x1f, %l7; \
+ cmp %l5, %l7; \
+ ble,a 4f; \
+ sethi %hi(_nwindowsm1), %l4; \
+ sub %l5, %l7, %l7; \
+ b 5f; \
+ sub %l7, 0x1, %l5; \
+4: ld [%l4 + %lo(_nwindowsm1)], %l4; \
+ sub %l4, %l7, %l4; \
+ add %l5, %l4, %l5; \
+5: st %l5, [%l6 + THREAD_UWINDOWS]; \
+ bz,a 2f; \
+ sethi %hi(_eintstack), %l7; \
+ TRAP_WIN_CLEAN; \
+ sethi %hi(_eintstack), %l7; \
+2: \
+ sub %l7, 0xb0, %sp; \
+3: \
+
+ .text
+ .align 4
+
+/* Default trap handler */
+ .globl my_trap_handler
+my_trap_handler:
+ rd %wim, %l4
+ or %g0, 0x1, %l5
+ sll %l5, %l0, %l5
+ cmp %l4, %l5 ! are we in the invalid window?
+
+ TRAP_WIN_CLEAN
+
+ nop
+ or %%g0, %l3, %o0
+ call _do_hw_interrupt
+ or %%g0, %%g0, %o1
+ wr %l0, 0x20, %psr ! re-enable traps and reset the condition codes
+ nop
+ nop
+ nop ! click our heels three times, "no place like home"
+ jmp %l1
+ rett %l2
+
+/* 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.
+ */
+
+/* Don't use local labels, or if you do be REAL CAREFUL. TRAP_WIN_CLEAN is
+ * full of them! If you think this routine is hairy, window spills are worse,
+ * see below.
+ */
+
+ .globl fill_window_entry
+fill_window_entry:
+ andcc %l0, 0x40, %g0 ! see if this is a user window fill
+ bz,a fill_from_user
+ nop
+
+ TRAP_WIN_CLEAN /* danger, danger... */
+ wr %l0, 0x0, %psr
+ nop
+ jmp %l1
+ rett %l2
+
+fill_from_user:
+ sethi %hi(_current), %l6
+ ld [%l6 + %lo(_current)], %l6
+ ld [%l6 + THREAD_WIM], %l5
+ and %l0, 0x1f, %l3
+
+/* I don't know whats worse, the extra comparison here, or an extra load
+ * from a lookup table, we'll see.
+ */
+ cmp %l5, %l3
+ ble,a 1f
+ sethi %hi(_nwindowsm1), %l4
+ sub %l5, %l3, %l3
+ b 2f
+ sub %l3, 0x1, %l5
+1: ld [%l4 + %lo(_nwindowsm1)], %l4
+ sub %l4, %l3, %l4
+ add %l5, %l4, %l5
+2: st %l5, [%l6 + THREAD_UWINDOWS]
+
+ TRAP_WIN_CLEAN /* danger, danger... */
+ sethi %hi(_current), %l6
+ ld [%l6 + %lo(_current)], %l6
+ ld [%l6 + THREAD_KSP], %sp
+ and %l0, 0x1f, %l3
+ sethi %hi(lnx_winmask), %l6
+ or %l6, %lo(lnx_winmask), %l6
+ ldub [%l6 + %l3], %l5
+ b back_to_userland_safety ! may need a sched()
+ rd %wim, %l4
+
+/* A window spill has occurred. This presents a weird situation, a restore
+ * was attempted and a trap occurred. Therefore the restore attempt had no
+ * effect on window movement and the trap saved, which means it went in the
+ * other direction. :-( We are in a trap window which is two restores away
+ * from the window we want to un-invalidate sorta speak and three away from
+ * the one which will become invalid after this routine. There are probably
+ * bugs already this routine. Bugs suck.
+ */
+
+/* This is a very complicated and hairy routine, don't expect to understand
+ * it the first time. :>
+ */
+
+ .globl spill_window_entry
+spill_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
+ 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
+ and %l0, 0x1f, %l0
+ sll %l1, %l0, %l1
+ wr %l1, 0x0, %wim
+ sethi %hi(_current), %l1
+ ld [%l1 + %lo(_current)], %l1
+ st %l0, [%l1 + THREAD_WIM]
+ save %g0, %g0, %g0 ! back to invalid register
+ ldd %l0, [%sp] ! load the window from stack
+ ldd %l2, [%sp + 8]
+ ldd %l4, [%sp + 16]
+ ldd %l6, [%sp + 24]
+ ldd %i0, [%sp + 32]
+ ldd %i2, [%sp + 40]
+ ldd %i4, [%sp + 48]
+ ldd %i6, [%sp + 56]
+ save %g0, %g0, %g0 ! to window where trap happened
+ save %g0, %g0, %g0 ! back to trap window, so rett works
+ wr %l0, 0x0, %psr ! load condition codes
+ nop
+ jmp %l1
+ rett %l2 ! are you as confused as I am?
+
+spill_from_user:
+ andcc %sp, 0x7, %g0 ! check for alignment of user stack
+ bne spill_bad_stack
+ sra %sp, 0x1e, %l7
+ cmp %l7, 0x0
+ be,a 1f
+ andn %sp, 0xfff, %l7
+ cmp %l7, -1
+ bne spill_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
+ and %sp, 0xfff, %l7
+ cmp %l7, 0xfc1
+ bl,a spill_stack_ok
+ restore %g0, 1, %l1
+ add %sp, 0x38, %l5
+ sra %sp, 0x1e, %l7
+ cmp %l7, 0x0
+ be,a 1f
+ andn %sp, 0xfff, %l7
+ cmp %l7, -1
+ bne spill_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
+ restore %g0, 0x1, %l1
+
+spill_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(_current), %l6
+ ld [%l6 + %lo(_current)], %l6
+ st %l4, [%l6 + THREAD_UWINDOWS] ! update current->tss values
+ ld [%l6 + THREAD_WIN], %l5
+ sll %l4, %l5, %l4
+ wr %l4, 0x0, %wim
+ ld [%l6 + THREAD_KSP], %sp ! set to kernel stack pointer
+ wr %l0, 0x20, %psr ! turn off traps
+ std %l0, [%sp + C_STACK] ! set up thread_frame on stack
+ rd %y, %l3
+ std %l2, [%sp + C_STACK + 0x8]
+ or %g0, 0x6, %o0 ! so _sparc_trap knows what to do
+ st %g1, [%sp + C_STACK + 0x14] ! no need to save %g0, always zero
+ or %g0, %l0, %o1
+ std %g2, [%sp + C_STACK + 0x18]
+ or %g0, %l1, %o2
+ std %g4, [%sp + C_STACK + 0x20]
+ add %sp, C_STACK, %o3
+ std %g6, [%sp + C_STACK + 0x28]
+ std %i0, [%sp + C_STACK + 0x30]
+ std %i2, [%sp + C_STACK + 0x38]
+ std %i4, [%sp + C_STACK + 0x40]
+ call _sparc_trap
+ std %i6, [%sp + C_STACK + 0x48]
+
+ ldd [%sp + C_STACK], %l0
+ ldd [%sp + C_STACK + 0x8], %l2
+ wr %l3, 0, %y
+ ld [%sp + C_STACK + 0x14], %g1
+ ldd [%sp + C_STACK + 0x18], %g2
+ ldd [%sp + C_STACK + 0x20], %g4
+ ldd [%sp + C_STACK + 0x28], %g6
+ ldd [%sp + C_STACK + 0x30], %i0
+ ldd [%sp + C_STACK + 0x38], %i2
+ ldd [%sp + C_STACK + 0x40], %i4
+ wr %l0, 0, %psr ! disable traps again
+ ldd [%sp + C_STACK + 0x48], %i6
+ sethi %hi(_current), %l6
+ ld [%l6 + %lo(_current)], %l6
+ ld [%l6 + THREAD_W_SAVED], %l7
+ cmp %l7, 0x0
+ bl,a 1f
+ wr %g0, 0x0, %wim
+ b,a leave_trap
+
+1: or %g0, %g6, %l3
+ or %g0, %l6, %g6
+ st %g0, [%g6 + THREAD_W_SAVED]
+ restore %g0, %g0, %g0
+ restore %g0, %g0, %g0
+ restore %g0, 0x1, %l1
+ rd %psr, %l0
+ sll %l1, %l0, %l1
+ wr %l1, 0x0, %wim
+ and %l0, 0x1f, %l0
+ st %l0, [%g6 + THREAD_WIM]
+ nop
+ save %g0, %g0, %g0
+ ldd [%sp], %l0 ! load number one
+ ldd [%sp + 0x8], %l2
+ ldd [%sp + 0x10], %l4
+ ldd [%sp + 0x18], %l6
+ ldd [%sp + 0x20], %i0
+ ldd [%sp + 0x28], %i2
+ ldd [%sp + 0x30], %i4
+ ldd [%sp + 0x38], %i6
+ save %g0, %g0, %g0
+ ldd [%sp], %l0 ! load number two
+ ldd [%sp + 0x8], %l2
+ ldd [%sp + 0x10], %l4
+ ldd [%sp + 0x18], %l6
+ ldd [%sp + 0x20], %i0
+ ldd [%sp + 0x28], %i2
+ ldd [%sp + 0x30], %i4
+ ldd [%sp + 0x38], %i6
+ save %g0, %g0, %g0 ! re-enter trap window
+ wr %l0, 0x0, %psr ! restore condition codes
+ or %g0, %l3, %g6 ! restore scratch register
+ jmp %l1
+ rett %l2
+
+spill_stack_ok:
+ rd %psr, %l0
+ sll %l1, %l0, %l1
+ wr %l1, 0x0, %wim
+ sethi %hi(_current), %l2
+ ld [%l2 + %lo(_current)], %l2
+ and %l0, 0x1f, %l0
+ st %l0, [%l2 + THREAD_WIM]
+ save %g0, %g0, %g0
+ ldd [%sp], %l0 ! only one load necessary
+ ldd [%sp + 0x8], %l2
+ ldd [%sp + 0x10], %l4
+ ldd [%sp + 0x18], %l6
+ ldd [%sp + 0x20], %i0
+ ldd [%sp + 0x28], %i2
+ ldd [%sp + 0x30], %i4
+ ldd [%sp + 0x38], %i6
+ save %g0, %g0, %g0
+ save %g0, %g0, %g0 ! save into trap window
+ wr %l0, 0x0, %psr ! local number 0 here has cond codes
+ nop
+ jmp %l1
+ rett %l2
+
+/* The following two things point to window management tables. The first
+ one is used to quickly look up how many user windows there are from
+ trap-land. The second is used in a trap handler to determine if a rett
+ instruction will land us smack inside the invalid window that possibly
+ the trap was called to fix-up.
+*/
+
+/* For now these are static tables geared for a 7 window sparc. */
+
+ .data
+ .align 4
+lnx_winmask: .byte 2, 4, 8, 16, 32, 64, 128,1 ! lnx_winmask[0..7]
+
+
@@ -488,20+488,6 @@ _msgbufmapped: .word 1
-/* The following two things point to window management tables. The first
- one is used to quickly look up how many user windows there are from
- trap-land. The second is used in a trap handler to determine if a rett
- instruction will land us smack inside the invalid window that possibly
- the trap was called to fix-up.
-*/
-
- .data
- .skip 32 ! alignment byte & negative indices
-lnx_uw: .skip 32 ! u_char uwtab[-31..31];
-lnx_winmask: .skip 32 ! u_char wmask[0..31];
-
- .text
-
/* Cool, here we go. Pick up the romvec pointer in %o0 and stash it in
%g7 and at _prom_vector_p. And also quickly check whether we are on
@@ -567,18+553,18 @@ found_v2: not_v2:
/* Get the machine type via the mysterious romvec node operations.
- Here we can find out whether we are on a sun4 sun4c, sun4m, or
- a sun4m. The "nodes" are set up as a bunch of n-ary trees which
- you can traverse to get information about devices and such. The
- information acquisition happens via the node-ops which are defined
- in the linux_openprom.h header file. Of particular interest is the
- 'nextnode(int node)' function as it does the smart thing when
- presented with a value of '0', it gives you the first node in the
- tree. These node integers probably offset into some internal prom
- pointer table the openboot has. It's completely undocumented, so
- I'm not about to go sifting through the prom address space, but may
- do so if I get suspicious enough. :-)
-*/
+ * Here we can find out whether we are on a sun4 sun4c, sun4m, or
+ * a sun4m. The "nodes" are set up as a bunch of n-ary trees which
+ * you can traverse to get information about devices and such. The
+ * information acquisition happens via the node-ops which are defined
+ * in the linux_openprom.h header file. Of particular interest is the
+ * 'nextnode(int node)' function as it does the smart thing when
+ * presented with a value of '0', it gives you the first node in the
+ * tree. These node integers probably offset into some internal prom
+ * pointer table the openboot has. It's completely undocumented, so
+ * I'm not about to go sifting through the prom address space, but may
+ * do so if I get suspicious enough. :-)
+ */
or %g0, %g7, %l1
add %l1, 0x1c, %l1
@@ -648,10+634,10 @@ is_sun4c: ! OK, this is a sun4c, yippie
/* That was easy, now lets try to print some message on the screen.
- We don't have to worry about bad address translations when the prom
- addresses our pointers because our pointers are at 0x0-kern_size
- as the prom expects.
-*/
+ * We don't have to worry about bad address translations when the prom
+ * addresses our pointers because our pointers are at 0x0-kern_size
+ * as the prom expects.
+ */
set boot_msg, %o0
ld [prom_printf], %o1
@@ -703,11+689,11 @@ rest_of_boot: */
/* Uh, oh, interrupt time. This crap is real confusing. What I want to do is
- clear all interrupts, map the interrupt enable register which in effect
- enables non-maskable interrupts (or NMI's). Actuall we take no interrupts
- until we frob with the %tbr (trap base register) which the prom has set
- to all its routines which allows some sanity during bootup.
-*/
+ * clear all interrupts, map the interrupt enable register which in effect
+ * enables non-maskable interrupts (or NMI's). Actuall we take no interrupts
+ * until we frob with the %tbr (trap base register) which the prom has set
+ * 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
@@ -722,8+708,8 @@ rest_of_boot: #endif /* paranoid, see above */
/* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's
- show-time!
-*/
+ * show-time!
+ */
set 1f, %g1
jmp %g1
@@ -779,9+765,9 @@ rest_of_boot:
/*
- Maybe the prom zero's out our BSS section, maybe it doesn't. I certainly
- don't know, do you?
-*/
+ * Maybe the prom zero's out our BSS section, maybe it doesn't. I certainly
+ * don't know, do you?
+ */
set _edata, %o0
set _end, %o1
@@ -831,6+817,9 @@ rest_of_boot: add %g3, 0x1, %g3
sethi %hi(_nwindows), %g4
st %g3, [%g4 + %lo(_nwindows)] ! store final value
+ sub %g3, 0x1, %g3
+ sethi %hi(_nwindowsm1), %g4
+ st %g3, [%g4 + %lo(_nwindowsm1)]
/* Here we go */
@@ -893,10+882,10 @@ halt_me: .align 4
/*
- Fill up the prom vector, note in particular the kind first element,
- no joke. I don't need all of them in here as the entire prom vector
- gets initialized in c-code so all routines can use it.
-*/
+ * Fill up the prom vector, note in particular the kind first element,
+ * no joke. I don't need all of them in here as the entire prom vector
+ * gets initialized in c-code so all routines can use it.
+ */
.globl _prom_vector_p
@@ -913,24+902,34 @@ prom_nodefuncs: .skip 4 ! Magical Node functions prom_printf: .skip 4 ! minimal printf()
/* The prom_abort pointer MUST be mapped in all contexts, because if you
- don't then if a user process is running when you press the abort key
- sequence, all sorts of bad things can happen
-*/
+ * don't then if a user process is running when you press the abort key
+ * sequence, all sorts of bad things can happen
+ */
prom_abort: .skip 4 ! "L1-A" magic cookie
! must be mapped in ALL contexts
/* prom_sync is a place where the kernel should place a pointer to a kernel
- function that when called will sync all pending information to the drives
- and then promptly return. If the kernel gets aborted with 'L1-A' one can
- give the 'sync' command to the boot prompt and this magic cookie gets
- executed. Nice feature eh?
-*/
+ * function that when called will sync all pending information to the drives
+ * and then promptly return. If the kernel gets aborted with 'L1-A' one can
+ * give the 'sync' command to the boot prompt and this magic cookie gets
+ * executed. Nice feature eh?
+ */
prom_sync: .skip 4 ! hook in prom for "sync" func
.align 4
+/* We calculate the following at boot time, window fills/spills and trap entry
+ * code uses these to keep track of the register windows.
+ */
+
+ .globl _nwindows
+ .globl _nwindowsm1
+_nwindows: .skip 4
+_nwindowsm1: .skip 4
+
+ .align 4
/* Boot time priviledged register values, plus magic %o2 value */
.globl _boot_wim
--- /dev/null
+/* arch/sparc/kernel/irq.c: Interrupt request handling routines. On the
+ * Sparc the IRQ's are basically 'cast in stone'
+ * and you are supposed to probe the prom's device
+ * node trees to find out who's got which IRQ.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ *
+ */
+
+/*
+ * IRQ's are in fact implemented a bit like signal handlers for the kernel.
+ * The same sigaction struct is used, and with similar semantics (ie there
+ * is a SA_INTERRUPT flag etc). Naturally it's not a 1:1 relation, but there
+ * are similarities.
+ *
+ * sa_handler(int irq_NR) is the default function called (0 if no).
+ * sa_mask is horribly ugly (I won't even mention it)
+ * sa_flags contains various info: SA_INTERRUPT etc
+ * sa_restorer is the unused
+ */
+
+
+void disable_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ restore_flags(flags);
+ return;
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ restore_flags(flags);
+ return;
+}
+
+int get_irq_list(char *buf)
+{
+ int len = 0;
+
+ return len;
+}
+
+/*
+ * do_IRQ handles IRQ's that have been installed without the
+ * SA_INTERRUPT flag: it uses the full signal-handling return
+ * and runs with other interrupts enabled. All relatively slow
+ * IRQ's should use this format: notably the keyboard/timer
+ * routines.
+ */
+asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+{
+ kstat.interrupts[irq]++;
+ return;
+}
+
+/*
+ * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return
+ * stuff - the handler is also running with interrupts disabled unless
+ * it explicitly enables them later.
+ */
+asmlinkage void do_fast_IRQ(int irq)
+{
+ kstat.interrupts[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,&sa);
+}
+
+void free_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ restore_flags(flags);
+ return;
+}
+
+static void math_error_irq(int cpl)
+{
+ return;
+}
+
+static void no_action(int cpl) { }
+
+unsigned int probe_irq_on (void)
+{
+ unsigned int irqs = 0;
+
+ return irqs;
+}
+
+int probe_irq_off (unsigned int irqs)
+{
+ unsigned int i = 0;
+
+ return i;
+}
+
+void init_IRQ(void)
+{
+ int i;
+
+ for (i = 0; i < 16 ; i++)
+ set_intr_gate(0x20+i,bad_interrupt[i]);
+
+ return;
+}
@@ -2863,7+2863,7 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end)
if (drive_found)
{
- register_iomem(sony_cd_base_io, 4,"cdu31a");
+ request_region(sony_cd_base_io, 4,"cdu31a");
if (register_blkdev(MAJOR_NR,"cdu31a",&scd_fops))
{
#include <linux/genhd.h>
#include <linux/malloc.h>
#include <linux/string.h>
+#include <linux/ioport.h>
#define REALLY_SLOW_IO
#include <asm/system.h>
@@ -1023,6+1024,9 @@ static void hd_geninit(void) if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) {
printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
NR_HD = 0;
+ } else {
+ request_region(HD_DATA, 8, "hd");
+ request_region(HD_CMD, 1, "hd(cmd)");
}
}
hd_gendisk.nr_real = NR_HD;
@@ -1885,8+1885,8 @@ static void probe_for_drives (byte hwif) (void) probe_irq_off(probe_irq_on()); /* clear dangling irqs */
#endif /* PROBE_FOR_IRQS */
if (devs[0].present || devs[1].present) {
- register_iomem(IDE_PORT(HD_DATA,HWIF),8,"ide");
- register_iomem(IDE_PORT(HD_CMD,HWIF),1,"ide");
+ request_region(IDE_PORT(HD_DATA,HWIF),8,"ide");
+ request_region(IDE_PORT(HD_CMD,HWIF),1,"ide");
}
restore_flags(flags);
}
@@ -1168,7+1168,7 @@ mcd_init(unsigned long mem_start, unsigned long mem_end) printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
return mem_start;
}
- register_iomem(mcd_port, 4,"mcd");
+ request_region(mcd_port, 4,"mcd");
outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
outb(0x02,MCDPORT(0));
@@ -4228,7+4228,7 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
read_ahead[MAJOR_NR] = SBP_BUFFER_FRAMES * (CD_FRAMESIZE / 512);
- register_iomem(CDo_command,4,"sbpcd");
+ request_region(CDo_command,4,"sbpcd");
for (j=0;j<NR_SBPCD;j++)
{
MODULES := lp.o
-all: char.a modules
+all: char.a
char.a: $(OBJS)
$(AR) rcs char.a $(OBJS)
@@ -83,8+83,7 @@ char.a: $(OBJS)
ifdef MODULES
-modules:
- $(MAKE) CFLAGS="$(CFLAGS) -DMODULE" $(MODULES)
+modules: $(MODULES)
(cd ../../modules;for i in $(MODULES); do ln -sf ../drivers/char/$$i .; done)
else
@@ -494,7+494,6 @@ long lp_init(long kmem_start) int offset = 0;
unsigned int testvalue = 0;
int count = 0;
- char buf[5];
if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
printk("unable to get major %d for line printer\n", LP_MAJOR);
@@ -513,8+512,7 @@ long lp_init(long kmem_start) LP_F(offset) |= LP_EXIST;
lp_reset(offset);
printk("lp%d at 0x%04x, ", offset,LP_B(offset));
- sprintf(buf,"lp%d",offset);
- register_iomem(LP_B(offset), 3,buf);
+ request_region(LP_B(offset), 3, "lp");
if (LP_IRQ(offset))
printk("using IRQ%d\n", LP_IRQ(offset));
else
@@ -536,7+534,6 @@ int init_module(void) int offset = 0;
unsigned int testvalue = 0;
int count = 0;
- char buf[5];
if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
printk("unable to get major %d for line printer\n", LP_MAJOR);
@@ -553,8+550,7 @@ int init_module(void) LP_F(offset) |= LP_EXIST;
lp_reset(offset);
printk("lp%d at 0x%04x, ", offset,LP_B(offset));
- sprintf(buf,"lp%d",offset);
- register_iomem(LP_B(offset),3,buf);
+ request_region(LP_B(offset),3,"lp");
if (LP_IRQ(offset))
printk("using IRQ%d\n", LP_IRQ(offset));
else
@@ -1479,7+1479,7 @@ static int set_serial_info(struct async_struct * info, info->hub6 = new_serial.hub6;
}
if(info->type != PORT_UNKNOWN)
- register_iomem(info->port,8,"serial(set)");
+ request_region(info->port,8,"serial(set)");
check_and_exit:
@@ -2353,7+2353,7 @@ static void autoconfig(struct async_struct * info) if ((status1 != 0xa5) || (status2 != 0x5a))
info->type = PORT_8250;
}
- register_iomem(info->port,8,"serial(auto)");
+ request_region(info->port,8,"serial(auto)");
/*
* Reset the UART.
#include <asm/io.h>
#include <asm/system.h>
+#include <asm/segment.h>
+
extern unsigned short video_port_reg, video_port_val;
/*
@@ -236,7+238,8 @@ void vesa_unblank(void) vesa_blanked = 0;
}
-void set_vesa_blanking(const unsigned long arg) {
+void set_vesa_blanking(const unsigned long arg)
+{
char *argp = (char *)(arg + 1);
unsigned int mode = get_fs_byte(argp);
vesa_blanking_mode = ((mode < 3) ? mode : 0);
@@ -81,6+81,7 @@ static char *version = #include <linux/string.h>
#include <linux/ioport.h>
#include <linux/errno.h>
+#include <linux/config.h>
#include <asm/bitops.h>
#include <asm/io.h>
@@ -229,7+230,7 @@ el1_probe1(struct device *dev, int ioaddr) return ENODEV;
/* Grab the region so we can find the another board if autoIRQ fails. */
- register_iomem(ioaddr, EL1_IO_EXTENT,"3c501");
+ request_region(ioaddr, EL1_IO_EXTENT,"3c501");
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct net_local), 0);
@@ -172,7+172,7 @@ el2_probe1(struct device *dev, int ioaddr) return ENODEV;
}
- register_iomem(ioaddr, EL2_IO_EXTENT,"3c503");
+ request_region(ioaddr, EL2_IO_EXTENT,"3c503");
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct ei_device), 0);
@@ -370,7+370,7 @@ int el16_probe1(struct device *dev, int ioaddr) }
/* We've committed to using the board, and can start filling in *dev. */
- register_iomem(ioaddr, EL16_IO_EXTENT,"3c507");
+ request_region(ioaddr, EL16_IO_EXTENT,"3c507");
dev->base_addr = ioaddr;
outb(0x01, ioaddr + MISC_CTRL);
@@ -224,7+224,7 @@ int el3_probe(struct device *dev) dev->base_addr = ioaddr;
dev->irq = irq;
dev->if_port = if_port;
- register_iomem(dev->base_addr, 16,"3c509");
+ request_region(dev->base_addr, 16,"3c509");
{
char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
ifdef MODULES
-modules:
+modules: $(MODULES)
echo $(MODULES) > ../../modules/NET_MODULES
- @(cd ../../modules; \
- for i in $(MODULES:.o=.c); \
- do ln -sf ../drivers/net/$$i .; \
- done ; \
- ln -sf ../drivers/net/CONFIG . ; \
- $(MAKE) -f../drivers/net/Makefile -I../drivers/net \
- CFLAGS="$(CFLAGS) -I../net/inet -I../drivers/net -DMODULE" $(MODULES); \
- rm $(MODULES:.o=.c) CONFIG)
+ cd ../../modules; \
+ for i in $(MODULES); do ln -sf ../drivers/net/$$i .; done
else
@@ -44,7+44,7 @@ static char *version = "apricot.c:v0.2 05/12/94\n";
#ifndef HAVE_PORTRESERVE
#define check_region(addr, size) 0
-#define register_iomem(addr, size,name) do ; while(0)
+#define request_region(addr, size,name) do ; while(0)
#endif
#ifndef HAVE_ALLOC_SKB
@@ -714,7+714,7 @@ int apricot_probe(struct device *dev) if(memcmp(eth_addr,"\x00\x00\x49",3)!= 0)
return ENODEV;
- register_iomem(ioaddr, APRICOT_TOTAL_SIZE,"apricot");
+ request_region(ioaddr, APRICOT_TOTAL_SIZE,"apricot");
dev->base_addr = ioaddr;
ether_setup(dev);
@@ -207,7+207,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
/* Grab the region so that we can find another board if the IRQ request
fails. */
- register_iomem(ioaddr, AT1700_IO_EXTENT,"at1700");
+ request_region(ioaddr, AT1700_IO_EXTENT,"at1700");
printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name,
ioaddr, irq);
@@ -113,7+113,7 @@ extern struct device *irq2dev_map[16];
#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 0
-#define register_iomem(ioaddr, size,name); do ; while (0)
+#define request_region(ioaddr, size,name); do ; while (0)
#endif
/* use 0 for production, 1 for verification, >2 for debug */
@@ -480,7+480,7 @@ depca_probe1(struct device *dev, short ioaddr) }
#ifdef HAVE_PORTRESERVE
- register_iomem(ioaddr, DEPCA_TOTAL_SIZE,"depca");
+ request_region(ioaddr, DEPCA_TOTAL_SIZE,"depca");
#endif
/*
@@ -147,7+147,7 @@ int e21_probe1(struct device *dev, int ioaddr) return ENODEV;
/* Grab the region so we can find a different board if IRQ select fails. */
- register_iomem(ioaddr, E21_IO_EXTENT,"e2100");
+ request_region(ioaddr, E21_IO_EXTENT,"e2100");
/* Read the station address PROM. */
for (i = 0; i < 6; i++)
@@ -363,7+363,7 @@ int eexp_probe1(struct device *dev, short ioaddr) }
/* We've committed to using the board, and can start filling in *dev. */
- register_iomem(ioaddr, 16,"eexpress");
+ request_region(ioaddr, 16,"eexpress");
dev->base_addr = ioaddr;
for (i = 0; i < 6; i++) {
@@ -352,7+352,7 @@ int ewrk3_probe(struct device *dev) if (!check_region(base_addr, EWRK3_IOP_INC)) {
if (((mem_chkd >> ((base_addr - EWRK3_IO_BASE)/ EWRK3_IOP_INC))&0x01)==1) {
if (DevicePresent(base_addr) == 0) { /* Is EWRK3 really here? */
- register_iomem(base_addr, EWRK3_IOP_INC,"ewrk3"); /* Register I/O region */
+ request_region(base_addr, EWRK3_IOP_INC,"ewrk3"); /* Register I/O region */
status = ewrk3_hw_init(dev, base_addr);
} else {
printk("ewrk3_probe(): No device found\n");
@@ -1344,7+1344,7 @@ static struct device *isa_probe(struct device *dev) ** Device found. Mark its (I/O) location for future reference. Only 24
** EtherWORKS devices can exist between 0x100 and 0x3e0.
*/
- register_iomem(iobase, EWRK3_IOP_INC,"ewrk3");
+ request_region(iobase, EWRK3_IOP_INC,"ewrk3");
if (num_ewrk3s > 0) { /* only gets here in autoprobe */
dev = alloc_device(dev, iobase);
} else {
@@ -1387,7+1387,7 @@ static struct device *eisa_probe(struct device *dev) ** EtherWORKS devices can exist in EISA space....
*/
mem_chkd |= (0x01 << (i + 24));
- register_iomem(iobase, EWRK3_IOP_INC,"ewrk3");
+ request_region(iobase, EWRK3_IOP_INC,"ewrk3");
if (num_ewrk3s > 0) { /* only gets here in autoprobe */
dev = alloc_device(dev, iobase);
} else {
@@ -178,7+178,7 @@ int hpp_probe1(struct device *dev, int ioaddr) }
/* Grab the region so we can find another board if something fails. */
- register_iomem(ioaddr, HP_IO_EXTENT,"hp-plus");
+ request_region(ioaddr, HP_IO_EXTENT,"hp-plus");
/* Read the IRQ line. */
outw(HW_Page, ioaddr + HP_PAGING);
@@ -125,7+125,7 @@ int hp_probe1(struct device *dev, int ioaddr) dev = init_etherdev(0, sizeof(struct ei_device), 0);
/* Grab the region so we can find another board if something fails. */
- register_iomem(ioaddr, HP_IO_EXTENT,"hp");
+ request_region(ioaddr, HP_IO_EXTENT,"hp");
printk("%s: %s (ID %02x) at %#3x,", dev->name, name, board_id, ioaddr);
@@ -365,7+365,7 @@ unsigned long lance_probe1(int ioaddr, unsigned long mem_start) printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
dev->base_addr = ioaddr;
- register_iomem(ioaddr, LANCE_TOTAL_SIZE,"lance");
+ request_region(ioaddr, LANCE_TOTAL_SIZE,"lance");
/* Make certain the data structures used by the LANCE are aligned. */
dev->priv = (void *)(((int)dev->priv + 7) & ~7);
@@ -259,7+259,7 @@ static int ne_probe1(struct device *dev, int ioaddr)
dev->base_addr = ioaddr;
- register_iomem(ioaddr, NE_IO_EXTENT,"ne2000");
+ request_region(ioaddr, NE_IO_EXTENT,"ne2000");
for(i = 0; i < ETHER_ADDR_LEN; i++)
dev->dev_addr[i] = SA_prom[i];
@@ -181,7+181,7 @@ extern void *irq2dev_map[16];
#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 0
-#define register_iomem(ioaddr, size,name); do ; while (0)
+#define request_region(ioaddr, size,name); do ; while (0)
#endif
#define NI52_TOTAL_SIZE 16
@@ -388,7+388,7 @@ static int ni52_probe1(struct device *dev,int ioaddr)
printk("%s: Ni52 found at %#3x, ",dev->name,dev->base_addr);
- register_iomem(ioaddr,NI52_TOTAL_SIZE,"ni52");
+ request_region(ioaddr,NI52_TOTAL_SIZE,"ni52");
dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL);
/* warning: we don't free it on errors */
#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 0
-#define register_iomem(ioaddr, size,name); do ; while (0)
+#define request_region(ioaddr, size,name); do ; while (0)
#endif
#ifndef NET_DEBUG
@@ -243,7+243,7 @@ static int ni65_probe1(struct device *dev,int ioaddr) irq2dev_map[dev->irq] = dev;
/* Grab the region so we can find another board if autoIRQ fails. */
- register_iomem(ioaddr,NI65_TOTAL_SIZE,"ni65");
+ request_region(ioaddr,NI65_TOTAL_SIZE,"ni65");
p = dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL);
memset((char *) dev->priv,0,sizeof(struct priv));
@@ -225,7+225,7 @@ plip_init(struct device *dev) }
}
- register_iomem(PAR_DATA(dev), 3,"plip");
+ request_region(PAR_DATA(dev), 3,"plip");
/* Fill in the generic fields of the device structure. */
ether_setup(dev);
@@ -329,7+329,7 @@ static char *rcsid = "$Id: sk_g16.c,v 1.1 1994/06/30 16:25:15 root Exp $"; #ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 0
-#define register_iomem(ioaddr, size,name); do ; while (0)
+#define request_region(ioaddr, size,name); do ; while (0)
#endif
@@ -782,7+782,7 @@ int SK_probe(struct device *dev, short ioaddr) dev->dev_addr[5]);
/* Grab the I/O Port region */
- register_iomem(ioaddr, ETHERCARD_TOTAL_SIZE,"sk_g16");
+ request_region(ioaddr, ETHERCARD_TOTAL_SIZE,"sk_g16");
/* Initialize device structure */
@@ -247,7+247,7 @@ static int netcard_probe1(struct device *dev, int ioaddr) #endif /* jumpered DMA */
/* Grab the region so we can find another board if autoIRQ fails. */
- register_iomem(ioaddr, NETCARD_IO_EXTENT,"skeleton");
+ request_region(ioaddr, NETCARD_IO_EXTENT,"skeleton");
/* Initialize the device structure. */
if (dev->priv == NULL)
@@ -71,6+71,11 @@ struct slip { unsigned long rx_dropped; /* No memory for skb */
unsigned long tx_dropped; /* When MTU change */
unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */
+#ifdef SL_INCLUDE_CSLIP
+ unsigned long tx_compressed;
+ unsigned long rx_compressed;
+ unsigned long tx_misses;
+#endif
/* Detailed SLIP statistics. */
int mtu; /* Our mtu (to spot changes!) */
@@ -147,7+147,7 @@ int ultra_probe1(struct device *dev, int ioaddr)
/* OK, were are certain this is going to work. Setup the device. */
- register_iomem(ioaddr, 32,"smc-ultra");
+ request_region(ioaddr, 32,"smc-ultra");
/* The 8390 isn't at the base address, so fake the offset */
dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
@@ -235,7+235,7 @@ int wd_probe1(struct device *dev, int ioaddr) }
/* OK, were are certain this is going to work. Setup the device. */
- register_iomem(ioaddr, WD_IO_EXTENT,"wd");
+ request_region(ioaddr, WD_IO_EXTENT,"wd");
ethdev_init(dev);
ei_status.name = model_name;
endif
+modules:
#
# include a dependency file if one exists
@@ -722,7+722,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt) can_disconnect ? "enabled" : "disabled",
can_doparity ? "enabled" : "disabled");
- register_iomem(port_base, TEST-SCSISEQ,"aha152x"); /* Register */
+ request_region(port_base, TEST-SCSISEQ,"aha152x"); /* Register */
/* not expecting any interrupts */
SETPORT(SIMODE0, 0);
@@ -1053,7+1053,7 @@ int aha1542_detect(Scsi_Host_Template * tpnt) aha1542_command(0, cmd, buffer, 512);
}
#endif
- register_iomem(bases[indx], 4,"aha1542"); /* Register the IO ports that we use */
+ request_region(bases[indx], 4,"aha1542"); /* Register the IO ports that we use */
count++;
continue;
unregister:
@@ -471,7+471,7 @@ int aha1740_detect(Scsi_Host_Template * tpnt) printk("Unable to allocate IRQ for adaptec controller.\n");
return 0;
}
- register_iomem(base, 0x5c,"aha1740"); /* Reserve the space that we need to use */
+ request_region(base, 0x5c,"aha1740"); /* Reserve the space that we need to use */
return 1;
}
@@ -1336,7+1336,7 @@ int buslogic_detect(Scsi_Host_Template *tpnt) }
#endif
- register_iomem(bases[indx], 4,"buslogic");
+ request_region(bases[indx], 4,"buslogic");
/* Register the IO ports that we use */
count++;
continue;
@@ -385,7+385,7 @@ static inline int port_detect(ushort *port_base, unsigned int j, sh[j]->cmd_per_lun = MAX_CMD_PER_LUN;
/* Register the I/O space that we use */
- register_iomem(sh[j]->io_port, REG_REGION,"eata");
+ request_region(sh[j]->io_port, REG_REGION,"eata");
memset(HD(j), 0, sizeof(struct hostdata));
HD(j)->subversion = subversion;
@@ -704,7+704,7 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
/* Log I/O ports with kernel */
- register_iomem( port_base, 0x10 ,"fdomain");
+ request_region( port_base, 0x10 ,"fdomain");
if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
adapter_mask = 0x80;
*/
/* Changes for 1.1.43+ kernels made 8/25/94, code added to check for
* new BIOS version, derived by jshiffle@netcom.com. (WDE)
+ *
+ * 1/7/95 Fix from Peter Lu (swift@world.std.com) for datalen vs. dataptr
+ * logic, much more stable under load.
*/
#include <linux/kernel.h>
@@ -195,10+198,9 @@ static void in2000_fifo_out(void) /* uses FIFOCNTR */ #endif
} while((in2000_datalen > 0) && ((infcnt = (inb(INFCNT)) & 0xfe) >= 0x20) );
/* If scatter-gather, go on to next segment */
- if( !in2000_datalen && in2000_current_segment < in2000_nsegment)
+ if( !in2000_datalen && ++in2000_current_segment < in2000_nsegment)
{
in2000_scatter++;
- in2000_current_segment++;
in2000_datalen = in2000_scatter->length;
in2000_dataptr = (unsigned short*)in2000_scatter->address;
}
@@ -253,10+255,9 @@ DEB(printk("FIr:%d %02x %08x %08x\n", in2000_datalen,fic,count2,(unsigned int)in DEB(printk("FIer:%d %02x %08x\n", in2000_datalen,fic,(unsigned int )in2000_dataptr));
/* while ( count-- )
inw(INFIFO);*/ /* Throw away some extra stuff */
- if( !in2000_datalen && in2000_current_segment < in2000_nsegment)
+ if( !in2000_datalen && ++in2000_current_segment < in2000_nsegment)
{
in2000_scatter++;
- in2000_current_segment++;
in2000_datalen = in2000_scatter->length;
in2000_dataptr = (unsigned short*)in2000_scatter->address;
}
@@ -288,13+289,16 @@ static void in2000_intr_handle(int foo) scsistatus,cmdphase,scsibyte));
/* Why do we assume that we need to send more data here??? ERY */
- if ( in2000_datalen && in2000_dataptr ) /* data xfer pending */
+ if ( in2000_datalen ) /* data xfer pending */
{
- if ( in2000_datawrite )
+ if ( in2000_dataptr == NULL )
+ printk("int2000: dataptr=NULL datalen=%d\n",
+ in2000_datalen);
+ else if ( in2000_datawrite )
in2000_fifo_out();
else
in2000_fifo_in();
- } else ficmsk = 0;
+ }
if ( (auxstatus & 0x8c) == 0x80 )
{ /* There is a WD Chip interrupt & register read good */
outb(2,ININTR); /* Disable fifo interrupts */
@@ -630,7+634,7 @@ int in2000_detect(Scsi_Host_Template * tpnt) shpnt->io_port = base;
shpnt->n_io_port = 12;
shpnt->irq = irq_level;
- register_iomem(base, 12,"in2000"); /* Prevent other drivers from using this space */
+ request_region(base, 12,"in2000"); /* Prevent other drivers from using this space */
return 1;
}
@@ -527,7+527,7 @@ struct Scsi_Host *hreg; /* registered host structure */ host->can_queue = 1;
sti();
#endif
- register_iomem( qbase , 0x10 ,"qlogic");
+ request_region( qbase , 0x10 ,"qlogic");
hreg = scsi_register( host , 0 ); /* no host data */
hreg->io_port = qbase;
@@ -352,7+352,7 @@ 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 */
- register_iomem(sh[j]->io_port, REG_REGION,"u14-34f");
+ request_region(sh[j]->io_port, REG_REGION,"u14-34f");
memset(HD(j), 0, sizeof(struct hostdata));
HD(j)->heads = mapping_table[config_2.mapping_mode].heads;
@@ -438,7+438,7 @@ static int ultrastor_14f_detect(Scsi_Host_Template * tpnt) /* All above tests passed, must be the right thing. Get some useful
info. */
- register_iomem(config.port_address, 0x0c,"ultrastor");
+ request_region(config.port_address, 0x0c,"ultrastor");
/* Register the I/O space that we use */
*(char *)&config_1 = inb(CONFIG(config.port_address + 0));
@@ -30,7+30,7 @@ int ultrastor_biosparam(Disk *, int, int *);
#define ULTRASTOR_14F { NULL, NULL, /* Ptr for modules*/ \
- NULL, \
+ "UltraStor 14F/24F/34F", \
ultrastor_detect, \
NULL, /* Release */ \
ultrastor_info, \
@@ -1162,7+1162,7 @@ int wd7000_detect(Scsi_Host_Template * tpnt) printk("using IO %xh IRQ %d DMA %d.\n",
host->iobase, host->irq, host->dma);
- register_iomem(host->iobase, 4,"wd7000"); /* Register our ports */
+ request_region(host->iobase, 4,"wd7000"); /* Register our ports */
/*
* For boards before rev 6.0, scatter/gather isn't supported.
*/
ifdef CONFIG_NFS_FS
FS_SUBDIRS := $(FS_SUBDIRS) nfs
+else
+MODULE_FS_SUBDIRS := $(MODULE_FS_SUBDIRS) nfs
endif
ifdef CONFIG_XIA_FS
@@ -93,8+95,10 @@ filesystems.a: dummy test ! -d $$i || \
{ $(MAKE) -C $$i; $(AR) rcs filesystems.a $$i/$$i.o; }; done
-modules:
- set -e; for i in $(MODULE_FS_SUBDIRS); do $(MAKE) -C $$i modules; done
+modules: $(MODULE_OBJS)
+ for i in $(MODULE_FS_SUBDIRS); do $(MAKE) -C $$i modules; done
+ cd ../modules;for i in $(MODULE_OBJS); do ln -sf ../fs/$$i .; done
+ cd ../modules;for i in $(MODULE_FS_SUBDIRS); do ln -sf ../fs/$$i/$$i.o .; done
depend dep:
$(CPP) -M *.c > .depend
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-ifndef CONFIG_ISO9660_FS
-CFLAGS := $(CFLAGS) -DMODULE
-endif
-
.c.s:
$(CC) $(CFLAGS) -S $<
.c.o:
@@ -251,7+251,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
brelse(bh);
}
- if(iso_blknum == 100) {
+ if(iso_blknum == vol_desc_start + 100) {
if (!silent)
printk("Unable to identify CD-ROM format.\n");
s->s_dev = 0;
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-ifndef CONFIG_MINIX_FS
-CFLAGS := $(CFLAGS) -DMODULE
-endif
-
.c.s:
$(CC) $(CFLAGS) -S $<
.c.o:
@@ -27,6+23,8 @@ minix.o: $(OBJS) dep:
$(CPP) -M *.c > .depend
+modules: minix.o
+
#
# include a dependency file if one exists
#
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-ifndef CONFIG_MSDOS_FS
-CFLAGS := $(CFLAGS) -DMODULE
-endif
-
.c.s:
$(CC) $(CFLAGS) -S $<
.c.o:
@@ -23,6+23,8 @@ nfs.o: $(OBJS) dep:
$(CPP) -M *.c > .depend
+modules: nfs.o
+
#
# include a dependency file if one exists
#
*
* Alessandro Rubini : profile extension.
* <rubini@ipvvis.unipv.it>
+ *
+ * Jeff Tranter : added BogoMips field to cpuinfo
+ * <Jeff_Tranter@Mitel.COM>
*/
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/ioport.h>
#include <linux/config.h>
+#include <linux/delay.h>
#include <asm/segment.h>
#include <asm/io.h>
@@ -262,6+266,7 @@ static int get_version(char * buffer)
static int get_cpuinfo(char * buffer)
{
+#ifdef __i386__
char *model[2][9]={{"DX","SX","DX/2","4","SX/2","6",
"7","DX/4"},
{"Pentium 60/66","Pentium 90/100","3",
@@ -284,7+289,8 @@ static int get_cpuinfo(char * buffer) "TS Counters\t: %s\n"
"Pentium MSR\t: %s\n"
"Mach. Ch. Exep.\t: %s\n"
- "CMPXCHGB8B\t: %s\n",
+ "CMPXCHGB8B\t: %s\n"
+ "BogoMips\t: %lu.%02lu\n",
x86+'0',
x86_model ? model[x86-4][x86_model-1] : "Unknown",
x86_mask ? mask : "Unknown",
@@ -300,8+306,12 @@ static int get_cpuinfo(char * buffer) x86_capability & 16 ? "yes" : "no",
x86_capability & 32 ? "yes" : "no",
x86_capability & 128 ? "yes" : "no",
- x86_capability & 256 ? "yes" : "no"
+ x86_capability & 256 ? "yes" : "no",
+ loops_per_sec/500000, (loops_per_sec/5000) % 100
);
+#else
+ return 0;
+#endif
}
static struct task_struct ** get_task(pid_t pid)
@@ -388,6+398,7 @@ static int get_arg(int pid, char * buffer)
static unsigned long get_wchan(struct task_struct *p)
{
+#ifdef __i386__
unsigned long ebp, eip;
unsigned long stack_page;
int count = 0;
@@ -407,6+418,7 @@ static unsigned long get_wchan(struct task_struct *p) return eip;
ebp = *(unsigned long *) ebp;
} while (count++ < 16);
+#endif
return 0;
}
@@ -438,7+450,7 @@ static int get_stat(int pid, char * buffer) }
wchan = get_wchan(*p);
for(i=0; i<32; ++i) {
- switch((int) (*p)->sigaction[i].sa_handler) {
+ switch((unsigned long) (*p)->sigaction[i].sa_handler) {
case 1: sigignore |= bit; break;
case 0: break;
default: sigcatch |= bit;
@@ -170,6+170,7 @@ static int proc_lookupnet(struct inode * dir,const char * name, int len, return -ENOENT;
return 0;
}
+ iput(dir);
return -ENOENT;
}
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-ifndef CONFIG_SYSV_FS
-CFLAGS := $(CFLAGS) -DMODULE
-endif
-
.c.s:
$(CC) $(CFLAGS) -S $<
.c.o:
@@ -334,7+334,6 @@ static struct super_block * detected_coherent (struct super_block *sb, struct bu sb->sv_sb_flc_blocks = &sbd->s_free[0];
sb->sv_sb_total_free_blocks = &sbd->s_tfree;
sb->sv_sb_time = &sbd->s_time;
- sb->sv_sb_state = &sbd->s_state;
sb->sv_block_base = 0;
sb->sv_firstinodezone = 2;
sb->sv_firstdatazone = sbd->s_isize;
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-ifndef CONFIG_UMSDOS_FS
-CFLAGS := $(CFLAGS) -DMODULE
-endif
-
.c.s:
$(CC) $(CFLAGS) -S $<
.c.o:
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-ifndef CONFIG_XIA_FS
-CFLAGS := $(CFLAGS) -DMODULE
-endif
-
.c.s:
$(CC) $(CFLAGS) -S $<
.c.o:
@@ -24,7+24,7 @@ extern int EISA_bus; struct thread_struct {
unsigned long ksp;
unsigned long usp;
- unsigned long cr3; /* ptbr */
+ unsigned long ptbr;
unsigned int pcc;
unsigned int asn;
unsigned long unique;
@@ -122,7+122,7 @@ __asm__ __volatile__( return __res;
}
-extern inline char * strchr(const char * s,char c)
+extern inline char * strchr(const char * s, int c)
{
register char * __res;
__asm__ __volatile__(
@@ -140,7+140,7 @@ __asm__ __volatile__( return __res;
}
-extern inline char * strrchr(const char * s,char c)
+extern inline char * strrchr(const char * s, int c)
{
register char * __res;
__asm__ __volatile__(
@@ -392,7+392,7 @@ __asm__("cld\n\t" \ case 0: COMMON(""); return to;
case 1: COMMON("\n\tmovsb"); return to;
case 2: COMMON("\n\tmovsw"); return to;
- case 3: COMMON("\n\tmovsw\n\tstosb"); return to;
+ case 3: COMMON("\n\tmovsw\n\tmovsb"); return to;
}
#undef COMMON
}
@@ -442,7+442,7 @@ __asm__ __volatile__( return __res;
}
-extern inline void * memchr(const void * cs,char c,size_t count)
+extern inline void * memchr(const void * cs,int c,size_t count)
{
register void * __res;
if (!count)
@@ -459,7+459,7 @@ __asm__ __volatile__( return __res;
}
-extern inline void * __memset_generic(void * s,char c,size_t count)
+extern inline void * __memset_generic(void * s, char c,size_t count)
{
__asm__ __volatile__(
"cld\n\t"
@@ -533,7+533,7 @@ __asm__("cld\n\t" \ /*
* find the first occurrence of byte 'c', or 1 past the area if none
*/
-extern inline void * memscan(void * addr, unsigned char c, size_t size)
+extern inline void * memscan(void * addr, int c, size_t size)
{
if (!size)
return addr;
#define TRAP_ENTRY_INTERRUPT_NMI(t_type, jmp_to) \
mov t_type, %l3; b jmp_to; mov %psr, %l0; nop;
+/* Trap entry code in entry.S needs the offsets into task_struct
+ * to get at the thread_struct goodies during window craziness.
+ *
+ * NOTE: We need to keep these values under 0x3ff in order to do
+ * efficient load/stores in the window fill/spill handlers.
+ * See TRAP_WIN_CLEAN in entry.S for details.
+ */
+
+#define THREAD_UWINDOWS 0x3a8
+#define THREAD_WIM 0x3ac
+#define THREAD_W_SAVED 0x3b0
+#define THREAD_KSP 0x3b4
+#define THREAD_USP 0x3b8
+#define THREAD_REG_WINDOW 0x3c0
#endif __SPARC_HEAD_H
@@ -25,16+25,25 @@ extern int EISA_bus; */
#define IO_BITMAP_SIZE 32
+/* The first five entries here MUST be the first four. This allows me to
+ * do %lo(offset) loads and stores in entry.S. See TRAP_WIN_CLEAN to see
+ * why.
+ */
+
struct thread_struct {
+ unsigned long uwindows; /* how many user windows are in the set */
+ unsigned long wim; /* user's window invalid mask */
+ unsigned long w_saved; /* how many windows saved in reg_window[] */
unsigned long ksp; /* kernel stack pointer */
unsigned long usp; /* user's sp, throw reg windows here */
+ unsigned long psr; /* save for condition codes */
+ unsigned long reg_window[16*24];
unsigned long cr3; /* why changed from ptbr? */
unsigned int pcc;
unsigned int asn;
unsigned long unique;
unsigned long flags;
unsigned long res1, res2;
- unsigned long psr; /* save for condition codes */
unsigned long pc; /* program counter */
unsigned long npc; /* next program counter */
@@ -44,9+53,7 @@ struct thread_struct { * in nwindows.
*/
unsigned long globl_regs[8]; /* global regs need to be saved too */
- unsigned long reg_window[16*24];
unsigned long yreg;
- unsigned long uwindows; /* how many user windows are in the set */
unsigned long float_regs[64]; /* V8 and below have 32, V9 has 64 */
};
@@ -77,13+84,30 @@ struct thread_struct { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
- 0, 0, \
+ 0, 0, 0, 0, \
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
}
+/* The thread_frame is what needs to be set up in certain circumstances
+ * upon entry to a trap. It is also loaded sometimes during a window
+ * spill if things don't go right (bad user stack pointer). In reality
+ * it is not per-process per se, it just sits in the kernel stack while
+ * the current process is in a handler then it is basically forgotten
+ * about.
+ */
+
+struct thread_frame {
+ unsigned int thr_psr;
+ unsigned int thr_pc;
+ unsigned int thr_npc;
+ unsigned int thr_y;
+ unsigned int thr_globals[8];
+ unsigned int thr_outs[8];
+};
+
/*
* These are the "cli()" and "sti()" for software interrupts
* They work by increasing/decreasing the "intr_count" value,
extern void reserve_setup(char *str, int *ints);
extern int check_region(unsigned int from, unsigned int extent);
extern void snarf_region(unsigned int from, unsigned int extent);
-extern void register_iomem(unsigned int from, unsigned int extent,char* name);
+extern void request_region(unsigned int from, unsigned int extent,const char *name);
extern void release_region(unsigned int from, unsigned int extent);
extern int get_ioport_list(char *);
* Note the 8-bit gid and atime and ctime.
*/
struct minix_inode {
- u16 i_mode;
- u16 i_uid;
- u32 i_size;
- u32 i_time;
- u8 i_gid;
- u8 i_nlinks;
- u16 i_zone[9];
+ __u16 i_mode;
+ __u16 i_uid;
+ __u32 i_size;
+ __u32 i_time;
+ __u8 i_gid;
+ __u8 i_nlinks;
+ __u16 i_zone[9];
};
/*
@@ -48,34+48,34 @@ struct minix_inode { * now 16-bit. The inode is now 64 bytes instead of 32.
*/
struct new_minix_inode {
- u16 i_mode;
- u16 i_nlinks;
- u16 i_uid;
- u16 i_gid;
- u32 i_size;
- u32 i_atime;
- u32 i_mtime;
- u32 i_ctime;
- u32 i_zone[10];
+ __u16 i_mode;
+ __u16 i_nlinks;
+ __u16 i_uid;
+ __u16 i_gid;
+ __u32 i_size;
+ __u32 i_atime;
+ __u32 i_mtime;
+ __u32 i_ctime;
+ __u32 i_zone[10];
};
/*
* minix super-block data on disk
*/
struct minix_super_block {
- u16 s_ninodes;
- u16 s_nzones;
- u16 s_imap_blocks;
- u16 s_zmap_blocks;
- u16 s_firstdatazone;
- u16 s_log_zone_size;
- u32 s_max_size;
- u16 s_magic;
- u16 s_state;
+ __u16 s_ninodes;
+ __u16 s_nzones;
+ __u16 s_imap_blocks;
+ __u16 s_zmap_blocks;
+ __u16 s_firstdatazone;
+ __u16 s_log_zone_size;
+ __u32 s_max_size;
+ __u16 s_magic;
+ __u16 s_state;
};
struct minix_dir_entry {
- u16 inode;
+ __u16 inode;
char name[0];
};
* minix fs inode data in memory
*/
struct minix_inode_info {
- u16 i_data[16];
+ __u16 i_data[16];
};
#endif
@@ -233,8+233,9 @@ struct pci_class_type { #define PCI_DEVICE_ID_ATI_M32 0x4158
#define PCI_DEVICE_ID_ATI_M64 0x4758
-#define PCI_VENDOR_ID_DIAMOND 0x100e
-#define PCI_DEVICE_ID_DIAMOND_VIPER 0x9001
+#define PCI_VENDOR_ID_WEITEK 0x100e
+#define PCI_DEVICE_ID_WEITEK_P9000 0x9001
+#define PCI_DEVICE_ID_WEITEK_P9100 0x9100
#define PCI_VENDOR_ID_CIRRUS 0x1013
#define PCI_DEVICE_ID_CIRRUS_5434 0x00A4
@@ -251,13+252,16 @@ struct pci_class_type { #define PCI_VENDOR_ID_TSENG 0x100c
#define PCI_DEVICE_ID_TSENG_W32P 0x3205
+#define PCI_VENDOR_ID_CMD 0x1095
+#define PCI_DEVICE_ID_CMD_640 0x0640
+
struct pci_vendor_type {
unsigned short vendor_id;
char *vendor_name;
};
-#define PCI_VENDOR_NUM 16
+#define PCI_VENDOR_NUM 17
#define PCI_VENDOR_TYPE { \
{PCI_VENDOR_ID_NCR, "NCR"}, \
{PCI_VENDOR_ID_ADAPTEC, "Adaptec"}, \
@@ -269,13+273,14 @@ struct pci_vendor_type { {PCI_VENDOR_ID_INTEL, "Intel"}, \
{PCI_VENDOR_ID_SMC, "SMC"}, \
{PCI_VENDOR_ID_ATI, "ATI"}, \
- {PCI_VENDOR_ID_DIAMOND, "Diamond"}, \
+ {PCI_VENDOR_ID_WEITEK, "Weitek"}, \
{PCI_VENDOR_ID_CIRRUS, "Cirrus Logic"}, \
{PCI_VENDOR_ID_BUSLOGIC, "Bus Logic"}, \
{PCI_VENDOR_ID_N9, "Number #9"}, \
{PCI_VENDOR_ID_ALI, "ALI"}, \
{PCI_VENDOR_ID_TSENG, "Tseng'Lab"}, \
- {0, "Unknown vendor"} \
+ {PCI_VENDOR_ID_CMD, "CMD"}, \
+ {0, ""} \
}
struct pci_device_type {
@@ -284,7+289,7 @@ struct pci_device_type { char *device_name;
};
-#define PCI_DEVICE_NUM 31
+#define PCI_DEVICE_NUM 33
#define PCI_DEVICE_TYPE { \
{PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, "53c810"}, \
{PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C815, "53c815"}, \
@@ -311,12+316,14 @@ struct pci_device_type { {PCI_VENDOR_ID_SMC, PCI_DEVICE_ID_SMC_37C665, "FDC 37C665"}, \
{PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_M32, "Mach 32"}, \
{PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_M64, "Mach 64"}, \
- {PCI_VENDOR_ID_DIAMOND, PCI_DEVICE_ID_DIAMOND_VIPER, "Viper"}, \
+ {PCI_VENDOR_ID_WEITEK, PCI_DEVICE_ID_WEITEK_P9000, "P9000"}, \
+ {PCI_VENDOR_ID_WEITEK, PCI_DEVICE_ID_WEITEK_P9100, "P9100"}, \
{PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5434, "GD 5434"}, \
{PCI_VENDOR_ID_BUSLOGIC,PCI_DEVICE_ID_BUSLOGIC_946C, "946C"}, \
{PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128, "Imagine 128"}, \
{PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_M1435, "M1435"}, \
- {PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_TSENG_W32P, "ET4000W32P"}, \
+ {PCI_VENDOR_ID_TSENG, PCI_DEVICE_ID_TSENG_W32P, "ET4000W32P"}, \
+ {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640, "640A"}, \
{0,0,"UNKNOWN DEVICE.PLEASE FIND OUT AND MAIL POTTER@CAO-VLSI.IBP.FR"} \
}
@@ -16,7+16,7 @@ extern char * strcpy(char *,const char *); extern char * strncpy(char *,const char *,size_t);
extern char * strcat(char *, const char *);
extern char * strncat(char *, const char *, size_t);
-extern char * strchr(const char *,char);
+extern char * strchr(const char *,int);
extern char * strpbrk(const char *,const char *);
extern char * strtok(char *,const char *);
extern char * strstr(const char *,const char *);
@@ -25,10+25,10 @@ extern size_t strspn(const char *,const char *); extern int strcmp(const char *,const char *);
extern int strncmp(const char *,const char *,size_t);
-extern void * memset(void *,char,size_t);
+extern void * memset(void *,int,size_t);
extern void * memcpy(void *,const void *,size_t);
extern void * memmove(void *,const void *,size_t);
-extern void * memscan(void *, unsigned char, size_t);
+extern void * memscan(void *,int,size_t);
extern int memcmp(const void *,const void *,size_t);
/*
@@ -247,7+247,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */ X(kfree_skb),
X(dev_kfree_skb),
X(snarf_region),
- X(register_iomem),
+ X(request_region),
X(release_region),
X(netif_rx),
X(dev_rint),
@@ -117,9+117,11 @@ asmlinkage unsigned long sys_signal(int signum, void (*handler)(int)) return -EINVAL;
if (signum==SIGKILL || signum==SIGSTOP)
return -EINVAL;
- err = verify_area(VERIFY_READ, handler, 1);
- if (err)
- return err;
+ if (handler != SIG_DFL && handler != SIG_IGN) {
+ err = verify_area(VERIFY_READ, handler, 1);
+ if (err)
+ return err;
+ }
tmp.sa_handler = handler;
tmp.sa_mask = 0;
tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
@@ -151,9+153,11 @@ asmlinkage int sys_sigaction(int signum, const struct sigaction * action, new_sa.sa_mask |= _S(signum);
new_sa.sa_mask &= _BLOCKABLE;
}
- err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
- if (err)
- return err;
+ if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
+ err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
+ if (err)
+ return err;
+ }
}
if (oldaction) {
int err = verify_area(VERIFY_WRITE, oldaction, sizeof(*oldaction));
@@ -137,8+137,8 @@ for (order = 0;BLOCKSIZE(order);order++) AREASIZE(order))
{
printk ("Cannot use %d bytes out of %d in order = %d block mallocs\n",
- NBLOCKS (order) * BLOCKSIZE(order) +
- sizeof (struct page_descriptor),
+ (int) (NBLOCKS (order) * BLOCKSIZE(order) +
+ sizeof (struct page_descriptor)),
(int) AREASIZE(order),
BLOCKSIZE (order));
panic ("This only happens if someone messes with kmalloc");
@@ -185,7+185,7 @@ void * kmalloc (size_t size, int priority) order = get_order (size);
if (order < 0)
{
- printk ("kmalloc of too large a block (%d bytes).\n",size);
+ printk ("kmalloc of too large a block (%d bytes).\n",(int) size);
return (NULL);
}
@@ -288,7+288,7 @@ printk ("Hey. This is very funny. I tried %d times to allocate a whole\n" "the author of this kmalloc: wolff@dutecai.et.tudelft.nl.\n"
"(Executive summary: This can't happen)\n",
MAX_GET_FREE_PAGE_TRIES,
- size);
+ (int) size);
return NULL;
}
@@ -738,6+738,10 @@ static int inet_release(struct socket *sock, struct socket *peer)
/* Start closing the connection. This may take a while. */
+#ifdef CONFIG_IP_MULTICAST
+ /* Applications forget to leave groups before exiting */
+ ip_mc_drop_socket(sk);
+#endif
/*
* If linger is set, we don't return until the close
* is complete. Other wise we return immediately. The
@@ -109,7+109,7 @@ void dev_mc_delete(struct device *dev, void *addr, int alen, int all) if(memcmp((*dmi)->dmi_addr,addr,(*dmi)->dmi_addrlen)==0 && alen==(*dmi)->dmi_addrlen)
{
struct dev_mc_list *tmp= *dmi;
- if((*dmi)->dmi_users-- && !all)
+ if(--(*dmi)->dmi_users && !all)
return;
*dmi=(*dmi)->next;
dev->mc_count--;
@@ -128,12+128,6 @@ struct ip_mib ip_statistics={1,64,}; /* Forwarding=Yes, Default TTL=64 */ struct ip_mib ip_statistics={0,64,}; /* Forwarding=No, Default TTL=64 */
#endif
-#ifdef CONFIG_IP_MULTICAST
-
-struct ip_mc_list *ip_mc_head=NULL;
-
-#endif
-
/*
* Handle the issuing of an ioctl() request
* for the ip device. This is scheduled to
@@ -2020,26+2014,34 @@ int ip_mc_procinfo(char *buffer, char **start, off_t offset, int length) struct ip_mc_list *im;
unsigned long flags;
int len=0;
+ struct device *dev;
-
- len=sprintf(buffer,"Device : Multicast\n");
+ len=sprintf(buffer,"Device : Count\tGroup Users Timer\n");
save_flags(flags);
cli();
- im=ip_mc_head;
-
- while(im!=NULL)
+ for(dev = dev_base; dev; dev = dev->next)
{
- len+=sprintf(buffer+len,"%-10s: %08lX\n", im->interface->name, im->multiaddr);
- pos=begin+len;
- if(pos<offset)
- {
- len=0;
- begin=pos;
- }
- if(pos>offset+length)
- break;
- im=im->next;
+ if((dev->flags&IFF_UP)&&(dev->flags&IFF_MULTICAST))
+ {
+ len+=sprintf(buffer+len,"%-10s: %5d\n",
+ dev->name, dev->mc_count);
+ for(im = dev->ip_mc_list; im; im = im->next)
+ {
+ len+=sprintf(buffer+len,
+ "\t\t\t%08lX %5d %d:%08lX\n",
+ im->multiaddr, im->users,
+ im->tm_running, im->timer.expires);
+ pos=begin+len;
+ if(pos<offset)
+ {
+ len=0;
+ begin=pos;
+ }
+ if(pos>offset+length)
+ break;
+ }
+ }
}
restore_flags(flags);
*start=buffer+(offset-begin);
@@ -640,7+640,7 @@ static void retransmit_timer(unsigned long data) * this reset_timer() call is a hack, this is not
* how KEEPOPEN is supposed to work.
*/
- reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
+ reset_xmit_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
/* Send something to keep the connection open. */
if (sk->prot->write_wakeup)