Commit e19a1bdb authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.38

parent eebbb0b8
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 37
SUBLEVEL = 38
all: Version zImage
......@@ -153,6 +153,7 @@ tools/version.h: $(CONFIGURE) Makefile
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
@echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h
@echo \#define LINUX_COMPILE_DOMAIN \"`domainname`\" >> tools/version.h
@echo \#define LINUX_COMPILER \"`$(HOSTCC) -v 2>&1 | tail -1`\" >> tools/version.h
tools/build: tools/build.c $(CONFIGURE)
$(HOSTCC) $(CFLAGS) -o $@ $<
......
......@@ -53,6 +53,7 @@ bool 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 n
bool 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC n
bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN n
bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 n
bool 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx n
#bool 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 n
bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 n
bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE n
......
......@@ -20,12 +20,13 @@ OBJS = fpu_entry.o div_small.o errors.o \
fpu_arith.o fpu_aux.o fpu_etc.o fpu_trig.o \
load_store.o get_address.o \
poly_atan.o poly_l2.o poly_2xm1.o poly_sin.o poly_tan.o \
poly_div.o poly_mul64.o polynomial.o \
reg_add_sub.o reg_compare.o reg_constant.o reg_ld_str.o \
reg_div.o reg_mul.o reg_norm.o \
reg_u_add.o reg_u_div.o reg_u_mul.o reg_u_sub.o \
reg_round.o \
wm_shrx.o wm_sqrt.o
wm_shrx.o wm_sqrt.o \
div_Xsig.o polynom_Xsig.o round_Xsig.o \
shr_Xsig.o mul_Xsig.o
math.a: $(OBJS)
rm -f math.a
......
This diff is collapsed.
This diff is collapsed.
......@@ -235,10 +235,8 @@ static struct {
0x1nn in a *.c file:
0x101 in reg_add_sub.c
0x102 in reg_mul.c
0x103 in poly_sin.c
0x104 in poly_atan.c
0x105 in reg_mul.c
0x106 in reg_ld_str.c
0x107 in fpu_trig.c
0x108 in reg_compare.c
0x109 in reg_compare.c
......@@ -246,7 +244,6 @@ static struct {
0x111 in fpe_entry.c
0x112 in fpu_trig.c
0x113 in errors.c
0x114 in reg_ld_str.c
0x115 in fpu_trig.c
0x116 in fpu_trig.c
0x117 in fpu_trig.c
......@@ -267,6 +264,12 @@ static struct {
0x133 in get_address.c
0x140 in load_store.c
0x141 in load_store.c
0x150 in poly_sin.c
0x151 in poly_sin.c
0x160 in reg_ld_str.c
0x161 in reg_ld_str.c
0x162 in reg_ld_str.c
0x163 in reg_ld_str.c
0x2nn in an *.S file:
0x201 in reg_u_add.S
0x202 in reg_u_div.S
......@@ -292,6 +295,9 @@ static struct {
0x234 in reg_round.S
0x235 in reg_round.S
0x236 in reg_round.S
0x240 in div_Xsig.S
0x241 in div_Xsig.S
0x242 in div_Xsig.S
*/
void exception(int n)
......
......@@ -143,13 +143,6 @@ extern unsigned char const data_sizes_16[32];
/*----- Prototypes for functions written in assembler -----*/
/* extern void reg_move(FPU_REG *a, FPU_REG *b); */
asmlinkage void mul64(unsigned long long const *a, unsigned long long const *b,
unsigned long long *result);
asmlinkage void poly_div2(unsigned long long *x);
asmlinkage void poly_div4(unsigned long long *x);
asmlinkage void poly_div16(unsigned long long *x);
asmlinkage void polynomial(unsigned accum[], unsigned const x[],
unsigned short const terms[][4], int const n);
asmlinkage void normalize(FPU_REG *x);
asmlinkage void normalize_nuo(FPU_REG *x);
asmlinkage int reg_div(FPU_REG const *arg1, FPU_REG const *arg2,
......
......@@ -78,18 +78,18 @@ extern int load_store_instr(unsigned char type, fpu_addr_modes addr_modes,
extern int poly_2xm1(FPU_REG const *arg, FPU_REG *result);
/* poly_atan.c */
extern void poly_atan(FPU_REG *arg);
extern void poly_add_1(FPU_REG *src);
extern void poly_atan(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *result);
/* poly_l2.c */
extern void poly_l2(FPU_REG const *arg, FPU_REG *result);
extern int poly_l2p1(FPU_REG const *arg, FPU_REG *result);
extern void poly_l2(FPU_REG const *arg, FPU_REG const *y, FPU_REG *result);
extern int poly_l2p1(FPU_REG const *arg, FPU_REG const *y, FPU_REG *result);
/* poly_sin.c */
extern void poly_sine(FPU_REG const *arg, FPU_REG *result);
extern void poly_cos(FPU_REG const *arg, FPU_REG *result);
/* poly_tan.c */
extern void poly_tan(FPU_REG const *arg, FPU_REG *result, int invert);
extern void poly_tan(FPU_REG const *arg, FPU_REG *result);
/* reg_add_sub.c */
extern int reg_add(FPU_REG const *a, FPU_REG const *b,
......
......@@ -25,8 +25,9 @@ static void rem_kernel(unsigned long long st0, unsigned long long *y,
#define BETTER_THAN_486
#define FCOS 4
/* Not needed now with new code
#define FPTAN 1
*/
/* Used only by fptan, fsin, fcos, and fsincos. */
/* This routine produces very accurate results, similar to
......@@ -64,6 +65,7 @@ static int trig_arg(FPU_REG *X, int even)
reg_move(&tmp, X);
}
#ifdef FPTAN
if ( even == FPTAN )
{
if ( ((X->exp >= EXP_BIAS) ||
......@@ -73,6 +75,7 @@ static int trig_arg(FPU_REG *X, int even)
else
even = 0;
}
#endif FPTAN
if ( (even && !(q & 1)) || (!even && (q & 1)) )
{
......@@ -234,43 +237,27 @@ static void f2xm1(FPU_REG *st0_ptr)
{
case TW_Valid:
{
FPU_REG rv, tmp;
if ( st0_ptr->exp >= 0 )
{
/* For an 80486 FPU, the result is undefined. */
}
else if ( st0_ptr->exp >= -64 )
{
if ( st0_ptr->sign == SIGN_POS )
{
/* poly_2xm1(x) requires 0 < x < 1. */
poly_2xm1(st0_ptr, &rv);
reg_mul(&rv, st0_ptr, st0_ptr, FULL_PRECISION);
}
#ifdef DENORM_OPERAND
else if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
return;
#endif DENORM_OPERAND
else
{
/* poly_2xm1(x) doesn't handle negative numbers yet. */
/* So we compute z=poly_2xm1(-x), and the answer is
then -z/(1+z) */
st0_ptr->sign = SIGN_POS;
poly_2xm1(st0_ptr, &rv);
reg_mul(&rv, st0_ptr, &rv, FULL_PRECISION);
reg_add(&rv, &CONST_1, &tmp, FULL_PRECISION);
reg_div(&rv, &tmp, st0_ptr, FULL_PRECISION);
st0_ptr->sign = SIGN_NEG;
}
/* poly_2xm1(x) requires 0 < x < 1. */
poly_2xm1(st0_ptr, st0_ptr);
}
else
if ( st0_ptr->exp <= EXP_UNDER )
{
#ifdef DENORM_OPERAND
if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
return;
#endif DENORM_OPERAND
/* For very small arguments, this is accurate enough. */
reg_mul(&CONST_LN2, st0_ptr, st0_ptr, FULL_PRECISION);
/* A denormal result has been produced.
Precision must have been lost, this is always
an underflow. */
arith_underflow(st0_ptr);
}
set_precision_flag_up();
set_precision_flag_up(); /* 80486 appears to always do this */
return;
}
case TW_Zero:
......@@ -315,15 +302,12 @@ static void fptan(FPU_REG *st0_ptr)
switch ( st0_tag )
{
case TW_Valid:
if ( st0_ptr->exp > EXP_BIAS - 40 )
{
st0_ptr->sign = SIGN_POS;
if ( (q = trig_arg(st0_ptr, FPTAN)) != -1 )
if ( (q = trig_arg(st0_ptr, 0)) != -1 )
{
reg_div(st0_ptr, &CONST_PI2, st0_ptr,
FULL_PRECISION);
poly_tan(st0_ptr, st0_ptr, q & FCOS);
poly_tan(st0_ptr, st0_ptr);
st0_ptr->sign = (q & 1) ^ arg_sign;
}
else
......@@ -332,6 +316,7 @@ static void fptan(FPU_REG *st0_ptr)
st0_ptr->sign = arg_sign; /* restore st(0) */
return;
}
set_precision_flag_up(); /* We do not really know if up or down */
}
else
{
......@@ -350,8 +335,7 @@ static void fptan(FPU_REG *st0_ptr)
if ( arith_underflow(st0_ptr) )
return;
}
else
set_precision_flag_up(); /* Must be up. */
set_precision_flag_down(); /* Must be down. */
}
push();
reg_move(&CONST_1, st_new_ptr);
......@@ -550,7 +534,6 @@ static void fsin(FPU_REG *st0_ptr)
st0_ptr->sign = SIGN_POS;
if ( (q = trig_arg(st0_ptr, 0)) != -1 )
{
reg_div(st0_ptr, &CONST_PI2, st0_ptr, FULL_PRECISION);
poly_sine(st0_ptr, &rv);
......@@ -619,10 +602,20 @@ static int f_cos(FPU_REG *arg)
if ( arg->exp > EXP_BIAS - 40 )
{
arg->sign = SIGN_POS;
if ( (q = trig_arg(arg, FCOS)) != -1 )
if ( (arg->exp < EXP_BIAS)
|| ((arg->exp == EXP_BIAS)
&& (significand(arg) <= 0xc90fdaa22168c234LL)) )
{
reg_div(arg, &CONST_PI2, arg, FULL_PRECISION);
poly_cos(arg, &rv);
reg_move(&rv, arg);
/* We do not really know if up or down */
set_precision_flag_down();
return 0;
}
else if ( (q = trig_arg(arg, FCOS)) != -1 )
{
poly_sine(arg, &rv);
if ((q+1) & 2)
......@@ -988,38 +981,57 @@ static void do_fprem(FPU_REG *st0_ptr, int round)
static void fyl2x(FPU_REG *st0_ptr)
{
char st0_tag = st0_ptr->tag;
FPU_REG *st1_ptr = &st(1);
FPU_REG *st1_ptr = &st(1), exponent;
char st1_tag = st1_ptr->tag;
int e;
clear_C1();
if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
{
if ( st0_ptr->sign == SIGN_POS )
{
int saved_control, saved_status;
#ifdef DENORM_OPERAND
if ( ((st0_ptr->exp <= EXP_UNDER) ||
(st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()) )
return;
#endif DENORM_OPERAND
/* We use the general purpose arithmetic,
so we need to save these. */
saved_status = partial_status;
saved_control = control_word;
control_word = FULL_PRECISION;
poly_l2(st0_ptr, st0_ptr);
/* Enough of the basic arithmetic is done now */
control_word = saved_control;
partial_status = saved_status;
/* Let the multiply set the flags */
reg_mul(st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION);
if ( (st0_ptr->sigh == 0x80000000) && (st0_ptr->sigl == 0) )
{
/* Special case. The result can be precise. */
e = st0_ptr->exp - EXP_BIAS;
if ( e > 0 )
{
exponent.sigh = e;
exponent.sign = SIGN_POS;
}
else
{
exponent.sigh = -e;
exponent.sign = SIGN_NEG;
}
exponent.sigl = 0;
exponent.exp = EXP_BIAS + 31;
exponent.tag = TW_Valid;
normalize_nuo(&exponent);
reg_mul(&exponent, st1_ptr, st1_ptr, FULL_PRECISION);
}
else
{
/* The usual case */
poly_l2(st0_ptr, st1_ptr, st1_ptr);
if ( st1_ptr->exp <= EXP_UNDER )
{
/* A denormal result has been produced.
Precision must have been lost, this is always
an underflow. */
arith_underflow(st1_ptr);
}
else
set_precision_flag_up(); /* 80486 appears to always do this */
}
pop();
return;
}
else
{
......@@ -1181,67 +1193,27 @@ static void fpatan(FPU_REG *st0_ptr)
char st0_tag = st0_ptr->tag;
FPU_REG *st1_ptr = &st(1);
char st1_tag = st1_ptr->tag;
char st1_sign = st1_ptr->sign, st0_sign = st0_ptr->sign;
clear_C1();
if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
{
int saved_control, saved_status;
FPU_REG sum;
char inverted;
#ifdef DENORM_OPERAND
if ( ((st0_ptr->exp <= EXP_UNDER) ||
(st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()) )
return;
#endif DENORM_OPERAND
/* We use the general purpose arithmetic so we need to save these. */
saved_status = partial_status;
saved_control = control_word;
control_word = FULL_PRECISION;
poly_atan(st0_ptr, st1_ptr, st1_ptr);
st1_ptr->sign = st0_ptr->sign = SIGN_POS;
if ( (compare(st1_ptr) & ~COMP_Denormal) == COMP_A_lt_B )
{
inverted = 1;
reg_div(st0_ptr, st1_ptr, &sum, FULL_PRECISION);
}
else
{
inverted = 0;
if ( (st0_sign == 0) &&
(st1_ptr->exp - st0_ptr->exp < -64) )
if ( st1_ptr->exp <= EXP_UNDER )
{
control_word = saved_control;
partial_status = saved_status;
reg_div(st1_ptr, st0_ptr, st1_ptr,
control_word | PR_64_BITS);
st1_ptr->sign = st1_sign;
/* A denormal result has been produced.
Precision must have been lost.
This is by definition an underflow. */
arith_underflow(st1_ptr);
pop();
set_precision_flag_down();
return;
}
reg_div(st1_ptr, st0_ptr, &sum, FULL_PRECISION);
}
poly_atan(&sum);
if ( inverted )
{
reg_sub(&CONST_PI2, &sum, &sum, FULL_PRECISION);
}
if ( st0_sign )
{
reg_sub(&CONST_PI, &sum, &sum, FULL_PRECISION);
}
sum.sign = st1_sign;
/* All of the basic arithmetic is done now */
control_word = saved_control;
partial_status = saved_status;
reg_move(&sum, st1_ptr);
}
else if ( (st0_tag == TW_Empty) || (st1_tag == TW_Empty) )
{
......@@ -1358,48 +1330,41 @@ static void fprem1(FPU_REG *st0_ptr)
static void fyl2xp1(FPU_REG *st0_ptr)
{
char st0_tag = st0_ptr->tag;
char st0_tag = st0_ptr->tag, sign;
FPU_REG *st1_ptr = &st(1);
char st1_tag = st1_ptr->tag;
clear_C1();
if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
{
int saved_control, saved_status;
#ifdef DENORM_OPERAND
if ( ((st0_ptr->exp <= EXP_UNDER) ||
(st1_ptr->exp <= EXP_UNDER)) && denormal_operand() )
return;
#endif DENORM_OPERAND
/* We use the general purpose arithmetic so we need to save these. */
saved_status = partial_status;
saved_control = control_word;
control_word = FULL_PRECISION;
if ( poly_l2p1(st0_ptr, st0_ptr) )
if ( poly_l2p1(st0_ptr, st1_ptr, st1_ptr) )
{
#ifdef PECULIAR_486 /* Stupid 80486 doesn't worry about log(negative). */
st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
control_word = saved_control;
partial_status = saved_status;
set_precision_flag_down();
#else
if ( arith_invalid(st1_ptr) ) /* poly_l2p1() returned invalid */
return;
#endif PECULIAR_486
pop(); return;
}
/* Enough of the basic arithmetic is done now */
control_word = saved_control;
partial_status = saved_status;
/* Let the multiply set the flags */
reg_mul(st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION);
if ( st1_ptr->exp <= EXP_UNDER )
{
/* A denormal result has been produced.
Precision must have been lost, this is always
an underflow. */
sign = st1_ptr->sign;
arith_underflow(st1_ptr);
st1_ptr->sign = sign;
}
else
set_precision_flag_up(); /* 80486 appears to always do this */
pop();
return;
}
else if ( (st0_tag == TW_Empty) | (st1_tag == TW_Empty) )
{
......
/*---------------------------------------------------------------------------+
| mul_Xsig.S |
| |
| Multiply a 12 byte fixed point number by another fixed point number. |
| |
| Copyright (C) 1992,1994 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| Call from C as: |
| void mul32_Xsig(Xsig *x, unsigned b) |
| |
| void mul64_Xsig(Xsig *x, unsigned long long *b) |
| |
| void mul_Xsig_Xsig(Xsig *x, unsigned *b) |
| |
| The result is neither rounded nor normalized, and the ls bit or so may |
| be wrong. |
| |
+---------------------------------------------------------------------------*/
.file "mul_Xsig.S"
#include "fpu_asm.h"
.text
.align 2,144
.globl _mul32_Xsig
_mul32_Xsig:
pushl %ebp
movl %esp,%ebp
subl $16,%esp
pushl %esi
movl PARAM1,%esi
movl PARAM2,%ecx
xor %eax,%eax
movl %eax,-4(%ebp)
movl %eax,-8(%ebp)
movl (%esi),%eax /* lsl of Xsig */
mull %ecx /* msl of b */
movl %edx,-12(%ebp)
movl 4(%esi),%eax /* midl of Xsig */
mull %ecx /* msl of b */
addl %eax,-12(%ebp)
adcl %edx,-8(%ebp)
adcl $0,-4(%ebp)
movl 8(%esi),%eax /* msl of Xsig */
mull %ecx /* msl of b */
addl %eax,-8(%ebp)
adcl %edx,-4(%ebp)
movl -12(%ebp),%eax
movl %eax,(%esi)
movl -8(%ebp),%eax
movl %eax,4(%esi)
movl -4(%ebp),%eax
movl %eax,8(%esi)
popl %esi
leave
ret
.align 2,144
.globl _mul64_Xsig
_mul64_Xsig:
pushl %ebp
movl %esp,%ebp
subl $16,%esp
pushl %esi
movl PARAM1,%esi
movl PARAM2,%ecx
xor %eax,%eax
movl %eax,-4(%ebp)
movl %eax,-8(%ebp)
movl (%esi),%eax /* lsl of Xsig */
mull 4(%ecx) /* msl of b */
movl %edx,-12(%ebp)
movl 4(%esi),%eax /* midl of Xsig */
mull (%ecx) /* lsl of b */
addl %edx,-12(%ebp)
adcl $0,-8(%ebp)
adcl $0,-4(%ebp)
movl 4(%esi),%eax /* midl of Xsig */
mull 4(%ecx) /* msl of b */
addl %eax,-12(%ebp)
adcl %edx,-8(%ebp)
adcl $0,-4(%ebp)
movl 8(%esi),%eax /* msl of Xsig */
mull (%ecx) /* lsl of b */
addl %eax,-12(%ebp)
adcl %edx,-8(%ebp)
adcl $0,-4(%ebp)
movl 8(%esi),%eax /* msl of Xsig */
mull 4(%ecx) /* msl of b */
addl %eax,-8(%ebp)
adcl %edx,-4(%ebp)
movl -12(%ebp),%eax
movl %eax,(%esi)
movl -8(%ebp),%eax
movl %eax,4(%esi)
movl -4(%ebp),%eax
movl %eax,8(%esi)
popl %esi
leave
ret
.align 2,144
.globl _mul_Xsig_Xsig
_mul_Xsig_Xsig:
pushl %ebp
movl %esp,%ebp
subl $16,%esp
pushl %esi
movl PARAM1,%esi
movl PARAM2,%ecx
xor %eax,%eax
movl %eax,-4(%ebp)
movl %eax,-8(%ebp)
movl (%esi),%eax /* lsl of Xsig */
mull 8(%ecx) /* msl of b */
movl %edx,-12(%ebp)
movl 4(%esi),%eax /* midl of Xsig */
mull 4(%ecx) /* midl of b */
addl %edx,-12(%ebp)
adcl $0,-8(%ebp)
adcl $0,-4(%ebp)
movl 8(%esi),%eax /* msl of Xsig */
mull (%ecx) /* lsl of b */
addl %edx,-12(%ebp)
adcl $0,-8(%ebp)
adcl $0,-4(%ebp)
movl 4(%esi),%eax /* midl of Xsig */
mull 8(%ecx) /* msl of b */
addl %eax,-12(%ebp)
adcl %edx,-8(%ebp)
adcl $0,-4(%ebp)
movl 8(%esi),%eax /* msl of Xsig */
mull 4(%ecx) /* midl of b */
addl %eax,-12(%ebp)
adcl %edx,-8(%ebp)
adcl $0,-4(%ebp)
movl 8(%esi),%eax /* msl of Xsig */
mull 8(%ecx) /* msl of b */
addl %eax,-8(%ebp)
adcl %edx,-4(%ebp)
movl -12(%ebp),%edx
movl %edx,(%esi)
movl -8(%ebp),%edx
movl %edx,4(%esi)
movl -4(%ebp),%edx
movl %edx,8(%esi)
popl %esi
leave
ret
/*---------------------------------------------------------------------------+
| poly.h |
| |
| Header file for the FPU-emu poly*.c source files. |
| |
| Copyright (C) 1994 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| Declarations and definitions for functions operating on Xsig (12-byte |
| extended-significand) quantities. |
| |
+---------------------------------------------------------------------------*/
#ifndef _POLY_H
#define _POLY_H
/* This 12-byte structure is used to improve the accuracy of computation
of transcendental functions.
Intended to be used to get results better than 8-byte computation
allows. 9-byte would probably be sufficient.
*/
typedef struct {
unsigned long lsw;
unsigned long midw;
unsigned long msw;
} Xsig;
asmlinkage void mul64(unsigned long long const *a, unsigned long long const *b,
unsigned long long *result);
asmlinkage void polynomial_Xsig(Xsig *, const unsigned long long *x,
const unsigned long long terms[], const int n);
asmlinkage void mul32_Xsig(Xsig *, const unsigned long mult);
asmlinkage void mul64_Xsig(Xsig *, const unsigned long long *mult);
asmlinkage void mul_Xsig_Xsig(Xsig *dest, const Xsig *mult);
asmlinkage void shr_Xsig(Xsig *, const int n);
asmlinkage int round_Xsig(Xsig *);
asmlinkage int norm_Xsig(Xsig *);
asmlinkage void div_Xsig(Xsig *x1, const Xsig *x2, const Xsig *dest);
/* Macro to extract the most significant 32 bits from a long long */
#define LL_MSW(x) (((unsigned long *)&x)[1])
/* Macro to initialize an Xsig struct */
#define MK_XSIG(a,b,c) { c, b, a }
/* Macro to access the 8 ms bytes of an Xsig as a long long */
#define XSIG_LL(x) (*(unsigned long long *)&x.midw)
/*
Need to run gcc with optimizations on to get these to
actually be in-line.
*/
/* Multiply two fixed-point 32 bit numbers. */
extern inline void mul_32_32(const unsigned long arg1,
const unsigned long arg2,
unsigned long *out)
{
asm volatile ("movl %1,%%eax; mull %2; movl %%edx,%0" \
:"=g" (*out) \
:"g" (arg1), "g" (arg2) \
:"ax","dx");
}
/* Add the 12 byte Xsig x2 to Xsig dest, with no checks for overflow. */
extern inline void add_Xsig_Xsig(Xsig *dest, const Xsig *x2)
{
asm volatile ("movl %1,%%edi; movl %2,%%esi;
movl (%%esi),%%eax; addl %%eax,(%%edi);
movl 4(%%esi),%%eax; adcl %%eax,4(%%edi);
movl 8(%%esi),%%eax; adcl %%eax,8(%%edi);"
:"=g" (*dest):"g" (dest), "g" (x2)
:"ax","si","di");
}
/* Add the 12 byte Xsig x2 to Xsig dest, adjust exp if overflow occurs. */
/* Note: the constraints in the asm statement didn't always work properly
with gcc 2.5.8. Changing from using edi to using ecx got around the
problem, but keep fingers crossed! */
extern inline int add_two_Xsig(Xsig *dest, const Xsig *x2, long int *exp)
{
asm volatile ("movl %2,%%ecx; movl %3,%%esi;
movl (%%esi),%%eax; addl %%eax,(%%ecx);
movl 4(%%esi),%%eax; adcl %%eax,4(%%ecx);
movl 8(%%esi),%%eax; adcl %%eax,8(%%ecx);
jnc 0f;
rcrl 8(%%ecx); rcrl 4(%%ecx); rcrl (%%ecx)
movl %4,%%ecx; incl (%%ecx)
movl $1,%%eax; jmp 1f;
0: xorl %%eax,%%eax;
1:"
:"=g" (*exp), "=g" (*dest)
:"g" (dest), "g" (x2), "g" (exp)
:"cx","si","ax");
}
/* Negate (subtract from 1.0) the 12 byte Xsig */
/* This is faster in a loop on my 386 than using the "neg" instruction. */
extern inline void negate_Xsig(Xsig *x)
{
asm volatile("movl %1,%%esi; "
"xorl %%ecx,%%ecx; "
"movl %%ecx,%%eax; subl (%%esi),%%eax; movl %%eax,(%%esi); "
"movl %%ecx,%%eax; sbbl 4(%%esi),%%eax; movl %%eax,4(%%esi); "
"movl %%ecx,%%eax; sbbl 8(%%esi),%%eax; movl %%eax,8(%%esi); "
:"=g" (*x):"g" (x):"si","ax","cx");
}
#endif _POLY_H
......@@ -3,7 +3,7 @@
| |
| Function to compute 2^x-1 by a polynomial approximation. |
| |
| Copyright (C) 1992,1993 |
| Copyright (C) 1992,1993,1994 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
......@@ -13,43 +13,54 @@
#include "exception.h"
#include "reg_constant.h"
#include "fpu_emu.h"
#include "control_w.h"
#include "poly.h"
#define HIPOWER 13
static unsigned short const lterms[HIPOWER][4] =
{
{ 0x79b5, 0xd1cf, 0x17f7, 0xb172 },
{ 0x1b56, 0x058b, 0x7bff, 0x3d7f },
{ 0x8bb0, 0x8250, 0x846b, 0x0e35 },
{ 0xbc65, 0xf747, 0x556d, 0x0276 },
{ 0x17cb, 0x9e39, 0x61ff, 0x0057 },
{ 0xe018, 0x9776, 0x1848, 0x000a },
{ 0x66f2, 0xff30, 0xffe5, 0x0000 },
{ 0x682f, 0xffb6, 0x162b, 0x0000 },
{ 0xb7ca, 0x2956, 0x01b5, 0x0000 },
{ 0xcd3e, 0x4817, 0x001e, 0x0000 },
{ 0xb7e2, 0xecbe, 0x0001, 0x0000 },
{ 0x0ed5, 0x1a27, 0x0000, 0x0000 },
{ 0x101d, 0x0222, 0x0000, 0x0000 },
};
#define HIPOWER 11
static const unsigned long long lterms[HIPOWER] =
{
0x0000000000000000LL, /* This term done separately as 12 bytes */
0xf5fdeffc162c7543LL,
0x1c6b08d704a0bfa6LL,
0x0276556df749cc21LL,
0x002bb0ffcf14f6b8LL,
0x0002861225ef751cLL,
0x00001ffcbfcd5422LL,
0x00000162c005d5f1LL,
0x0000000da96ccb1bLL,
0x0000000078d1b897LL,
0x000000000422b029LL
};
static const Xsig hiterm = MK_XSIG(0xb17217f7, 0xd1cf79ab, 0xc8a39194);
/* Four slices: 0.0 : 0.25 : 0.50 : 0.75 : 1.0,
These numbers are 2^(1/4), 2^(1/2), and 2^(3/4)
*/
static const Xsig shiftterm0 = MK_XSIG(0, 0, 0);
static const Xsig shiftterm1 = MK_XSIG(0x9837f051, 0x8db8a96f, 0x46ad2318);
static const Xsig shiftterm2 = MK_XSIG(0xb504f333, 0xf9de6484, 0x597d89b3);
static const Xsig shiftterm3 = MK_XSIG(0xd744fcca, 0xd69d6af4, 0x39a68bb9);
static const Xsig *shiftterm[] = { &shiftterm0, &shiftterm1,
&shiftterm2, &shiftterm3 };
/*--- poly_2xm1() -----------------------------------------------------------+
| Requires a positive argument which is TW_Valid and < 1. |
| Requires an argument which is TW_Valid and < 1. |
+---------------------------------------------------------------------------*/
int poly_2xm1(FPU_REG const *arg, FPU_REG *result)
{
short exponent;
long long Xll;
FPU_REG accum;
long int exponent, shift;
unsigned long long Xll;
Xsig accumulator, Denom, argSignif;
exponent = arg->exp - EXP_BIAS;
#ifdef PARANOID
if ( (arg->sign != SIGN_POS) /* Can't hack a number < 0.0 */
|| (exponent >= 0) /* or a |number| >= 1.0 */
if ( (exponent >= 0) /* Don't want a |number| >= 1.0 */
|| (arg->tag != TW_Valid) )
{
/* Number negative, too large, or not Valid. */
......@@ -58,27 +69,83 @@ int poly_2xm1(FPU_REG const *arg, FPU_REG *result)
}
#endif PARANOID
*(unsigned *)&Xll = arg->sigl;
*(((unsigned *)&Xll)+1) = arg->sigh;
if ( exponent < -1 )
argSignif.lsw = 0;
XSIG_LL(argSignif) = Xll = significand(arg);
if ( exponent == -1 )
{
shift = (argSignif.msw & 0x40000000) ? 3 : 2;
/* subtract 0.5 or 0.75 */
exponent -= 2;
XSIG_LL(argSignif) <<= 2;
Xll <<= 2;
}
else if ( exponent == -2 )
{
shift = 1;
/* subtract 0.25 */
exponent--;
XSIG_LL(argSignif) <<= 1;
Xll <<= 1;
}
else
shift = 0;
if ( exponent < -2 )
{
/* Shift the argument right by the required places. */
if ( shrx(&Xll, -1-exponent) >= 0x80000000U )
if ( shrx(&Xll, -2-exponent) >= 0x80000000U )
Xll++; /* round up */
}
*(short *)&(accum.sign) = 0; /* Will be a valid positive nr with expon = 0 */
accum.exp = 0;
accumulator.lsw = accumulator.midw = accumulator.msw = 0;
polynomial_Xsig(&accumulator, &Xll, lterms, HIPOWER-1);
mul_Xsig_Xsig(&accumulator, &argSignif);
shr_Xsig(&accumulator, 3);
/* Do the basic fixed point polynomial evaluation */
polynomial((unsigned *)&accum.sigl, (unsigned *)&Xll, lterms, HIPOWER-1);
mul_Xsig_Xsig(&argSignif, &hiterm); /* The leading term */
add_two_Xsig(&accumulator, &argSignif, &exponent);
/* Convert to 64 bit signed-compatible */
accum.exp += EXP_BIAS - 1;
if ( shift )
{
/* The argument is large, use the identity:
f(x+a) = f(a) * (f(x) + 1) - 1;
*/
shr_Xsig(&accumulator, - exponent);
accumulator.msw |= 0x80000000; /* add 1.0 */
mul_Xsig_Xsig(&accumulator, shiftterm[shift]);
accumulator.msw &= 0x3fffffff; /* subtract 1.0 */
exponent = 1;
}
reg_move(&accum, result);
if ( arg->sign != SIGN_POS )
{
/* The argument is negative, use the identity:
f(-x) = -f(x) / (1 + f(x))
*/
Denom.lsw = accumulator.lsw;
XSIG_LL(Denom) = XSIG_LL(accumulator);
if ( exponent < 0 )
shr_Xsig(&Denom, - exponent);
else if ( exponent > 0 )
{
/* exponent must be 1 here */
XSIG_LL(Denom) <<= 1;
if ( Denom.lsw & 0x80000000 )
XSIG_LL(Denom) |= 1;
(Denom.lsw) <<= 1;
}
Denom.msw |= 0x80000000; /* add 1.0 */
div_Xsig(&accumulator, &Denom, &accumulator);
}
/* Convert to 64 bit signed-compatible */
exponent += round_Xsig(&accumulator);
normalize(result);
significand(result) = XSIG_LL(accumulator);
result->tag = TW_Valid;
result->exp = exponent + EXP_BIAS;
result->sign = arg->sign;
return 0;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*---------------------------------------------------------------------------+
| polynomial_Xsig.S |
| |
| Fixed point arithmetic polynomial evaluation. |
| |
| Copyright (C) 1992,1993,1994 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| Call from C as: |
| void polynomial_Xsig(Xsig *accum, unsigned long long x, |
| unsigned long long terms[], int n) |
| |
| Computes: |
| terms[0] + (terms[1] + (terms[2] + ... + (terms[n-1]*x)*x)*x)*x) ... )*x |
| and adds the result to the 12 byte Xsig. |
| The terms[] are each 8 bytes, but all computation is performed to 12 byte |
| precision. |
| |
| This function must be used carefully: most overflow of intermediate |
| results is controlled, but overflow of the result is not. |
| |
+---------------------------------------------------------------------------*/
.file "polynomial_Xsig.S"
#include "fpu_asm.h"
#define TERM_SIZE $8
#define SUM_MS -20(%ebp) /* sum ms long */
#define SUM_MIDDLE -24(%ebp) /* sum middle long */
#define SUM_LS -28(%ebp) /* sum ls long */
#define ACCUM_MS -4(%ebp) /* accum ms long */
#define ACCUM_MIDDLE -8(%ebp) /* accum middle long */
#define ACCUM_LS -12(%ebp) /* accum ls long */
#define OVERFLOWED -16(%ebp) /* addition overflow flag */
.text
.align 2,144
.globl _polynomial_Xsig
_polynomial_Xsig:
pushl %ebp
movl %esp,%ebp
subl $32,%esp
pushl %esi
pushl %edi
pushl %ebx
movl PARAM2,%esi /* x */
movl PARAM3,%edi /* terms */
movl TERM_SIZE,%eax
mull PARAM4 /* n */
addl %eax,%edi
movl 4(%edi),%edx /* terms[n] */
movl %edx,SUM_MS
movl (%edi),%edx /* terms[n] */
movl %edx,SUM_MIDDLE
xor %eax,%eax
movl %eax,SUM_LS
movb %al,OVERFLOWED
subl TERM_SIZE,%edi
decl PARAM4
js L_accum_done
L_accum_loop:
xor %eax,%eax
movl %eax,ACCUM_MS
movl %eax,ACCUM_MIDDLE
movl SUM_MIDDLE,%eax
mull (%esi) /* x ls long */
movl %edx,ACCUM_LS
movl SUM_MIDDLE,%eax
mull 4(%esi) /* x ms long */
addl %eax,ACCUM_LS
adcl %edx,ACCUM_MIDDLE
adcl $0,ACCUM_MS
movl SUM_MS,%eax
mull (%esi) /* x ls long */
addl %eax,ACCUM_LS
adcl %edx,ACCUM_MIDDLE
adcl $0,ACCUM_MS
movl SUM_MS,%eax
mull 4(%esi) /* x ms long */
addl %eax,ACCUM_MIDDLE
adcl %edx,ACCUM_MS
testb $0xff,OVERFLOWED
jz L_no_overflow
movl (%esi),%eax
addl %eax,ACCUM_MIDDLE
movl 4(%esi),%eax
adcl %eax,ACCUM_MS /* This could overflow too */
L_no_overflow:
/*
* Now put the sum of next term and the accumulator
* into the sum register
*/
movl ACCUM_LS,%eax
addl (%edi),%eax /* term ls long */
movl %eax,SUM_LS
movl ACCUM_MIDDLE,%eax
adcl (%edi),%eax /* term ls long */
movl %eax,SUM_MIDDLE
movl ACCUM_MS,%eax
adcl 4(%edi),%eax /* term ms long */
movl %eax,SUM_MS
sbbb %al,%al
movb %al,OVERFLOWED /* Used in the next iteration */
subl TERM_SIZE,%edi
decl PARAM4
jns L_accum_loop
L_accum_done:
movl PARAM1,%edi /* accum */
movl SUM_LS,%eax
addl %eax,(%edi)
movl SUM_MIDDLE,%eax
adcl %eax,4(%edi)
movl SUM_MS,%eax
adcl %eax,8(%edi)
popl %ebx
popl %edi
popl %esi
leave
ret
......@@ -825,7 +825,7 @@ int reg_store_single(float *single, FPU_REG *st0_ptr)
#ifdef PARANOID
else
{
EXCEPTION(EX_INTERNAL|0x106);
EXCEPTION(EX_INTERNAL|0x163);
return 0;
}
#endif
......@@ -1389,16 +1389,16 @@ static void write_to_extended(FPU_REG *rp, char *d)
{
case TW_Zero:
if ( rp->sigh | rp->sigl | e )
EXCEPTION(EX_INTERNAL | 0x114);
EXCEPTION(EX_INTERNAL | 0x160);
break;
case TW_Infinity:
case TW_NaN:
if ( (e ^ 0x7fff) | !(rp->sigh & 0x80000000) )
EXCEPTION(EX_INTERNAL | 0x114);
EXCEPTION(EX_INTERNAL | 0x161);
break;
default:
if (e > 0x7fff || e < -63)
EXCEPTION(EX_INTERNAL | 0x114);
EXCEPTION(EX_INTERNAL | 0x162);
}
#endif PARANOID
......
/*---------------------------------------------------------------------------+
| round_Xsig.S |
| |
| Copyright (C) 1992,1993,1994 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| Normalize and round a 12 byte quantity. |
| Call from C as: |
| int round_Xsig(Xsig *n) |
| |
| Normalize a 12 byte quantity. |
| Call from C as: |
| int norm_Xsig(Xsig *n) |
| |
| Each function returns the size of the shift (nr of bits). |
| |
+---------------------------------------------------------------------------*/
.file "round_Xsig.S"
#include "fpu_asm.h"
.text
.align 2,144
.globl _round_Xsig
_round_Xsig:
pushl %ebp
movl %esp,%ebp
pushl %ebx /* Reserve some space */
pushl %ebx
pushl %esi
movl PARAM1,%esi
movl 8(%esi),%edx
movl 4(%esi),%ebx
movl (%esi),%eax
movl $0,-4(%ebp)
orl %edx,%edx /* ms bits */
js L_round /* Already normalized */
jnz L_shift_1 /* Shift left 1 - 31 bits */
movl %ebx,%edx
movl %eax,%ebx
xorl %eax,%eax
movl $-32,-4(%ebp)
/* We need to shift left by 1 - 31 bits */
L_shift_1:
bsrl %edx,%ecx /* get the required shift in %ecx */
subl $31,%ecx
negl %ecx
subl %ecx,-4(%ebp)
shld %cl,%ebx,%edx
shld %cl,%eax,%ebx
shl %cl,%eax
L_round:
testl $0x80000000,%eax
jz L_exit
addl $1,%ebx
adcl $0,%edx
jnz L_exit
movl $0x80000000,%edx
incl -4(%ebp)
L_exit:
movl %edx,8(%esi)
movl %ebx,4(%esi)
movl %eax,(%esi)
movl -4(%ebp),%eax
popl %esi
popl %ebx
leave
ret
.align 2,144
.globl _norm_Xsig
_norm_Xsig:
pushl %ebp
movl %esp,%ebp
pushl %ebx /* Reserve some space */
pushl %ebx
pushl %esi
movl PARAM1,%esi
movl 8(%esi),%edx
movl 4(%esi),%ebx
movl (%esi),%eax
movl $0,-4(%ebp)
orl %edx,%edx /* ms bits */
js L_n_exit /* Already normalized */
jnz L_n_shift_1 /* Shift left 1 - 31 bits */
movl %ebx,%edx
movl %eax,%ebx
xorl %eax,%eax
movl $-32,-4(%ebp)
orl %edx,%edx /* ms bits */
js L_n_exit /* Normalized now */
jnz L_n_shift_1 /* Shift left 1 - 31 bits */
movl %ebx,%edx
movl %eax,%ebx
xorl %eax,%eax
addl $-32,-4(%ebp)
jmp L_n_exit /* Might not be normalized,
but shift no more. */
/* We need to shift left by 1 - 31 bits */
L_n_shift_1:
bsrl %edx,%ecx /* get the required shift in %ecx */
subl $31,%ecx
negl %ecx
subl %ecx,-4(%ebp)
shld %cl,%ebx,%edx
shld %cl,%eax,%ebx
shl %cl,%eax
L_n_exit:
movl %edx,8(%esi)
movl %ebx,4(%esi)
movl %eax,(%esi)
movl -4(%ebp),%eax
popl %esi
popl %ebx
leave
ret
.file "shr_Xsig.S"
/*---------------------------------------------------------------------------+
| shr_Xsig.S |
| |
| 12 byte right shift function |
| |
| Copyright (C) 1992,1994 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@vaxc.cc.monash.edu.au |
| |
| Call from C as: |
| void shr_Xsig(Xsig *arg, unsigned nr) |
| |
| Extended shift right function. |
| Fastest for small shifts. |
| Shifts the 12 byte quantity pointed to by the first arg (arg) |
| right by the number of bits specified by the second arg (nr). |
| |
+---------------------------------------------------------------------------*/
#include "fpu_asm.h"
.text
.align 2,144
.globl _shr_Xsig
_shr_Xsig:
push %ebp
movl %esp,%ebp
pushl %esi
movl PARAM2,%ecx
movl PARAM1,%esi
cmpl $32,%ecx /* shrd only works for 0..31 bits */
jnc L_more_than_31
/* less than 32 bits */
pushl %ebx
movl (%esi),%eax /* lsl */
movl 4(%esi),%ebx /* midl */
movl 8(%esi),%edx /* msl */
shrd %cl,%ebx,%eax
shrd %cl,%edx,%ebx
shr %cl,%edx
movl %eax,(%esi)
movl %ebx,4(%esi)
movl %edx,8(%esi)
popl %ebx
popl %esi
leave
ret
L_more_than_31:
cmpl $64,%ecx
jnc L_more_than_63
subb $32,%cl
movl 4(%esi),%eax /* midl */
movl 8(%esi),%edx /* msl */
shrd %cl,%edx,%eax
shr %cl,%edx
movl %eax,(%esi)
movl %edx,4(%esi)
movl $0,8(%esi)
popl %esi
leave
ret
L_more_than_63:
cmpl $96,%ecx
jnc L_more_than_95
subb $64,%cl
movl 8(%esi),%eax /* msl */
shr %cl,%eax
xorl %edx,%edx
movl %eax,(%esi)
movl %edx,4(%esi)
movl %edx,8(%esi)
popl %esi
leave
ret
L_more_than_95:
xorl %eax,%eax
movl %eax,(%esi)
movl %eax,4(%esi)
movl %eax,8(%esi)
popl %esi
leave
ret
......@@ -9,4 +9,4 @@
| |
+---------------------------------------------------------------------------*/
#define FPU_VERSION "wm-FPU-emu version 1.12"
#define FPU_VERSION "wm-FPU-emu version 1.20"
This README belongs to release 2.3 of the SoundBlaster Pro (Matsushita,
This README belongs to release 2.5 of the SoundBlaster Pro (Matsushita,
Kotobuki, Panasonic, CreativeLabs) CD-ROM driver for Linux.
The driver is able to drive the whole family of IDE-style
Matsushita/Kotobuki/Panasonic drives (the "double speed" versions like CR-562
and CR-563, too), and it will work with the soundcard interfaces (SB Pro,
SB 16, Galaxy, SoundFX, ...) and/or with the "no-sound" cards (Panasonic
CI-101P, LaserMate, WDH-7001C, Aztech, ...).
The driver is able to drive the whole family of "traditional" IDE-style (that
has nothing to do with the new "Enhanced IDE" drive standard) Matsushita,
Kotobuki, Panasonic drives, sometimes labelled as "CreativeLabs". The
well-known drives are CR-521, CR-522, CR-523, CR-562, CR-563.
This driver is NOT for Mitsumi or Sony or Aztech or Philips or XXX drives.
The matter that some other brand's drives work with newer sound card
interfaces does NOT make the drives compatible. :-)
It will work with the soundcard interfaces (SB Pro, SB 16, Galaxy, SoundFX,
...) and/or with the "no-sound" cards (Panasonic CI-101P, LaserMate,
WDH-7001C, older Aztech cards, ...).
It should work too now with the "configurable" interface "Sequoia S-1000",
which is found on the Spea Media FX sound card.
The interface type has to get configured in /usr/include/linux/sbpcd.h,
......@@ -15,11 +22,12 @@ The driver respects different drive firmware releases - my old drive is a 2.11,
but it should work with "old" drives <2.01 ... >3.00 and with "new" drives
(which count the releases around 0.75 or 1.00).
Up to 4 drives are supported. CR-52x ("old") and CR-56x ("new") drives can be
mixed, but the CR-521 ones are hard-wired to drive ID 0. The drives have to
use different drive IDs, and each drive has to get a unique minor number
(0...3), corresponding to it's drive ID. The drive IDs may be selected freely
from 0 to 3 - they must not be in consecutive order.
Up to 4 drives per interface card, and up to 4 interface cards are supported.
CR-52x ("old") and CR-56x ("new") drives can be mixed, but the CR-521 ones are
hard-wired to drive ID 0. The drives have to use different drive IDs, and each
drive has to get a unique minor number (0...3), corresponding to it's drive ID.
The drive IDs may be selected freely from 0 to 3 - they do not have to be in
consecutive order.
As Don Carroll, don@ds9.us.dell.com or FIDO 1:382/14, told me, it is possible
to change old drives to any ID, too. He writes in this sense:
......@@ -39,8 +47,9 @@ to change old drives to any ID, too. He writes in this sense:
ID 3 behaves like ID 0."
To use more than 4 drives (now that the single-speed CR-521's are as cheap as
50$), you have to "duplicate" the driver. Just copy sbpcd.c into sbpcd2.c and
change SBPCD_ISSUE accordingly.
50$), you need a second interface card and you have to "duplicate" the driver.
Just copy sbpcd.c into sbpcd2.c and so forth and change SBPCD_ISSUE
accordingly.
The driver supports reading of data from the CD and playing of audio tracks.
The audio part should run with WorkMan, xcdplayer, with the "non-X11" products
......@@ -168,7 +177,9 @@ execution of a binary from the CD; you have to copy it to a device with the
standard BLOCK_SIZE (1024) before. So, do not use this if your system is
directly "running from the CDROM" (like some of YGGDRASIL's installation
variants). There are CDs on the market (like the german "unifix" Linux
distribution) which MUST get handled with a block_size of 1024.
distribution) which MUST get handled with a block_size of 1024. Generally,
one can say all the CDs which hold files of the name YMTRANS.TBL are defective;
do not use block=2048 with those.
Auto-probing at boot time:
......@@ -209,9 +220,9 @@ Most of the "SoundBlaster compatible" cards behave like the no-sound
interfaces!
With "original" SB Pro cards, an initial setting of CD_volume through the
sound cards MIXER register gets done. That happens at the end of "sbpcd_init".
If you are using a "compatible" sound card of type "LaserMate", you can change
that code to get it done with your card, too...
sound cards MIXER register gets done.
If you are using a "compatible" sound card of types "LaserMate" or "SPEA",
you can set SOUND_BASE (in sbpcd.h) to get it done with your card, too...
Using audio CDs:
......@@ -367,9 +378,9 @@ Known problems:
Currently, the detection of disk change or removal is actively disabled.
All attempts to read the UPC/EAN code result in a stream of zeroes. All my
drives are telling there is no UPC/EAN code on disk or there is, but it is an
all-zero number.
Most attempts to read the UPC/EAN code result in a stream of zeroes. All my
drives are mostly telling there is no UPC/EAN code on disk or there is, but it
is an all-zero number. I guess now almost no CD holds such a number.
Bug reports, comments, wishes, donations (technical information is a donation,
too :-) etc. to
......
......@@ -1773,7 +1773,7 @@ scd_open(struct inode *inode,
if (filp->f_mode & 2)
return -EACCES;
return -EROFS;
if (!sony_spun_up)
{
......
......@@ -1417,7 +1417,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
if (filp->f_mode & 2) {
if (1 & (read_only >> drive)) {
floppy_release(inode, filp);
return -EACCES;
return -EROFS;
}
}
}
......
......@@ -1031,7 +1031,7 @@ mcd_open(struct inode *ip, struct file *fp)
return -ENXIO; /* no hardware */
if (fp->f_mode & 2) /* write access? */
return -EACCES;
return -EROFS;
if (!mcd_open_count && mcd_state == MCD_S_IDLE) {
......
......@@ -5,7 +5,7 @@
* and for "no-sound" interfaces like Lasermate and the
* Panasonic CI-101P.
*
* NOTE: This is release 2.4.
* NOTE: This is release 2.5.
* It works with my SbPro & drive CR-521 V2.11 from 2/92
* and with the new CR-562-B V0.75 on a "naked" Panasonic
* CI-101P interface. And vice versa.
......@@ -119,6 +119,12 @@
*
* 2.4 Use different names for device registering.
*
* 2.5 Added "#ifdef EJECT" code (default: enabled) to automatically eject
* the tray during last call to "sbpcd_release".
* Added "#ifdef JUKEBOX" code (default: disabled) to automatically eject
* the tray during call to "sbpcd_open" if no disk is in.
* Turn on the CD volume of "compatible" sound cards, too; just define
* SOUND_BASE (in sbpcd.h) accordingly (default: disabled).
*
* TODO
*
......@@ -195,7 +201,7 @@
#include "blk.h"
#define VERSION "2.4 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define VERSION "2.5 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define SBPCD_DEBUG
......@@ -211,6 +217,8 @@
/*
* still testing around...
*/
#define JUKEBOX 0 /* tray control: eject if no disk is in */
#define EJECT 1 /* tray control: eject tray after last use */
#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
#define MANY_SESSION 0 /* this will conflict with "true" multi-session! */
#undef FUTURE
......@@ -3226,7 +3234,7 @@ static int sbpcd_open(struct inode *ip, struct file *fp)
if (ndrives==0) return (-ENXIO); /* no hardware */
if (fp->f_mode & 2)
return -EACCES;
return -EROFS;
i = MINOR(ip->i_rdev);
if ( (i<0) || (i>=NR_SBPCD) )
......@@ -3254,9 +3262,14 @@ static int sbpcd_open(struct inode *ip, struct file *fp)
if (!st_door_closed||!st_caddy_in)
{
printk("SBPCD: sbpcd_open: no disk in drive\n");
#if JUKEBOX
do
i=yy_LockDoor(0);
while (i!=0);
if (new_drive) yy_SpinDown(); /* eject tray */
#endif
return (-ENXIO);
}
/*
* try to keep an "open" counter here and lock the door if 0->1.
*/
......@@ -3308,6 +3321,9 @@ static void sbpcd_release(struct inode * ip, struct file * file)
do
i=yy_LockDoor(0);
while (i!=0);
#ifdef EJECT
if (new_drive) yy_SpinDown();
#endif
}
}
}
......@@ -3559,10 +3575,20 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
if (i>=0) DriveStruct[d].CD_changed=1;
}
if (sbpro_type==1)
/*
* Turn on the CD audio channels.
* For "compatible" soundcards (with "SBPRO 0" or "SBPRO 2"), the addresses
* are obtained from SOUND_BASE (see sbpcd.h).
*/
if ((sbpro_type==1) || (SOUND_BASE))
{
OUT(MIXER_addr,MIXER_CD_Volume);
OUT(MIXER_data,0xCC); /* one nibble per channel */
if (sbpro_type!=1)
{
MIXER_addr=SOUND_BASE+0x04; /* sound card's address register */
MIXER_data=SOUND_BASE+0x05; /* sound card's data register */
}
OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */
OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
}
if (register_blkdev(MAJOR_NR, major_name, &sbpcd_fops) != 0)
......
......@@ -58,7 +58,7 @@ extern int ni52_probe(struct device *);
extern int ni65_probe(struct device *);
extern int SK_init(struct device *);
/* Detachable devices ("pocket adaptors" and special PCMCIA drivers). */
/* Detachable devices ("pocket adaptors") */
extern int atp_init(struct device *);
extern int de600_probe(struct device *);
extern int de620_probe(struct device *);
......@@ -144,38 +144,6 @@ ethif_probe(struct device *dev)
return 0;
}
#ifdef CONFIG_PCMCIA_NET
extern int dl_open(struct device *dev);
extern int tc589_open(struct device *dev);
extern int ibmccae_open(struct device *dev);
static int pc_eth_open(struct device *dev);
static int pc_eth_probe(struct device *dev)
{
dev->open = &pc_eth_open;
dev->set_config = &ether_config;
dev->tbusy = 1;
return 0;
}
static int pc_eth_open(struct device *dev)
{
if (1
#ifdef CONFIG_DE650
&& dl_open(dev)
#endif
#ifdef CONFIG_3C589
&& tc589_open(dev)
#endif
#ifdef CONFIG_IBMCCAE
&& ibmccae_open(dev)
#endif
&& 1)
return -ENODEV;
else
return 0;
}
#endif /* CONFIG_PCMCIA_NET */
/* Run-time ATtachable (Pocket) devices have a different (not "eth#") name. */
......@@ -186,17 +154,6 @@ static struct device atp_dev = {
# define NEXT_DEV (&atp_dev)
#endif
#ifdef CONFIG_PCMCIA_NET
static struct device pc_eth1_dev = {
"pc_eth1", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, pc_eth_probe,
};
static struct device pc_eth0_dev = {
"pc_eth0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &pc_eth1_dev, pc_eth_probe,
};
# undef NEXT_DEV
# define NEXT_DEV (&pc_eth0_dev)
#endif /* CONFIG_PCMCIA_NET */
/* The first device defaults to I/O base '0', which means autoprobe. */
#ifndef ETH0_ADDR
# define ETH0_ADDR 0
......
......@@ -114,6 +114,29 @@
used and the common memory area is in low memory on the network card (my
current system has 20MB and I've not had problems yet).
The ability to load this driver as a loadable module has been added. To
utilise this ability, you have to do <8 things:
1) copy depca.c from the /linux/drivers/net directory to your favourite
temporary directory.
2) edit the source code near line 1530 to reflect the I/O address and
IRQ you're using.
3) compile depca.c, but include -DMODULE in the command line to ensure
that the correct bits are compiled (see end of source code).
4) if you are wanting to add a new card, goto 5. Otherwise, recompile a
kernel with the depca configuration turned off and reboot.
5) insmod depca.o
6) run the net startup bits for your eth?? interface manually
(usually /etc/rc.inet[12] at boot time).
7) enjoy!
Note that autoprobing is not allowed in loadable modules - the system is
already up and running and you're messing with interrupts. Also, there
is no way to check on the number of depcas installed at the moment.
To unload a module, turn off the associated interface
'ifconfig eth?? down' then 'rmmod depca'.
TO DO:
------
......@@ -125,7 +148,7 @@
Version Date Description
0.1 25-jan-94 Initial writing.
0.2 27-jan-94 Added LANCE TX buffer chaining.
0.2 27-jan-94 Added LANCE TX hardware buffer chaining.
0.3 1-feb-94 Added multiple DEPCA support.
0.31 4-feb-94 Added DE202 recognition.
0.32 19-feb-94 Tidy up. Improve multi-DEPCA support.
......@@ -136,11 +159,12 @@
0.35 8-mar-94 Added DE201 recognition. Tidied up.
0.351 30-apr-94 Added EISA support. Added DE422 recognition.
0.36 16-may-94 DE422 fix released.
0.37 22-jul-94 Added MODULE support
=========================================================================
*/
static char *version = "depca.c:v0.36 5/16/94 davies@wanton.lkg.dec.com\n";
static char *version = "depca.c:v0.37 7/22/94 davies@wanton.lkg.dec.com\n";
#include <stdarg.h>
#include <linux/config.h>
......@@ -159,12 +183,18 @@ static char *version = "depca.c:v0.36 5/16/94 davies@wanton.lkg.dec.com\n";
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#ifdef MODULE
#include <linux/module.h>
#include "/linux/tools/version.h"
#endif /* MODULE */
#include "depca.h"
#ifdef DEPCA_DEBUG
int depca_debug = DEPCA_DEBUG;
static int depca_debug = DEPCA_DEBUG;
#else
int depca_debug = 1;
static int depca_debug = 1;
#endif
#ifndef PROBE_LENGTH
......@@ -302,12 +332,20 @@ static int DevicePresent(short ioaddr);
#ifdef HAVE_MULTICAST
static void SetMulticastFilter(int num_addrs, char *addrs, char *multicast_table);
#endif
#ifndef MODULE
static struct device *isa_probe(struct device *dev);
static struct device *eisa_probe(struct device *dev);
static struct device *alloc_device(struct device *dev, int ioaddr);
static int num_depcas = 0, num_eth = 0;;
#else
int init_module(void);
void cleanup_module(void);
#endif /* MODULE */
/*
** Miscellaneous defines...
*/
......@@ -320,9 +358,11 @@ static int num_depcas = 0, num_eth = 0;;
int depca_probe(struct device *dev)
{
int base_addr = dev->base_addr;
short base_addr = dev->base_addr;
int status = -ENODEV;
#ifndef MODULE
struct device *eth0;
#endif
if (base_addr > 0x1ff) { /* Check a single specified location. */
if (DevicePresent(base_addr) == 0) { /* Is DEPCA really here? */
......@@ -331,10 +371,16 @@ int depca_probe(struct device *dev)
} else if (base_addr > 0) { /* Don't probe at all. */
status = -ENXIO;
} else { /* First probe for the DEPCA test */
/* pattern in ROM */
#ifdef MODULE /* pattern in ROM */
printk("Autoprobing is not supported when loading a module based driver.\n");
status = -EIO;
#else
eth0=isa_probe(dev);
eth0=eisa_probe(eth0);
if (dev->priv) status=0;
#endif /* MODULE */
}
if (status) dev->base_addr = base_addr;
......@@ -563,6 +609,7 @@ depca_probe1(struct device *dev, short ioaddr)
/* To auto-IRQ we enable the initialization-done and DMA err,
interrupts. For now we will always get a DMA error. */
if (dev->irq < 2) {
#ifndef MODULE
autoirq_setup(0);
/* Trigger an initialization just for the interrupt. */
......@@ -575,6 +622,7 @@ depca_probe1(struct device *dev, short ioaddr)
printk(" and failed to detect IRQ line.\n");
status = -EAGAIN;
}
#endif /* MODULE */
} else {
printk(" and assigned IRQ%d.\n", dev->irq);
}
......@@ -690,6 +738,10 @@ depca_open(struct device *dev)
printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR));
}
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
return 0; /* Always succeed */
}
......@@ -1091,6 +1143,10 @@ depca_close(struct device *dev)
irq2dev_map[dev->irq] = 0;
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
return 0;
}
......@@ -1229,6 +1285,7 @@ static void SetMulticastFilter(int num_addrs, char *addrs, char *multicast_table
#endif /* HAVE_MULTICAST */
#ifndef MODULE
/*
** ISA bus I/O device probe
*/
......@@ -1242,11 +1299,6 @@ struct device *dev;
*port && (num_depcas < MAX_NUM_DEPCAS); port++) {
int ioaddr = *port;
#ifdef HAVE_PORTRESERVE
if (check_region(ioaddr, DEPCA_TOTAL_SIZE))
continue;
#endif
if (DevicePresent(ioaddr) == 0) {
if (num_depcas > 0) { /* only gets here in autoprobe */
dev = alloc_device(dev, ioaddr);
......@@ -1274,10 +1326,6 @@ struct device *dev;
ioaddr+=0x1000; /* get the first slot address */
for (status = -ENODEV, i=1; i<MAX_EISA_SLOTS; i++, ioaddr+=0x1000) {
#ifdef HAVE_PORTRESERVE
if (check_region(ioaddr, DEPCA_TOTAL_SIZE))
continue;
#endif
if (DevicePresent(ioaddr) == 0) {
if (num_depcas > 0) { /* only gets here in autoprobe */
dev = alloc_device(dev, ioaddr);
......@@ -1340,6 +1388,7 @@ int ioaddr;
return dev;
}
#endif /* MODULE */
/*
** Look for a particular board name in the on-board Remote Diagnostics
......@@ -1473,12 +1522,38 @@ static char asc2hex(char value)
return value; /* return hex char or error */
}
#ifdef MODULE
char kernel_version[] = UTS_RELEASE;
static struct device thisDepca = {
" ", /* device name inserted by /linux/drivers/net/net_init.c */
0, 0, 0, 0,
0x200, 7, /* I/O address, IRQ <--- EDIT THIS LINE FOR YOUR CONFIGURATION */
0, 0, 0, NULL, depca_probe };
int
init_module(void)
{
if (register_netdev(&thisDepca) != 0)
return -EIO;
return 0;
}
void
cleanup_module(void)
{
if (MOD_IN_USE) {
printk("%s: device busy, remove delayed\n",thisDepca.name);
} else {
unregister_netdev(&thisDepca);
}
}
#endif /* MODULE */
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c depca.c"
* kernel-compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c depca.c"
*
* module-compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c depca.c"
* End:
*/
......@@ -194,28 +194,29 @@ int register_netdev(struct device *dev)
{
struct device *d = dev_base;
unsigned long flags;
int i;
int i=MAX_ETH_CARDS;
save_flags(flags);
cli();
if (dev && dev->init) {
if (dev->init(dev) != 0) {
restore_flags(flags);
return -EIO;
}
if (dev->name &&
((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
for (i = 0; i < MAX_ETH_CARDS; ++i)
if (ethdev_index[i] == NULL) {
sprintf(dev->name, "eth%d", i);
printk("device '%s' loaded\n", dev->name);
printk("loading device '%s'...\n", dev->name);
ethdev_index[i] = dev;
break;
}
}
if (dev->init(dev) != 0) {
if (i < MAX_ETH_CARDS) ethdev_index[i] = NULL;
restore_flags(flags);
return -EIO;
}
/* Add device to end of chain */
if (dev_base) {
while (d->next)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#undef A_addr_scratch
#undef A_addr_sfbr
#undef A_addr_temp
#undef A_dmode_memory_to_memory
#undef A_dmode_memory_to_ncr
#undef A_dmode_ncr_to_memory
#undef A_dmode_ncr_to_ncr
#undef A_dsa_check_reselect
#undef A_dsa_cmdout
#undef A_dsa_cmnd
#undef A_dsa_datain
#undef A_dsa_dataout
#undef A_dsa_end
#undef A_dsa_fields_start
#undef A_dsa_msgin
#undef A_dsa_msgout
#undef A_dsa_msgout_other
#undef A_dsa_next
#undef A_dsa_select
#undef A_dsa_status
#undef A_dsa_temp_dsa_next
#undef A_dsa_temp_jump_resume
#undef A_dsa_temp_lun
#undef A_dsa_temp_sync
#undef A_dsa_temp_target
#undef A_int_debug_break
#undef A_int_debug_dsa_loaded
#undef A_int_debug_head
#undef A_int_debug_idle
#undef A_int_debug_reselected
#undef A_int_debug_scheduled
#undef A_int_err_check_condition
#undef A_int_err_no_phase
#undef A_int_err_selected
#undef A_int_err_unexpected_phase
#undef A_int_err_unexpected_reselect
#undef A_int_msg_1
#undef A_int_msg_sdtr
#undef A_int_msg_wdtr
#undef A_int_norm_aborted
#undef A_int_norm_command_complete
#undef A_int_norm_disconnected
#undef A_int_norm_reselect_complete
#undef A_int_norm_reset
#undef A_int_norm_select_complete
#undef A_int_test_1
#undef A_int_test_2
#undef A_int_test_3
#undef A_issue_dsa_head
#undef A_msg_buf
#undef A_reconnect_dsa_head
#undef A_reselected_identify
#undef A_reselected_tag
#undef A_test_dest
#undef A_test_src
#undef Ent_accept_message
#undef Ent_cmdout_cmdout
#undef Ent_command_complete
#undef Ent_command_complete_msgin
#undef Ent_debug_break
#undef Ent_dsa_code_check_reselect
#undef Ent_dsa_code_template
#undef Ent_dsa_code_template_end
#undef Ent_dsa_jump_resume
#undef Ent_dsa_schedule
#undef Ent_dsa_zero
#undef Ent_initiator_abort
#undef Ent_msg_in
#undef Ent_other_transfer
#undef Ent_reject_message
#undef Ent_reselected_check_next
#undef Ent_respond_message
#undef Ent_schedule
#undef Ent_select
#undef Ent_select_msgout
#undef Ent_target_abort
#undef Ent_test_1
#undef Ent_test_2
#undef Ent_test_2_msgout
#
# Makefile for kernel/blk_drv/scsi
#
# Note! Dependencies are done automagically by 'make dep', which also
......@@ -24,8 +24,8 @@ SCSI_SRCS =
ifdef CONFIG_SCSI
SCSI_OBJS := hosts.o scsi.o scsi_ioctl.o constants.o
SCSI_SRCS := hosts.c scsi.c scsi_ioctl.c constants.c
SCSI_OBJS := hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o
SCSI_SRCS := hosts.c scsi.c scsi_ioctl.c constants.c scsicam.c
ifdef CONFIG_CHR_DEV_ST
SCSI_OBJS := $(SCSI_OBJS) st.o
......@@ -87,6 +87,11 @@ SCSI_OBJS := $(SCSI_OBJS) g_NCR5380.o
SCSI_SRCS := $(SCSI_SRCS) g_NCR5380.c
endif
#ifdef CONFIG_SCSI_NCR53C7xx
SCSI_OBJS := $(SCSI_OBJS) 53c7,8xx.o
SCSI_SRCS := $(SCSI_SRCS) 53c7,8xx.c
#endif
ifdef CONFIG_SCSI_PAS16
SCSI_OBJS := $(SCSI_OBJS) pas16.o
SCSI_SRCS := $(SCSI_SRCS) pas16.c
......@@ -131,6 +136,17 @@ aha152x.o: aha152x.c
seagate.o: seagate.c
$(CC) $(CFLAGS) -DARBITRATE -DSLOW_HANDSHAKE -DFAST32 -c seagate.c
# For debugging, use the -g flag
53c7,8xx.o : 53c7,8xx.c
$(CC) $(CFLAGS) -g -c 53c7,8xx.c
53c8xx_d.h 53c8xx_u.h : 53c7,8xx.scr script_asm.pl
ln 53c7,8xx.scr fake.c
$(CPP) -DCHIP=810 fake.c | grep -v ^# | perl script_asm.pl
mv script.h 53c8xx_d.h
mv scriptu.h 53c8xx_u.h
rm fake.c
dep:
$(CPP) -M $(AHA152X) $(SCSI_SRCS) > .depend
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* fdomain.h -- Header for Future Domain TMC-16x0 driver
* Created: Sun May 3 18:47:33 1992 by faith@cs.unc.edu
* Revised: Sat Mar 19 16:07:14 1994 by faith@cs.unc.edu
* Revised: Sat Jul 30 20:20:31 1994 by faith@cs.unc.edu
* Author: Rickard E. Faith, faith@cs.unc.edu
* Copyright 1992, 1993, 1994 Rickard E. Faith
*
* $Id: fdomain.h,v 5.5 1994/03/19 21:07:38 root Exp $
* $Id: fdomain.h,v 5.7 1994/07/31 03:09:15 faith Exp $
* 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
......@@ -27,12 +27,11 @@
int fdomain_16x0_detect( Scsi_Host_Template * );
int fdomain_16x0_command( Scsi_Cmnd * );
int fdomain_16x0_abort( Scsi_Cmnd *);
int fdomain_16x0_abort( Scsi_Cmnd * );
const char *fdomain_16x0_info( void );
int fdomain_16x0_reset( Scsi_Cmnd * );
int fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
int fdomain_16x0_biosparam(Disk *, int, int * );
int fdomain_16x0_biosparam( Disk *, int, int * );
#define FDOMAIN_16X0 { NULL, \
"Future Domain TMC-16x0", \
......@@ -47,9 +46,9 @@ int fdomain_16x0_biosparam(Disk *, int, int * );
fdomain_16x0_biosparam, \
1, \
6, \
64 /* SG_NONE */, \
64, \
1, \
0, \
0, \
DISABLE_CLUSTERING}
DISABLE_CLUSTERING }
#endif
......@@ -79,6 +79,10 @@ int generic_NCR5380_reset(Scsi_Cmnd *);
#define NCR5380_abort generic_NCR5380_abort
#define NCR5380_reset generic_NCR5380_reset
#define BOARD_NORMAL 0
#define BOARD_NCR53C400 1
#endif /* else def HOSTS_C */
#endif /* ndef ASM */
#endif /* GENERIC_NCR5380_H */
......@@ -67,6 +67,10 @@
#include "t128.h"
#endif
#ifdef CONFIG_SCSI_NCR53C7xx
#include "53c7,8xx.h"
#endif
#ifdef CONFIG_SCSI_ULTRASTOR
#include "ultrastor.h"
#endif
......@@ -146,6 +150,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_T128
TRANTOR_T128,
#endif
#ifdef CONFIG_SCSI_NCR53C7xx
NCR53c7xx,
#endif
#ifdef CONFIG_SCSI_7000FASST
WD7000,
#endif
......
This diff is collapsed.
......@@ -36,7 +36,7 @@
#ifndef PAS16_H
#define PAS16_H
#define PAS16_PUBLIC_RELEASE 1
#define PAS16_PUBLIC_RELEASE 2
#define PDEBUG_INIT 0x1
#define PDEBUG_TRANSFER 0x2
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -5,6 +5,7 @@
#define SCSI_IOCTL_SEND_COMMAND 1
#define SCSI_IOCTL_TEST_UNIT_READY 2
#define SCSI_IOCTL_BENCHMARK_COMMAND 3
#define SCSI_IOCTL_SYNC 4 /* Request synchronous parameters */
/* The door lock/unlock constants are compatible with Sun constants for
the cdrom */
#define SCSI_IOCTL_DOORLOCK 0x5380 /* lock the eject mechanism */
......
This diff is collapsed.
This diff is collapsed.
......@@ -672,7 +672,7 @@ static int internal_command(unsigned char target, unsigned char lun, const void
*/
for (clock = jiffies + 10, temp = 0; (jiffies < clock) &&
!(STATUS & STAT_IO););
!((temp = STATUS) & STAT_IO) || (STAT & STAT_BSY););
if (jiffies >= clock)
{
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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