Commit d392db36 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.3.32

parent 89eabf14
...@@ -211,6 +211,15 @@ S: Northampton ...@@ -211,6 +211,15 @@ S: Northampton
S: NN1 3QT S: NN1 3QT
S: United Kingdom S: United Kingdom
N: Ray Dassen
E: jdassen@wi.LeidenUniv.nl
U: http://www.wi.leidenuniv.nl/~jdassen/
D: Debian GNU/Linux: www.debian.org maintainer, FAQ co-maintainer,
D: packages testing, nit-picking & fixing. Enjoying BugFree (TM) kernels.
S: Zuidsingel 10A
S: 2312 SB Leiden
S: The Netherlands
N: Wayne Davison N: Wayne Davison
E: davison@borland.com E: davison@borland.com
D: Second extended file system co-designer D: Second extended file system co-designer
...@@ -621,7 +630,6 @@ S: Fairfax, Virginia 22033 ...@@ -621,7 +630,6 @@ S: Fairfax, Virginia 22033
S: USA S: USA
N: William (Bill) Metzenthen N: William (Bill) Metzenthen
E: billm@vaxc.cc.monash.edu.au
E: billm@jacobi.maths.monash.edu.au E: billm@jacobi.maths.monash.edu.au
D: Author of the FPU emulator. D: Author of the FPU emulator.
D: Minor kernel hacker for other lost causes (Hercules mono, etc). D: Minor kernel hacker for other lost causes (Hercules mono, etc).
......
VERSION = 1 VERSION = 1
PATCHLEVEL = 3 PATCHLEVEL = 3
SUBLEVEL = 31 SUBLEVEL = 32
ARCH = i386 ARCH = i386
......
...@@ -424,18 +424,17 @@ int apecs_pci_clr_err(void) ...@@ -424,18 +424,17 @@ int apecs_pci_clr_err(void)
void apecs_machine_check(unsigned long vector, unsigned long la_ptr, void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs) struct pt_regs * regs)
{ {
struct el_common_logout_header *mchk_header; struct el_common *mchk_header;
struct el_apecs_sysdata_mcheck *mchk_sysdata; struct el_apecs_sysdata_mcheck *mchk_sysdata;
mchk_header = (struct el_common_logout_header *)la_ptr; mchk_header = (struct el_common *)la_ptr;
mchk_sysdata = mchk_sysdata =
(struct el_apecs_sysdata_mcheck *)(la_ptr + mchk_header->elfl_sysoffset); (struct el_apecs_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset);
DBG(("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n", vector, la_ptr)); DBG(("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n", vector, la_ptr));
DBG((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", DBG((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset, regs->pc, mchk_header->size, mchk_header->proc_offset, mchk_header->sys_offset));
mchk_header->elfl_sysoffset));
DBG(("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", DBG(("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
apecs_mcheck_expected, mchk_sysdata->epic_dcsr, mchk_sysdata->epic_pear)); apecs_mcheck_expected, mchk_sysdata->epic_dcsr, mchk_sysdata->epic_pear));
#ifdef DEBUG #ifdef DEBUG
...@@ -443,7 +442,7 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr, ...@@ -443,7 +442,7 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
int i; int i;
ptr = (unsigned long *)la_ptr; ptr = (unsigned long *)la_ptr;
for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) { for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
printk(" +%x %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); printk(" +%x %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
} }
#endif /* DEBUG */ #endif /* DEBUG */
......
...@@ -310,17 +310,17 @@ int pcibios_find_device (unsigned short vendor, unsigned short device_id, ...@@ -310,17 +310,17 @@ int pcibios_find_device (unsigned short vendor, unsigned short device_id,
unsigned short index, unsigned char *bus, unsigned short index, unsigned char *bus,
unsigned char *devfn) unsigned char *devfn)
{ {
unsigned int current = 0; unsigned int curr = 0;
struct pci_dev *dev; struct pci_dev *dev;
for (dev = pci_devices; dev; dev = dev->next) { for (dev = pci_devices; dev; dev = dev->next) {
if (dev->vendor == vendor && dev->device == device_id) { if (dev->vendor == vendor && dev->device == device_id) {
if (current == index) { if (curr == index) {
*devfn = dev->devfn; *devfn = dev->devfn;
*bus = dev->bus->number; *bus = dev->bus->number;
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
++current; ++curr;
} }
} }
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
...@@ -334,17 +334,17 @@ int pcibios_find_device (unsigned short vendor, unsigned short device_id, ...@@ -334,17 +334,17 @@ int pcibios_find_device (unsigned short vendor, unsigned short device_id,
int pcibios_find_class (unsigned int class_code, unsigned short index, int pcibios_find_class (unsigned int class_code, unsigned short index,
unsigned char *bus, unsigned char *devfn) unsigned char *bus, unsigned char *devfn)
{ {
unsigned int current = 0; unsigned int curr = 0;
struct pci_dev *dev; struct pci_dev *dev;
for (dev = pci_devices; dev; dev = dev->next) { for (dev = pci_devices; dev; dev = dev->next) {
if (dev->class == class_code) { if (dev->class == class_code) {
if (current == index) { if (curr == index) {
*devfn = dev->devfn; *devfn = dev->devfn;
*bus = dev->bus->number; *bus = dev->bus->number;
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
++current; ++curr;
} }
} }
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
......
...@@ -478,7 +478,7 @@ ret_from_sys_call: ...@@ -478,7 +478,7 @@ ret_from_sys_call:
beq $0,restore_all beq $0,restore_all
ret_from_reschedule: ret_from_reschedule:
lda $0,need_resched lda $0,need_resched
lda $1,current lda $1,current_set
ldl $2,0($0) ldl $2,0($0)
lda $4,init_task lda $4,init_task
ldq $3,0($1) ldq $3,0($1)
......
...@@ -23,6 +23,29 @@ ...@@ -23,6 +23,29 @@
#define vulp volatile unsigned long * #define vulp volatile unsigned long *
/*
* Machine check reasons. Defined according to PALcode sources
* (osf.h and platform.h).
*/
#define MCHK_K_TPERR 0x0080
#define MCHK_K_TCPERR 0x0082
#define MCHK_K_HERR 0x0084
#define MCHK_K_ECC_C 0x0086
#define MCHK_K_ECC_NC 0x0088
#define MCHK_K_UNKNOWN 0x008A
#define MCHK_K_CACKSOFT 0x008C
#define MCHK_K_BUGCHECK 0x008E
#define MCHK_K_OS_BUGCHECK 0x0090
#define MCHK_K_DCPERR 0x0092
#define MCHK_K_ICPERR 0x0094
/*
* Platform-specific machine-check reasons:
*/
#define MCHK_K_SIO_SERR 0x204 /* all platforms so far */
#define MCHK_K_SIO_IOCHK 0x206 /* all platforms so far */
#define MCHK_K_DCSR 0x208 /* all but Noname */
/* /*
* Given a bus, device, and function number, compute resulting * Given a bus, device, and function number, compute resulting
* configuration space address and setup the LCA_IOC_CONF register * configuration space address and setup the LCA_IOC_CONF register
...@@ -280,19 +303,60 @@ unsigned long lca_init(unsigned long mem_start, unsigned long mem_end) ...@@ -280,19 +303,60 @@ unsigned long lca_init(unsigned long mem_start, unsigned long mem_end)
} }
void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *regs) void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *regs)
{ {
unsigned long mces; const char * reason;
union el_lca el;
mces = rdmces();
wrmces(mces); /* reset machine check asap */ printk("lca: machine check (la=0x%lx)\n", la);
printk("Machine check (la=0x%lx,mces=0x%lx)\n", la, mces); el.c = (struct el_common *) la;
printk("esr=%lx, ear=%lx, ioc_stat0=%lx, ioc_stat1=%lx\n", /*
*(unsigned long*)LCA_MEM_ESR, *(unsigned long*)LCA_MEM_EAR, * The first quadword after the common header always seems to
*(unsigned long*)LCA_IOC_STAT0, *(unsigned long*)LCA_IOC_STAT1); * be the machine check reason---don't know why this isn't
#ifdef CONFIG_ALPHA_NONAME * part of the common header instead.
printk("NMMI status & control (0x61)=%02x\n", inb(0x61)); */
#endif switch (el.s->reason) {
case MCHK_K_TPERR: reason = "tag parity error"; break;
case MCHK_K_TCPERR: reason = "tag something parity error"; break;
case MCHK_K_HERR: reason = "access to non-existent memory"; break;
case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break;
case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break; /* what's this? */
case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break;
case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break;
case MCHK_K_DCPERR: reason = "d-cache parity error"; break;
case MCHK_K_ICPERR: reason = "i-cache parity error"; break;
case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on on PCI bus"; break;
case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break;
case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break;
case MCHK_K_UNKNOWN:
default: reason = "reason for machine-check unknown"; break;
}
switch (el.c->size) {
case sizeof(struct el_lca_mcheck_short):
printk(" Reason: %s (short frame%s):\n",
reason, el.h->retry ? ", retryable" : "");
printk("\tesr: %lx ear: %lx\n", el.s->esr, el.s->ear);
printk("\tdc_stat: %lx ioc_stat0: %lx ioc_stat1: %lx\n",
el.s->dc_stat, el.s->ioc_stat0, el.s->ioc_stat1);
break;
case sizeof(struct el_lca_mcheck_long):
printk(" Reason: %s (long frame%s):\n",
reason, el.h->retry ? ", retryable" : "");
printk("\treason: %lx exc_addr: %lx dc_stat: %lx\n",
el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
printk("\tesr: %lx ear: %lx car: %lx\n", el.l->esr, el.l->ear, el.l->car);
printk("\tioc_stat0: %lx ioc_stat1: %lx\n", el.l->ioc_stat0, el.l->ioc_stat1);
break;
default:
printk(" Unknown errorlog size %d\n", el.c->size);
}
wrmces(rdmces()); /* reset machine check asap */
} }
#endif /* CONFIG_ALPHA_LCA */ #endif /* CONFIG_ALPHA_LCA */
...@@ -83,6 +83,10 @@ void flush_thread(void) ...@@ -83,6 +83,10 @@ void flush_thread(void)
{ {
} }
void release_thread(struct task_struct *dead_task)
{
}
/* /*
* "alpha_clone()".. By the time we get here, the * "alpha_clone()".. By the time we get here, the
* non-volatile registers have also been saved on the * non-volatile registers have also been saved on the
......
...@@ -17,7 +17,7 @@ if [ "$CONFIG_ST506" = "y" ]; then ...@@ -17,7 +17,7 @@ if [ "$CONFIG_ST506" = "y" ]; then
bool ' Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE y bool ' Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE y
fi fi
if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
bool ' Include support for IDE/ATAPI CDROMs' CONFIG_BLK_DEV_IDECD n bool ' Include support for IDE/ATAPI CDROMs' CONFIG_BLK_DEV_IDECD y
fi fi
fi fi
...@@ -80,7 +80,7 @@ fi ...@@ -80,7 +80,7 @@ fi
comment 'SCSI support' comment 'SCSI support'
tristate 'SCSI support' CONFIG_SCSI y tristate 'SCSI support' CONFIG_SCSI n
if [ "$CONFIG_SCSI" = "n" ]; then if [ "$CONFIG_SCSI" = "n" ]; then
...@@ -101,8 +101,8 @@ bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN n ...@@ -101,8 +101,8 @@ bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN n
comment 'SCSI low-level drivers' comment 'SCSI low-level drivers'
dep_tristate 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X y $CONFIG_SCSI dep_tristate 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X n $CONFIG_SCSI
dep_tristate 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 n $CONFIG_SCSI dep_tristate 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 y $CONFIG_SCSI
dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 n $CONFIG_SCSI dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 n $CONFIG_SCSI
dep_tristate 'Adaptec AHA274X/284X/294X support' CONFIG_SCSI_AIC7XXX n $CONFIG_SCSI dep_tristate 'Adaptec AHA274X/284X/294X support' CONFIG_SCSI_AIC7XXX n $CONFIG_SCSI
dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC n $CONFIG_SCSI dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC n $CONFIG_SCSI
......
...@@ -178,6 +178,10 @@ void flush_thread(void) ...@@ -178,6 +178,10 @@ void flush_thread(void)
current->debugreg[i] = 0; current->debugreg[i] = 0;
} }
void release_thread(struct task_struct *dead_task)
{
}
void copy_thread(int nr, unsigned long clone_flags, unsigned long esp, void copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
struct task_struct * p, struct pt_regs * regs) struct task_struct * p, struct pt_regs * regs)
{ {
......
+---------------------------------------------------------------------------+ +---------------------------------------------------------------------------+
| wm-FPU-emu an FPU emulator for 80386 and 80486SX microprocessors. | | wm-FPU-emu an FPU emulator for 80386 and 80486SX microprocessors. |
| | | |
| Copyright (C) 1992,1993,1994 | | Copyright (C) 1992,1993,1994,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| This program is free software; you can redistribute it and/or modify | | This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License version 2 as | | it under the terms of the GNU General Public License version 2 as |
...@@ -42,13 +42,11 @@ but is very close. See "Limitations" later in this file for a list of ...@@ -42,13 +42,11 @@ but is very close. See "Limitations" later in this file for a list of
some differences. some differences.
Please report bugs, etc to me at: Please report bugs, etc to me at:
billm@vaxc.cc.monash.edu.au
or at:
billm@jacobi.maths.monash.edu.au billm@jacobi.maths.monash.edu.au
--Bill Metzenthen --Bill Metzenthen
August 1994 October 1995
----------------------- Internals of wm-FPU-emu ----------------------- ----------------------- Internals of wm-FPU-emu -----------------------
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
| | | |
| Division subroutine for 96 bit quantities | | Division subroutine for 96 bit quantities |
| | | |
| Copyright (C) 1994 | | Copyright (C) 1994,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| | | |
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#include "exception.h" #include "exception.h"
#include "fpu_asm.h" #include "fpu_emu.h"
#define XsigLL(x) (x) #define XsigLL(x) (x)
......
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
| | | |
| Divide a 64 bit integer by a 32 bit integer & return remainder. | | Divide a 64 bit integer by a 32 bit integer & return remainder. |
| | | |
| Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | Copyright (C) 1992,1995 |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| | | |
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
...@@ -14,7 +15,7 @@ ...@@ -14,7 +15,7 @@
| unsigned long div_small(unsigned long long *x, unsigned long y) | | unsigned long div_small(unsigned long long *x, unsigned long y) |
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#include "fpu_asm.h" #include "fpu_emu.h"
.text .text
ENTRY(div_small) ENTRY(div_small)
......
/*---------------------------------------------------------------------------+ /*---------------------------------------------------------------------------+
| fpu_asm.h | | fpu_asm.h |
| | | |
| Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | Copyright (C) 1992,1995 |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
...@@ -10,7 +11,6 @@ ...@@ -10,7 +11,6 @@
#define _FPU_ASM_H_ #define _FPU_ASM_H_
#include <linux/linkage.h> #include <linux/linkage.h>
#include "fpu_emu.h"
#define EXCEPTION SYMBOL_NAME(exception) #define EXCEPTION SYMBOL_NAME(exception)
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
| | | |
| Multiply a 12 byte fixed point number by another fixed point number. | | Multiply a 12 byte fixed point number by another fixed point number. |
| | | |
| Copyright (C) 1992,1994 | | Copyright (C) 1992,1994,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| Call from C as: | | Call from C as: |
| void mul32_Xsig(Xsig *x, unsigned b) | | void mul32_Xsig(Xsig *x, unsigned b) |
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
.file "mul_Xsig.S" .file "mul_Xsig.S"
#include "fpu_asm.h" #include "fpu_emu.h"
.text .text
ENTRY(mul32_Xsig) ENTRY(mul32_Xsig)
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
| | | |
| Fixed point arithmetic polynomial evaluation. | | Fixed point arithmetic polynomial evaluation. |
| | | |
| Copyright (C) 1992,1993,1994 | | Copyright (C) 1992,1993,1994,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| Call from C as: | | Call from C as: |
| void polynomial_Xsig(Xsig *accum, unsigned long long x, | | void polynomial_Xsig(Xsig *accum, unsigned long long x, |
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
.file "polynomial_Xsig.S" .file "polynomial_Xsig.S"
#include "fpu_asm.h" #include "fpu_emu.h"
#define TERM_SIZE $8 #define TERM_SIZE $8
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
| | | |
| Divide one FPU_REG by another and put the result in a destination FPU_REG.| | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
| | | |
| Copyright (C) 1992,1993,1994 | | Copyright (C) 1992,1993,1994,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| Call from C as: | | Call from C as: |
| void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest, | | void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest, |
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#include "exception.h" #include "exception.h"
#include "fpu_asm.h" #include "fpu_emu.h"
.text .text
......
/*---------------------------------------------------------------------------+ /*---------------------------------------------------------------------------+
| reg_norm.S | | reg_norm.S |
| | | |
| Copyright (C) 1992,1993,1994 | | Copyright (C) 1992,1993,1994,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| Normalize the value in a FPU_REG. | | Normalize the value in a FPU_REG. |
| | | |
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
| | | |
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#include "fpu_asm.h" #include "fpu_emu.h"
.text .text
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
| | | |
| Rounding/truncation/etc for FPU basic arithmetic functions. | | Rounding/truncation/etc for FPU basic arithmetic functions. |
| | | |
| Copyright (C) 1993 | | Copyright (C) 1993,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| This code has four possible entry points. | | This code has four possible entry points. |
| The following must be entered by a jmp instruction: | | The following must be entered by a jmp instruction: |
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#include "fpu_asm.h" #include "fpu_emu.h"
#include "exception.h" #include "exception.h"
#include "control_w.h" #include "control_w.h"
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
| Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the | | Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the |
| result in a destination FPU_REG. | | result in a destination FPU_REG. |
| | | |
| Copyright (C) 1992,1993 | | Copyright (C) 1992,1993,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| Call from C as: | | Call from C as: |
| void reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, | | void reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, |
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
*/ */
#include "exception.h" #include "exception.h"
#include "fpu_asm.h" #include "fpu_emu.h"
#include "control_w.h" #include "control_w.h"
.text .text
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
| | | |
| Core division routines | | Core division routines |
| | | |
| Copyright (C) 1992,1993 | | Copyright (C) 1992,1993,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| | | |
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#include "exception.h" #include "exception.h"
#include "fpu_asm.h" #include "fpu_emu.h"
#include "control_w.h" #include "control_w.h"
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
| | | |
| Core multiplication routine | | Core multiplication routine |
| | | |
| Copyright (C) 1992,1993 | | Copyright (C) 1992,1993,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| | | |
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#include "exception.h" #include "exception.h"
#include "fpu_asm.h" #include "fpu_emu.h"
#include "control_w.h" #include "control_w.h"
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
| | | |
| Core floating point subtraction routine. | | Core floating point subtraction routine. |
| | | |
| Copyright (C) 1992,1993 | | Copyright (C) 1992,1993,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| Call from C as: | | Call from C as: |
| void reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, | | void reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, |
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
*/ */
#include "exception.h" #include "exception.h"
#include "fpu_asm.h" #include "fpu_emu.h"
#include "control_w.h" #include "control_w.h"
.text .text
......
/*---------------------------------------------------------------------------+ /*---------------------------------------------------------------------------+
| round_Xsig.S | | round_Xsig.S |
| | | |
| Copyright (C) 1992,1993,1994 | | Copyright (C) 1992,1993,1994,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| Normalize and round a 12 byte quantity. | | Normalize and round a 12 byte quantity. |
| Call from C as: | | Call from C as: |
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
.file "round_Xsig.S" .file "round_Xsig.S"
#include "fpu_asm.h" #include "fpu_emu.h"
.text .text
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
| | | |
| 12 byte right shift function | | 12 byte right shift function |
| | | |
| Copyright (C) 1992,1994 | | Copyright (C) 1992,1994,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| Call from C as: | | Call from C as: |
| void shr_Xsig(Xsig *arg, unsigned nr) | | void shr_Xsig(Xsig *arg, unsigned nr) |
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
| | | |
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#include "fpu_asm.h" #include "fpu_emu.h"
.text .text
ENTRY(shr_Xsig) ENTRY(shr_Xsig)
......
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
| | | |
| 64 bit right shift functions | | 64 bit right shift functions |
| | | |
| Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | Copyright (C) 1992,1995 |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| Call from C as: | | Call from C as: |
| unsigned shrx(void *arg1, unsigned arg2) | | unsigned shrx(void *arg1, unsigned arg2) |
...@@ -14,7 +15,7 @@ ...@@ -14,7 +15,7 @@
| | | |
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#include "fpu_asm.h" #include "fpu_emu.h"
.text .text
/*---------------------------------------------------------------------------+ /*---------------------------------------------------------------------------+
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
| | | |
| Fixed point arithmetic square root evaluation. | | Fixed point arithmetic square root evaluation. |
| | | |
| Copyright (C) 1992,1993 | | Copyright (C) 1992,1993,1995 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au | | Australia. E-mail billm@jacobi.maths.monash.edu.au |
| | | |
| Call from C as: | | Call from C as: |
| void wm_sqrt(FPU_REG *n, unsigned int control_word) | | void wm_sqrt(FPU_REG *n, unsigned int control_word) |
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#include "exception.h" #include "exception.h"
#include "fpu_asm.h" #include "fpu_emu.h"
#ifndef NON_REENTRANT_FPU #ifndef NON_REENTRANT_FPU
......
...@@ -85,6 +85,13 @@ void flush_thread(void) ...@@ -85,6 +85,13 @@ void flush_thread(void)
*/ */
} }
void release_thread(struct task_struct *dead_task)
{
/*
* Nothing to do
*/
}
#define IS_CLONE (regs->orig_reg2 == __NR_clone) #define IS_CLONE (regs->orig_reg2 == __NR_clone)
void copy_thread(int nr, unsigned long clone_flags, struct task_struct * p, struct pt_regs * regs) void copy_thread(int nr, unsigned long clone_flags, struct task_struct * p, struct pt_regs * regs)
......
...@@ -72,6 +72,11 @@ void flush_thread(void) ...@@ -72,6 +72,11 @@ void flush_thread(void)
halt(); halt();
} }
void release_thread(struct task_struct *dead_task)
{
halt();
}
extern void ret_sys_call(void); extern void ret_sys_call(void);
/* /*
......
...@@ -830,7 +830,7 @@ el16_rx(struct device *dev) ...@@ -830,7 +830,7 @@ el16_rx(struct device *dev)
ushort pkt_len = data_frame[0]; ushort pkt_len = data_frame[0];
if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
|| pkt_len & 0xC000 != 0xC000) { || (pkt_len & 0xC000) != 0xC000) {
printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x" printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x"
"next %04x data-buf @%04x %04x.\n", dev->name, rx_head, "next %04x data-buf @%04x %04x.\n", dev->name, rx_head,
frame_status, rfd_cmd, next_rx_frame, data_buffer_addr, frame_status, rfd_cmd, next_rx_frame, data_buffer_addr,
......
...@@ -187,7 +187,7 @@ int at1700_probe1(struct device *dev, short ioaddr) ...@@ -187,7 +187,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
#endif #endif
if (at1700_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr if (at1700_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr
|| read_eeprom(ioaddr, 4) != 0x0000 || read_eeprom(ioaddr, 4) != 0x0000
|| read_eeprom(ioaddr, 5) & 0xff00 != 0xF400) || (read_eeprom(ioaddr, 5) & 0xff00) != 0xF400)
return -ENODEV; return -ENODEV;
/* Reset the internal state machines. */ /* Reset the internal state machines. */
......
...@@ -923,7 +923,7 @@ eexp_rx(struct device *dev) ...@@ -923,7 +923,7 @@ eexp_rx(struct device *dev)
pkt_len = inw(ioaddr); pkt_len = inw(ioaddr);
if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
|| pkt_len & 0xC000 != 0xC000) { || (pkt_len & 0xC000) != 0xC000) {
printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x" printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x"
"next %04x data-buf @%04x %04x.\n", dev->name, rx_head, "next %04x data-buf @%04x %04x.\n", dev->name, rx_head,
frame_status, rfd_cmd, next_rx_frame, data_buffer_addr, frame_status, rfd_cmd, next_rx_frame, data_buffer_addr,
......
...@@ -417,7 +417,7 @@ ewrk3_hw_init(struct device *dev, short iobase) ...@@ -417,7 +417,7 @@ ewrk3_hw_init(struct device *dev, short iobase)
*/ */
DISABLE_IRQs; DISABLE_IRQs;
if (nicsr == TXD|RXD) { if (nicsr == (TXD|RXD)) {
/* /*
** Check that the EEPROM is alive and well and not living on Pluto... ** Check that the EEPROM is alive and well and not living on Pluto...
......
...@@ -83,6 +83,10 @@ ...@@ -83,6 +83,10 @@
#include <net/checksum.h> #include <net/checksum.h>
#include "slhc.h" #include "slhc.h"
#ifdef __alpha__
# include <asm/unaligned.h>
#endif
int last_retran; int last_retran;
static unsigned char *encode(unsigned char *cp, unsigned short n); static unsigned char *encode(unsigned char *cp, unsigned short n);
...@@ -621,7 +625,11 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize) ...@@ -621,7 +625,11 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
cp += (ip->ihl - 5) * 4; cp += (ip->ihl - 5) * 4;
} }
#ifdef __alpha__
stw_u(ip_fast_csum(icp, ip->ihl), &((struct iphdr *)icp)->check);
#else
((struct iphdr *)icp)->check = ip_fast_csum(icp, ((struct iphdr*)icp)->ihl); ((struct iphdr *)icp)->check = ip_fast_csum(icp, ((struct iphdr*)icp)->ihl);
#endif
memcpy(cp, thp, 20); memcpy(cp, thp, 20);
cp += 20; cp += 20;
......
...@@ -448,7 +448,7 @@ static void znet_interrupt(int irq, struct pt_regs * regs) ...@@ -448,7 +448,7 @@ static void znet_interrupt(int irq, struct pt_regs * regs)
if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++; if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++;
if (tx_status & 0x0020) lp->stats.tx_aborted_errors++; if (tx_status & 0x0020) lp->stats.tx_aborted_errors++;
/* ...and the catch-all. */ /* ...and the catch-all. */
if (tx_status | 0x0760 != 0x0760) if ((tx_status | 0x0760) != 0x0760)
lp->stats.tx_errors++; lp->stats.tx_errors++;
} }
dev->tbusy = 0; dev->tbusy = 0;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# Note 2! The CFLAGS definitions are now in the main makefile... # Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := nfs.o O_TARGET := nfs.o
O_OBJS := proc.o sock.o inode.o file.o dir.o symlink.o mmap.o O_OBJS := proc.o sock.o rpcsock.o inode.o file.o dir.o symlink.o mmap.o
M_OBJS := $(O_TARGET) M_OBJS := $(O_TARGET)
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
...@@ -59,6 +59,7 @@ static void nfs_put_inode(struct inode * inode) ...@@ -59,6 +59,7 @@ static void nfs_put_inode(struct inode * inode)
void nfs_put_super(struct super_block *sb) void nfs_put_super(struct super_block *sb)
{ {
close_fp(sb->u.nfs_sb.s_server.file); close_fp(sb->u.nfs_sb.s_server.file);
rpc_closesock(sb->u.nfs_sb.s_server.rsock);
lock_super(sb); lock_super(sb);
sb->s_dev = 0; sb->s_dev = 0;
unlock_super(sb); unlock_super(sb);
...@@ -163,6 +164,12 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data, ...@@ -163,6 +164,12 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data,
} }
/* End of JSP NFS patch */ /* End of JSP NFS patch */
if ((server->rsock = rpc_makesock(filp)) == NULL) {
printk("NFS: cannot create RPC socket.\n");
MOD_DEC_USE_COUNT;
return NULL;
}
sb->u.nfs_sb.s_root = data->root; sb->u.nfs_sb.s_root = data->root;
unlock_super(sb); unlock_super(sb);
if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) { if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) {
......
/*
* linux/fs/nfs/rpcsock.c
*
* This is a generic RPC call interface for datagram sockets that is able
* to place several concurrent RPC requests at the same time. It works like
* this:
*
* - When a process places a call, it allocates a request slot if
* one is available. Otherwise, it sleeps on the backlog queue.
* - The first process on the receive queue waits for the next RPC reply,
* and peeks at the XID. If it finds a matching request, it receives
* the datagram on behalf of that process and wakes it up. Otherwise,
* the datagram is discarded.
* - If the process having received the datagram was the first one on
* the receive queue, it wakes up the next one to listen for replies.
* - It then removes itself from the request queue. If there are more
* callers waiting on the backlog queue, they are woken up, too.
*
* Copyright (C) 1995, Olaf Kirch <okir@monad.swb.de>
*/
#ifdef MODULE
#include <linux/module.h>
#endif
#include <linux/types.h>
#include <linux/malloc.h>
#include <linux/sched.h>
#include <linux/nfs_fs.h>
#include <linux/errno.h>
#include <linux/socket.h>
#include <linux/fcntl.h>
#include <asm/segment.h>
#include <linux/in.h>
#include <linux/net.h>
#include <linux/mm.h>
#include <linux/rpcsock.h>
#define msleep(sec) { current->timeout = sec * HZ / 1000; \
current->state = TAKS_INTERRUPTIBLE; \
schedule(); \
}
#define dprintk if (0) printk
static inline void
rpc_insque(struct rpc_sock *rsock, struct rpc_wait *slot)
{
struct rpc_wait *tmp;
if ((tmp = rsock->tail) != NULL) {
tmp->next = slot;
} else {
rsock->head = slot;
}
rsock->tail = slot;
slot->prev = tmp;
slot->next = NULL;
dprintk("RPC: inserted %08lx into queue.\n", (long)slot);
dprintk("RPC: head = %08lx, tail = %08lx.\n",
(long) rsock->head, (long) rsock->tail);
}
static inline void
rpc_remque(struct rpc_sock *rsock, struct rpc_wait *slot)
{
struct rpc_wait *prev = slot->prev,
*next = slot->next;
if (prev != NULL)
prev->next = next;
else
rsock->head = next;
if (next != NULL)
next->prev = prev;
else
rsock->tail = prev;
dprintk("RPC: removed %08lx from queue.\n", (long)slot);
dprintk("RPC: head = %08lx, tail = %08lx.\n",
(long) rsock->head, (long) rsock->tail);
}
static inline int
rpc_sendto(struct rpc_sock *rsock, const int *buf, int len,
struct sockaddr *sap, int salen)
{
struct socket *sock = rsock->sock;
unsigned long oldfs;
int result;
dprintk("RPC: sending %d bytes (buf %08lx)\n", len, (long) buf);
oldfs = get_fs();
set_fs(get_ds());
result = sock->ops->sendto(sock, buf, len, 0, 0, sap, salen);
set_fs(oldfs);
dprintk("RPC: result = %d\n", result);
return result;
}
/*
* This code is slightly complicated. Since the networking code does not
* honor the current->timeout value, we have to select on the socket.
*/
static inline int
rpc_select(struct rpc_sock *rsock)
{
struct select_table_entry entry;
struct file *file = rsock->file;
select_table wait_table;
dprintk("RPC: selecting on socket...\n");
wait_table.nr = 0;
wait_table.entry = &entry;
current->state = TASK_INTERRUPTIBLE;
if (!file->f_op->select(file->f_inode, file, SEL_IN, &wait_table)
&& !file->f_op->select(file->f_inode, file, SEL_IN, NULL)) {
schedule();
remove_wait_queue(entry.wait_address, &entry.wait);
current->state = TASK_RUNNING;
if (current->signal & ~current->blocked)
return -ERESTARTSYS;
if (current->timeout == 0)
return -ETIMEDOUT;
} else if (wait_table.nr)
remove_wait_queue(entry.wait_address, &entry.wait);
current->state = TASK_RUNNING;
dprintk("RPC: ...Okay, there appears to be some data.\n");
return 0;
}
static inline int
rpc_recvfrom(struct rpc_sock *rsock, int *buf, int len,
struct sockaddr *sap, int salen, int flags)
{
struct socket *sock = rsock->sock;
struct sockaddr sa;
int alen = sizeof(sa);
unsigned long oldfs;
int result;
dprintk("RPC: receiving %d bytes max (buf %08lx)\n", len, (long) buf);
oldfs = get_fs();
set_fs(get_ds());
result = sock->ops->recvfrom(sock, buf, len, 1, flags, &sa, &alen);
set_fs(oldfs);
dprintk("RPC: result = %d\n", result);
#if 0
if (alen != salen || memcmp(&sa, sap, alen)) {
dprintk("RPC: reply address mismatch... rejected.\n");
result = -EAGAIN;
}
#endif
return result;
}
/*
* Place the actual RPC call.
*/
static int
rpc_call_one(struct rpc_sock *rsock, struct rpc_wait *slot,
struct sockaddr *sap, int salen,
const int *sndbuf, int slen, int *rcvbuf, int rlen)
{
struct rpc_wait *rovr = NULL;
int result;
u32 xid;
int safe;
dprintk("RPC: placing one call, rsock = %08lx, slot = %08lx, "
"sap = %08lx, salen = %d, "
"sndbuf = %08lx, slen = %d, rcvbuf = %08lx, rlen = %d\n",
(long) rsock, (long) slot, (long) sap,
salen, (long) sndbuf, slen, (long) rcvbuf, rlen);
result = rpc_sendto(rsock, sndbuf, slen, sap, salen);
if (result < 0)
return result;
do {
/* We are not the receiver. Wait on the side lines. */
if (rsock->head != slot) {
slot->wait = NULL;
interruptible_sleep_on(&slot->wait);
if (slot->gotit)
break;
if (current->timeout != 0)
continue;
if (rsock->shutdown) {
printk("RPC: aborting call due to shutdown.\n");
return -EIO;
}
return -ETIMEDOUT;
}
/* wait for data to arrive */
result = rpc_select(rsock);
if (result < 0) {
dprintk("RPC: select error = %d\n", result);
break;
}
result = rpc_recvfrom(rsock, (int *)&xid, sizeof(xid),
sap, salen, MSG_PEEK);
if (result < 0) {
switch (-result) {
case EAGAIN: case ECONNREFUSED:
continue;
default:
dprintk("rpc_call: recv error = %d\n", result);
case ERESTARTSYS:
return result;
}
}
/* Look for the caller */
safe = 0;
for (rovr = rsock->head; rovr; rovr = rovr->next) {
if (safe++ > NRREQS) {
printk("RPC: loop in request Q!!\n");
rovr = NULL;
break;
}
if (rovr->xid == xid)
break;
}
if (!rovr || rovr->gotit) {
/* bad XID or duplicate reply, discard dgram */
dprintk("RPC: bad XID or duplicate reply.\n");
rpc_recvfrom(rsock, (int *)&xid, sizeof(xid),
sap, salen, 0);
continue;
}
rovr->gotit = 1;
/* Now receive the reply */
result = rpc_recvfrom(rsock, rovr->buf, rovr->len,
sap, salen, 0);
/* If this is not for ourselves, wake up the caller */
if (rovr != slot)
wake_up(&rovr->wait);
} while (rovr != slot);
/* This is somewhat tricky. We rely on the fact that we are able to
* remove ourselves from the queues before the next reader is scheduled,
* otherwise it would find that we're still at the head of the queue
* and go to sleep again.
*/
if (rsock->head == slot && slot->next != NULL)
wake_up(&slot->next->wait);
return result;
}
/*
* Generic RPC call routine. This handles retries and timeouts etc pp
*/
int
rpc_call(struct rpc_sock *rsock, struct sockaddr *sap, int addrlen,
const int *sndbuf, int slen, int *rcvbuf, int rlen,
struct rpc_timeout *strategy, int flag)
{
struct rpc_wait *slot;
int result, retries;
unsigned long timeout;
timeout = strategy->init_timeout;
retries = 0;
slot = NULL;
do {
dprintk("RPC call TP1\n");
current->timeout = jiffies + timeout;
if (slot == NULL) {
while ((slot = rsock->free) == NULL) {
if (!flag) {
current->timeout = 0;
return -ENOBUFS;
}
interruptible_sleep_on(&rsock->backlog);
if (current->timeout == 0) {
result = -ETIMEDOUT;
goto timedout;
}
if (rsock->shutdown) {
printk("RPC: aborting call due to shutdown.\n");
current->timeout = 0;
return -EIO;
}
}
dprintk("RPC call TP2\n");
slot->gotit = 0;
slot->xid = *(u32 *)sndbuf;
slot->buf = rcvbuf;
slot->len = rlen;
rsock->free = slot->next;
rpc_insque(rsock, slot);
}
dprintk("RPC call TP3\n");
result = rpc_call_one(rsock, slot, sap, addrlen,
sndbuf, slen, rcvbuf, rlen);
if (result != -ETIMEDOUT)
break;
timedout:
dprintk("RPC call TP4\n");
dprintk("RPC: rpc_call_one returned timeout.\n");
if (strategy->exponential)
timeout <<= 1;
else
timeout += strategy->increment;
if (strategy->max_timeout && timeout >= strategy->max_timeout)
timeout = strategy->max_timeout;
if (strategy->retries && ++retries >= strategy->retries)
break;
} while (1);
dprintk("RPC call TP5\n");
current->timeout = 0;
if (slot != NULL) {
dprintk("RPC call TP6\n");
rpc_remque(rsock, slot);
slot->next = rsock->free;
rsock->free = slot;
/* wake up tasks that haven't sent anything yet. (Waking
* up the first one the wait queue would be enough) */
if (rsock->backlog)
wake_up(&rsock->backlog);
}
if (rsock->shutdown)
wake_up(&rsock->shutwait);
return result;
}
struct rpc_sock *
rpc_makesock(struct file *file)
{
struct rpc_sock *rsock;
struct rpc_wait *slot;
int i;
dprintk("RPC: make RPC socket...\n");
if ((rsock = kmalloc(sizeof(struct rpc_sock), GFP_KERNEL)) == NULL)
return NULL;
rsock->sock = &file->f_inode->u.socket_i;
rsock->file = file;
rsock->free = rsock->waiting;
for (i = 0, slot = rsock->waiting; i < NRREQS-1; i++, slot++)
slot->next = slot + 1;
slot->next = NULL;
rsock->backlog = NULL;
rsock->head = rsock->tail = NULL;
rsock->shutwait = NULL;
rsock->shutdown = 0;
dprintk("RPC: made socket %08lx", (long) rsock);
return rsock;
}
int
rpc_closesock(struct rpc_sock *rsock)
{
unsigned long t0 = jiffies;
rsock->shutdown = 1;
while (rsock->head) {
interruptible_sleep_on(&rsock->shutwait);
if (current->signal & ~current->blocked)
return -EINTR;
#if 1
if (t0 && t0 - jiffies > 60 * HZ) {
printk("RPC: hanging in rpc_closesock.\n");
t0 = 0;
}
#endif
}
kfree(rsock);
return 0;
}
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/in.h> #include <linux/in.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/rpcsock.h>
/* JEJB/JSP 2/7/94 /* JEJB/JSP 2/7/94
* this must match the value of NFS_SLACK_SPACE in linux/fs/nfs/proc.c * this must match the value of NFS_SLACK_SPACE in linux/fs/nfs/proc.c
...@@ -49,197 +50,64 @@ ...@@ -49,197 +50,64 @@
* to the server socket. * to the server socket.
*/ */
static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size) int
nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
{ {
struct file *file; struct rpc_timeout timeout;
struct inode *inode; unsigned long maxtimeo;
struct socket *sock; unsigned long oldmask;
unsigned short fs; int major_timeout_seen, result;
int result;
int xid;
int len;
select_table wait_table;
struct select_table_entry entry;
int (*select) (struct inode *, struct file *, int, select_table *);
int init_timeout, max_timeout;
int timeout;
int retrans;
int major_timeout_seen;
char *server_name;
int n;
int addrlen;
unsigned long old_mask;
/* JEJB/JSP 2/7/94
* This is for a 4 byte recv of the xid only */
int recv_xid;
xid = start[0]; timeout.init_timeout = server->timeo;
len = ((char *) end) - ((char *) start); timeout.max_timeout = maxtimeo = NFS_MAX_RPC_TIMEOUT*HZ/10;
file = server->file; timeout.retries = server->retrans;
inode = file->f_inode; timeout.exponential = 1;
select = file->f_op->select;
sock = &inode->u.socket_i; oldmask = current->blocked;
if (!sock) {
printk("nfs_rpc_call: socki_lookup failed\n");
return -EBADF;
}
init_timeout = server->timeo;
max_timeout = NFS_MAX_RPC_TIMEOUT*HZ/10;
retrans = server->retrans;
major_timeout_seen = 0;
server_name = server->hostname;
old_mask = current->blocked;
current->blocked |= ~(_S(SIGKILL) current->blocked |= ~(_S(SIGKILL)
#if 0
| _S(SIGSTOP)
#endif
| ((server->flags & NFS_MOUNT_INTR) | ((server->flags & NFS_MOUNT_INTR)
? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL ? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL
? _S(SIGINT) : 0) ? _S(SIGINT) : 0)
| (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL | (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL
? _S(SIGQUIT) : 0)) ? _S(SIGQUIT) : 0))
: 0)); : 0));
fs = get_fs(); major_timeout_seen = 0;
set_fs(get_ds());
for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) { do {
/* JSP 1995-07-01 Use sendto() not send() to cope with multi-homed hosts result = rpc_call(server->rsock,
as we have set the socket to have INADDR_ANY as it's desination */ &server->toaddr, sizeof(server->toaddr),
result = sock->ops->sendto(sock, (void *) start, len, 0, 0, start, ((char *) end) - ((char *) start),
&(server->toaddr), sizeof((server->toaddr))) ; start, size + 1024,
if (result < 0) { &timeout, 1);
printk("nfs_rpc_call: send error = %d\n", result); if (current->signal & ~current->blocked)
break;
}
re_select:
wait_table.nr = 0;
wait_table.entry = &entry;
current->state = TASK_INTERRUPTIBLE;
if (!select(inode, file, SEL_IN, &wait_table)
&& !select(inode, file, SEL_IN, NULL)) {
if (timeout > max_timeout) {
/* JEJB/JSP 2/7/94
* This is useful to see if the system is
* hanging */
printk("NFS max timeout reached on %s\n",
server_name);
timeout = max_timeout;
}
current->timeout = jiffies + timeout;
schedule();
remove_wait_queue(entry.wait_address, &entry.wait);
current->state = TASK_RUNNING;
if (current->signal & ~current->blocked) {
current->timeout = 0;
result = -ERESTARTSYS; result = -ERESTARTSYS;
break; if (result == -ETIMEDOUT) {
}
if (!current->timeout) {
if (n < retrans)
continue;
if (server->flags & NFS_MOUNT_SOFT) { if (server->flags & NFS_MOUNT_SOFT) {
printk("NFS server %s not responding, " printk("NFS server %s not responding, "
"timed out\n", server_name); "still trying.\n", server->hostname);
result = -EIO; result = -EIO;
break; break;
} }
n = 0;
timeout = init_timeout;
init_timeout <<= 1;
if (!major_timeout_seen) { if (!major_timeout_seen) {
printk("NFS server %s not responding, " printk("NFS server %s not responding, "
"still trying\n", server_name); "timed out.\n", server->hostname);
}
major_timeout_seen = 1; major_timeout_seen = 1;
continue;
} }
else if ((timeout.init_timeout <<= 1) >= maxtimeo)
current->timeout = 0; timeout.init_timeout = maxtimeo;
} } else if (result < 0) {
else if (wait_table.nr) printk("NFS: notice message: result = %d.\n", result);
remove_wait_queue(entry.wait_address, &entry.wait);
current->state = TASK_RUNNING;
addrlen = 0;
/* JEJB/JSP 2/7/94
* Get the xid from the next packet using a peek, so keep it
* on the recv queue. If it is wrong, it will be some reply
* we don't now need, so discard it */
result = sock->ops->recvfrom(sock, (void *)&recv_xid,
sizeof(recv_xid), 1, MSG_PEEK,
NULL, &addrlen);
if (result < 0) {
if (result == -EAGAIN) {
#if 0
printk("nfs_rpc_call: bad select ready\n");
#endif
goto re_select;
} }
if (result == -ECONNREFUSED) { } while (result == -ETIMEDOUT && !(server->flags & NFS_MOUNT_SOFT));
#if 0
printk("nfs_rpc_call: server playing coy\n"); if (result >= 0 && major_timeout_seen)
#endif printk("NFS server %s OK.\n", server->hostname);
goto re_select; /* 20 is the minimum RPC reply header size */
} if (result >= 0 && result < 20) {
if (result != -ERESTARTSYS) { printk("NFS: too small read memory size (%d bytes)\n", result);
printk("nfs_rpc_call: recv error = %d\n",
-result);
}
break;
}
if (recv_xid == xid) {
if (major_timeout_seen)
printk("NFS server %s OK\n", server_name);
break;
}
/* JEJB/JSP 2/7/94
* we have xid mismatch, so discard the packet and start
* again. What a hack! but I can't call recvfrom with
* a null buffer yet. */
(void)sock->ops->recvfrom(sock, (void *)&recv_xid,
sizeof(recv_xid), 1, 0, NULL,
&addrlen);
#if 0
printk("nfs_rpc_call: XID mismatch\n");
#endif
goto re_select;
}
/* JEJB/JSP 2/7/94
*
* we have the correct xid, so read into the correct place and
* return it
*
*/
result=sock->ops->recvfrom(sock, (void *)start,
size + 1024, 1, 0, NULL,
/* Here is NFS_SLACK_SPACE..., hack */
&addrlen);
if (result < 0) {
printk("NFS: notice message: result=%d\n", result);
} else if (result < addrlen) {
printk("NFS: just caught a too small read memory size..., email to NET channel\n");
printk("NFS: result=%d,addrlen=%d\n", result, addrlen);
result = -EIO; result = -EIO;
} }
current->blocked = old_mask;
set_fs(fs);
return result;
}
/*
* For now we lock out other simultaneous nfs calls for the same filesystem
* because we are single-threaded and don't want to get mismatched
* RPC replies.
*/
int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
{
int result;
while (server->lock) current->blocked = oldmask;
sleep_on(&server->wait);
server->lock = 1;
result = do_nfs_rpc_call(server, start, end, size);
server->lock = 0;
wake_up(&server->wait);
return result; return result;
} }
...@@ -351,17 +351,8 @@ extern unsigned long apecs_init (unsigned long mem_start, ...@@ -351,17 +351,8 @@ extern unsigned long apecs_init (unsigned long mem_start,
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
/* /*
* data structures for handling APECS machine checks * Data structure for handling APECS machine checks:
*/ */
struct el_common_logout_header {
u_int elfl_size; /* size in bytes of logout area. */
int elfl_sbz1:31; /* Should be zero. */
char elfl_retry:1; /* Retry flag. */
u_int elfl_procoffset; /* Processor-specific offset. */
u_int elfl_sysoffset; /* Offset of system-specific. */
};
struct el_apecs_sysdata_mcheck { struct el_apecs_sysdata_mcheck {
u_long coma_gcr; u_long coma_gcr;
u_long coma_edsr; u_long coma_edsr;
......
...@@ -52,6 +52,8 @@ ...@@ -52,6 +52,8 @@
* ugh). * ugh).
*/ */
#include <asm/system.h>
#define LCA_DMA_WIN_BASE (1024*1024*1024) #define LCA_DMA_WIN_BASE (1024*1024*1024)
#define LCA_DMA_WIN_SIZE (1024*1024*1024) #define LCA_DMA_WIN_SIZE (1024*1024*1024)
...@@ -324,6 +326,45 @@ extern unsigned long lca_init (unsigned long mem_start, unsigned long mem_end); ...@@ -324,6 +326,45 @@ extern unsigned long lca_init (unsigned long mem_start, unsigned long mem_end);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
/*
* Data structure for handling LCA machine checks. Correctable errors
* result in a short logout frame, uncorrectably ones in a long one.
*/
struct el_lca_mcheck_short {
struct el_common h; /* common logout header */
unsigned long reason; /* reason for machine check */
unsigned long esr; /* error-status register */
unsigned long ear; /* error-address register */
unsigned long dc_stat; /* dcache status register */
unsigned long ioc_stat0; /* I/O controller status register 0 */
unsigned long ioc_stat1; /* I/O controller status register 1 */
};
struct el_lca_mcheck_long {
struct el_common h; /* common logout header */
unsigned long pt[32]; /* PAL temps (pt[0] is reason) */
unsigned long exc_addr; /* exception address */
unsigned long pal_base; /* PALcode base address */
unsigned long hier; /* hw interrupt enable */
unsigned long hirr; /* hw interrupt request */
unsigned long mm_csr; /* MMU control & status */
unsigned long dc_stat; /* data cache status */
unsigned long dc_addr; /* data cache addr register */
unsigned long abox_ctl; /* address box control register */
unsigned long esr; /* error status register */
unsigned long ear; /* error address register */
unsigned long car; /* cache control register */
unsigned long ioc_stat0; /* I/O controller status register 0 */
unsigned long ioc_stat1; /* I/O controller status register 1 */
unsigned long va; /* virtual address register */
};
union el_lca {
struct el_common * c;
struct el_lca_mcheck_long * l;
struct el_lca_mcheck_short * s;
};
#define RTC_PORT(x) (0x70 + (x)) #define RTC_PORT(x) (0x70 + (x))
#define RTC_ADDR(x) (0x80 | (x)) #define RTC_ADDR(x) (0x80 | (x))
#define RTC_ALWAYS_BCD 0 #define RTC_ALWAYS_BCD 0
......
...@@ -31,6 +31,18 @@ ...@@ -31,6 +31,18 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
/*
* This is the logout header that should be common to all platforms
* (assuming they are running OSF/1 PALcode, I guess).
*/
struct el_common {
unsigned int size; /* size in bytes of logout area */
int sbz1 : 31; /* should be zero */
char retry : 1; /* retry flag */
unsigned int proc_offset; /* processor-specific offset */
unsigned int sys_offset; /* system-specific offset */
};
extern void wrent(void *, unsigned long); extern void wrent(void *, unsigned long);
extern void wrkgp(unsigned long); extern void wrkgp(unsigned long);
extern void wrusp(unsigned long); extern void wrusp(unsigned long);
......
...@@ -19,10 +19,10 @@ extern unsigned short int ntohs(unsigned short int); ...@@ -19,10 +19,10 @@ extern unsigned short int ntohs(unsigned short int);
extern unsigned long int htonl(unsigned long int); extern unsigned long int htonl(unsigned long int);
extern unsigned short int htons(unsigned short int); extern unsigned short int htons(unsigned short int);
extern unsigned long int __ntohl(unsigned long int); extern __inline__ unsigned long int __ntohl(unsigned long int);
extern unsigned short int __ntohs(unsigned short int); extern __inline__ unsigned short int __ntohs(unsigned short int);
extern unsigned long int __constant_ntohl(unsigned long int); extern __inline__ unsigned long int __constant_ntohl(unsigned long int);
extern unsigned short int __constant_ntohs(unsigned short int); extern __inline__ unsigned short int __constant_ntohs(unsigned short int);
extern __inline__ unsigned long int extern __inline__ unsigned long int
__ntohl(unsigned long int x) __ntohl(unsigned long int x)
......
...@@ -82,6 +82,7 @@ ...@@ -82,6 +82,7 @@
/* used to decode ioctl numbers.. */ /* used to decode ioctl numbers.. */
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) #define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) #define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) #define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#ifndef _LINUX_IF_EQL_H #ifndef _LINUX_IF_EQL_H
#define _LINUX_IF_EQL_H #define _LINUX_IF_EQL_H
#include <linux/timer.h>
#define EQL_DEFAULT_SLAVE_PRIORITY 28800 #define EQL_DEFAULT_SLAVE_PRIORITY 28800
#define EQL_DEFAULT_MAX_SLAVES 4 #define EQL_DEFAULT_MAX_SLAVES 4
#define EQL_DEFAULT_MTU 576 #define EQL_DEFAULT_MTU 576
......
...@@ -140,6 +140,35 @@ struct mtpos { ...@@ -140,6 +140,35 @@ struct mtpos {
}; };
/* structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended
* as an interim solution for QIC-02 until DDI is fully implemented.
*/
struct mtconfiginfo {
long mt_type; /* drive type */
long ifc_type; /* interface card type */
unsigned short irqnr; /* IRQ number to use */
unsigned short dmanr; /* DMA channel to use */
unsigned short port; /* IO port base address */
unsigned long debug; /* debugging flags */
unsigned have_dens:1;
unsigned have_bsf:1;
unsigned have_fsr:1;
unsigned have_bsr:1;
unsigned have_eod:1;
unsigned have_seek:1;
unsigned have_tell:1;
unsigned have_ras1:1;
unsigned have_ras2:1;
unsigned have_ras3:1;
unsigned have_qfa:1;
unsigned pad1:5;
char reserved[10];
};
/* mag tape io control commands */ /* mag tape io control commands */
#define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */ #define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */
#define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */ #define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */
......
#ifndef _NFS_FS_SB #ifndef _NFS_FS_SB
#define _NFS_FS_SB #define _NFS_FS_SB
#include <linux/rpcsock.h>
#include <linux/nfs.h> #include <linux/nfs.h>
struct nfs_server { struct nfs_server {
struct file *file; struct file *file;
struct rpc_sock *rsock;
struct sockaddr toaddr ; /* Added for change to NFS code to use sendto() 1995-06-02 JSP */ struct sockaddr toaddr ; /* Added for change to NFS code to use sendto() 1995-06-02 JSP */
int lock; int lock;
struct wait_queue *wait; struct wait_queue *wait;
......
#ifndef _LINUX_RESOURCE_H #ifndef _LINUX_RESOURCE_H
#define _LINUX_RESOURCE_H #define _LINUX_RESOURCE_H
#include <linux/time.h>
/* /*
* Resource control/accounting header file for linux * Resource control/accounting header file for linux
*/ */
......
/*
* rpcsock.h Declarations for the RPC call interface.
*
* Coypright (C) 1995 Olaf Kirch <okir@monad.swb.de>
*
*/
#ifndef _LINUX_RPCSOCK_H
#define _LINUX_RPCSOCK_H
/* Maximum number of outstanding RPCs per socket.
* With 32 slots, IP fragment reassembly would frequently
* fail due to low memory.
*/
#define NRREQS 16
/* This describes a timeout strategy */
struct rpc_timeout {
unsigned long init_timeout,
max_timeout,
increment;
int retries;
char exponential;
};
/* Wait information */
struct rpc_wait {
struct rpc_wait *prev, *next;
struct wait_queue *wait;
int *buf;
int len;
char gotit;
u32 xid;
};
struct rpc_sock {
struct file *file;
struct socket *sock;
struct rpc_wait waiting[NRREQS];
struct rpc_wait *head, *tail, *free;
struct wait_queue *backlog;
struct wait_queue *shutwait;
int shutdown;
};
#ifdef __KERNEL__
int rpc_call(struct rpc_sock *, struct sockaddr *, int,
const int *, int, int *, int,
struct rpc_timeout *, int);
struct rpc_sock * rpc_makesock(struct file *);
int rpc_closesock(struct rpc_sock *);
#endif /* __KERNEL__*/
#endif /* _LINUX_RPCSOCK_H */
...@@ -325,6 +325,7 @@ extern void exit_thread(void); ...@@ -325,6 +325,7 @@ extern void exit_thread(void);
extern void exit_fs(struct task_struct *); extern void exit_fs(struct task_struct *);
extern void exit_files(struct task_struct *); extern void exit_files(struct task_struct *);
extern void exit_sighand(struct task_struct *); extern void exit_sighand(struct task_struct *);
extern void release_thread(struct task_struct *);
extern int do_execve(char *, char **, char **, struct pt_regs *); extern int do_execve(char *, char **, char **, struct pt_regs *);
extern int do_fork(unsigned long, unsigned long, struct pt_regs *); extern int do_fork(unsigned long, unsigned long, struct pt_regs *);
......
...@@ -107,6 +107,9 @@ struct serial_multiport_struct { ...@@ -107,6 +107,9 @@ struct serial_multiport_struct {
* For definitions of the flags field, see tty.h * For definitions of the flags field, see tty.h
*/ */
#include <linux/termios.h>
#include <linux/tqueue.h>
struct async_struct { struct async_struct {
int magic; int magic;
int baud_base; int baud_base;
......
...@@ -628,34 +628,6 @@ typedef char flag; ...@@ -628,34 +628,6 @@ typedef char flag;
#define BLOCKS_BEYOND_EW 2 /* nr of blocks after Early Warning hole */ #define BLOCKS_BEYOND_EW 2 /* nr of blocks after Early Warning hole */
#define BOGUS_IRQ 32009 #define BOGUS_IRQ 32009
/* structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended
* as an interim solution for QIC-02 until DDI is fully implemented.
*/
struct mtconfiginfo {
long mt_type; /* drive type */
long ifc_type; /* interface card type */
unsigned short irqnr; /* IRQ number to use */
unsigned short dmanr; /* DMA channel to use */
unsigned short port; /* IO port base address */
unsigned long debug; /* debugging flags */
unsigned have_dens:1;
unsigned have_bsf:1;
unsigned have_fsr:1;
unsigned have_bsr:1;
unsigned have_eod:1;
unsigned have_seek:1;
unsigned have_tell:1;
unsigned have_ras1:1;
unsigned have_ras2:1;
unsigned have_ras3:1;
unsigned have_qfa:1;
unsigned pad1:5;
char reserved[10];
};
/* This is internal data, filled in based on the ifc_type field given /* This is internal data, filled in based on the ifc_type field given
* by the user. Everex is mapped to Wangtek with a different * by the user. Everex is mapped to Wangtek with a different
......
...@@ -94,6 +94,7 @@ void release(struct task_struct * p) ...@@ -94,6 +94,7 @@ void release(struct task_struct * p)
nr_tasks--; nr_tasks--;
task[i] = NULL; task[i] = NULL;
REMOVE_LINKS(p); REMOVE_LINKS(p);
release_thread(p);
if (STACK_MAGIC != *(unsigned long *)p->kernel_stack_page) if (STACK_MAGIC != *(unsigned long *)p->kernel_stack_page)
printk(KERN_ALERT "release: %s kernel stack corruption. Aiee\n", p->comm); printk(KERN_ALERT "release: %s kernel stack corruption. Aiee\n", p->comm);
free_page(p->kernel_stack_page); free_page(p->kernel_stack_page);
......
...@@ -1527,12 +1527,12 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, ...@@ -1527,12 +1527,12 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
unsigned char *ptr; /* Data pointer */ unsigned char *ptr; /* Data pointer */
unsigned long raddr; /* Router IP address */ unsigned long raddr; /* Router IP address */
struct options * opt = (struct options*)skb->proto_priv; struct options * opt = (struct options*)skb->proto_priv;
int encap = 0; /* Encap length */
#ifdef CONFIG_IP_FIREWALL #ifdef CONFIG_IP_FIREWALL
int fw_res = 0; /* Forwarding result */ int fw_res = 0; /* Forwarding result */
#ifdef CONFIG_IP_MASQUERADE #ifdef CONFIG_IP_MASQUERADE
struct sk_buff *skb_in = skb; /* So we can remember if the masquerader did some swaps */ struct sk_buff *skb_in = skb; /* So we can remember if the masquerader did some swaps */
#endif #endif
int encap = 0; /* Encap length */
/* /*
* See if we are allowed to forward this. * See if we are allowed to forward this.
......
/* ksymoops.c -- simple Linux Oops-log symbol resolver // ksymoops.cc v1.7 -- A simple filter to resolve symbols in Linux Oops-logs
Copyright (C) 1995 Greg McGary // Copyright (C) 1995 Greg McGary <gkm@magilla.cichlid.com>
// compile like so: g++ -o ksymoops ksymoops.cc -liostream
This program is free software; you can redistribute it and/or modify //////////////////////////////////////////////////////////////////////////////
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option) // This program is free software; you can redistribute it and/or modify
any later version. // it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
This program is distributed in the hope that it will be useful, // You should have received a copy of the GNU General Public License
but WITHOUT ANY WARRANTY; without even the implied warranty of // along with this program; see the file COPYING. If not, write to the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License // This is a simple filter to resolve EIP and call-trace symbols from
along with this program; see the file COPYING. If not, write to the // a Linux kernel "Oops" log. Supply the symbol-map file name as a
Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // command-line argument, and redirect the oops-log into stdin. Out
*/ // will come the EIP and call-trace in symbolic form.
/* This is a simple filter to resolve EIP and call-trace symbols from //////////////////////////////////////////////////////////////////////////////
a Linux kernel "Oops" log. Supply the symbol-map file name as a
command-line argument, and redirect the oops-log into stdin. // BUGS:
Out will come the EIP and call-trace in symbolic form. */ // * Doesn't deal with line-prefixes prepended by syslog--strip
// these off first, before submitting to ksymoops.
// * Only resolves operands of jump and call instructions.
#include <fstream.h> #include <fstream.h>
#include <iomanip.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
inline int strequ(char const* x, char const* y) { return (::strcmp(x, y) == 0); } inline int strequ(char const* x, char const* y) { return (::strcmp(x, y) == 0); }
inline int strnequ(char const* x, char const* y, size_t n) { return (::strncmp(x, y, n) == 0); }
const int code_size = 20;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
...@@ -35,37 +51,41 @@ class KSym ...@@ -35,37 +51,41 @@ class KSym
private: private:
long address_; long address_;
char type_;
char* name_; char* name_;
long offset_; long offset_;
long extent_; long extent_;
public: private:
istream& scan(istream&);
ostream& print(ostream&) const;
void set_extent(KSym const& next_ksym) { extent_ = next_ksym.address_ - address_; } void set_extent(KSym const& next_ksym) { extent_ = next_ksym.address_ - address_; }
friend istream& operator >> (istream&, KSym&);
friend ostream& operator << (ostream&, const KSym&); public:
friend istream& operator >> (istream& is, KSym& k) { return k.scan(is); }
friend ostream& operator << (ostream& os, const KSym& k) { return k.print(os); }
}; };
istream& istream&
operator >> (istream& is, KSym& n) KSym::scan(istream& is)
{ {
is >> hex >> n.address_; is >> ::hex >> address_;
is >> n.type_; char type;
is >> type;
char name[128]; char name[128];
is >> name; is >> name;
n.name_ = new char [strlen(name)+1]; name_ = new char [strlen(name)+1];
strcpy(n.name_, name); strcpy(name_, name);
n.offset_ = 0; offset_ = 0;
return is; return is;
} }
ostream& ostream&
operator << (ostream& os, const KSym& n) KSym::print(ostream& os) const
{ {
os << hex << n.address_ + n.offset_ << ' ' << n.type_ << ' ' << n.name_; os << ::hex << address_ + offset_ << ' ' << '<' << name_;
if (n.offset_) if (offset_)
os << '+' << hex << n.offset_ << '/' << hex << n.extent_; os << '+' << ::hex << offset_ << '/' << ::hex << extent_;
return os; return os << '>';
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
...@@ -81,20 +101,30 @@ class NameList ...@@ -81,20 +101,30 @@ class NameList
public: public:
NameList() : cardinality_(0) { } NameList() : cardinality_(0) { }
private:
istream& scan(istream&);
public: public:
int valid() { return (cardinality_ > 0); }
KSym* find(long address); KSym* find(long address);
void decode(unsigned char* code, long eip_addr);
public: public:
friend istream& operator >> (istream&, NameList&); friend istream& operator >> (istream& is, NameList& n) { return n.scan(is); }
}; };
KSym* KSym*
NameList::find(long address) NameList::find(long address)
{ {
if (!valid())
return 0;
KSym* start = ksyms_0_; KSym* start = ksyms_0_;
KSym* end = &ksyms_0_[cardinality_]; KSym* end = &ksyms_0_[cardinality_ - 1];
KSym* mid; if (address < start->address_ || address >= end->address_)
return 0;
KSym* mid;
while (start <= end) { while (start <= end) {
mid = &start[(end - start) / 2]; mid = &start[(end - start) / 2];
if (mid->address_ < address) if (mid->address_ < address)
...@@ -112,18 +142,101 @@ NameList::find(long address) ...@@ -112,18 +142,101 @@ NameList::find(long address)
return mid; return mid;
} }
void
NameList::decode(unsigned char* code, long eip_addr)
{
/* This is a hack to avoid using gcc. We create an object file by
concatenating objfile_head, the twenty bytes of code, and
objfile_tail. */
unsigned char objfile_head[] = {
0x07, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned char objfile_tail[] = {
0x00, 0x90, 0x90, 0x90,
0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x25, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
'g', 'c', 'c', '2', '_', 'c', 'o', 'm',
'p', 'i', 'l', 'e', 'd', '.', '\0', '_',
'E', 'I', 'P', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0'
};
char const* objdump_command = "objdump -d oops_decode.o";
char const* objfile_name = &objdump_command[11];
ofstream objfile_stream(objfile_name);
objfile_stream.write(objfile_head, sizeof(objfile_head));
objfile_stream.write(code, code_size);
objfile_stream.write(objfile_tail, sizeof(objfile_tail));
objfile_stream.close();
FILE* objdump_FILE = popen(objdump_command, "r");
if (objdump_FILE == 0) {
clog << "Sorry, without " << objdump_command << ", I can't disassemble the `Code' section." << endl;
return;
}
char buf[1024];
int lines = 0;
while (fgets(buf, sizeof(buf), objdump_FILE)) {
if (!strnequ(&buf[9], "<_EIP", 5))
continue;
if (strstr(buf, " is out of bounds"))
break;
lines++;
cout << "Code: ";
if (!valid()) {
cout << buf;
continue;
}
long offset = strtol(buf, 0, 16);
char* bp_0 = strchr(buf, '>') + 2;
KSym* ksym = find(eip_addr + offset);
if (ksym)
cout << *ksym << ' ';
char* bp = bp_0;
while (!isspace(*bp))
bp++;
while (isspace(*bp))
bp++;
if (*bp != '0') {
cout << bp_0;
} else if (*bp_0 == 'j' || strnequ(bp_0, "call", 4)) { // a jump or call insn
long rel_addr = strtol(bp, 0, 16);
ksym = find(eip_addr + rel_addr);
if (ksym) {
*bp++ = '\0';
cout << bp_0 << *ksym << endl;
} else
cout << bp_0;
} else {
cout << bp_0;
}
}
if (!lines)
clog << "Sorry, your " << objdump_command << " can't disassemble--you must upgrade your binutils." << endl;
pclose(objdump_FILE);
unlink(objfile_name);
}
istream& istream&
operator >> (istream& is, NameList& n) NameList::scan(istream& is)
{ {
KSym* ksyms = n.ksyms_0_; KSym* ksyms = ksyms_0_;
int cardinality = 0; int cardinality = 0;
while (!is.eof()) { while (!is.eof()) {
is >> *ksyms; is >> *ksyms;
if (cardinality++ > 0)
ksyms[-1].set_extent(*ksyms); ksyms[-1].set_extent(*ksyms);
ksyms++; ksyms++;
cardinality++;
} }
n.cardinality_ = --cardinality; cardinality_ = --cardinality;
return is; return is;
} }
...@@ -134,7 +247,7 @@ char const* program_name; ...@@ -134,7 +247,7 @@ char const* program_name;
void void
usage() usage()
{ {
clog << "Usage: " << program_name << " system-map-file < oops-log" << endl; clog << "Usage: " << program_name << " [ System.map ] < oops-log" << endl;
exit(1); exit(1);
} }
...@@ -142,38 +255,64 @@ int ...@@ -142,38 +255,64 @@ int
main(int argc, char** argv) main(int argc, char** argv)
{ {
program_name = (argc--, *argv++); program_name = (argc--, *argv++);
if (argc != 1)
usage();
NameList names;
if (argc > 1)
usage();
else if (argc == 1) {
char const* map_file_name = (argc--, *argv++); char const* map_file_name = (argc--, *argv++);
ifstream map(map_file_name); ifstream map(map_file_name);
if (map.bad()) { if (map.bad())
clog << program_name << ": Can't open `" << map_file_name << "'" << endl; clog << program_name << ": Can't open `" << map_file_name << "'" << endl;
return 1; else {
}
NameList names;
map >> names; map >> names;
cout << "Using `" << map_file_name << "' to map addresses to symbols." << endl;
}
}
if (!names.valid())
cout << "No symbol map. I'll only show you disassembled code." << endl;
cout << endl;
char buffer[1024]; char buffer[1024];
while (!cin.eof()) while (!cin.eof())
{ {
long address; long eip_addr;
cin >> buffer; cin >> buffer;
if (strequ(buffer, "EIP:")) { if (strequ(buffer, "EIP:") && names.valid()) {
cin >> hex >> address; cin >> ::hex >> eip_addr;
cin >> buffer[0]; cin >> buffer[0];
cin >> hex >> address; cin >> ::hex >> eip_addr;
KSym* ksym = names.find(address); cin >> buffer;
if (!strequ(buffer, "EFLAGS:")) {
clog << "Please strip the line-prefixes and rerun " << program_name << endl;
exit(1);
}
KSym* ksym = names.find(eip_addr);
if (ksym) if (ksym)
cout << "EIP: " << *ksym << endl; cout << ">>EIP: " << *ksym << endl;
} else if (strequ(buffer, "Trace:")) { } else if (strequ(buffer, "Trace:") && names.valid()) {
while ((cin >> address) && address > 0xc) { long address;
while ((cin >> ::hex >> address) && address > 0xc) {
cout << "Trace: ";
KSym* ksym = names.find(address); KSym* ksym = names.find(address);
if (ksym) if (ksym)
cout << "Trace: " << *ksym << endl; cout << *ksym;
else
cout << ::hex << address;
cout << endl;
} }
cout << endl; cout << endl;
} else if (strequ(buffer, "ode:") || strequ(buffer, "Code:")) {
// The 'C' might have been consumed as a hex number
unsigned char code[code_size];
unsigned char* cp = code;
unsigned char* end = &code[code_size];
while (cp < end) {
int c;
cin >> ::hex >> c;
*cp++ = c;
}
names.decode(code, eip_addr);
} }
} }
cout << flush; cout << flush;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment