Commit fde9fa96 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.93

parent 24a1c2a7
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 92
SUBLEVEL = 93
ARCH = i386
......
......@@ -107,7 +107,7 @@ void *malloc(int size)
}
if (free_mem_ptr < 0x90000)
return p;
puts("memory is tight...");
puts("large kernel, low 1M tight...");
free_mem_ptr = (long)input_data;
}
}
......
......@@ -765,8 +765,12 @@ unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
}
printk ("bios32_init : BIOS32 Service Directory structure at 0x%p\n", check);
if (!bios32_entry) {
bios32_indirect.address = bios32_entry = check->fields.entry;
printk ("bios32_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
if (check->fields.entry >= 0x100000) {
printk("bios32_init: entry in high memory, unable to access\n");
} else {
bios32_indirect.address = bios32_entry = check->fields.entry;
printk ("bios32_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
}
} else {
printk ("bios32_init : multiple entries, mail drew@colorado.edu\n");
/*
......
......@@ -10,7 +10,9 @@
#include <asm/head.h>
#include <asm/asi.h>
#include <asm/psr.h>
#include <asm/cprefix.h>
#include <asm/vaddrs.h>
/* Here are macros for routines we do often, this allows me to inline this
* without making the code look real ugly. Well, the macro looks ugly too but
......@@ -179,12 +181,15 @@
andcc %l0, 0x40, %g0; \
bz 1f; \
andcc %l4, %l5, %g0; \
bz,a 0f; \
sethi %hi( C_LABEL(eintstack) ), %l7; \
or %l7, %lo( C_LABEL(eintstack) ), %l7; \
bz 0f; \
nop; \
TRAP_WIN_CLEAN \
sethi %hi( C_LABEL(eintstack) ), %l7; \
0: cmp %fp, %l7; \
bge,a 3f; \
or %l7, %lo( C_LABEL(eintstack) ), %l7; \
0: subcc %fp, %l7, %g0; \
bg,a 3f; \
sub %l7, 0xb0, %sp; \
b 3f; \
sub %fp, 0xb0, %sp; \
......@@ -204,12 +209,13 @@
5: st %l5, [%l6 + THREAD_UWINDOWS]; \
bz,a 2f; \
sethi %hi( C_LABEL(eintstack) ), %l7; \
TRAP_WIN_CLEAN; \
TRAP_WIN_CLEAN \
sethi %hi( C_LABEL(eintstack) ), %l7; \
2: \
sub %l7, 0xb0, %sp; \
3:
.text
.align 4
......@@ -240,15 +246,257 @@ my_trap_handler:
rett %l2
#endif /* bogon */
.align 4
.globl sparc_timer
sparc_timer:
ENTER_IRQ
or %g0, 0x10, %o0
call C_LABEL(do_IRQ)
sethi %hi(TIMER_VADDR), %l4
or %l4, %lo(TIMER_VADDR), %l4 ! read the limit register
ld [%l4 + 0xc], %l4 ! to clear the interrupt
rd %wim, %l4
or %g0, 0x1, %l5
sll %l5, %l0, %l5
andcc %l0, 0x40, %g0
bz st1
sethi %hi( C_LABEL(eintstack) ), %l7
andcc %l4, %l5, %g0
bz st0
or %l7, %lo( C_LABEL(eintstack) ), %l7
TRAP_WIN_CLEAN
sethi %hi( C_LABEL(eintstack) ), %l7
or %l7, %lo( C_LABEL(eintstack) ), %l7
st0: subcc %fp, %l7, %g0
bg,a st3
sub %l7, 0xb0, %sp
b st3
sub %fp, 0xb0, %sp
st1: sethi %hi( C_LABEL(current) ), %l6
ld [%l6 + %lo( C_LABEL(current) )], %l6
ld [%l6 + THREAD_WIM], %l5
and %l0, 0x1f, %l7
cmp %l5, %l7
ble,a st4
sethi %hi( C_LABEL(nwindowsm1) ), %l4
sub %l5, %l7, %l7
b st5
sub %l7, 0x1, %l5
st4: ld [%l4 + %lo( C_LABEL(nwindowsm1) )], %l4
sub %l4, %l7, %l4
add %l5, %l4, %l5
st5: st %l5, [%l6 + THREAD_UWINDOWS]
sethi %hi( C_LABEL(eintstack) ), %l7
bz,a st2
or %l7, %lo( C_LABEL(eintstack) ), %l7
TRAP_WIN_CLEAN
sethi %hi( C_LABEL(eintstack) ), %l7
or %l7, %lo( C_LABEL(eintstack) ), %l7
st2: sub %l7, 0xb0, %sp
st3: std %g2, [%sp + 96 + 24]
or %g0, %g1, %l7
rd %y, %l6
std %g4, [%sp + 96 + 32]
andn %l0, PSR_PIL, %l4
sll %l3, 0x8, %l5
std %g6, [%sp + 96 + 40]
or %l5, %l4, %l4
wr %l4, 0x0, %psr
wr %l4, PSR_ET, %psr
std %l0, [%sp + 96 + 0]
std %l2, [%sp + 96 + 8]
st %fp, [%sp + 96 + 16]
or %g0, 14, %o0
or %g0, %g0, %o1
call C_LABEL(do_sparc_timer)
nop
or %g0, %l7, %g1
wr %l6, 0x0, %y
ldd [%sp + 96 + 24], %g2
ldd [%sp + 96 + 32], %g4
ldd [%sp + 96 + 40], %g6
wr %l0, 0x0, %psr
nop
nop
nop
and %l0, 31, %l5
sethi %hi(lnx_winmask), %l6
or %l6, %lo(lnx_winmask), %l6
ldub [%l6 + %l5], %l5
andcc %l0, PSR_PS, %g0
bnz 1f
rd %wim, %l4
1: andcc %l5, %l4, %g0
bnz 2f
wr %l0, 0x0, %psr
nop
nop
nop
jmp %l1
rett %l2
2: wr %g0, 0x0, %wim
nop
nop
nop
restore
restore %g0, 0x1, %l1
rd %psr, %l0
and %l0, 31, %l0
sll %l1, %l0, %l1
wr %l1, 0x0, %wim
sethi %hi( C_LABEL(current) ), %l1
ld [%l1 + %lo( C_LABEL(current) ) ], %l1
st %l0, [%l1 + THREAD_WIM]
save %g0, %g0, %g0
ldd [%sp], %l0
ldd [%sp + 0x8], %l2
ldd [%sp + 0x10], %l4
ldd [%sp + 0x18], %l6
ldd [%sp + 0x20], %i0
ldd [%sp + 0x28], %i2
ldd [%sp + 0x30], %i4
ldd [%sp + 0x38], %i6
save %g0, %g0, %g0
jmp %l1
rett %l2
/* For now all IRQ's not registered get sent here so I can see
* what is poking the chip.
*/
.align 4
.globl stray_irq_entry
stray_irq_entry:
rd %wim, %l4
or %g0, 0x1, %l5
sll %l5, %l0, %l5
andcc %l0, 0x40, %g0
bz tt1
sethi %hi( C_LABEL(eintstack) ), %l7
andcc %l4, %l5, %g0
bz tt0
or %l7, %lo( C_LABEL(eintstack) ), %l7
TRAP_WIN_CLEAN
sethi %hi( C_LABEL(eintstack) ), %l7
or %l7, %lo( C_LABEL(eintstack) ), %l7
tt0: subcc %fp, %l7, %g0
bg,a tt3
sub %l7, 0xb0, %sp
b tt3
sub %fp, 0xb0, %sp
tt1: sethi %hi( C_LABEL(current) ), %l6
ld [%l6 + %lo( C_LABEL(current) )], %l6
ld [%l6 + THREAD_WIM], %l5
and %l0, 0x1f, %l7
cmp %l5, %l7
ble,a tt4
sethi %hi( C_LABEL(nwindowsm1) ), %l4
sub %l5, %l7, %l7
b tt5
sub %l7, 0x1, %l5
tt4: ld [%l4 + %lo( C_LABEL(nwindowsm1) )], %l4
sub %l4, %l7, %l4
add %l5, %l4, %l5
tt5: st %l5, [%l6 + THREAD_UWINDOWS]
sethi %hi( C_LABEL(eintstack) ), %l7
bz,a tt2
or %l7, %lo( C_LABEL(eintstack) ), %l7
TRAP_WIN_CLEAN
sethi %hi( C_LABEL(eintstack) ), %l7
or %l7, %lo( C_LABEL(eintstack) ), %l7
tt2: sub %l7, 0xb0, %sp
tt3: std %g2, [%sp + 96 + 24]
or %g0, %g1, %l7
rd %y, %l6
std %g4, [%sp + 96 + 32]
andn %l0, PSR_PIL, %l4
sll %l3, 0x8, %l5
std %g6, [%sp + 96 + 40]
or %l5, %l4, %l4
wr %l4, 0x0, %psr
wr %l4, PSR_ET, %psr
std %l0, [%sp + 96 + 0]
std %l2, [%sp + 96 + 8]
st %fp, [%sp + 96 + 16]
or %g0, %l3, %o0
or %g0, %g0, %o1
call C_LABEL(unexpected_irq)
nop
or %g0, %l7, %g1
wr %l6, 0x0, %y
ldd [%sp + 96 + 24], %g2
ldd [%sp + 96 + 32], %g4
ldd [%sp + 96 + 40], %g6
wr %l0, 0x0, %psr
nop
nop
nop
and %l0, 31, %l5
sethi %hi(lnx_winmask), %l6
or %l6, %lo(lnx_winmask), %l6
ldub [%l6 + %l5], %l5
andcc %l0, PSR_PS, %g0
bnz 1f
rd %wim, %l4
1: andcc %l5, %l4, %g0
bnz 2f
wr %l0, 0x0, %psr
nop
nop
nop
jmp %l1
rett %l2
nop
2: wr %g0, 0x0, %wim
nop
nop
nop
restore
restore %g0, 0x1, %l1
rd %psr, %l0
and %l0, 31, %l0
sll %l1, %l0, %l1
wr %l1, 0x0, %wim
sethi %hi( C_LABEL(current) ), %l1
ld [%l1 + %lo( C_LABEL(current) ) ], %l1
st %l0, [%l1 + THREAD_WIM]
save %g0, %g0, %g0
ldd [%sp], %l0
ldd [%sp + 0x8], %l2
ldd [%sp + 0x10], %l4
ldd [%sp + 0x18], %l6
ldd [%sp + 0x20], %i0
ldd [%sp + 0x28], %i2
ldd [%sp + 0x30], %i4
ldd [%sp + 0x38], %i6
save %g0, %g0, %g0
jmp %l1
rett %l2
/* This routine is optimized for kernel window fills. User fills take about two
* or three extra jumps on the average. We'll see how this works out.
......@@ -529,7 +777,7 @@ leave_trap:
.data
.align 4
lnx_winmask: .byte 2, 4, 8, 16, 32, 64, 128,1 ! lnx_winmask[0..7]
lnx_winmask: .byte 2, 4, 8, 16, 32, 64, 128, 1 ! lnx_winmask[0..7]
.align 4
......
......@@ -263,7 +263,7 @@ C_LABEL(trapbase):
TRAP_ENTRY_INTERRUPT(11) /* Interrupt Level 11 */
TRAP_ENTRY_INTERRUPT(12) /* Interrupt Level 12 */
TRAP_ENTRY_INTERRUPT(13) /* Interrupt Level 13 */
TRAP_ENTRY(0x27, sparc_timer) /* Interrupt Level 14 */
TRAP_ENTRY_TIMER /* Interrupt Level 14 */
TRAP_ENTRY_INTERRUPT_NMI(15, linux_trap_nmi) /* Level 15 (nmi) */
TRAP_ENTRY(0x20, my_trap_handler) /* General Register Access Error */
......@@ -370,7 +370,7 @@ C_LABEL(trapbase):
TRAP_ENTRY(0x85, my_trap_handler) /* Software Trap */
TRAP_ENTRY(0x86, my_trap_handler) /* Fix Unaligned Access Trap XXX */
TRAP_ENTRY(0x87, my_trap_handler) /* Integer Overflow Trap XXX */
TRAP_ENTRY(0x88, my_trap_handler) /* Software Trap */
TRAP_ENTRY(0x88, my_trap_handler) /* Slowaris System Call */
TRAP_ENTRY(0x89, my_trap_handler) /* NetBSD System Call */
TRAP_ENTRY(0x8a, my_trap_handler) /* Software Trap */
TRAP_ENTRY(0x8b, my_trap_handler) /* Software Trap */
......@@ -725,10 +725,7 @@ rest_of_boot:
sta %l1, [%l0] ASI_PTE
or %g0, INTS_ENAB, %l1
nop
nop
or %g0, 0x1, %l1
stb %l1, [%l0]
......
/* ioport.c: I/O access on the Sparc. Work in progress.. Most of the things
* in this file are for the sole purpose of getting the kernel
* through the compiler. :-)
* through the compiler. :-)
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
......
......@@ -30,6 +30,11 @@
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/psr.h>
#include <asm/vaddrs.h>
#include <asm/clock.h>
#include <asm/openprom.h>
#define DEBUG_IRQ
void disable_irq(unsigned int irq_nr)
{
......@@ -43,7 +48,7 @@ void disable_irq(unsigned int irq_nr)
* have to do here is frob the bits.
*/
int_reg = (char *) IRQ_ENA_ADR;
int_reg = (unsigned char *) IRQ_ENA_ADR;
switch(irq_nr)
{
......@@ -78,7 +83,7 @@ void disable_irq(unsigned int irq_nr)
void enable_irq(unsigned int irq_nr)
{
unsigned long flags;
unsigned int *int_reg;
unsigned char *int_reg;
save_flags(flags);
cli();
......@@ -87,8 +92,12 @@ void enable_irq(unsigned int irq_nr)
* have to do here is frob the bits.
*/
int_reg = (unsigned int *) IRQ_ENA_ADR;
int_reg = (unsigned char *) IRQ_ENA_ADR;
#ifdef DEBUG_IRQ
printk(" --- Enabling IRQ level %d ---\n", irq_nr);
#endif
switch(irq_nr)
{
case 1:
......@@ -116,6 +125,7 @@ void enable_irq(unsigned int irq_nr)
};
restore_flags(flags);
return;
}
......@@ -163,7 +173,7 @@ void free_irq(unsigned int irq)
unsigned long flags;
if (irq > 14) { /* 14 irq levels on the sparc */
printk("Trying to free IRQ%d\n", irq);
printk("Trying to free IRQ %d\n", irq);
return;
}
if (!action->handler) {
......@@ -188,7 +198,7 @@ static void handle_nmi(struct pt_regs * regs)
}
#endif
static void unexpected_irq(int irq, struct pt_regs * regs)
void unexpected_irq(int irq, struct pt_regs * regs)
{
int i;
......@@ -229,6 +239,28 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
return;
}
/*
* Since we need to special things to clear up the clock chip around
* the do_timer() call we have a special version of do_IRQ for the
* level 14 interrupt which does these things.
*/
asmlinkage void do_sparc_timer(int irq, struct pt_regs * regs)
{
struct irqaction *action = irq + irq_action;
register volatile int clear;
kstat.interrupts[irq]++;
/* I do the following already in the entry code, better safe than
* sorry for now. Reading the limit register clears the interrupt.
*/
clear = TIMER_STRUCT->timer_limit14;
action->handler(irq, regs);
return;
}
/*
* do_fast_IRQ handles IRQ's that don't need the fancy interrupt return
* stuff - the handler is also running with interrupts disabled unless
......@@ -241,6 +273,8 @@ asmlinkage void do_fast_IRQ(int irq)
return;
}
extern int first_descent;
extern void probe_clock(int);
int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
unsigned long irqflags, const char * devname)
......@@ -252,7 +286,10 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
return -EINVAL;
if(irq == 0) /* sched_init() requesting the timer IRQ */
irq = 14;
{
irq = 14;
probe_clock(first_descent);
}
action = irq + irq_action;
......@@ -263,6 +300,7 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
return -EINVAL;
save_flags(flags);
cli();
action->handler = handler;
......@@ -273,6 +311,7 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
enable_irq(irq);
restore_flags(flags);
return 0;
}
......
......@@ -23,6 +23,8 @@ extern int node_get_child(int node);
extern char* get_str_from_prom(int node, char* name, char* value);
extern unsigned int* get_int_from_prom(int node, char* name, unsigned int *value);
int first_descent;
/* Cpu-type information and manufacturer strings */
......@@ -275,13 +277,12 @@ probe_clock(int fchild)
printk("%s\n", node_str);
printk("At OBIO address: 0x%x Virtual address: 0x%x\n",
(unsigned int) 0xf3000000, (unsigned int) TIMER_STRUCT);
(unsigned int) TIMER_PHYSADDR, (unsigned int) TIMER_STRUCT);
mapioaddr((unsigned long) 0xf3000000,
mapioaddr((unsigned long) TIMER_PHYSADDR,
(unsigned long) TIMER_STRUCT);
TIMER_STRUCT->timer_limit14=(((10000) << 10) | 0x80000000);
TIMER_STRUCT->timer_limit10=(((10000) << 10) | 0x80000000);
TIMER_STRUCT->timer_limit14=(((1000000/HZ) << 10) | 0x80000000);
return;
}
......@@ -390,7 +391,7 @@ probe_sbus(register int cpu_child_node)
void
probe_devices(void)
{
register int nd, first_descent;
register int nd;
register char* str;
nd = prom_node_root;
......@@ -427,7 +428,6 @@ probe_devices(void)
probe_cpu();
probe_vac();
probe_mmu();
probe_clock(first_descent);
/*
printk("PROM Root Child Node: 0x%x Name: %s \n", nd,
......
......@@ -92,8 +92,6 @@ void setup_arch(char **cmdline_p,
printk("calling probe_devices...\n");
probe_devices(); /* cpu/fpu, mmu probes */
swpipl(13);
*memory_start_p = (((unsigned long) &end));
}
......
......@@ -156,7 +156,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
*/
/* Make the kernel text unwritable and cacheable, the prom
* loaded out text as writable, only sneaky sunos kernels need
* loaded our text as writable, only sneaky sunos kernels need
* self-modifying code.
*/
......
README.ide -- Information regarding ide.c and ide-cd.c
README.ide -- Information regarding ide.c and ide-cd.c (IDE driver in 1.1.93)
================================================================================
Supported by: mlord@bnr.ca -- disks, interfaces, probing
snyder@fnald0.fnal.gov -- cdroms, ATAPI, audio
......@@ -12,13 +12,13 @@ Major features of ide.c & ide-cd.c:
- support for reading IDE ATAPI cdrom drives (NEC, MITSUMI, VERSA, SONY)
- support for audio functions on FX400,NEC-260 cdrom drives (others?)
- auto-detection of interfaces, drives, IRQs, and disk geometries
-- "single" drives should be jumpered as "master", not "slave"
- support for BIOSs which report "more than 16 heads" on disk drives
- uses LBA (slightly faster) on disk drives which support it
- support for lots of fancy (E)IDE drive functions with hdparm utility
- optional (compile time) support for 32-bit VLB data transfers
- support for IDE multiple (block) mode (same as hd.c)
- support for interrupt unmasking during I/O (better than hd.c)
- compile flag for auto detection/use of multiple mode setting from BIOS
- improved handshaking and error detection/recovery
- can co-exist with hd.c to control only the secondary interface
......@@ -66,6 +66,11 @@ or
hdc=768,16,32
hdc=noprobe
Note that when only one IDE device is attached to an interface,
it must be jumpered as "single" or "master", *not* "slave".
Many folks have had "trouble" with cdroms because of this requirement
of the ATA (IDE) standard.
Courtesy of Scott Snyder, the driver now supports ATAPI cdrom drives
such as the NEC-260 and the new MITSUMI triple/quad speed drives.
Such drives will be identified at boot time, as hda,hdb,hdc or hdd,
......
/*
* linux/drivers/block/ide.c Version 3.11 January 25, 1995
* linux/drivers/block/ide.c Version 3.12 February 19, 1995
*
* Copyright (C) 1994, 1995 Linus Torvalds & authors (see below)
*/
......@@ -101,6 +101,8 @@
* fix byte-ordering for some NEC cdrom drives
* Version 3.10 disable multiple mode by default; was causing trouble
* Version 3.11 fix mis-identification of old WD disks as cdroms
* Version 3,12 simplify logic for selecting initial mult_count
* (fixes problems with buggy WD drives)
*
* To do:
* - special 32-bit controller-type detection & support
......@@ -136,8 +138,7 @@
#include <asm/io.h>
#undef REALLY_FAST_IO /* define if ide ports are perfect */
#define INITIAL_MULT_COUNT 0 /* undef to use BIOS setting on entry */
/* or non-zero to enable block mode */
#define INITIAL_MULT_COUNT 0 /* use zero to disable block mode */
#ifndef VLB_32BIT_IDE /* 0 for safety, 1 for 32-bit chipset:*/
#define VLB_32BIT_IDE 0 /* Winbond 83759F or OPTi 82C621 */
#endif
......@@ -903,8 +904,7 @@ static int do_special (ide_dev_t *dev)
if (dev->type == disk) {
if (dev->id && dev->mult_req > dev->id->max_multsect)
dev->mult_req = dev->id->max_multsect;
if (dev->mult_req != dev->mult_count)
ide_cmd(dev,WIN_SETMULT,dev->mult_req,&set_multmode_intr);
ide_cmd(dev,WIN_SETMULT,dev->mult_req,&set_multmode_intr);
} else {
dev->mult_req = 0;
printk("%s: multmode not supported by this device\n", dev->name);
......@@ -1696,24 +1696,13 @@ static void do_identify (ide_dev_t *dev, byte cmd)
dev->select.b.lba ? "LBA, " : "",
dev->bios_cyl, dev->bios_head, dev->bios_sect);
/* Keep current multiplemode setting, if any (from DOS/BIOS) */
dev->mult_count = 0;
if (id->max_multsect) {
if ((id->multsect_valid & 1) && id->multsect)
dev->mult_count = id->multsect; /* current setting */
#ifdef INITIAL_MULT_COUNT
dev->mult_req = INITIAL_MULT_COUNT;
#if INITIAL_MULT_COUNT
/* use specified value, or maximum, whichever is less */
if (INITIAL_MULT_COUNT > id->max_multsect)
if (dev->mult_req > id->max_multsect)
dev->mult_req = id->max_multsect;
#endif
#else /* use existing setting from DOS/BIOS: */
if (dev->mult_count <= id->max_multsect) /* valid? */
dev->mult_req = dev->mult_count; /* keep it */
#endif /* INITIAL_MULT_COUNT */
if (dev->mult_req != dev->mult_count)
dev->special.b.set_multmode = 1;
printk(", Mult=%d/%d", dev->mult_req, id->max_multsect);
dev->special.b.set_multmode = 1;
printk(", MaxMult=%d", id->max_multsect);
}
printk("\n");
}
......
......@@ -171,6 +171,9 @@ struct plip_local {
#elif defined(__mc68000__)
unsigned char msb;
unsigned char lsb;
#elif defined(__sparc__)
unsigned char msb;
unsigned char lsb;
#elif defined(__MIPSEL__)
unsigned char lsb;
unsigned char msb;
......
......@@ -2810,7 +2810,7 @@ static void intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
/* 250ms selection timeout */
if ((((hostdata->chip / 100) == 8) && (sist1 & SIST1_800_STO)) ||
(((hostdata->chip / 100) != 8) && sstat0_sist0 && SSTAT0_700_STO)) {
(((hostdata->chip / 100) != 8) && (sstat0_sist0 & SSTAT0_700_STO))) {
fatal = 1;
if (hostdata->options & OPTION_DEBUG_INTR) {
printk ("scsi%d : Selection Timeout\n", host->host_no);
......
......@@ -387,3 +387,20 @@ void scsi_mem_init(unsigned long memory_end)
continue;
}
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
......@@ -247,7 +247,7 @@ struct Scsi_Host
/* These parameters should be set by the detect routine */
unsigned char *base;
short unsigned int io_port;
unsigned int io_port;
unsigned char n_io_port;
unsigned char irq;
unsigned char dma_channel;
......@@ -356,3 +356,19 @@ extern void scsi_unregister_module(int, void *);
#define SG_EXTRA_DEVS (SD_EXTRA_DEVS + SR_EXTRA_DEVS + ST_EXTRA_DEVS)
#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
......@@ -18,7 +18,7 @@
Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994
(you can reference it, but it is incomplete and inaccurate in places)
Version 0.39a
Version 0.40a
Functions as standalone, loadable, and PCMCIA driver, the latter from
Dave Hind's PCMCIA package.
......@@ -29,14 +29,6 @@
/*----------------------------------------------------------------*/
/* Configuration */
/* The following option is normally left alone. PCMCIA support needs to
change this to adapt to the different way the interrupt pin works.
Set the following to 2 to use normal interrupt (active high/totempole-
tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open
drain */
#define QL_INT_ACTIVE_HIGH 2
/* Set the following to 1 to enable the use of interrupts. Note that 0 tends
to be more stable, but slower (or ties up the system more) */
#define QL_USE_IRQ 1
......@@ -51,21 +43,36 @@
without requiring a cold boot. It does take some time to recover from a
reset, so it is slower, and I have seen timeouts so that devices weren't
recognized when this was set. */
#define QL_RESET_AT_START 1
#define QL_RESET_AT_START 0
/* crystal frequency in megahertz (for offset 5 and 9) */
#define XTALFREQ 40
/* This will set fast (10Mhz) synchronous timing, FASTCLK must also be 1 */
/*****/
/* offset 0xc */
/* This will set fast (10Mhz) synchronous timing when set to 1
FASTCLK must also be 0 */
#define FASTSCSI 0
/* This will set a faster sync transfer rate */
/* This when set to 1 will set a faster sync transfer rate */
#define FASTCLK 0
/* This bit needs to be set to 1 if your cabling is long or noisy */
/*****/
/* config register 1 (offset 8) options */
/* This needs to be set to 1 if your cabling is long or noisy */
#define SLOWCABLE 0
/* This should be 1 to enable parity detection */
#define QL_ENABLE_PARITY 1
/*****/
/* offset 6 */
/* This is the sync transfer divisor, 40Mhz/X will be the data rate
The power on default is 5, the maximum normal value is 5 */
#define SYNCXFRPD 4
/*****/
/* offset 7 */
/* This is the count of how many synchronous transfers can take place
i.e. how many reqs can occur before an ack is given.
The maximum value for this is 15, the upper bits can modify
......@@ -77,15 +84,9 @@
cause the deassertion to be early by 1/2 clock. Bits 5&4 control
the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */
/* PCMCIA option adjustment */
#ifdef PCMCIA
#undef QL_INT_ACTIVE_HIGH
#define QL_INT_ACTIVE_HIGH 0
#endif
/*----------------------------------------------------------------*/
#ifdef MODULE
#if defined(MODULE) || defined(PCMCIA)
#include <linux/config.h>
#include <linux/module.h>
#endif
......@@ -103,17 +104,24 @@
/*----------------------------------------------------------------*/
/* driver state info, local to driver */
static int qbase; /* Port */
static int qbase = 0; /* Port */
static int qinitid; /* initiator ID */
static int qabort; /* Flag to cause an abort */
static int qlirq; /* IRQ being used */
static int qlirq = -1; /* IRQ being used */
static char qinfo[80]; /* description */
static Scsi_Cmnd *qlcmd; /* current command being processed */
static int qlcfg5 = ( XTALFREQ << 5 ); /* 15625/512 */
static int qlcfg6 = SYNCXFRPD;
static int qlcfg7 = SYNCOFFST;
static int qlcfg8 = ( SLOWCABLE << 7 ) | ( QL_ENABLE_PARITY << 4 );
static int qlcfg9 = ( ( XTALFREQ + 4 ) / 5 );
static int qlcfgc = ( FASTCLK << 3 ) | ( FASTSCSI << 4 );
/*----------------------------------------------------------------*/
/* The qlogic card uses two register maps - These macros select which one */
#define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd ))
#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb6 , qbase + 0xd ))
/* following is watchdog timeout in microseconds */
#define WATCHDOG 5000000
......@@ -270,27 +278,15 @@ unsigned long flags;
outb(0x40, qbase + 0xb); /* enable features */
/* configurables */
#if FASTSCSI
#if FASTCLK
outb(0x18, qbase + 0xc);
#else
outb(0x10, qbase + 0xc);
#endif
#else
#if FASTCLK
outb(8, qbase + 0xc);
#endif
#endif
#if SLOWCABLE
outb(0xd0 | qinitid, qbase + 8); /* (initiator) bus id */
#else
outb(0x50 | qinitid, qbase + 8); /* (initiator) bus id */
#endif
outb( SYNCOFFST , qbase + 7 );
outb( SYNCXFRPD , qbase + 6 );
outb( qlcfgc , qbase + 0xc);
/* config: no reset interrupt, (initiator) bus id */
outb( 0x40 | qlcfg8 | qinitid, qbase + 8);
outb( qlcfg7 , qbase + 7 );
outb( qlcfg6 , qbase + 6 );
/**/
outb(0x99, qbase + 5); /* timer */
outb(qlcfg5, qbase + 5); /* select timer */
outb(qlcfg9 & 7, qbase + 9); /* prescaler */
/* outb(0x99, qbase + 5); */
outb(cmd->target, qbase + 4);
for (i = 0; i < cmd->cmd_len; i++)
......@@ -482,6 +478,17 @@ int qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
}
#endif
#ifdef PCMCIA
/*----------------------------------------------------------------*/
/* allow PCMCIA code to preset the port */
/* port should be 0 and irq to -1 respectively for autoprobing */
void qlogic_preset(int port, int irq)
{
qbase=port;
qlirq=irq;
}
#endif
/*----------------------------------------------------------------*/
/* look for qlogic card and init if found */
int qlogic_detect(Scsi_Host_Template * host)
......@@ -499,16 +506,20 @@ unsigned long flags;
card, but I haven't tested this.
*/
for (qbase = 0x230; qbase < 0x430; qbase += 0x100) {
if( check_region( qbase , 0x10 ) )
continue;
REG1;
if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
&& ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
break;
if( !qbase ) {
for (qbase = 0x230; qbase < 0x430; qbase += 0x100) {
if( check_region( qbase , 0x10 ) )
continue;
REG1;
if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
&& ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
break;
}
if (qbase == 0x430)
return 0;
}
if (qbase == 0x430)
return 0;
else
printk( "Ql: Using preset base address of %03x\n", qbase );
qltyp = inb(qbase + 0xe) & 0xf8;
qinitid = host->this_id;
......@@ -516,8 +527,9 @@ unsigned long flags;
qinitid = 7; /* if no ID, use 7 */
outb(1, qbase + 8); /* set for PIO pseudo DMA */
REG0;
outb(0xd0 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */
outb(0x99, qbase + 5); /* select timer */
outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */
outb(qlcfg5, qbase + 5); /* select timer */
outb(qlcfg9, qbase + 9); /* prescaler */
qlirq = -1;
#if QL_RESET_AT_START
outb( 3 , qbase + 3 );
......@@ -527,27 +539,31 @@ unsigned long flags;
#endif
#if QL_USE_IRQ
/* IRQ probe - toggle pin and check request pending */
save_flags( flags );
cli();
i = 0xffff;
j = 3;
outb(0x90, qbase + 3); /* illegal command - cause interrupt */
REG1;
outb(10, 0x20); /* access pending interrupt map */
outb(10, 0xa0);
while (j--) {
outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin off */
i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */
outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin on */
i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */
if( qlirq == -1 ) {
save_flags( flags );
cli();
i = 0xffff;
j = 3;
outb(0x90, qbase + 3); /* illegal command - cause interrupt */
REG1;
outb(10, 0x20); /* access pending interrupt map */
outb(10, 0xa0);
while (j--) {
outb(0xb2 , qbase + 0xd); /* int pin off */
i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */
outb(0xb6 , qbase + 0xd); /* int pin on */
i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */
}
REG0;
while (inb(qbase + 5)); /* purge int */
while (i) /* find on bit */
i >>= 1, qlirq++; /* should check for exactly 1 on */
if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic"))
host->can_queue = 1;
restore_flags( flags );
}
REG0;
while (inb(qbase + 5)); /* purge int */
while (i) /* find on bit */
i >>= 1, qlirq++; /* should check for exactly 1 on */
if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic"))
host->can_queue = 1;
restore_flags( flags );
else
printk( "Ql: Using preset IRQ of %d\n", qlirq );
#endif
request_region( qbase , 0x10 ,"qlogic");
hreg = scsi_register( host , 0 ); /* no host data */
......@@ -557,8 +573,8 @@ unsigned long flags;
if( qlirq != -1 )
hreg->irq = qlirq;
sprintf(qinfo, "Qlogic Driver version 0.39a, chip %02X at %03X, IRQ %d, Opts:%d%d",
qltyp, qbase, qlirq, QL_INT_ACTIVE_HIGH, QL_TURBO_PDMA );
sprintf(qinfo, "Qlogic Driver version 0.40a, chip %02X at %03X, IRQ %d, TPdma:%d",
qltyp, qbase, qlirq, QL_TURBO_PDMA );
host->name = qinfo;
return 1;
......
This diff is collapsed.
......@@ -622,3 +622,20 @@ static Scsi_Cmnd * end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors
}; }
#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
......@@ -311,3 +311,20 @@ int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) {
set_fs(oldfs);
return tmp;
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
......@@ -384,7 +384,15 @@ static void do_sd_request (void)
SCpnt = allocate_device(&CURRENT,
rscsi_disks[DEVICE_NR(MINOR(CURRENT->dev))].device, 0);
else SCpnt = NULL;
/*
* The following restore_flags leads to latency problems. FIXME.
*/
#if 0
restore_flags(flags);
#else
sti();
#endif
/* This is a performance enhancement. We dig down into the request list and
try and find a queueable request (i.e. device not busy, and host able to
......@@ -1273,3 +1281,20 @@ static void sd_detach(Scsi_Device * SDp)
}
return;
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
......@@ -73,3 +73,19 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device , cmd, (void *) arg);
}
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
......@@ -347,7 +347,8 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt)
*/
instance = scsi_register(tpnt, 0);
hostno = instance->host_no;
if (request_irq((int) irq, seagate_reconnect_intr, SA_INTERRUPT, "seagate")) {
if (request_irq((int) irq, seagate_reconnect_intr, SA_INTERRUPT,
(controller_type == SEAGATE) ? "seagate" : "tmc-8xx")) {
printk("scsi%d : unable to allocate IRQ%d\n",
hostno, (int) irq);
return 0;
......
......@@ -422,3 +422,20 @@ static void sg_detach(Scsi_Device * SDp)
}
return;
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
......@@ -305,8 +305,15 @@ static void sr_photocd(struct inode *inode)
unsigned char *cmd; /* the scsi-command */
unsigned char *send; /* the data we send to the drive ... */
unsigned char *rec; /* ... and get back */
int rc,is_xa;
int rc,is_xa,no_multi;
if (scsi_CDs[MINOR(inode->i_rdev)].xa_flags & 0x02) {
#ifdef DEBUG
printk("sr_photocd: drive does not support multisession CD's");
#endif
return;
}
if (!suser()) {
/* I'm not the superuser, so SCSI_IOCTL_SEND_COMMAND isn't allowed for me.
* That's why mpcd_sector will be initialized with zero, because I'm not
......@@ -314,12 +321,18 @@ static void sr_photocd(struct inode *inode)
* no disk change happened since the last call of this function and we can
* keep the old value.
*/
if (1 == scsi_CDs[MINOR(inode->i_rdev)].device->access_count)
if (1 == scsi_CDs[MINOR(inode->i_rdev)].device->access_count) {
scsi_CDs[MINOR(inode->i_rdev)].mpcd_sector = 0;
scsi_CDs[MINOR(inode->i_rdev)].xa_flags &= ~0x01;
}
return;
}
sector = 0;
is_xa = 0;
no_multi = 0;
cmd = rec = &buf[8];
switch(scsi_CDs[MINOR(inode->i_rdev)].device->manufacturer) {
case SCSI_MAN_NEC:
......@@ -336,22 +349,23 @@ static void sr_photocd(struct inode *inode)
SCSI_IOCTL_SEND_COMMAND, buf);
if (rc != 0) {
printk("sr_photocd: ioctl error (NEC): 0x%x\n",rc);
sector = 0;
is_xa = 0;
} else {
min = (unsigned long) rec[15]/16*10 + (unsigned long) rec[15]%16;
sec = (unsigned long) rec[16]/16*10 + (unsigned long) rec[16]%16;
frame = (unsigned long) rec[17]/16*10 + (unsigned long) rec[17]%16;
/* if rec[14] isn't 0xb0, the drive does not support multisession CD's, use zero */
sector = (0xb0 == rec[14]) ? min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame : 0;
is_xa = (rec[14] == 0xb0);
break;
}
if (rec[14] != 0 && rec[14] != 0xb0) {
printk("sr_photocd: Hmm, seems the CDROM does'nt support multisession CD's\n");
no_multi = 1;
break;
}
min = (unsigned long) rec[15]/16*10 + (unsigned long) rec[15]%16;
sec = (unsigned long) rec[16]/16*10 + (unsigned long) rec[16]%16;
frame = (unsigned long) rec[17]/16*10 + (unsigned long) rec[17]%16;
sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
is_xa = (rec[14] == 0xb0);
#ifdef DEBUG
printk("NEC: (%2x) %2li:%02li:%02li = %li\n",buf[8+14],min,sec,frame,sector);
if (sector) {
printk("sr_photocd: multisession CD detected. start: %lu\n",sector);
}
#endif
if (sector) {
printk("sr_photocd: multisession CD detected. start: %lu\n",sector);
}
#endif
break;
case SCSI_MAN_TOSHIBA:
......@@ -369,15 +383,22 @@ static void sr_photocd(struct inode *inode)
rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
SCSI_IOCTL_SEND_COMMAND, buf);
if (rc != 0) {
printk("sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc);
sector = 0;
is_xa = 0;
if (rc == 0x28000002) {
/* Got a "not ready" - error. No chance to find out if this is
becauce there is no CD in the drive or becauce the drive
don't knows multisession CD's. So I need to do an extra check... */
if (kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
SCSI_IOCTL_TEST_UNIT_READY, NULL)) {
printk("sr_photocd: drive not ready\n");
} else {
printk("sr_photocd: Hmm, seems the CDROM does'nt support multisession CD's\n");
no_multi = 1;
}
} else
printk("sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc);
break; /* if the first ioctl fails, we don't call the second one */
}
is_xa = (rec[0] == 0x20);
#ifdef DEBUG
printk("sr_photocd: TOSHIBA %x\n",rec[0]);
#endif
min = (unsigned long) rec[1]/16*10 + (unsigned long) rec[1]%16;
sec = (unsigned long) rec[2]/16*10 + (unsigned long) rec[2]%16;
frame = (unsigned long) rec[3]/16*10 + (unsigned long) rec[3]%16;
......@@ -436,12 +457,15 @@ static void sr_photocd(struct inode *inode)
#ifdef DEBUG
printk("sr_photocd: unknown drive, no special multisession code\n");
#endif
sector = 0;
is_xa = 0;
break; }
scsi_CDs[MINOR(inode->i_rdev)].mpcd_sector = sector;
scsi_CDs[MINOR(inode->i_rdev)].is_xa = is_xa;
if (is_xa)
scsi_CDs[MINOR(inode->i_rdev)].xa_flags |= 0x01;
else
scsi_CDs[MINOR(inode->i_rdev)].xa_flags &= ~0x01;
if (no_multi)
scsi_CDs[MINOR(inode->i_rdev)].xa_flags |= 0x02;
return;
}
......@@ -1045,3 +1069,20 @@ static void sr_detach(Scsi_Device * SDp)
}
return;
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
......@@ -25,7 +25,7 @@ typedef struct
unsigned sector_size; /* size in bytes */
Scsi_Device *device;
unsigned long mpcd_sector; /* for reading multisession-CD's */
char is_xa; /* is it an XA-CD ? */
char xa_flags; /* some flags for handling XA-CD's */
unsigned char sector_bit_size; /* sector size = 2^sector_bit_size */
unsigned char sector_bit_shift; /* sectors/FS block = 2^sector_bit_shift*/
unsigned needs_sector_size:1; /* needs to get sector size */
......
......@@ -409,7 +409,7 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
ms_info.addr.lba=scsi_CDs[target].mpcd_sector;
else return (-EINVAL);
ms_info.xa_flag=scsi_CDs[target].is_xa;
ms_info.xa_flag=scsi_CDs[target].xa_flags & 0x01;
err=verify_area(VERIFY_WRITE,(void *) arg,
sizeof(struct cdrom_multisession));
......@@ -430,3 +430,20 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
}
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 8
* c-brace-imaginary-offset: 0
* c-brace-offset: -8
* c-argdecl-indent: 8
* c-label-offset: -8
* c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* End:
*/
......@@ -11,7 +11,7 @@
Copyright 1992, 1993, 1994, 1995 Kai Makisara
email Kai.Makisara@metla.fi
Last modified: Mon Jan 30 23:20:07 1995 by root@kai.home
Last modified: Sat Feb 18 10:51:25 1995 by root@kai.home
*/
#include <linux/fs.h>
......@@ -74,6 +74,7 @@ static int debugging = 1;
#endif
#define MAX_RETRIES 0
#define MAX_WRITE_RETRIES 0
#define MAX_READY_RETRIES 5
#define NO_TAPE NOT_READY
......@@ -110,10 +111,10 @@ st_chk_result(Scsi_Cmnd * SCpnt)
{
int dev = SCpnt->request.dev;
int result = SCpnt->result;
unsigned char * sense = SCpnt->sense_buffer;
unsigned char * sense = SCpnt->sense_buffer, scode;
char *stp;
if (!result && SCpnt->sense_buffer[0] == 0)
if (!result /* && SCpnt->sense_buffer[0] == 0 */ )
return 0;
#ifdef DEBUG
if (debugging) {
......@@ -123,13 +124,25 @@ st_chk_result(Scsi_Cmnd * SCpnt)
SCpnt->request_bufflen);
if (driver_byte(result) & DRIVER_SENSE)
print_sense("st", SCpnt);
}
} else
#endif
/* if ((sense[0] & 0x70) == 0x70 &&
((sense[2] & 0x80) ))
return 0; */
scode = sense[2] & 0x0f;
if (!(driver_byte(result) & DRIVER_SENSE) ||
((sense[0] & 0x70) == 0x70 &&
scode != NO_SENSE &&
scode != RECOVERED_ERROR &&
scode != UNIT_ATTENTION &&
scode != BLANK_CHECK &&
scode != VOLUME_OVERFLOW)) { /* Abnormal conditions for tape */
printk("st%d: Error %x. ", dev, result);
if (driver_byte(result) & DRIVER_SENSE)
print_sense("st", SCpnt);
else
printk("\n");
}
if ((sense[0] & 0x70) == 0x70 &&
sense[2] == RECOVERED_ERROR
scode == RECOVERED_ERROR
#ifdef ST_RECOVERED_WRITE_FATAL
&& SCpnt->cmnd[0] != WRITE_6
&& SCpnt->cmnd[0] != WRITE_FILEMARKS
......@@ -312,7 +325,7 @@ flush_write_buffer(int dev)
SCpnt->request.dev = dev;
scsi_do_cmd (SCpnt,
(void *) cmd, (STp->buffer)->b_data, transfer,
st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
......@@ -472,7 +485,6 @@ scsi_tape_open(struct inode * inode, struct file * filp)
printk("st%d: No tape.\n", dev);
STp->ready = ST_NO_TAPE;
} else {
printk("st%d: Error %x.\n", dev, SCpnt->result);
(STp->mt_status)->mt_fileno = STp->drv_block = (-1);
STp->ready = ST_NOT_READY;
}
......@@ -484,6 +496,8 @@ scsi_tape_open(struct inode * inode, struct file * filp)
STp->block_size = 0;
STp->eof = ST_NOEOF;
(STp->mt_status)->mt_fileno = STp->drv_block = 0;
if (scsi_tapes[dev].device->host->hostt->usage_count)
(*scsi_tapes[dev].device->host->hostt->usage_count)++;
return 0;
}
......@@ -637,7 +651,7 @@ scsi_tape_close(struct inode * inode, struct file * filp)
SCpnt->request.dev = dev;
scsi_do_cmd( SCpnt,
(void *) cmd, (void *) (STp->buffer)->b_data,
0, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
0, st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
......@@ -797,7 +811,7 @@ st_write(struct inode * inode, struct file * filp, char * buf, int count)
SCpnt->request.dev = dev;
scsi_do_cmd (SCpnt,
(void *) cmd, (STp->buffer)->b_data, transfer,
st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
......@@ -910,7 +924,7 @@ st_write(struct inode * inode, struct file * filp, char * buf, int count)
scsi_do_cmd (SCpnt,
(void *) cmd, (STp->buffer)->b_data,
(STp->buffer)->writing,
st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
}
else
SCpnt->request.dev = -1; /* Mark as not busy */
......
......@@ -46,6 +46,8 @@ struct sparc_clock_info {
unsigned char foo[14];
};
#define TIMER_PHYSADDR 0xf3000000
/* YUCK YUCK YUCK, grrr... */
#define TIMER_STRUCT ((struct sparc_timer_info *)((struct sparc_clock_info *) TIMER_VADDR))
......@@ -14,7 +14,7 @@ extern __inline__ void __delay(unsigned int loops)
{
__asm__ __volatile__("\n1:\tcmp %0, 0\n\t"
"bne,a 1b\n\t"
"sub %0, 1, %0\n": "=r" (loops) : "0" (loops));
"sub %0, 1, %0\n": "=&r" (loops) : "0" (loops));
}
/* udelay(usecs) is used for very short delays up to 1 millisecond. */
......
......@@ -22,28 +22,36 @@
/* Generic trap entry. */
#define TRAP_ENTRY(type, label) \
mov (type), %l3; b label; mov %psr, %l0; nop;
mov (type), %l3; b label; rd %psr, %l0; nop;
/* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and
* gets handled with another macro.
*/
#define TRAP_ENTRY_INTERRUPT(int_level) \
mov int_level, %l4; b trap_entry; mov %psr, %l0; nop;
mov int_level, %l3; b stray_irq_entry; rd %psr, %l0; nop;
/* Here is the macro for soft interrupts (ie. not as urgent as hard ones)
which need to jump to a different handler.
*/
* which need to jump to a different handler.
*/
#define TRAP_ENTRY_INTERRUPT_SOFT(int_level, ident) \
mov int_level, %l4; mov %psr, %l0; b trap_entry; mov ident, %l3;
mov int_level, %l3; rd %psr, %l0; b stray_irq_entry; mov ident, %l4;
/* The above two macros are for generic traps. The following is made
* especially for timer interrupts at IRQ level 14.
*/
#define TRAP_ENTRY_TIMER \
mov 10, %l3; rd %psr, %l0; b sparc_timer; nop;
/* Non-maskable interrupt entry macro. You have to turn off all interrupts
to not receive this. This is usually due to a asynchronous memory error.
All we can really do is stop the show. :-(
*/
* to not receive this. This is usually due to a asynchronous memory error.
* All we can really do is stop the show. :-(
*/
#define TRAP_ENTRY_INTERRUPT_NMI(t_type, jmp_to) \
mov t_type, %l3; b jmp_to; mov %psr, %l0; nop;
mov t_type, %l3; b jmp_to; rd %psr, %l0; nop;
/* Trap entry code in entry.S needs the offsets into task_struct
* to get at the thread_struct goodies during window craziness.
......@@ -53,11 +61,11 @@
* See TRAP_WIN_CLEAN in entry.S for details.
*/
#define THREAD_UWINDOWS 0x3a8
#define THREAD_WIM 0x3ac
#define THREAD_W_SAVED 0x3b0
#define THREAD_KSP 0x3b4
#define THREAD_USP 0x3b8
#define THREAD_REG_WINDOW 0x3c0
#define THREAD_UWINDOWS 0x3bc
#define THREAD_WIM 0x3c0
#define THREAD_W_SAVED 0x3c4
#define THREAD_KSP 0x3c8
#define THREAD_USP 0x3cc
#define THREAD_REG_WINDOW 0x3d4
#endif __SPARC_HEAD_H
......@@ -91,9 +91,9 @@ extern inline void mapioaddr(unsigned long physaddr, unsigned long virt_addr)
unsigned long page_entry;
page_entry = physaddr >> PAGE_SHIFT;
page_entry |= (PTE_V | PTE_ACC | PTE_W | PTE_P | PTE_IO); /* kernel io addr */
page_entry |= (PTE_V | PTE_ACC | PTE_NC | PTE_IO); /* kernel io addr */
put_pte(page_entry, virt_addr);
put_pte(virt_addr, page_entry);
return;
}
......
......@@ -145,17 +145,31 @@ extern unsigned long high_memory;
extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; }
extern inline int pte_inuse(pte_t *ptep) { return mem_map[MAP_NR(ptep)] > 1; }
extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; }
extern inline void pte_reuse(pte_t *ptep)
{
if(!(mem_map[MAP_NR(ptep)] & MAP_PAGE_RESERVED))
mem_map[MAP_NR(ptep)]++;
}
extern inline int pmd_none(pmd_t pmd) { return !pmd_val(pmd); }
extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE || pmd_val(pmd) > high_memory; }
extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_VALID; }
extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = 0; }
extern inline int pmd_inuse(pmd_t *pmdp) { return 0; }
extern inline void pmd_clear(pmd_t *pmdp) { pmd_val(*pmdp) = 0; }
extern inline void pmd_reuse(pmd_t * pmdp) { }
extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); }
extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~PAGE_MASK) != _PAGE_TABLE || pgd_val(pgd) > high_memory; }
extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_VALID; }
extern inline int pgd_inuse(pgd_t *pgdp) { return mem_map[MAP_NR(pgdp)] > 1; }
extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; }
extern inline void pgd_reuse(pgd_t *pgdp)
{
if (!(mem_map[MAP_NR(pgdp)] & MAP_PAGE_RESERVED))
mem_map[MAP_NR(pgdp)]++;
}
/*
* The following only work if pte_present() is true.
......@@ -312,6 +326,15 @@ extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
return (pmd_t *) pgd;
}
extern inline void pgd_free(pgd_t *pgd)
{
free_page((unsigned long) pgd);
}
extern inline pgd_t *pgd_alloc(void)
{
return (pgd_t *) get_free_page(GFP_KERNEL);
}
extern pgd_t swapper_pg_dir[1024];
#endif /* !(_SPARC_PGTABLE_H) */
......@@ -64,7 +64,7 @@ retval = ((retval>>8)&15); \
retval; })
#define cli() swpipl(15) /* 15 = no int's except nmi's */
#define sti() swpipl(0) /* same as alpha */
#define sti() swpipl(0) /* I'm scared */
#define save_flags(flags) do { flags = swpipl(15); } while (0)
#define restore_flags(flags) swpipl(flags)
......
......@@ -49,6 +49,9 @@ struct timestamp {
#elif defined(__alpha__)
__u8 flags:4,
overflow:4;
#elif defined(__sparc__)
__u8 overflow:4,
flags:4;
#else
#error "Adjust this structure to match your CPU"
#endif
......@@ -96,6 +99,9 @@ struct iphdr {
#elif defined(__alpha__)
__u8 ihl:4,
version:4;
#elif defined (__sparc__)
__u8 version:4,
ihl:4;
#else
#error "Adjust this structure to match your CPU"
#endif
......
......@@ -76,6 +76,16 @@ struct tcphdr {
ack:1,
urg:1,
res2:2;
#elif defined(__sparc__)
__u16 res2:2,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1,
doff:4,
res1:4;
#else
#error "Adjust this structure for your cpu alignment rules"
#endif
......
......@@ -207,8 +207,11 @@ while (tries --)
page->nfree--;
if (!page->nfree)
{
sizes[order].firstfree = page->next;
page->next = NULL;
if(dma_flag)
sizes[order].dmafree = page->next;
else
sizes[order].firstfree = page->next;
page->next = NULL;
}
restore_flags(flags);
......
......@@ -502,7 +502,13 @@ static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned
end = PMD_SIZE;
do {
pte_t oldpage = *pte;
*pte = mk_pte(offset, prot);
pte_clear(pte);
if (offset >= high_memory || (mem_map[MAP_NR(offset)] & MAP_PAGE_RESERVED))
*pte = mk_pte(offset, prot);
else if (mem_map[MAP_NR(offset)]) {
mem_map[MAP_NR(offset)]++;
*pte = mk_pte(offset, prot);
}
forget_pte(oldpage);
address += PAGE_SIZE;
offset += PAGE_SIZE;
......
......@@ -389,10 +389,10 @@ static inline int try_to_swap_out(struct vm_area_struct* vma, unsigned offset, p
#define SWAP_RATIO 128
static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir,
unsigned long address, unsigned long size, unsigned long offset)
unsigned long address, unsigned long end)
{
pte_t * pte;
unsigned long end;
unsigned long pmd_end;
if (pmd_none(*dir))
return 0;
......@@ -401,21 +401,22 @@ static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir,
pmd_clear(dir);
return 0;
}
pte = pte_offset(dir, address);
offset += address & PMD_MASK;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
end = PMD_SIZE;
pmd_end = (address + PMD_SIZE) & PMD_MASK;
if (end > pmd_end)
end = pmd_end;
do {
switch (try_to_swap_out(vma, offset+address-vma->vm_start, pte)) {
switch (try_to_swap_out(vma, address-vma->vm_start, pte)) {
case 0:
break;
case 1:
vma->vm_task->mm->rss--;
/* continue with the following page the next time */
vma->vm_task->mm->swap_address = address + offset + PAGE_SIZE;
vma->vm_task->mm->swap_address = address + PAGE_SIZE;
return 1;
default:
......@@ -429,10 +430,10 @@ static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir,
}
static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir,
unsigned long address, unsigned long size)
unsigned long address, unsigned long end)
{
pmd_t * pmd;
unsigned long offset, end;
unsigned long pgd_end;
if (pgd_none(*dir))
return 0;
......@@ -441,14 +442,15 @@ static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir,
pgd_clear(dir);
return 0;
}
pmd = pmd_offset(dir, address);
offset = address & PGDIR_MASK;
address &= ~PGDIR_MASK;
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
pgd_end = (address + PGDIR_SIZE) & PGDIR_MASK;
if (end > pgd_end)
end = pgd_end;
do {
if (swap_out_pmd(vma, pmd, address, end - address, offset))
if (swap_out_pmd(vma, pmd, address, end))
return 1;
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
......@@ -457,10 +459,13 @@ static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir,
}
static int swap_out_vma(struct vm_area_struct * vma, pgd_t *pgdir,
unsigned long start, unsigned long end)
unsigned long start)
{
unsigned long end;
end = vma->vm_end;
while (start < end) {
if (swap_out_pgd(vma, pgdir, start, end - start))
if (swap_out_pgd(vma, pgdir, start, end))
return 1;
start = (start + PGDIR_SIZE) & PGDIR_MASK;
pgdir++;
......@@ -489,7 +494,7 @@ static int swap_out_process(struct task_struct * p)
address = vma->vm_start;
for (;;) {
if (swap_out_vma(vma, pgd_offset(p, address), address, vma->vm_end))
if (swap_out_vma(vma, pgd_offset(p, address), address))
return 1;
vma = vma->vm_next;
if (!vma)
......@@ -554,16 +559,29 @@ static int swap_out(unsigned int priority)
static int try_to_free_page(int priority)
{
static int state = 0;
int i=6;
while (i--) {
if (priority != GFP_NOBUFFER && shrink_buffers(i))
return 1;
if (shm_swap(i))
return 1;
if (swap_out(i))
return 1;
switch (state) {
do {
case 0:
if (priority != GFP_NOBUFFER && shrink_buffers(i)) {
state = 1;
return 1;
}
case 1:
if (shm_swap(i)) {
state = 2;
return 1;
}
case 2:
if (swap_out(i)) {
state = 0;
return 1;
}
} while(--i);
}
state = 2;
return 0;
}
......
......@@ -734,6 +734,20 @@ static int inet_dup(struct socket *newsock, struct socket *oldsock)
return(inet_create(newsock,((struct sock *)(oldsock->data))->protocol));
}
/*
* Return 1 if we still have things to send in our buffers.
*/
static inline int closing(struct sock * sk)
{
switch (sk->state) {
case TCP_FIN_WAIT1:
case TCP_CLOSING:
case TCP_LAST_ACK:
return 1;
}
return 0;
}
/*
* The peer socket should always be NULL (or else). When we call this
......@@ -772,8 +786,7 @@ static int inet_release(struct socket *sock, struct socket *peer)
cli();
if (sk->lingertime)
current->timeout = jiffies + HZ*sk->lingertime;
while(sk->state < TCP_LAST_ACK && sk->state!= TCP_FIN_WAIT2 &&
sk->state != TCP_TIME_WAIT && current->timeout>0)
while(closing(sk) && current->timeout>0)
{
interruptible_sleep_on(sk->sleep);
if (current->signal & ~current->blocked)
......@@ -856,7 +869,7 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
destroy_sock(sk2);
goto outside_loop;
}
if (!sk->reuse || sk2->state==TCP_LISTEN)
if (!sk->reuse)
{
sti();
return(-EADDRINUSE);
......@@ -866,7 +879,7 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
continue; /* more than one */
if (sk2->saddr != sk->saddr)
continue; /* socket per slot ! -FB */
if (!sk2->reuse)
if (!sk2->reuse || sk2->state==TCP_LISTEN)
{
sti();
return(-EADDRINUSE);
......
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