Commit 651caa58 authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/home/davem/src/BK/sparcwork-2.5

into nuts.ninka.net:/home/davem/src/BK/sparc-2.5
parents 8939a01d eb0ad91a
...@@ -12,7 +12,7 @@ NM := $(NM) -B ...@@ -12,7 +12,7 @@ NM := $(NM) -B
LDFLAGS_vmlinux = -static -N #-relax LDFLAGS_vmlinux = -static -N #-relax
CFLAGS := $(CFLAGS) -pipe -mno-fp-regs -ffixed-8 CFLAGS := $(CFLAGS) -pipe -mno-fp-regs -ffixed-8
ARCHBLOBLFLAGS := -I binary -O elf64-alpha -B alpha LDFLAGS_BLOB := --format binary --oformat elf64-alpha
# Determine if we can use the BWX instructions with GAS. # Determine if we can use the BWX instructions with GAS.
old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi) old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi)
......
...@@ -69,7 +69,7 @@ SECTIONS ...@@ -69,7 +69,7 @@ SECTIONS
.init.ramfs ALIGN(8192): { .init.ramfs ALIGN(8192): {
__initramfs_start = .; __initramfs_start = .;
*(.init.initramfs) *(.init.ramfs)
__initramfs_end = .; __initramfs_end = .;
} }
......
...@@ -337,7 +337,6 @@ config PREEMPT ...@@ -337,7 +337,6 @@ config PREEMPT
config X86_UP_APIC config X86_UP_APIC
bool "Local APIC support on uniprocessors" if !SMP bool "Local APIC support on uniprocessors" if !SMP
default y if SMP
---help--- ---help---
A local APIC (Advanced Programmable Interrupt Controller) is an A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU integrated interrupt controller in the CPU. If you have a single-CPU
...@@ -447,7 +446,7 @@ config X86_MCE ...@@ -447,7 +446,7 @@ config X86_MCE
the 386 and 486, so nearly everyone can say Y here. the 386 and 486, so nearly everyone can say Y here.
config X86_MCE_NONFATAL config X86_MCE_NONFATAL
bool "Check for non-fatal errors on Athlon/Duron" bool "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4"
depends on X86_MCE depends on X86_MCE
help help
Enabling this feature starts a timer that triggers every 5 seconds which Enabling this feature starts a timer that triggers every 5 seconds which
...@@ -456,12 +455,12 @@ config X86_MCE_NONFATAL ...@@ -456,12 +455,12 @@ config X86_MCE_NONFATAL
Disable this if you don't want to see these messages. Disable this if you don't want to see these messages.
Seeing the messages this option prints out may be indicative of dying hardware, Seeing the messages this option prints out may be indicative of dying hardware,
or out-of-spec (ie, overclocked) hardware. or out-of-spec (ie, overclocked) hardware.
This option only does something on hardware with Intel P6 style MCE. This option only does something on certain CPUs.
(Pentium Pro and above, AMD Athlon/Duron) (AMD Athlon/Duron and Intel Pentium 4)
config X86_MCE_P4THERMAL config X86_MCE_P4THERMAL
bool "check for P4 thermal throttling interrupt." bool "check for P4 thermal throttling interrupt."
depends on X86_MCE && X86_UP_APIC depends on X86_MCE && (X86_UP_APIC || SMP)
help help
Enabling this feature will cause a message to be printed when the P4 Enabling this feature will cause a message to be printed when the P4
enters thermal throttling. enters thermal throttling.
......
...@@ -42,7 +42,7 @@ cflags-$(CONFIG_MCRUSOE) += -march=i686 -malign-functions=0 -malign-jumps=0 -mal ...@@ -42,7 +42,7 @@ cflags-$(CONFIG_MCRUSOE) += -march=i686 -malign-functions=0 -malign-jumps=0 -mal
cflags-$(CONFIG_MWINCHIPC6) += $(call check_gcc,-march=winchip-c6,-march=i586) cflags-$(CONFIG_MWINCHIPC6) += $(call check_gcc,-march=winchip-c6,-march=i586)
cflags-$(CONFIG_MWINCHIP2) += $(call check_gcc,-march=winchip2,-march=i586) cflags-$(CONFIG_MWINCHIP2) += $(call check_gcc,-march=winchip2,-march=i586)
cflags-$(CONFIG_MWINCHIP3D) += -march=i586 cflags-$(CONFIG_MWINCHIP3D) += -march=i586
cflags-$(CONFIG_MCYRIXIII) += $(call check_gcc,-march=c3,-march=i586) cflags-$(CONFIG_MCYRIXIII) += $(call check_gcc,-march=c3,-march=i486) -malign-functions=0 -malign-jumps=0 -malign-loops=0
CFLAGS += $(cflags-y) CFLAGS += $(cflags-y)
......
...@@ -8,8 +8,7 @@ export-objs := mca.o i386_ksyms.o time.o ...@@ -8,8 +8,7 @@ export-objs := mca.o i386_ksyms.o time.o
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o \ pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o
bootflag.o
obj-y += cpu/ obj-y += cpu/
obj-y += timers/ obj-y += timers/
......
...@@ -13,7 +13,10 @@ obj-y += rise.o ...@@ -13,7 +13,10 @@ obj-y += rise.o
obj-y += nexgen.o obj-y += nexgen.o
obj-y += umc.o obj-y += umc.o
obj-$(CONFIG_X86_MCE) += mcheck/
obj-$(CONFIG_MTRR) += mtrr/ obj-$(CONFIG_MTRR) += mtrr/
obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_CPU_FREQ) += cpufreq/
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
...@@ -358,7 +358,9 @@ void __init identify_cpu(struct cpuinfo_x86 *c) ...@@ -358,7 +358,9 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
boot_cpu_data.x86_capability[3]); boot_cpu_data.x86_capability[3]);
/* Init Machine Check Exception if available. */ /* Init Machine Check Exception if available. */
#ifdef CONFIG_X86_MCE
mcheck_init(c); mcheck_init(c);
#endif
} }
/* /*
* Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c * Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/timer.h>
#include "cpu.h" #include "cpu.h"
...@@ -170,7 +171,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c) ...@@ -170,7 +171,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
c->coma_bug = 1; c->coma_bug = 1;
break; break;
case 4: /* MediaGX/GXm */ case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
/* It isn't really a PCI quirk directly, but the cure is the /* It isn't really a PCI quirk directly, but the cure is the
same. The MediaGX has deep magic SMM stuff that handles the same. The MediaGX has deep magic SMM stuff that handles the
...@@ -188,29 +189,26 @@ static void __init init_cyrix(struct cpuinfo_x86 *c) ...@@ -188,29 +189,26 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
isa_dma_bridge_buggy = 2; isa_dma_bridge_buggy = 2;
#endif #endif
c->x86_cache_size=16; /* Yep 16K integrated cache thats it */ c->x86_cache_size=16; /* Yep 16K integrated cache thats it */
/*
* The 5510/5520 companion chips have a funky PIT.
*/
if (pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, NULL) ||
pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, NULL))
pit_latch_buggy = 1;
/* GXm supports extended cpuid levels 'ala' AMD */ /* GXm supports extended cpuid levels 'ala' AMD */
if (c->cpuid_level == 2) { if (c->cpuid_level == 2) {
/* Enable Natsemi MMX extensions */ /* Enable cxMMX extensions (GX1 Datasheet 54) */
setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1); setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
get_model_name(c); /* get CPU marketing name */ get_model_name(c); /* get CPU marketing name */
/*
* The 5510/5520 companion chips have a funky PIT
* that breaks the TSC synchronizing, so turn it off
*/
if (pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, NULL) ||
pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, NULL))
clear_bit(X86_FEATURE_TSC, c->x86_capability);
return; return;
} }
else { /* MediaGX */ else { /* MediaGX */
Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4'; Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
p = Cx86_cb+2; p = Cx86_cb+2;
c->x86_model = (dir1 & 0x20) ? 1 : 2; c->x86_model = (dir1 & 0x20) ? 1 : 2;
#ifndef CONFIG_CS5520
clear_bit(X86_FEATURE_TSC, c->x86_capability);
#endif
} }
break; break;
......
obj-y = mce.o k7.o p4.o p5.o p6.o winchip.o
obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o
include $(TOPDIR)/Rules.make
/*
* Athlon specific Machine Check Exception Reporting
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/msr.h>
#include "mce.h"
/* Machine Check Handler For AMD Athlon/Duron */
static void k7_machine_check(struct pt_regs * regs, long error_code)
{
int recover=1;
u32 alow, ahigh, high, low;
u32 mcgstl, mcgsth;
int i;
rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
if (mcgstl & (1<<0)) /* Recoverable ? */
recover=0;
printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
smp_processor_id(), mcgsth, mcgstl);
for (i=0; i<nr_mce_banks; i++) {
rdmsr (MSR_IA32_MC0_STATUS+i*4,low, high);
if (high&(1<<31)) {
if (high & (1<<29))
recover |= 1;
if (high & (1<<25))
recover |= 2;
printk (KERN_EMERG "Bank %d: %08x%08x", i, high, low);
high &= ~(1<<31);
if (high & (1<<27)) {
rdmsr (MSR_IA32_MC0_MISC+i*4, alow, ahigh);
printk ("[%08x%08x]", ahigh, alow);
}
if (high & (1<<26)) {
rdmsr (MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
printk (" at %08x%08x", ahigh, alow);
}
printk ("\n");
/* Clear it */
wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
/* Serialize */
wmb();
}
}
if (recover&2)
panic ("CPU context corrupt");
if (recover&1)
panic ("Unable to continue");
printk (KERN_EMERG "Attempting to continue.\n");
mcgstl &= ~(1<<2);
wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
}
/* AMD K7 machine check is Intel like */
void __init amd_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
machine_check_vector = k7_machine_check;
wmb();
printk (KERN_INFO "Intel machine check architecture supported.\n");
rdmsr (MSR_IA32_MCG_CAP, l, h);
if (l & (1<<8)) /* Control register present ? */
wrmsr (MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
nr_mce_banks = l & 0xff;
for (i=0; i<nr_mce_banks; i++) {
wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
}
set_in_cr4 (X86_CR4_MCE);
printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
smp_processor_id());
#ifdef CONFIG_X86_MCE_NONFATAL
init_nonfatal_mce_checker();
#endif
}
/*
* mce.c - x86 Machine Check Exception Reporting
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/smp.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/thread_info.h>
#include "mce.h"
int mce_disabled __initdata = 0;
int nr_mce_banks;
/* Handle unconfigured int18 (should never happen) */
static void unexpected_machine_check(struct pt_regs * regs, long error_code)
{
printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
}
/* Call the installed machine check handler for this CPU setup. */
void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
asmlinkage void do_machine_check(struct pt_regs * regs, long error_code)
{
machine_check_vector(regs, error_code);
}
/* This has to be run for each processor */
void __init mcheck_init(struct cpuinfo_x86 *c)
{
if (mce_disabled==1)
return;
switch (c->x86_vendor) {
case X86_VENDOR_AMD:
if (c->x86==6 || c->x86==15)
amd_mcheck_init(c);
break;
case X86_VENDOR_INTEL:
if (c->x86==5)
intel_p5_mcheck_init(c);
if (c->x86==6)
intel_p6_mcheck_init(c);
if (c->x86==15)
intel_p4_mcheck_init(c);
break;
case X86_VENDOR_CENTAUR:
if (c->x86==5)
winchip_mcheck_init(c);
break;
default:
break;
}
}
static int __init mcheck_disable(char *str)
{
mce_disabled = 1;
return 0;
}
static int __init mcheck_enable(char *str)
{
mce_disabled = -1;
return 0;
}
__setup("nomce", mcheck_disable);
__setup("mce", mcheck_enable);
#include <linux/init.h>
void amd_mcheck_init(struct cpuinfo_x86 *c);
void intel_p4_mcheck_init(struct cpuinfo_x86 *c);
void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
void intel_p6_mcheck_init(struct cpuinfo_x86 *c);
void winchip_mcheck_init(struct cpuinfo_x86 *c);
void init_nonfatal_mce_checker(void);
/* Call the installed machine check handler for this CPU setup. */
extern void (*machine_check_vector)(struct pt_regs *, long error_code);
extern int mce_disabled __initdata;
extern int nr_mce_banks;
/*
* P4 specific Machine Check Exception Reporting
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/config.h>
#include <linux/irq.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/msr.h>
#include "mce.h"
static struct timer_list mce_timer;
static int timerset;
#define MCE_RATE 15*HZ /* timer rate is 15s */
static void mce_checkregs (void *info)
{
u32 low, high;
int i;
preempt_disable();
for (i=0; i<nr_mce_banks; i++) {
rdmsr (MSR_IA32_MC0_STATUS+i*4, low, high);
if (high & (1<<31)) {
printk (KERN_EMERG "MCE: The hardware reports a non fatal, correctable incident occured on CPU %d.\n",
smp_processor_id());
printk (KERN_EMERG "Bank %d: %08x%08x\n", i, high, low);
/* Scrub the error so we don't pick it up in MCE_RATE seconds time. */
wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
/* Serialize */
wmb();
}
}
preempt_enable();
}
static void do_mce_timer(void *data)
{
mce_checkregs (NULL);
smp_call_function (mce_checkregs, NULL, 1, 1);
}
static DECLARE_WORK(mce_work, do_mce_timer, NULL);
static void mce_timerfunc (unsigned long data)
{
#ifdef CONFIG_SMP
if (num_online_cpus() > 1)
schedule_work (&mce_work);
#else
mce_checkregs (NULL);
#endif
mce_timer.expires = jiffies + MCE_RATE;
add_timer (&mce_timer);
}
void init_nonfatal_mce_checker()
{
if (timerset == 0) {
/* Set the timer to check for non-fatal
errors every MCE_RATE seconds */
init_timer (&mce_timer);
mce_timer.expires = jiffies + MCE_RATE;
mce_timer.data = 0;
mce_timer.function = &mce_timerfunc;
add_timer (&mce_timer);
timerset = 1;
printk(KERN_INFO "Machine check exception polling timer started.\n");
}
}
/* /*
* arch/i386/kernel/bluesmoke.c - x86 Machine Check Exception Reporting * P4 specific Machine Check Exception Reporting
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/smp.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/hardirq.h>
#ifdef CONFIG_X86_MCE #include "mce.h"
/* as supported by the P4/Xeon family */ /* as supported by the P4/Xeon family */
struct intel_mce_extended_msrs { struct intel_mce_extended_msrs {
...@@ -37,17 +32,16 @@ struct intel_mce_extended_msrs { ...@@ -37,17 +32,16 @@ struct intel_mce_extended_msrs {
/* u32 *reserved[]; */ /* u32 *reserved[]; */
}; };
static int mce_disabled __initdata = 0;
static int mce_num_extended_msrs = 0; static int mce_num_extended_msrs = 0;
static int banks;
#ifdef CONFIG_X86_MCE_P4THERMAL #ifdef CONFIG_X86_MCE_P4THERMAL
/* static void unexpected_thermal_interrupt(struct pt_regs *regs)
* P4/Xeon Thermal transition interrupt handler {
*/ printk(KERN_ERR "CPU#%d: Unexpected LVT TMR interrupt!\n", smp_processor_id());
}
/* P4/Xeon Thermal transition interrupt handler */
static void intel_thermal_interrupt(struct pt_regs *regs) static void intel_thermal_interrupt(struct pt_regs *regs)
{ {
u32 l, h; u32 l, h;
...@@ -55,7 +49,7 @@ static void intel_thermal_interrupt(struct pt_regs *regs) ...@@ -55,7 +49,7 @@ static void intel_thermal_interrupt(struct pt_regs *regs)
ack_APIC_irq(); ack_APIC_irq();
rdmsr(MSR_IA32_THERM_STATUS, l, h); rdmsr (MSR_IA32_THERM_STATUS, l, h);
if (l & 1) { if (l & 1) {
printk(KERN_EMERG "CPU#%d: Temperature above threshold\n", cpu); printk(KERN_EMERG "CPU#%d: Temperature above threshold\n", cpu);
printk(KERN_EMERG "CPU#%d: Running in modulated clock mode\n", cpu); printk(KERN_EMERG "CPU#%d: Running in modulated clock mode\n", cpu);
...@@ -64,15 +58,7 @@ static void intel_thermal_interrupt(struct pt_regs *regs) ...@@ -64,15 +58,7 @@ static void intel_thermal_interrupt(struct pt_regs *regs)
} }
} }
static void unexpected_thermal_interrupt(struct pt_regs *regs) /* Thermal interrupt handler for this CPU setup */
{
printk(KERN_ERR "CPU#%d: Unexpected LVT TMR interrupt!\n", smp_processor_id());
}
/*
* Thermal interrupt handler for this CPU setup
*/
static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt; static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt;
asmlinkage void smp_thermal_interrupt(struct pt_regs regs) asmlinkage void smp_thermal_interrupt(struct pt_regs regs)
...@@ -83,7 +69,6 @@ asmlinkage void smp_thermal_interrupt(struct pt_regs regs) ...@@ -83,7 +69,6 @@ asmlinkage void smp_thermal_interrupt(struct pt_regs regs)
} }
/* P4/Xeon Thermal regulation detect and init */ /* P4/Xeon Thermal regulation detect and init */
static void __init intel_init_thermal(struct cpuinfo_x86 *c) static void __init intel_init_thermal(struct cpuinfo_x86 *c)
{ {
u32 l, h; u32 l, h;
...@@ -101,7 +86,7 @@ static void __init intel_init_thermal(struct cpuinfo_x86 *c) ...@@ -101,7 +86,7 @@ static void __init intel_init_thermal(struct cpuinfo_x86 *c)
* be some SMM goo which handles it, so we can't even put a handler * be some SMM goo which handles it, so we can't even put a handler
* since it might be delivered via SMI already -zwanem. * since it might be delivered via SMI already -zwanem.
*/ */
rdmsr(MSR_IA32_MISC_ENABLE, l, h); rdmsr (MSR_IA32_MISC_ENABLE, l, h);
h = apic_read(APIC_LVTTHMR); h = apic_read(APIC_LVTTHMR);
if ((l & (1<<3)) && (h & APIC_DM_SMI)) { if ((l & (1<<3)) && (h & APIC_DM_SMI)) {
printk(KERN_DEBUG "CPU#%d: Thermal monitoring handled by SMI\n", cpu); printk(KERN_DEBUG "CPU#%d: Thermal monitoring handled by SMI\n", cpu);
...@@ -120,25 +105,24 @@ static void __init intel_init_thermal(struct cpuinfo_x86 *c) ...@@ -120,25 +105,24 @@ static void __init intel_init_thermal(struct cpuinfo_x86 *c)
h |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */ h |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */
apic_write_around(APIC_LVTTHMR, h); apic_write_around(APIC_LVTTHMR, h);
rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); rdmsr (MSR_IA32_THERM_INTERRUPT, l, h);
wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03 , h); wrmsr (MSR_IA32_THERM_INTERRUPT, l | 0x03 , h);
/* ok we're good to go... */ /* ok we're good to go... */
vendor_thermal_interrupt = intel_thermal_interrupt; vendor_thermal_interrupt = intel_thermal_interrupt;
rdmsr(MSR_IA32_MISC_ENABLE, l, h); rdmsr (MSR_IA32_MISC_ENABLE, l, h);
wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h); wrmsr (MSR_IA32_MISC_ENABLE, l | (1<<3), h);
l = apic_read(APIC_LVTTHMR); l = apic_read (APIC_LVTTHMR);
apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); apic_write_around (APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
printk(KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu); printk (KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu);
return; return;
} }
#endif /* CONFIG_X86_MCE_P4THERMAL */ #endif /* CONFIG_X86_MCE_P4THERMAL */
/* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */ /* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */
static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r) static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
{ {
u32 h; u32 h;
...@@ -146,16 +130,16 @@ static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r) ...@@ -146,16 +130,16 @@ static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
if (mce_num_extended_msrs == 0) if (mce_num_extended_msrs == 0)
goto done; goto done;
rdmsr(MSR_IA32_MCG_EAX, r->eax, h); rdmsr (MSR_IA32_MCG_EAX, r->eax, h);
rdmsr(MSR_IA32_MCG_EBX, r->ebx, h); rdmsr (MSR_IA32_MCG_EBX, r->ebx, h);
rdmsr(MSR_IA32_MCG_ECX, r->ecx, h); rdmsr (MSR_IA32_MCG_ECX, r->ecx, h);
rdmsr(MSR_IA32_MCG_EDX, r->edx, h); rdmsr (MSR_IA32_MCG_EDX, r->edx, h);
rdmsr(MSR_IA32_MCG_ESI, r->esi, h); rdmsr (MSR_IA32_MCG_ESI, r->esi, h);
rdmsr(MSR_IA32_MCG_EDI, r->edi, h); rdmsr (MSR_IA32_MCG_EDI, r->edi, h);
rdmsr(MSR_IA32_MCG_EBP, r->ebp, h); rdmsr (MSR_IA32_MCG_EBP, r->ebp, h);
rdmsr(MSR_IA32_MCG_ESP, r->esp, h); rdmsr (MSR_IA32_MCG_ESP, r->esp, h);
rdmsr(MSR_IA32_MCG_EFLAGS, r->eflags, h); rdmsr (MSR_IA32_MCG_EFLAGS, r->eflags, h);
rdmsr(MSR_IA32_MCG_EIP, r->eip, h); rdmsr (MSR_IA32_MCG_EIP, r->eip, h);
/* can we rely on kmalloc to do a dynamic /* can we rely on kmalloc to do a dynamic
* allocation for the reserved registers? * allocation for the reserved registers?
...@@ -164,10 +148,6 @@ static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r) ...@@ -164,10 +148,6 @@ static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
return mce_num_extended_msrs; return mce_num_extended_msrs;
} }
/*
* Machine Check Handler For PII/PIII
*/
static void intel_machine_check(struct pt_regs * regs, long error_code) static void intel_machine_check(struct pt_regs * regs, long error_code)
{ {
int recover=1; int recover=1;
...@@ -176,329 +156,106 @@ static void intel_machine_check(struct pt_regs * regs, long error_code) ...@@ -176,329 +156,106 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
int i; int i;
struct intel_mce_extended_msrs dbg; struct intel_mce_extended_msrs dbg;
rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
if(mcgstl&(1<<0)) /* Recoverable ? */ if (mcgstl & (1<<0)) /* Recoverable ? */
recover=0; recover=0;
printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl); printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
smp_processor_id(), mcgsth, mcgstl);
if (intel_get_extended_msrs(&dbg)) { if (intel_get_extended_msrs(&dbg)) {
printk(KERN_DEBUG "CPU %d: EIP: %08x EFLAGS: %08x\n", printk (KERN_DEBUG "CPU %d: EIP: %08x EFLAGS: %08x\n",
smp_processor_id(), dbg.eip, dbg.eflags); smp_processor_id(), dbg.eip, dbg.eflags);
printk(KERN_DEBUG "\teax: %08x ebx: %08x ecx: %08x edx: %08x\n", printk (KERN_DEBUG "\teax: %08x ebx: %08x ecx: %08x edx: %08x\n",
dbg.eax, dbg.ebx, dbg.ecx, dbg.edx); dbg.eax, dbg.ebx, dbg.ecx, dbg.edx);
printk(KERN_DEBUG "\tesi: %08x edi: %08x ebp: %08x esp: %08x\n", printk (KERN_DEBUG "\tesi: %08x edi: %08x ebp: %08x esp: %08x\n",
dbg.esi, dbg.edi, dbg.ebp, dbg.esp); dbg.esi, dbg.edi, dbg.ebp, dbg.esp);
} }
for (i=0;i<banks;i++) { for (i=0; i<nr_mce_banks; i++) {
rdmsr(MSR_IA32_MC0_STATUS+i*4,low, high); rdmsr (MSR_IA32_MC0_STATUS+i*4,low, high);
if(high&(1<<31)) { if (high & (1<<31)) {
if(high&(1<<29)) if (high & (1<<29))
recover|=1; recover |= 1;
if(high&(1<<25)) if (high & (1<<25))
recover|=2; recover |= 2;
printk(KERN_EMERG "Bank %d: %08x%08x", i, high, low); printk (KERN_EMERG "Bank %d: %08x%08x", i, high, low);
high&=~(1<<31); high &= ~(1<<31);
if(high&(1<<27)) { if (high & (1<<27)) {
rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh); rdmsr (MSR_IA32_MC0_MISC+i*4, alow, ahigh);
printk("[%08x%08x]", ahigh, alow); printk ("[%08x%08x]", ahigh, alow);
} }
if(high&(1<<26)) { if (high & (1<<26)) {
rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh); rdmsr (MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
printk(" at %08x%08x", ahigh, alow); printk (" at %08x%08x", ahigh, alow);
} }
printk("\n"); printk ("\n");
/* Clear it */
wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
/* Serialize */
wmb();
} }
} }
if(recover&2) if (recover & 2)
panic("CPU context corrupt"); panic ("CPU context corrupt");
if(recover&1) if (recover & 1)
panic("Unable to continue"); panic ("Unable to continue");
printk(KERN_EMERG "Attempting to continue.\n");
mcgstl&=~(1<<2);
wrmsr(MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
}
/*
* Machine check handler for Pentium class Intel
*/
static void pentium_machine_check(struct pt_regs * regs, long error_code)
{
u32 loaddr, hi, lotype;
rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
if(lotype&(1<<5))
printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
}
/*
* Machine check handler for WinChip C6
*/
static void winchip_machine_check(struct pt_regs * regs, long error_code)
{
printk(KERN_EMERG "CPU#%d: Machine Check Exception.\n", smp_processor_id());
}
/*
* Handle unconfigured int18 (should never happen)
*/
static void unexpected_machine_check(struct pt_regs * regs, long error_code)
{
printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
}
/*
* Call the installed machine check handler for this CPU setup.
*/
static void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
asmlinkage void do_machine_check(struct pt_regs * regs, long error_code)
{
machine_check_vector(regs, error_code);
}
#ifdef CONFIG_X86_MCE_NONFATAL
static struct timer_list mce_timer;
static int timerset = 0;
#define MCE_RATE 15*HZ /* timer rate is 15s */
static void mce_checkregs (void *info)
{
u32 low, high;
int i;
preempt_disable();
for (i=0; i<banks; i++) {
rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high);
if ((low | high) != 0) {
printk (KERN_EMERG "MCE: The hardware reports a non fatal, correctable incident occured on CPU %d.\n", smp_processor_id());
printk (KERN_EMERG "Bank %d: %08x%08x\n", i, high, low);
/* Scrub the error so we don't pick it up in MCE_RATE seconds time. */
wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
printk(KERN_EMERG "Attempting to continue.\n");
/*
* Do not clear the MSR_IA32_MCi_STATUS if the error is not
* recoverable/continuable.This will allow BIOS to look at the MSRs
* for errors if the OS could not log the error.
*/
for (i=0; i<nr_mce_banks; i++) {
u32 msr;
msr = MSR_IA32_MC0_STATUS+i*4;
rdmsr (msr, low, high);
if (high&(1<<31)) {
/* Clear it */
wrmsr(msr, 0UL, 0UL);
/* Serialize */ /* Serialize */
wmb(); wmb();
} }
} }
preempt_enable(); mcgstl &= ~(1<<2);
wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
} }
static void do_mce_timer(void *data)
{
smp_call_function (mce_checkregs, NULL, 1, 1);
}
static DECLARE_WORK(mce_work, do_mce_timer, NULL); void __init intel_p4_mcheck_init(struct cpuinfo_x86 *c)
static void mce_timerfunc (unsigned long data)
{
#ifdef CONFIG_SMP
if (num_online_cpus() > 1)
schedule_work(&mce_work);
#else
mce_checkregs(NULL);
#endif
mce_timer.expires = jiffies + MCE_RATE;
add_timer (&mce_timer);
}
#endif
/*
* Set up machine check reporting for processors with Intel style MCE
*/
static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
{ {
u32 l, h; u32 l, h;
int i; int i;
static int done;
/*
* Check for MCE support
*/
if( !cpu_has(c, X86_FEATURE_MCE) )
return;
/*
* Pentium machine check
*/
if(c->x86 == 5)
{
/* Default P5 to off as its often misconnected */
if(mce_disabled != -1)
return;
machine_check_vector = pentium_machine_check;
wmb();
/* Read registers before enabling */
rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
if(done==0)
printk(KERN_INFO "Intel old style machine check architecture supported.\n");
/* Enable MCE */
set_in_cr4(X86_CR4_MCE);
printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id());
return;
}
/*
* Check for PPro style MCA
*/
if( !cpu_has(c, X86_FEATURE_MCA) )
return;
/* Ok machine check is available */
machine_check_vector = intel_machine_check; machine_check_vector = intel_machine_check;
wmb(); wmb();
if(done==0) printk (KERN_INFO "Intel machine check architecture supported.\n");
printk(KERN_INFO "Intel machine check architecture supported.\n"); rdmsr (MSR_IA32_MCG_CAP, l, h);
rdmsr(MSR_IA32_MCG_CAP, l, h); if (l & (1<<8)) /* Control register present ? */
if(l&(1<<8)) /* Control register present ? */ wrmsr (MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); nr_mce_banks = l & 0xff;
banks = l&0xff;
for (i=0; i<nr_mce_banks; i++) {
/* Don't enable bank 0 on intel P6 cores, it goes bang quickly. */ wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 == 6) { wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
for(i=1; i<banks; i++)
wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
} else {
for(i=0; i<banks; i++)
wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
} }
for(i=0; i<banks; i++) set_in_cr4 (X86_CR4_MCE);
wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0); printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
smp_processor_id());
set_in_cr4(X86_CR4_MCE); /* Check for P4/Xeon extended MCE MSRs */
printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id()); rdmsr (MSR_IA32_MCG_CAP, l, h);
if (l & (1<<9)) {/* MCG_EXT_P */
mce_num_extended_msrs = (l >> 16) & 0xff;
printk (KERN_INFO "CPU#%d: Intel P4/Xeon Extended MCE MSRs (%d) available\n",
smp_processor_id(), mce_num_extended_msrs);
/*
* Check for P4/Xeon specific MCE extensions
*/
if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 == 15) {
/* Check for P4/Xeon extended MCE MSRs */
rdmsr(MSR_IA32_MCG_CAP, l, h);
if (l & (1<<9)) {/* MCG_EXT_P */
mce_num_extended_msrs = (l >> 16) & 0xff;
printk(KERN_INFO "CPU#%d: Intel P4/Xeon Extended MCE MSRs (%d) available\n",
smp_processor_id(), mce_num_extended_msrs);
}
#ifdef CONFIG_X86_MCE_P4THERMAL #ifdef CONFIG_X86_MCE_P4THERMAL
/* Check for P4/Xeon Thermal monitor */ /* Check for P4/Xeon Thermal monitor */
intel_init_thermal(c); intel_init_thermal(c);
#endif #endif
} }
done=1;
}
/*
* Set up machine check reporting on the Winchip C6 series
*/
static void __init winchip_mcheck_init(struct cpuinfo_x86 *c)
{
u32 lo, hi;
/* Not supported on C3 */
if(c->x86 != 5)
return;
/* Winchip C6 */
machine_check_vector = winchip_machine_check;
wmb();
rdmsr(MSR_IDT_FCR1, lo, hi);
lo|= (1<<2); /* Enable EIERRINT (int 18 MCE) */
lo&= ~(1<<4); /* Enable MCE */
wrmsr(MSR_IDT_FCR1, lo, hi);
set_in_cr4(X86_CR4_MCE);
printk(KERN_INFO "Winchip machine check reporting enabled on CPU#%d.\n", smp_processor_id());
}
/*
* This has to be run for each processor
*/
void __init mcheck_init(struct cpuinfo_x86 *c)
{
if(mce_disabled==1)
return;
switch(c->x86_vendor)
{
case X86_VENDOR_AMD:
/* AMD K7 machine check is Intel like */
if(c->x86 == 6 || c->x86 == 15) {
intel_mcheck_init(c);
#ifdef CONFIG_X86_MCE_NONFATAL #ifdef CONFIG_X86_MCE_NONFATAL
if (timerset == 0) { init_nonfatal_mce_checker();
/* Set the timer to check for non-fatal
errors every MCE_RATE seconds */
init_timer (&mce_timer);
mce_timer.expires = jiffies + MCE_RATE;
mce_timer.data = 0;
mce_timer.function = &mce_timerfunc;
add_timer (&mce_timer);
timerset = 1;
printk(KERN_INFO "Machine check exception polling timer started.\n");
}
#endif #endif
}
break;
case X86_VENDOR_INTEL:
intel_mcheck_init(c);
break;
case X86_VENDOR_CENTAUR:
winchip_mcheck_init(c);
break;
default:
break;
}
} }
static int __init mcheck_disable(char *str)
{
mce_disabled = 1;
return 0;
}
static int __init mcheck_enable(char *str)
{
mce_disabled = -1;
return 0;
}
__setup("nomce", mcheck_disable);
__setup("mce", mcheck_enable);
#else
asmlinkage void do_machine_check(struct pt_regs * regs, long error_code) {}
asmlinkage void smp_thermal_interrupt(struct pt_regs regs) {}
void __init mcheck_init(struct cpuinfo_x86 *c) {}
#endif
/*
* P5 specific Machine Check Exception Reporting
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/msr.h>
#include "mce.h"
/* Machine check handler for Pentium class Intel */
static void pentium_machine_check(struct pt_regs * regs, long error_code)
{
u32 loaddr, hi, lotype;
rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
if(lotype&(1<<5))
printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
}
/* Set up machine check reporting for processors with Intel style MCE */
void __init intel_p5_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
/*Check for MCE support */
if( !cpu_has(c, X86_FEATURE_MCE) )
return;
/* Default P5 to off as its often misconnected */
if(mce_disabled != -1)
return;
machine_check_vector = pentium_machine_check;
wmb();
/* Read registers before enabling */
rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
printk(KERN_INFO "Intel old style machine check architecture supported.\n");
/* Enable MCE */
set_in_cr4(X86_CR4_MCE);
printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id());
}
/*
* P6 specific Machine Check Exception Reporting
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/msr.h>
#include "mce.h"
/* Machine Check Handler For PII/PIII */
static void intel_machine_check(struct pt_regs * regs, long error_code)
{
int recover=1;
u32 alow, ahigh, high, low;
u32 mcgstl, mcgsth;
int i;
rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
if (mcgstl & (1<<0)) /* Recoverable ? */
recover=0;
printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
smp_processor_id(), mcgsth, mcgstl);
for (i=0; i<nr_mce_banks; i++) {
rdmsr (MSR_IA32_MC0_STATUS+i*4,low, high);
if (high & (1<<31)) {
if (high & (1<<29))
recover |= 1;
if (high & (1<<25))
recover |= 2;
printk (KERN_EMERG "Bank %d: %08x%08x", i, high, low);
high &= ~(1<<31);
if (high & (1<<27)) {
rdmsr (MSR_IA32_MC0_MISC+i*4, alow, ahigh);
printk ("[%08x%08x]", ahigh, alow);
}
if (high & (1<<26)) {
rdmsr (MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
printk (" at %08x%08x", ahigh, alow);
}
printk ("\n");
}
}
if (recover & 2)
panic ("CPU context corrupt");
if (recover & 1)
panic ("Unable to continue");
printk (KERN_EMERG "Attempting to continue.\n");
/*
* Do not clear the MSR_IA32_MCi_STATUS if the error is not
* recoverable/continuable.This will allow BIOS to look at the MSRs
* for errors if the OS could not log the error.
*/
for (i=0; i<nr_mce_banks; i++) {
unsigned int msr;
msr = MSR_IA32_MC0_STATUS+i*4;
rdmsr (msr,low, high);
if (high & (1<<31)) {
/* Clear it */
wrmsr (msr, 0UL, 0UL);
/* Serialize */
wmb();
}
}
mcgstl &= ~(1<<2);
wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
}
/* Set up machine check reporting for processors with Intel style MCE */
void __init intel_p6_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
/* Check for MCE support */
if (!cpu_has(c, X86_FEATURE_MCE))
return;
/* Check for PPro style MCA */
if (!cpu_has(c, X86_FEATURE_MCA))
return;
/* Ok machine check is available */
machine_check_vector = intel_machine_check;
wmb();
printk (KERN_INFO "Intel machine check architecture supported.\n");
rdmsr (MSR_IA32_MCG_CAP, l, h);
if (l & (1<<8)) /* Control register present ? */
wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
nr_mce_banks = l & 0xff;
/* Don't enable bank 0 on intel P6 cores, it goes bang quickly. */
for (i=1; i<nr_mce_banks; i++) {
wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
}
set_in_cr4 (X86_CR4_MCE);
printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
smp_processor_id());
}
/*
* IDT Winchip specific Machine Check Exception Reporting
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/msr.h>
#include "mce.h"
/* Machine check handler for WinChip C6 */
static void winchip_machine_check(struct pt_regs * regs, long error_code)
{
printk(KERN_EMERG "CPU0: Machine Check Exception.\n");
}
/* Set up machine check reporting on the Winchip C6 series */
void __init winchip_mcheck_init(struct cpuinfo_x86 *c)
{
u32 lo, hi;
machine_check_vector = winchip_machine_check;
wmb();
rdmsr(MSR_IDT_FCR1, lo, hi);
lo|= (1<<2); /* Enable EIERRINT (int 18 MCE) */
lo&= ~(1<<4); /* Enable MCE */
wrmsr(MSR_IDT_FCR1, lo, hi);
set_in_cr4(X86_CR4_MCE);
printk(KERN_INFO "Winchip machine check reporting enabled on CPU#0.\n");
}
...@@ -471,10 +471,12 @@ ENTRY(page_fault) ...@@ -471,10 +471,12 @@ ENTRY(page_fault)
pushl $do_page_fault pushl $do_page_fault
jmp error_code jmp error_code
#ifdef CONFIG_X86_MCE
ENTRY(machine_check) ENTRY(machine_check)
pushl $0 pushl $0
pushl $do_machine_check pushl $do_machine_check
jmp error_code jmp error_code
#endif
ENTRY(spurious_interrupt_bug) ENTRY(spurious_interrupt_bug)
pushl $0 pushl $0
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include <asm/arch_hooks.h> #include <asm/arch_hooks.h>
extern spinlock_t i8259A_lock; extern spinlock_t i8259A_lock;
int pit_latch_buggy; /* extern */
#include "do_timer.h" #include "do_timer.h"
......
...@@ -60,6 +60,8 @@ static unsigned long get_offset_tsc(void) ...@@ -60,6 +60,8 @@ static unsigned long get_offset_tsc(void)
static void mark_offset_tsc(void) static void mark_offset_tsc(void)
{ {
int count; int count;
int countmp;
static int count1=0, count2=LATCH;
/* /*
* It is important that these two operations happen almost at * It is important that these two operations happen almost at
* the same time. We do the RDTSC stuff first, since it's * the same time. We do the RDTSC stuff first, since it's
...@@ -83,6 +85,20 @@ static void mark_offset_tsc(void) ...@@ -83,6 +85,20 @@ static void mark_offset_tsc(void)
count |= inb(0x40) << 8; count |= inb(0x40) << 8;
spin_unlock(&i8253_lock); spin_unlock(&i8253_lock);
if (pit_latch_buggy) {
/* get center value of last 3 time lutch */
if ((count2 >= count && count >= count1)
|| (count1 >= count && count >= count2)) {
count2 = count1; count1 = count;
} else if ((count1 >= count2 && count2 >= count)
|| (count >= count2 && count2 >= count1)) {
countmp = count;count = count2;
count2 = count1;count1 = countmp;
} else {
count2 = count1; count1 = count; count = count1;
}
}
count = ((LATCH-1) - count) * TICK_SIZE; count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH; delay_at_last_interrupt = (count + LATCH/2) / LATCH;
} }
...@@ -111,10 +127,12 @@ static unsigned long __init calibrate_tsc(void) ...@@ -111,10 +127,12 @@ static unsigned long __init calibrate_tsc(void)
* Set the Gate high, program CTC channel 2 for mode 0, * Set the Gate high, program CTC channel 2 for mode 0,
* (interrupt on terminal count mode), binary count, * (interrupt on terminal count mode), binary count,
* load 5 * LATCH count, (LSB and MSB) to begin countdown. * load 5 * LATCH count, (LSB and MSB) to begin countdown.
*
* Some devices need a delay here.
*/ */
outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */ outb_p(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */ outb_p(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
{ {
unsigned long startlow, starthigh; unsigned long startlow, starthigh;
...@@ -238,8 +256,6 @@ static int init_tsc(void) ...@@ -238,8 +256,6 @@ static int init_tsc(void)
* moaned if you have the only one in the world - you fix it! * moaned if you have the only one in the world - you fix it!
*/ */
dodgy_tsc();
if (cpu_has_tsc) { if (cpu_has_tsc) {
unsigned long tsc_quotient = calibrate_tsc(); unsigned long tsc_quotient = calibrate_tsc();
if (tsc_quotient) { if (tsc_quotient) {
......
...@@ -906,7 +906,9 @@ void __init trap_init(void) ...@@ -906,7 +906,9 @@ void __init trap_init(void)
set_trap_gate(15,&spurious_interrupt_bug); set_trap_gate(15,&spurious_interrupt_bug);
set_trap_gate(16,&coprocessor_error); set_trap_gate(16,&coprocessor_error);
set_trap_gate(17,&alignment_check); set_trap_gate(17,&alignment_check);
#ifdef CONFIG_X86_MCE
set_trap_gate(18,&machine_check); set_trap_gate(18,&machine_check);
#endif
set_trap_gate(19,&simd_coprocessor_error); set_trap_gate(19,&simd_coprocessor_error);
set_system_gate(SYSCALL_VECTOR,&system_call); set_system_gate(SYSCALL_VECTOR,&system_call);
......
...@@ -3139,12 +3139,12 @@ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) ...@@ -3139,12 +3139,12 @@ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt)
*/ */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44) #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44)
static int sbp2scsi_biosparam (struct scsi_device *sdev, static int sbp2scsi_biosparam (struct scsi_device *sdev,
struct block_device *dev, sector_t capacy, int geom[]) struct block_device *dev, sector_t capacity, int geom[])
{ {
#else #else
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]) static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[])
{ {
sector_t capacy = disk->capacity; sector_t capacity = disk->capacity;
#endif #endif
int heads, sectors, cylinders; int heads, sectors, cylinders;
......
...@@ -549,10 +549,10 @@ static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id ...@@ -549,10 +549,10 @@ static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id
static int sbp2scsi_detect (Scsi_Host_Template *tpnt); static int sbp2scsi_detect (Scsi_Host_Template *tpnt);
static const char *sbp2scsi_info (struct Scsi_Host *host); static const char *sbp2scsi_info (struct Scsi_Host *host);
void sbp2scsi_setup(char *str, int *ints); void sbp2scsi_setup(char *str, int *ints);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44)
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]); static int sbp2scsi_biosparam (struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int geom[]);
#else #else
static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[]); static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]);
#endif #endif
static int sbp2scsi_abort (Scsi_Cmnd *SCpnt); static int sbp2scsi_abort (Scsi_Cmnd *SCpnt);
static int sbp2scsi_reset (Scsi_Cmnd *SCpnt); static int sbp2scsi_reset (Scsi_Cmnd *SCpnt);
......
...@@ -345,6 +345,51 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd) ...@@ -345,6 +345,51 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
} }
} }
/**
* NCR5380_poll_politely - wait for NCR5380 status bits
* @instance: controller to poll
* @reg: 5380 register to poll
* @bit: Bitmask to check
* @val: Value required to exit
*
* Polls the NCR5380 in a reasonably efficient manner waiting for
* an event to occur, after a short quick poll we begin giving the
* CPU back in non IRQ contexts
*
* Returns the value of the register or a negative error code.
*/
static int NCR5380_poll_politely(struct Scsi_Host *instance, int reg, int bit, int val, int t)
{
NCR5380_local_declare();
int n = 500; /* At about 8uS a cycle for the cpu access */
unsigned long end = jiffies + t;
int r;
NCR5380_setup(instance);
while( n-- > 0)
{
r = NCR5380_read(reg);
if((r & bit) == val)
return r;
cpu_relax();
}
/* t time yet ? */
while(time_before(jiffies, end))
{
r = NCR5380_read(reg);
if((r & bit) == val)
return r;
if(!in_interrupt())
yield();
else
cpu_relax();
}
return -ETIMEDOUT;
}
static struct { static struct {
unsigned char value; unsigned char value;
const char *name; const char *name;
...@@ -679,8 +724,11 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible) ...@@ -679,8 +724,11 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
while (probe_irq == IRQ_NONE && time_before(jiffies, timeout)) while (probe_irq == IRQ_NONE && time_before(jiffies, timeout))
barrier(); {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
NCR5380_write(SELECT_ENABLE_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
...@@ -1026,11 +1074,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1026,11 +1074,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
case 5: case 5:
printk(KERN_INFO "scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no); printk(KERN_INFO "scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no);
timeout = jiffies + 5 * HZ; timeout = jiffies + 5 * HZ;
while (time_before(jiffies, timeout) && (NCR5380_read(STATUS_REG) & SR_BSY)) NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, 0, 5*HZ);
{
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
break; break;
case 2: case 2:
printk(KERN_WARNING "scsi%d: bus busy, attempting abort\n", instance->host_no); printk(KERN_WARNING "scsi%d: bus busy, attempting abort\n", instance->host_no);
...@@ -1057,8 +1101,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1057,8 +1101,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
* twiddling done to the host specific fields of cmd. If the * twiddling done to the host specific fields of cmd. If the
* main coroutine is not running, it is restarted. * main coroutine is not running, it is restarted.
* *
* Locks: host lock taken by caller. Called functions drop and * Locks: host lock taken by caller
* retake this lock. Called functions take dma lock.
*/ */
static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
...@@ -1164,7 +1207,8 @@ static void NCR5380_main(void *p) ...@@ -1164,7 +1207,8 @@ static void NCR5380_main(void *p)
instance = hostdata->host; instance = hostdata->host;
spin_lock_irqsave(instance->host_lock, flags); if(instance->irq != IRQ_NONE)
spin_lock_irqsave(instance->host_lock, flags);
do { do {
/* Lock held here */ /* Lock held here */
...@@ -1243,12 +1287,9 @@ static void NCR5380_main(void *p) ...@@ -1243,12 +1287,9 @@ static void NCR5380_main(void *p)
do not respond to commands immediately do not respond to commands immediately
after a scan */ after a scan */
printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->target); printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->target);
//spin_lock_irq(&io_request_lock);
LIST(tmp, hostdata->issue_queue); LIST(tmp, hostdata->issue_queue);
tmp->host_scribble = (unsigned char *) hostdata->issue_queue; tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
hostdata->issue_queue = tmp; hostdata->issue_queue = tmp;
//spin_unlock_irq(&io_request_lock);
hostdata->time_expires = jiffies + USLEEP_WAITLONG; hostdata->time_expires = jiffies + USLEEP_WAITLONG;
NCR5380_set_timer(instance); NCR5380_set_timer(instance);
} }
...@@ -1267,7 +1308,8 @@ static void NCR5380_main(void *p) ...@@ -1267,7 +1308,8 @@ static void NCR5380_main(void *p)
break; break;
} while (!done); } while (!done);
spin_unlock_irqrestore(instance->host_lock, flags); if(instance->irq != IRQ_NONE)
spin_unlock_irqrestore(instance->host_lock, flags);
} }
#ifndef DONT_USE_INTR #ifndef DONT_USE_INTR
...@@ -1341,24 +1383,9 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1341,24 +1383,9 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
hostdata->dmalen = 0; hostdata->dmalen = 0;
(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
#if NCR_TIMEOUT
{
unsigned long timeout = jiffies + NCR_TIMEOUT;
spin_unlock_irq(instance->host_lock);
/* FIXME: prove timer is always running here! */
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK && time_before(jiffies, timeout))
cpu_relax();
spin_lock_irq(instance->host_lock);
if (time_after_eq(jiffies, timeout))
printk("scsi%d: timeout at NCR5380.c:%d\n", host->host_no, __LINE__);
}
#else /* NCR_TIMEOUT */ /* FIXME: we need to poll briefly then defer a workqueue task ! */
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK) NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2*HZ);
cpu_relax();
#endif
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
...@@ -1438,7 +1465,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) ...@@ -1438,7 +1465,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
* If failed (no target) : cmd->scsi_done() will be called, and the * If failed (no target) : cmd->scsi_done() will be called, and the
* cmd->result host byte set to DID_BAD_TARGET. * cmd->result host byte set to DID_BAD_TARGET.
* *
* Locks: caller holds hostdata lock * Locks: caller holds hostdata lock in IRQ mode
*/ */
static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
...@@ -1451,8 +1478,11 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1451,8 +1478,11 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
unsigned long timeout; unsigned long timeout;
unsigned char value; unsigned char value;
NCR5380_setup(instance); NCR5380_setup(instance);
int err;
if (hostdata->selecting) { if (hostdata->selecting) {
if(instance->irq != IRQ_NONE)
spin_unlock_irq(instance->host_lock);
goto part2; /* RvC: sorry prof. Dijkstra, but it keeps the goto part2; /* RvC: sorry prof. Dijkstra, but it keeps the
rest of the code nearly the same */ rest of the code nearly the same */
} }
...@@ -1476,29 +1506,22 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1476,29 +1506,22 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(MODE_REG, MR_ARBITRATE); NCR5380_write(MODE_REG, MR_ARBITRATE);
/* Wait for arbitration logic to complete */ if(instance->irq != IRQ_NONE)
#if NCR_TIMEOUT
{
unsigned long timeout = jiffies + 2 * NCR_TIMEOUT;
spin_unlock_irq(instance->host_lock); spin_unlock_irq(instance->host_lock);
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) /* We can be relaxed here, interrupts are on, we are
&& time_before(jiffies, timeout)) in workqueue context, the birds are singing in the trees */
cpu_relax();
err = NCR5380_poll_politely(instance, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, 5*HZ);
if(instance->irq != IRQ_NONE)
spin_lock_irq(instance->host_lock); spin_lock_irq(instance->host_lock);
if (time_after_eq(jiffies, timeout)) { if (err < 0) {
printk("scsi: arbitration timeout at %d\n", __LINE__); printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__);
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1; goto failed;
}
} }
#else /* NCR_TIMEOUT */
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS));
#endif
dprintk(NDEBUG_ARBITRATION, ("scsi%d : arbitration complete\n", instance->host_no)); dprintk(NDEBUG_ARBITRATION, ("scsi%d : arbitration complete\n", instance->host_no));
...@@ -1515,7 +1538,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1515,7 +1538,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no)); dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no));
return -1; goto failed;
} }
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL);
...@@ -1528,7 +1551,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1528,7 +1551,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no)); dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no));
return -1; goto failed;
} }
/* /*
* Again, bus clear + bus settle time is 1.2us, however, this is * Again, bus clear + bus settle time is 1.2us, however, this is
...@@ -1613,8 +1636,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1613,8 +1636,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
we poll only once ech clock tick */ we poll only once ech clock tick */
value = NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO); value = NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO);
/* FIXME HZ=100 assumption ? */ if (!value && (hostdata->select_time < HZ/4)) {
if (!value && (hostdata->select_time < 25)) {
/* RvC: we still must wait for a device response */ /* RvC: we still must wait for a device response */
hostdata->select_time++; /* after 25 ticks the device has failed */ hostdata->select_time++; /* after 25 ticks the device has failed */
hostdata->time_expires = jiffies + 1; hostdata->time_expires = jiffies + 1;
...@@ -1627,6 +1649,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1627,6 +1649,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
waiting period */ waiting period */
if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
if(instance->irq != IRQ_NONE)
spin_lock_irq(instance->host_lock);
NCR5380_reselect(instance); NCR5380_reselect(instance);
printk("scsi%d : reselection after won arbitration?\n", instance->host_no); printk("scsi%d : reselection after won arbitration?\n", instance->host_no);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
...@@ -1645,13 +1669,15 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1645,13 +1669,15 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
if (hostdata->targets_present & (1 << cmd->target)) { if (hostdata->targets_present & (1 << cmd->target)) {
printk("scsi%d : weirdness\n", instance->host_no); printk(KERN_DEBUG "scsi%d : weirdness\n", instance->host_no);
if (hostdata->restart_select) if (hostdata->restart_select)
printk("\trestart select\n"); printk(KERN_DEBUG "\trestart select\n");
NCR5380_dprint(NDEBUG_SELECTION, instance); NCR5380_dprint(NDEBUG_SELECTION, instance);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1; return -1;
} }
if(instance->irq != IRQ_NONE)
spin_lock_irq(instance->host_lock);
cmd->result = DID_BAD_TARGET << 16; cmd->result = DID_BAD_TARGET << 16;
collect_stats(hostdata, cmd); collect_stats(hostdata, cmd);
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
...@@ -1678,29 +1704,21 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1678,29 +1704,21 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
*/ */
/* Wait for start of REQ/ACK handshake */ /* Wait for start of REQ/ACK handshake */
#ifdef NCR_TIMEOUT
{ err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
unsigned long timeout = jiffies + NCR_TIMEOUT;
if(err)
spin_unlock_irq(instance->host_lock); { printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
while (!(NCR5380_read(STATUS_REG) & SR_REQ) && time_before(jiffies, timeout)) NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
cpu_relax(); goto failed;
spin_lock_irq(instance->host_lock);
if (time_after_eq(jiffies, timeout)) {
printk("scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1;
}
} }
#else /* NCR_TIMEOUT */
while (!(NCR5380_read(STATUS_REG) & SR_REQ))
cpu_relax();
#endif /* def NCR_TIMEOUT */
dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target)); dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target));
tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun); tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun);
if(instance->irq != IRQ_NONE)
spin_lock_irq(instance->host_lock);
len = 1; len = 1;
cmd->tag = 0; cmd->tag = 0;
...@@ -1717,6 +1735,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) ...@@ -1717,6 +1735,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
return 0; return 0;
/* Selection failed */
failed:
if(instance->irq != IRQ_NONE)
spin_lock_irq(instance->host_lock);
return -1;
} }
/* /*
...@@ -1786,6 +1811,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase ...@@ -1786,6 +1811,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
* if breaking is not allowed, we keep polling as long as needed * if breaking is not allowed, we keep polling as long as needed
*/ */
/* FIXME */
while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed); while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed);
if (!(tmp & SR_REQ)) { if (!(tmp & SR_REQ)) {
/* timeout condition */ /* timeout condition */
...@@ -1832,8 +1858,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase ...@@ -1832,8 +1858,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
} }
while (NCR5380_read(STATUS_REG) & SR_REQ); /* FIXME - if this fails bus reset ?? */
NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 5*HZ);
dprintk(NDEBUG_HANDSHAKE, ("scsi%d : req false, handshake complete\n", instance->host_no)); dprintk(NDEBUG_HANDSHAKE, ("scsi%d : req false, handshake complete\n", instance->host_no));
/* /*
...@@ -1905,8 +1931,9 @@ static void do_reset(struct Scsi_Host *host) { ...@@ -1905,8 +1931,9 @@ static void do_reset(struct Scsi_Host *host) {
static int do_abort(struct Scsi_Host *host) { static int do_abort(struct Scsi_Host *host) {
NCR5380_local_declare(); NCR5380_local_declare();
unsigned char tmp, *msgptr, phase; unsigned char *msgptr, phase, tmp;
int len; int len;
int rc;
NCR5380_setup(host); NCR5380_setup(host);
...@@ -1923,15 +1950,21 @@ static int do_abort(struct Scsi_Host *host) { ...@@ -1923,15 +1950,21 @@ static int do_abort(struct Scsi_Host *host) {
* the target sees, so we just handshake. * the target sees, so we just handshake.
*/ */
while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ) rc = NCR5380_poll_politely(host, STATUS_REG, SR_REQ, SR_REQ, 60 * HZ);
cpu_relax();
if(rc < 0)
return -1;
tmp = (unsigned char)rc;
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
if ((tmp & PHASE_MASK) != PHASE_MSGOUT) { if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
while (NCR5380_read(STATUS_REG) & SR_REQ); rc = NCR5380_poll_politely(host, STATUS_REG, SR_REQ, 0, 3*HZ);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
if(rc == -1)
return -1;
} }
tmp = ABORT; tmp = ABORT;
msgptr = &tmp; msgptr = &tmp;
...@@ -2245,7 +2278,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase ...@@ -2245,7 +2278,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
* XXX Note : we need to watch for bus free or a reset condition here * XXX Note : we need to watch for bus free or a reset condition here
* to recover from an unexpected bus free condition. * to recover from an unexpected bus free condition.
* *
* Locks: io_request_lock held by caller * Locks: io_request_lock held by caller in IRQ mode
*/ */
static void NCR5380_information_transfer(struct Scsi_Host *instance) { static void NCR5380_information_transfer(struct Scsi_Host *instance) {
...@@ -2503,7 +2536,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2503,7 +2536,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
/* Enable reselect interrupts */ /* Enable reselect interrupts */
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
/* Wait for bus free to avoid nasty timeouts */ /* Wait for bus free to avoid nasty timeouts - FIXME timeout !*/
/* NCR538_poll_politely(instance, STATUS_REG, SR_BSY, 0, 30 * HZ); */
while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
barrier(); barrier();
return; return;
...@@ -2658,7 +2692,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ...@@ -2658,7 +2692,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
* *
* Inputs : instance - this instance of the NCR5380. * Inputs : instance - this instance of the NCR5380.
* *
* Locks: io_request_lock held by caller * Locks: io_request_lock held by caller if IRQ driven
*/ */
static void NCR5380_reselect(struct Scsi_Host *instance) { static void NCR5380_reselect(struct Scsi_Host *instance) {
...@@ -2696,16 +2730,19 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -2696,16 +2730,19 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
while (NCR5380_read(STATUS_REG) & SR_SEL); /* FIXME: timeout too long, must fail to workqueue */
if(NCR5380_poll_politely(instance, STATUS_REG, SR_SEL, 0, 2*HZ)<0)
abort = 1;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
/* /*
* Wait for target to go into MSGIN. * Wait for target to go into MSGIN.
* FIXME: timeout needed * FIXME: timeout needed and fail to work queeu
*/ */
while (!(NCR5380_read(STATUS_REG) & SR_REQ)) if(NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 2*HZ))
cpu_relax(); abort = 1;
len = 1; len = 1;
data = msg; data = msg;
...@@ -2713,7 +2750,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -2713,7 +2750,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
NCR5380_transfer_pio(instance, &phase, &len, &data); NCR5380_transfer_pio(instance, &phase, &len, &data);
if (!msg[0] & 0x80) { if (!msg[0] & 0x80) {
printk("scsi%d : expecting IDENTIFY message, got ", instance->host_no); printk(KERN_ERR "scsi%d : expecting IDENTIFY message, got ", instance->host_no);
print_msg(msg); print_msg(msg);
abort = 1; abort = 1;
} else { } else {
...@@ -2747,7 +2784,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { ...@@ -2747,7 +2784,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
break; break;
} }
if (!tmp) { if (!tmp) {
printk("scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n", instance->host_no, target_mask, lun); printk(KERN_ERR "scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n", instance->host_no, target_mask, lun);
/* /*
* Since we have an established nexus that we can't do anything with, * Since we have an established nexus that we can't do anything with,
* we must abort it. * we must abort it.
...@@ -2790,9 +2827,11 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) { ...@@ -2790,9 +2827,11 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
* *
* We should use the Last Byte Sent bit, unfortunately this is * We should use the Last Byte Sent bit, unfortunately this is
* not available on the 5380/5381 (only the various CMOS chips) * not available on the 5380/5381 (only the various CMOS chips)
*
* FIXME: timeout, and need to handle long timeout/irq case
*/ */
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK); NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, BASR_ACK, 0, 5*HZ);
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
...@@ -2827,21 +2866,15 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) { ...@@ -2827,21 +2866,15 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
* a problem, we could implement longjmp() / setjmp(), setjmp() * a problem, we could implement longjmp() / setjmp(), setjmp()
* called where the loop started in NCR5380_main(). * called where the loop started in NCR5380_main().
* *
* Locks: host lock taken by function * Locks: host lock taken by caller
*/ */
#ifndef NCR5380_abort static int NCR5380_abort(Scsi_Cmnd * cmd) {
static
#endif
int NCR5380_abort(Scsi_Cmnd * cmd) {
NCR5380_local_declare(); NCR5380_local_declare();
struct Scsi_Host *instance = cmd->host; struct Scsi_Host *instance = cmd->host;
unsigned long flags;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
Scsi_Cmnd *tmp, **prev; Scsi_Cmnd *tmp, **prev;
spin_lock_irqsave(instance->host_lock, flags);
printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no); printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no);
print_Scsi_Cmnd(cmd); print_Scsi_Cmnd(cmd);
...@@ -2884,7 +2917,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2884,7 +2917,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* aborted flag and get back into our main loop. * aborted flag and get back into our main loop.
*/ */
spin_unlock_irqrestore(instance->host_lock, flags);
return 0; return 0;
} }
#endif #endif
...@@ -2894,8 +2926,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2894,8 +2926,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* from the issue queue. * from the issue queue.
*/ */
/* FIXME: check - I think we need the hostdata lock here */
/* KLL */
dprintk(NDEBUG_ABORT, ("scsi%d : abort going into loop.\n", instance->host_no)); dprintk(NDEBUG_ABORT, ("scsi%d : abort going into loop.\n", instance->host_no));
for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble) for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
if (cmd == tmp) { if (cmd == tmp) {
...@@ -2905,7 +2935,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2905,7 +2935,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
tmp->result = DID_ABORT << 16; tmp->result = DID_ABORT << 16;
dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no)); dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
tmp->done(tmp); tmp->done(tmp);
spin_unlock_irqrestore(instance->host_lock, flags);
return SUCCESS; return SUCCESS;
} }
#if (NDEBUG & NDEBUG_ABORT) #if (NDEBUG & NDEBUG_ABORT)
...@@ -2927,7 +2956,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2927,7 +2956,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
if (hostdata->connected) { if (hostdata->connected) {
dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no)); dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no));
spin_unlock_irqrestore(instance->host_lock, flags);
return FAILED; return FAILED;
} }
/* /*
...@@ -2972,7 +3000,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2972,7 +3000,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
tmp->host_scribble = NULL; tmp->host_scribble = NULL;
tmp->result = DID_ABORT << 16; tmp->result = DID_ABORT << 16;
tmp->done(tmp); tmp->done(tmp);
spin_unlock_irqrestore(instance->host_lock, flags);
return SUCCESS; return SUCCESS;
} }
} }
...@@ -2985,7 +3012,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2985,7 +3012,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* so we won't panic, but we will notify the user in case something really * so we won't panic, but we will notify the user in case something really
* broke. * broke.
*/ */
spin_unlock_irqrestore(instance->host_lock, flags);
printk(KERN_WARNING "scsi%d : warning : SCSI command probably completed successfully\n" printk(KERN_WARNING "scsi%d : warning : SCSI command probably completed successfully\n"
" before abortion\n", instance->host_no); " before abortion\n", instance->host_no);
return FAILED; return FAILED;
...@@ -2999,22 +3025,15 @@ int NCR5380_abort(Scsi_Cmnd * cmd) { ...@@ -2999,22 +3025,15 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* *
* Returns : SUCCESS * Returns : SUCCESS
* *
* Locks: host lock taken by function * Locks: host lock taken by caller
*/ */
#ifndef NCR5380_bus_reset static int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
static
#endif
int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
unsigned long flags;
struct Scsi_Host *instance = cmd->host;
NCR5380_local_declare(); NCR5380_local_declare();
NCR5380_setup(cmd->host); NCR5380_setup(cmd->host);
spin_lock_irqsave(instance->host_lock, flags);
NCR5380_print_status(cmd->host); NCR5380_print_status(cmd->host);
do_reset(cmd->host); do_reset(cmd->host);
spin_unlock_irqrestore(instance->host_lock, flags);
return SUCCESS; return SUCCESS;
} }
...@@ -3028,12 +3047,7 @@ int NCR5380_bus_reset(Scsi_Cmnd * cmd) { ...@@ -3028,12 +3047,7 @@ int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
* Locks: io_request_lock held by caller * Locks: io_request_lock held by caller
*/ */
#ifndef NCR5380_device_reset static int NCR5380_device_reset(Scsi_Cmnd * cmd) {
static
#endif
int NCR5380_device_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
NCR5380_setup(cmd->host);
return FAILED; return FAILED;
} }
...@@ -3047,11 +3061,6 @@ int NCR5380_device_reset(Scsi_Cmnd * cmd) { ...@@ -3047,11 +3061,6 @@ int NCR5380_device_reset(Scsi_Cmnd * cmd) {
* Locks: io_request_lock held by caller * Locks: io_request_lock held by caller
*/ */
#ifndef NCR5380_host_reset static int NCR5380_host_reset(Scsi_Cmnd * cmd) {
static
#endif
int NCR5380_host_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
NCR5380_setup(cmd->host);
return FAILED; return FAILED;
} }
...@@ -677,22 +677,6 @@ static void wait_intr(void) ...@@ -677,22 +677,6 @@ static void wait_intr(void)
NCR53c406a_intr(0, NULL, NULL); NCR53c406a_intr(0, NULL, NULL);
} }
static int NCR53c406a_command(Scsi_Cmnd * SCpnt)
{
DEB(printk("NCR53c406a_command called\n"));
NCR53c406a_queue(SCpnt, internal_done);
if (irq_level)
while (!internal_done_flag)
cpu_relax();
else /* interrupts not supported */
while (!internal_done_flag)
wait_intr();
internal_done_flag = 0;
return internal_done_errcode;
}
static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
{ {
int i; int i;
...@@ -726,6 +710,21 @@ static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -726,6 +710,21 @@ static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
return 0; return 0;
} }
static int NCR53c406a_command(Scsi_Cmnd * SCpnt)
{
DEB(printk("NCR53c406a_command called\n"));
NCR53c406a_queue(SCpnt, internal_done);
if (irq_level)
while (!internal_done_flag)
cpu_relax();
else /* interrupts not supported */
while (!internal_done_flag)
wait_intr();
internal_done_flag = 0;
return internal_done_errcode;
}
static int NCR53c406a_abort(Scsi_Cmnd * SCpnt) static int NCR53c406a_abort(Scsi_Cmnd * SCpnt)
{ {
DEB(printk("NCR53c406a_abort called\n")); DEB(printk("NCR53c406a_abort called\n"));
...@@ -755,7 +754,7 @@ static int NCR53c406a_bus_reset(Scsi_Cmnd * SCpnt) ...@@ -755,7 +754,7 @@ static int NCR53c406a_bus_reset(Scsi_Cmnd * SCpnt)
return FAILED; return FAILED;
} }
static int NCR53c406a_biosparm(struct scsi_disk *disk, static int NCR53c406a_biosparm(struct scsi_device *disk,
struct block_device *dev, struct block_device *dev,
sector_t capacity, int *info_array) sector_t capacity, int *info_array)
{ {
...@@ -1065,8 +1064,30 @@ static void __init calc_port_addr(void) ...@@ -1065,8 +1064,30 @@ static void __init calc_port_addr(void)
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* Eventually this will go into an include file, but this will be later */ /* NOTE: scatter-gather support only works in PIO mode.
static Scsi_Host_Template driver_template = NCR53c406a; * Use SG_NONE if DMA mode is enabled!
*/
static Scsi_Host_Template driver_template =
{
proc_name: "NCR53c406a" /* proc_name */,
name: "NCR53c406a" /* name */,
detect: NCR53c406a_detect /* detect */,
info: NCR53c406a_info /* info */,
command: NCR53c406a_command /* command */,
queuecommand: NCR53c406a_queue /* queuecommand */,
eh_abort_handler: NCR53c406a_abort /* abort */,
eh_bus_reset_handler: NCR53c406a_bus_reset /* reset */,
eh_device_reset_handler: NCR53c406a_device_reset /* reset */,
eh_host_reset_handler: NCR53c406a_host_reset /* reset */,
bios_param: NCR53c406a_biosparm /* biosparm */,
can_queue: 1 /* can_queue */,
this_id: 7 /* SCSI ID of the chip */,
sg_tablesize: 32 /*SG_ALL*/ /*SG_NONE*/,
cmd_per_lun: 1 /* commands per lun */,
unchecked_isa_dma: 1 /* unchecked_isa_dma */,
use_clustering: ENABLE_CLUSTERING
};
#include "scsi_module.c" #include "scsi_module.c"
......
#ifndef _NCR53C406A_H
#define _NCR53C406A_H
/*
* NCR53c406a.h
*
* Copyright (C) 1994 Normunds Saumanis (normunds@rx.tech.swh.lv)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
#ifndef NULL
#define NULL 0
#endif
/* NOTE: scatter-gather support only works in PIO mode.
* Use SG_NONE if DMA mode is enabled!
*/
#define NCR53c406a { \
proc_name: "NCR53c406a" /* proc_name */, \
name: "NCR53c406a" /* name */, \
detect: NCR53c406a_detect /* detect */, \
info: NCR53c406a_info /* info */, \
command: NCR53c406a_command /* command */, \
queuecommand: NCR53c406a_queue /* queuecommand */, \
eh_abort_handler: NCR53c406a_abort /* abort */, \
eh_bus_reset_handler: NCR53c406a_bus_reset /* reset */, \
eh_device_reset_handler: NCR53c406a_device_reset /* reset */, \
eh_host_reset_handler: NCR53c406a_host_reset /* reset */, \
bios_param: NCR53c406a_biosparm /* biosparm */, \
can_queue: 1 /* can_queue */, \
this_id: 7 /* SCSI ID of the chip */, \
sg_tablesize: 32 /*SG_ALL*/ /*SG_NONE*/, \
cmd_per_lun: 1 /* commands per lun */, \
unchecked_isa_dma: 1 /* unchecked_isa_dma */, \
use_clustering: ENABLE_CLUSTERING \
}
static int NCR53c406a_detect(Scsi_Host_Template *);
static const char *NCR53c406a_info(struct Scsi_Host *);
static int NCR53c406a_command(Scsi_Cmnd *);
static int NCR53c406a_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int NCR53c406a_abort(Scsi_Cmnd *);
static int NCR53c406a_bus_reset(Scsi_Cmnd *);
static int NCR53c406a_device_reset(Scsi_Cmnd *);
static int NCR53c406a_host_reset(Scsi_Cmnd *);
static int NCR53c406a_biosparm(Disk *, struct block_device *, sector_t, int[]);
#endif /* _NCR53C406A_H */
...@@ -20,6 +20,14 @@ ...@@ -20,6 +20,14 @@
* *
* aha1740_makecode may still need even more work * aha1740_makecode may still need even more work
* if it doesn't work for your devices, take a look. * if it doesn't work for your devices, take a look.
*
* Reworked for new_eh and new locking by Alan Cox <alan@redhat.com>
*
* For the avoidance of doubt the "preferred form" of this code is one which
* is in an open non patent encumbered format. Where cryptographic key signing
* forms part of the process of creating an executable the information
* including keys needed to generate an equivalently functional executable
* are deemed to be part of the source code.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -68,7 +76,7 @@ static spinlock_t aha1740_lock = SPIN_LOCK_UNLOCKED; ...@@ -68,7 +76,7 @@ static spinlock_t aha1740_lock = SPIN_LOCK_UNLOCKED;
/* One for each IRQ level (9-15) */ /* One for each IRQ level (9-15) */
static struct Scsi_Host * aha_host[8] = {NULL, }; static struct Scsi_Host * aha_host[8] = {NULL, };
int aha1740_proc_info(char *buffer, char **start, off_t offset, static int aha1740_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int inout) int length, int hostno, int inout)
{ {
int len; int len;
...@@ -76,7 +84,7 @@ int aha1740_proc_info(char *buffer, char **start, off_t offset, ...@@ -76,7 +84,7 @@ int aha1740_proc_info(char *buffer, char **start, off_t offset,
struct aha1740_hostdata *host; struct aha1740_hostdata *host;
if (inout) if (inout)
return(-ENOSYS); return-ENOSYS;
for (len = 0; len < 8; len++) { for (len = 0; len < 8; len++) {
shpnt = aha_host[len]; shpnt = aha_host[len];
...@@ -103,7 +111,7 @@ int aha1740_proc_info(char *buffer, char **start, off_t offset, ...@@ -103,7 +111,7 @@ int aha1740_proc_info(char *buffer, char **start, off_t offset,
} }
int aha1740_makecode(unchar *sense, unchar *status) static int aha1740_makecode(unchar *sense, unchar *status)
{ {
struct statusword struct statusword
{ {
...@@ -179,7 +187,7 @@ int aha1740_makecode(unchar *sense, unchar *status) ...@@ -179,7 +187,7 @@ int aha1740_makecode(unchar *sense, unchar *status)
return status[3] | retval << 16; return status[3] | retval << 16;
} }
int aha1740_test_port(unsigned int base) static int aha1740_test_port(unsigned int base)
{ {
char name[4], tmp; char name[4], tmp;
...@@ -212,7 +220,7 @@ int aha1740_test_port(unsigned int base) ...@@ -212,7 +220,7 @@ int aha1740_test_port(unsigned int base)
} }
/* A "high" level interrupt handler */ /* A "high" level interrupt handler */
void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs) static void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
{ {
struct Scsi_Host *host = aha_host[irq - 9]; struct Scsi_Host *host = aha_host[irq - 9];
void (*my_done)(Scsi_Cmnd *); void (*my_done)(Scsi_Cmnd *);
...@@ -303,7 +311,7 @@ void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs) ...@@ -303,7 +311,7 @@ void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
spin_unlock_irqrestore(host->host_lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
} }
int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
{ {
unchar direction; unchar direction;
unchar *cmd = (unchar *) SCpnt->cmnd; unchar *cmd = (unchar *) SCpnt->cmnd;
...@@ -317,16 +325,6 @@ int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -317,16 +325,6 @@ int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
if(*cmd == REQUEST_SENSE) if(*cmd == REQUEST_SENSE)
{ {
#if 0
/* scsi_request_sense() provides a buffer of size 256,
so there is no reason to expect equality */
if (bufflen != sizeof(SCpnt->sense_buffer))
{
printk("Wrong buffer length supplied for request sense (%d)\n",
bufflen);
}
#endif
SCpnt->result = 0; SCpnt->result = 0;
done(SCpnt); done(SCpnt);
return 0; return 0;
...@@ -486,7 +484,7 @@ static void internal_done(Scsi_Cmnd * SCpnt) ...@@ -486,7 +484,7 @@ static void internal_done(Scsi_Cmnd * SCpnt)
SCpnt->SCp.Status++; SCpnt->SCp.Status++;
} }
int aha1740_command(Scsi_Cmnd * SCpnt) static int aha1740_command(Scsi_Cmnd * SCpnt)
{ {
aha1740_queuecommand(SCpnt, internal_done); aha1740_queuecommand(SCpnt, internal_done);
SCpnt->SCp.Status = 0; SCpnt->SCp.Status = 0;
...@@ -501,7 +499,7 @@ int aha1740_command(Scsi_Cmnd * SCpnt) ...@@ -501,7 +499,7 @@ int aha1740_command(Scsi_Cmnd * SCpnt)
/* Query the board for its irq_level. Nothing else matters /* Query the board for its irq_level. Nothing else matters
in enhanced mode on an EISA bus. */ in enhanced mode on an EISA bus. */
void aha1740_getconfig(unsigned int base, unsigned int *irq_level, static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
unsigned int *translation) unsigned int *translation)
{ {
static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 }; static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
...@@ -511,7 +509,7 @@ void aha1740_getconfig(unsigned int base, unsigned int *irq_level, ...@@ -511,7 +509,7 @@ void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
outb(inb(INTDEF(base)) | 0x10, INTDEF(base)); outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
} }
int aha1740_detect(Scsi_Host_Template * tpnt) static int aha1740_detect(Scsi_Host_Template * tpnt)
{ {
int count = 0, slot; int count = 0, slot;
...@@ -540,8 +538,8 @@ int aha1740_detect(Scsi_Host_Template * tpnt) ...@@ -540,8 +538,8 @@ int aha1740_detect(Scsi_Host_Template * tpnt)
outb(G2CNTRL_HRST, G2CNTRL(slotbase)); outb(G2CNTRL_HRST, G2CNTRL(slotbase));
outb(0, G2CNTRL(slotbase)); outb(0, G2CNTRL(slotbase));
} }
printk("Configuring aha174x at IO:%x, IRQ %d\n", slotbase, irq_level); printk(KERN_INFO "Configuring aha174x at IO:%x, IRQ %d\n", slotbase, irq_level);
printk("aha174x: Extended translation %sabled.\n", printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
translation ? "en" : "dis"); translation ? "en" : "dis");
DEB(printk("aha1740_detect: enable interrupt channel %d\n",irq_level)); DEB(printk("aha1740_detect: enable interrupt channel %d\n",irq_level));
if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",NULL)) { if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",NULL)) {
...@@ -572,31 +570,7 @@ int aha1740_detect(Scsi_Host_Template * tpnt) ...@@ -572,31 +570,7 @@ int aha1740_detect(Scsi_Host_Template * tpnt)
return count; return count;
} }
/* Note: They following two functions do not apply very well to the Adaptec, static int aha1740_biosparam(struct scsi_device *sdev, struct block_device *dev,
which basically manages its own affairs quite well without our interference,
so I haven't put anything into them. I can faintly imagine someone with a
*very* badly behaved SCSI target (perhaps an old tape?) wanting the abort(),
but it hasn't happened yet, and doing aborts brings the Adaptec to its
knees. I cannot (at this moment in time) think of any reason to reset the
card once it's running. So there. */
int aha1740_abort(Scsi_Cmnd * SCpnt)
{
DEB(printk("aha1740_abort called\n"));
return SCSI_ABORT_SNOOZE;
}
/* We do not implement a reset function here, but the upper level code assumes
that it will get some kind of response for the command in SCpnt. We must
oblige, or the command will hang the scsi system */
int aha1740_reset(Scsi_Cmnd * SCpnt, unsigned int ignored)
{
DEB(printk("aha1740_reset called\n"));
return SCSI_RESET_PUNT;
}
int aha1740_biosparam(struct scsi_device *sdev, struct block_device *dev,
sector_t capacity, int* ip) sector_t capacity, int* ip)
{ {
int size = capacity; int size = capacity;
......
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
#include <linux/types.h> #include <linux/types.h>
/* Eisa Enhanced mode operation - slot locating and addressing */ /* Eisa Enhanced mode operation - slot locating and addressing */
#define MINEISA 1 /* I don't have an EISA Spec to know these ranges, so I */ #define MINEISA 1 /* I don't have an EISA Spec to know these ranges, so I */
#define MAXEISA 8 /* Just took my machine's specifications. Adjust to fit.*/ #define MAXEISA 8 /* Just took my machine's specifications. Adjust to fit. */
/* I just saw an ad, and bumped this from 6 to 8 */ /* I just saw an ad, and bumped this from 6 to 8 */
#define SLOTBASE(x) ((x << 12) + 0xc80) #define SLOTBASE(x) ((x << 12) + 0xc80)
#define SLOTSIZE 0x5c #define SLOTSIZE 0x5c
...@@ -75,14 +75,14 @@ ...@@ -75,14 +75,14 @@
#define ATTN_START 0x40 /* Start CCB */ #define ATTN_START 0x40 /* Start CCB */
#define ATTN_ABORT 0x50 /* Abort CCB */ #define ATTN_ABORT 0x50 /* Abort CCB */
#define G2CNTRL_HRST 0x80 /* Hard Reset */ #define G2CNTRL_HRST 0x80 /* Hard Reset */
#define G2CNTRL_IRST 0x40 /* Clear EISA Interrupt */ #define G2CNTRL_IRST 0x40 /* Clear EISA Interrupt */
#define G2CNTRL_HRDY 0x20 /* Sets HOST ready */ #define G2CNTRL_HRDY 0x20 /* Sets HOST ready */
/* This is used with scatter-gather */ /* This is used with scatter-gather */
struct aha1740_chain { struct aha1740_chain {
u32 dataptr; /* Location of data */ u32 dataptr; /* Location of data */
u32 datalen; /* Size of this part of chain */ u32 datalen; /* Size of this part of chain */
}; };
/* These belong in scsi.h */ /* These belong in scsi.h */
...@@ -107,40 +107,40 @@ struct aha1740_chain { ...@@ -107,40 +107,40 @@ struct aha1740_chain {
#define MAX_STATUS 32 #define MAX_STATUS 32
struct ecb { /* Enhanced Control Block 6.1 */ struct ecb { /* Enhanced Control Block 6.1 */
u16 cmdw; /* Command Word */ u16 cmdw; /* Command Word */
/* Flag Word 1 */ /* Flag Word 1 */
u16 cne:1, /* Control Block Chaining */ u16 cne:1, /* Control Block Chaining */
:6, di:1, /* Disable Interrupt */ :6, di:1, /* Disable Interrupt */
:2, ses:1, /* Suppress Underrun error */ :2, ses:1, /* Suppress Underrun error */
:1, sg:1, /* Scatter/Gather */ :1, sg:1, /* Scatter/Gather */
:1, dsb:1, /* Disable Status Block */ :1, dsb:1, /* Disable Status Block */
ars:1; /* Automatic Request Sense */ ars:1; /* Automatic Request Sense */
/* Flag Word 2 */ /* Flag Word 2 */
u16 lun:3, /* Logical Unit */ u16 lun:3, /* Logical Unit */
tag:1, /* Tagged Queuing */ tag:1, /* Tagged Queuing */
tt:2, /* Tag Type */ tt:2, /* Tag Type */
nd:1, /* No Disconnect */ nd:1, /* No Disconnect */
:1, dat:1, /* Data transfer - check direction */ :1, dat:1, /* Data transfer - check direction */
dir:1, /* Direction of transfer 1 = datain */ dir:1, /* Direction of transfer 1 = datain */
st:1, /* Suppress Transfer */ st:1, /* Suppress Transfer */
chk:1, /* Calculate Checksum */ chk:1, /* Calculate Checksum */
:2, rec:1, :1; /* Error Recovery */ :2, rec:1,:1; /* Error Recovery */
u16 nil0; /* nothing */ u16 nil0; /* nothing */
u32 dataptr; /* Data or Scatter List ptr */ u32 dataptr; /* Data or Scatter List ptr */
u32 datalen; /* Data or Scatter List len */ u32 datalen; /* Data or Scatter List len */
u32 statusptr; /* Status Block ptr */ u32 statusptr; /* Status Block ptr */
u32 linkptr; /* Chain Address */ u32 linkptr; /* Chain Address */
u32 nil1; /* nothing */ u32 nil1; /* nothing */
u32 senseptr; /* Sense Info Pointer */ u32 senseptr; /* Sense Info Pointer */
u8 senselen; /* Sense Length */ u8 senselen; /* Sense Length */
u8 cdblen; /* CDB Length */ u8 cdblen; /* CDB Length */
u16 datacheck; /* Data checksum */ u16 datacheck; /* Data checksum */
u8 cdb[MAX_CDB]; /* CDB area */ u8 cdb[MAX_CDB]; /* CDB area */
/* Hardware defined portion ends here, rest is driver defined */ /* Hardware defined portion ends here, rest is driver defined */
u8 sense[MAX_SENSE]; /* Sense area */ u8 sense[MAX_SENSE]; /* Sense area */
u8 status[MAX_STATUS]; /* Status area */ u8 status[MAX_STATUS]; /* Status area */
Scsi_Cmnd *SCpnt; /* Link to the SCSI Command Block */ Scsi_Cmnd *SCpnt; /* Link to the SCSI Command Block */
void (*done)(Scsi_Cmnd *); /* Completion Function */ void (*done) (Scsi_Cmnd *); /* Completion Function */
}; };
#define AHA1740CMD_NOP 0x00 /* No OP */ #define AHA1740CMD_NOP 0x00 /* No OP */
...@@ -152,32 +152,22 @@ struct ecb { /* Enhanced Control Block 6.1 */ ...@@ -152,32 +152,22 @@ struct ecb { /* Enhanced Control Block 6.1 */
#define AHA1740CMD_RINQ 0x0a /* Read Host Adapter Inquiry Data */ #define AHA1740CMD_RINQ 0x0a /* Read Host Adapter Inquiry Data */
#define AHA1740CMD_TARG 0x10 /* Target SCSI Command */ #define AHA1740CMD_TARG 0x10 /* Target SCSI Command */
int aha1740_detect(Scsi_Host_Template *); static int aha1740_detect(Scsi_Host_Template *);
int aha1740_command(Scsi_Cmnd *); static int aha1740_command(Scsi_Cmnd *);
int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int aha1740_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
int aha1740_abort(Scsi_Cmnd *); static int aha1740_biosparam(struct scsi_device *, struct block_device *, sector_t, int *);
int aha1740_reset(Scsi_Cmnd *, unsigned int); static int aha1740_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout);
int aha1740_biosparam(struct scsi_device *, struct block_device *,
sector_t, int*);
int aha1740_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int inout);
#define AHA1740_ECBS 32 #define AHA1740_ECBS 32
#define AHA1740_SCATTER 16 #define AHA1740_SCATTER 16
#define AHA1740_CMDLUN 1 #define AHA1740_CMDLUN 1
#ifndef NULL
#define NULL 0
#endif
#define AHA1740 { proc_name: "aha1740", \ #define AHA1740 { proc_name: "aha1740", \
proc_info: aha1740_proc_info, \ proc_info: aha1740_proc_info, \
name: "Adaptec 174x (EISA)", \ name: "Adaptec 174x (EISA)", \
detect: aha1740_detect, \ detect: aha1740_detect, \
command: aha1740_command, \ command: aha1740_command, \
queuecommand: aha1740_queuecommand, \ queuecommand: aha1740_queuecommand, \
abort: aha1740_abort, \
reset: aha1740_reset, \
bios_param: aha1740_biosparam, \ bios_param: aha1740_biosparam, \
can_queue: AHA1740_ECBS, \ can_queue: AHA1740_ECBS, \
this_id: 7, \ this_id: 7, \
......
...@@ -476,7 +476,6 @@ MODULE_AUTHOR("Dario Ballabio"); ...@@ -476,7 +476,6 @@ MODULE_AUTHOR("Dario Ballabio");
#include <linux/blk.h> #include <linux/blk.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
#include "sd.h"
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/irq.h> #include <asm/irq.h>
#include "eata.h" #include "eata.h"
...@@ -1838,7 +1837,7 @@ int eata2x_bios_param(struct scsi_device *sdev, struct block_device *bdev, ...@@ -1838,7 +1837,7 @@ int eata2x_bios_param(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int *dkinfo) { sector_t capacity, int *dkinfo) {
int size = capacity; int size = capacity;
if (ext_tran || (scsicam_bios_param(disk, bdev, dkinfo) < 0)) { if (ext_tran || (scsicam_bios_param(bdev, capacity, dkinfo) < 0)) {
dkinfo[0] = 255; dkinfo[0] = 255;
dkinfo[1] = 63; dkinfo[1] = 63;
dkinfo[2] = size / (dkinfo[0] * dkinfo[1]); dkinfo[2] = size / (dkinfo[0] * dkinfo[1]);
......
...@@ -18,8 +18,6 @@ static int eata2x_slave_attach(Scsi_Device *); ...@@ -18,8 +18,6 @@ static int eata2x_slave_attach(Scsi_Device *);
detect: eata2x_detect, \ detect: eata2x_detect, \
release: eata2x_release, \ release: eata2x_release, \
queuecommand: eata2x_queuecommand, \ queuecommand: eata2x_queuecommand, \
abort: NULL, \
reset: NULL, \
eh_abort_handler: eata2x_eh_abort, \ eh_abort_handler: eata2x_eh_abort, \
eh_device_reset_handler: NULL, \ eh_device_reset_handler: NULL, \
eh_bus_reset_handler: NULL, \ eh_bus_reset_handler: NULL, \
......
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
* neuffer@goofy.zdv.uni-mainz.de * * neuffer@goofy.zdv.uni-mainz.de *
* a.arnold@kfa-juelich.de * * a.arnold@kfa-juelich.de *
* * * *
* Updated 2002 by Alan Cox <alan@redhat.com> for Linux *
* 2.5.x and the newer locking and error handling *
* *
* This program is free software; you can redistribute it * * This program is free software; you can redistribute it *
* and/or modify it under the terms of the GNU General * * and/or modify it under the terms of the GNU General *
* Public License as published by the Free Software * * Public License as published by the Free Software *
...@@ -30,15 +33,23 @@ ...@@ -30,15 +33,23 @@
* Public License along with this kernel; if not, write to * * Public License along with this kernel; if not, write to *
* the Free Software Foundation, Inc., 675 Mass Ave, * * the Free Software Foundation, Inc., 675 Mass Ave, *
* Cambridge, MA 02139, USA. * * Cambridge, MA 02139, USA. *
* *
* For the avoidance of doubt the "preferred form" of this *
* code is one which is in an open non patent encumbered *
* format. Where cryptographic key signing forms part of *
* the process of creating an executable the information *
* including keys needed to generate an equivalently *
* functional executable are deemed to be part of the *
* source code are deemed to be part of the source code. *
* * * *
************************************************************ ************************************************************
* last change: 96/07/16 OS: Linux 2.0.8 * * last change: 2002/11/02 OS: Linux 2.5.45 *
************************************************************/ ************************************************************/
/* Look in eata_pio.h for configuration information */ /* Look in eata_pio.h for configuration information */
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -57,902 +68,830 @@ ...@@ -57,902 +68,830 @@
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
static uint ISAbases[MAXISA] = static uint ISAbases[MAXISA] = {
{0x1F0, 0x170, 0x330, 0x230}; 0x1F0, 0x170, 0x330, 0x230
static uint ISAirqs[MAXISA] = };
{14,12,15,11};
static unchar EISAbases[] = static uint ISAirqs[MAXISA] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; 14, 12, 15, 11
};
static unsigned char EISAbases[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1
};
static uint registered_HBAs = 0; static uint registered_HBAs = 0;
static struct Scsi_Host *last_HBA = NULL; static struct Scsi_Host *last_HBA;
static struct Scsi_Host *first_HBA = NULL; static struct Scsi_Host *first_HBA;
static unchar reg_IRQ[] = static unsigned char reg_IRQ[];
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static unsigned char reg_IRQL[];
static unchar reg_IRQL[] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static ulong int_counter = 0; static unsigned long int_counter = 0;
static ulong queue_counter = 0; static unsigned long queue_counter = 0;
#include "eata_pio_proc.c" #include "eata_pio_proc.c"
#ifdef MODULE static int eata_pio_release(struct Scsi_Host *sh)
int eata_pio_release(struct Scsi_Host *sh)
{ {
if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq, NULL); if (sh->irq && reg_IRQ[sh->irq] == 1)
else reg_IRQ[sh->irq]--; free_irq(sh->irq, NULL);
if (SD(sh)->channel == 0) { else
if (sh->io_port && sh->n_io_port) reg_IRQ[sh->irq]--;
release_region(sh->io_port, sh->n_io_port); if (SD(sh)->channel == 0) {
} if (sh->io_port && sh->n_io_port)
return(TRUE); release_region(sh->io_port, sh->n_io_port);
}
return (TRUE);
} }
#endif
void IncStat(Scsi_Pointer *SCp, uint Increment) static void IncStat(Scsi_Pointer * SCp, uint Increment)
{ {
SCp->ptr+=Increment; SCp->ptr += Increment;
if ((SCp->this_residual-=Increment)==0) if ((SCp->this_residual -= Increment) == 0) {
{ if ((--SCp->buffers_residual) == 0)
if ((--SCp->buffers_residual)==0) SCp->Status=FALSE; SCp->Status = FALSE;
else else {
{ SCp->buffer++;
SCp->buffer++; SCp->ptr = page_address(SCp->buffer->page) + SCp->buffer->offset;
SCp->ptr=page_address(SCp->buffer->page) + SCp->buffer->offset; SCp->this_residual = SCp->buffer->length;
SCp->this_residual=SCp->buffer->length; }
} }
}
} }
void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs * regs); static void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs *regs);
void do_eata_pio_int_handler(int irq, void *dev_id, struct pt_regs * regs) static void do_eata_pio_int_handler(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned long flags; unsigned long flags;
struct Scsi_Host *dev = dev_id; struct Scsi_Host *dev = dev_id;
spin_lock_irqsave(dev->host_lock, flags); spin_lock_irqsave(dev->host_lock, flags);
eata_pio_int_handler(irq, dev_id, regs); eata_pio_int_handler(irq, dev_id, regs);
spin_unlock_irqrestore(dev->host_lock, flags); spin_unlock_irqrestore(dev->host_lock, flags);
} }
void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs * regs) static void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs *regs)
{ {
uint eata_stat = 0xfffff; uint eata_stat = 0xfffff;
Scsi_Cmnd *cmd; Scsi_Cmnd *cmd;
hostdata *hd; hostdata *hd;
struct eata_ccb *cp; struct eata_ccb *cp;
uint base; uint base;
uint x,z; uint x, z;
struct Scsi_Host *sh; struct Scsi_Host *sh;
ushort zwickel=0; unsigned short zwickel = 0;
unchar stat,odd; unsigned char stat, odd;
for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev) { for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev)
if (sh->irq != irq)
continue;
if (inb((uint)sh->base + HA_RSTATUS) & HA_SBUSY)
continue;
int_counter++;
hd=SD(sh);
cp = &hd->ccb[0];
cmd = cp->cmd;
base = (uint) cmd->host->base;
do
{ {
stat=inb(base+HA_RSTATUS); if (sh->irq != irq)
if (stat&HA_SDRQ) { continue;
if (cp->DataIn) if (inb((uint) sh->base + HA_RSTATUS) & HA_SBUSY)
{ continue;
z=256; odd=FALSE;
while ((cmd->SCp.Status)&&((z>0)||(odd))) int_counter++;
{
if (odd) hd = SD(sh);
{
*(cmd->SCp.ptr)=zwickel>>8; cp = &hd->ccb[0];
IncStat(&cmd->SCp,1); cmd = cp->cmd;
odd=FALSE; base = (uint) cmd->host->base;
do {
stat = inb(base + HA_RSTATUS);
if (stat & HA_SDRQ) {
if (cp->DataIn) {
z = 256;
odd = FALSE;
while ((cmd->SCp.Status) && ((z > 0) || (odd))) {
if (odd) {
*(cmd->SCp.ptr) = zwickel >> 8;
IncStat(&cmd->SCp, 1);
odd = FALSE;
}
x = min_t(unsigned int, z, cmd->SCp.this_residual / 2);
insw(base + HA_RDATA, cmd->SCp.ptr, x);
z -= x;
IncStat(&cmd->SCp, 2 * x);
if ((z > 0) && (cmd->SCp.this_residual == 1)) {
zwickel = inw(base + HA_RDATA);
*(cmd->SCp.ptr) = zwickel & 0xff;
IncStat(&cmd->SCp, 1);
z--;
odd = TRUE;
}
}
while (z > 0) {
zwickel = inw(base + HA_RDATA);
z--;
}
} else { /* cp->DataOut */
odd = FALSE;
z = 256;
while ((cmd->SCp.Status) && ((z > 0) || (odd))) {
if (odd) {
zwickel += *(cmd->SCp.ptr) << 8;
IncStat(&cmd->SCp, 1);
outw(zwickel, base + HA_RDATA);
z--;
odd = FALSE;
}
x = min_t(unsigned int, z, cmd->SCp.this_residual / 2);
outsw(base + HA_RDATA, cmd->SCp.ptr, x);
z -= x;
IncStat(&cmd->SCp, 2 * x);
if ((z > 0) && (cmd->SCp.this_residual == 1)) {
zwickel = *(cmd->SCp.ptr);
zwickel &= 0xff;
IncStat(&cmd->SCp, 1);
odd = TRUE;
}
}
while (z > 0 || odd) {
outw(zwickel, base + HA_RDATA);
z--;
odd = FALSE;
}
}
} }
x=min_t(unsigned int,z,cmd->SCp.this_residual/2);
insw(base+HA_RDATA,cmd->SCp.ptr,x);
z-=x;
IncStat(&cmd->SCp,2*x);
if ((z>0)&&(cmd->SCp.this_residual==1))
{
zwickel=inw(base+HA_RDATA);
*(cmd->SCp.ptr)=zwickel&0xff;
IncStat(&cmd->SCp,1); z--;
odd=TRUE;
}
}
while (z>0) {
zwickel=inw(base+HA_RDATA);
z--;
}
} }
else /* cp->DataOut */ while ((stat & HA_SDRQ) || ((stat & HA_SMORE) && hd->moresupport));
{
odd=FALSE; z=256; /* terminate handler if HBA goes busy again, i.e. transfers
while ((cmd->SCp.Status)&&((z>0)||(odd))) * more data */
{
if (odd) if (stat & HA_SBUSY)
{ break;
zwickel+=*(cmd->SCp.ptr)<<8;
IncStat(&cmd->SCp,1); /* OK, this is quite stupid, but I haven't found any correct
outw(zwickel,base+HA_RDATA); * way to get HBA&SCSI status so far */
z--;
odd=FALSE; if (!(inb(base + HA_RSTATUS) & HA_SERROR)) {
} cmd->result = (DID_OK << 16);
x=min_t(unsigned int,z,cmd->SCp.this_residual/2); hd->devflags |= (1 << cp->cp_id);
outsw(base+HA_RDATA,cmd->SCp.ptr,x); } else if (hd->devflags & 1 << cp->cp_id)
z-=x; cmd->result = (DID_OK << 16) + 0x02;
IncStat(&cmd->SCp,2*x); else
if ((z>0)&&(cmd->SCp.this_residual==1)) cmd->result = (DID_NO_CONNECT << 16);
{
zwickel=*(cmd->SCp.ptr); if (cp->status == LOCKED) {
zwickel&=0xff; cp->status = FREE;
IncStat(&cmd->SCp,1); eata_stat = inb(base + HA_RSTATUS);
odd=TRUE; printk(KERN_CRIT "eata_pio: int_handler, freeing locked " "queueslot\n");
} return;
}
while (z>0||odd) {
outw(zwickel,base+HA_RDATA);
z--;
odd=FALSE;
}
} }
}
}
while ((stat&HA_SDRQ)||((stat&HA_SMORE)&&hd->moresupport));
/* terminate handler if HBA goes busy again, i.e. transfers
* more data */
if (stat&HA_SBUSY) break;
/* OK, this is quite stupid, but I haven't found any correct
* way to get HBA&SCSI status so far */
if (!(inb(base+HA_RSTATUS)&HA_SERROR))
{
cmd->result=(DID_OK<<16);
hd->devflags|=(1<<cp->cp_id);
}
else if (hd->devflags&1<<cp->cp_id)
cmd->result=(DID_OK<<16)+0x02;
else cmd->result=(DID_NO_CONNECT<<16);
if (cp->status == LOCKED) {
cp->status = FREE;
eata_stat = inb(base + HA_RSTATUS);
printk(KERN_CRIT "eata_pio: int_handler, freeing locked "
"queueslot\n");
return;
}
#if DBG_INTR2 #if DBG_INTR2
if (stat != 0x50) if (stat != 0x50)
printk(KERN_DEBUG "stat: %#.2x, result: %#.8x\n", stat, printk(KERN_DEBUG "stat: %#.2x, result: %#.8x\n", stat, cmd->result);
cmd->result);
#endif #endif
cp->status = FREE; /* now we can release the slot */ cp->status = FREE; /* now we can release the slot */
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
} }
return; return;
} }
inline uint eata_pio_send_command(uint base, unchar command) static inline uint eata_pio_send_command(uint base, unsigned char command)
{ {
uint loop = HZ/2; uint loop = HZ / 2;
while (inb(base + HA_RSTATUS) & HA_SBUSY) while (inb(base + HA_RSTATUS) & HA_SBUSY)
if (--loop == 0) if (--loop == 0)
return(TRUE); return (TRUE);
/* Enable interrupts for HBA. It is not the best way to do it at this /* Enable interrupts for HBA. It is not the best way to do it at this
* place, but I hope that it doesn't interfere with the IDE driver * place, but I hope that it doesn't interfere with the IDE driver
* initialization this way */ * initialization this way */
outb(HA_CTRL_8HEADS,base+HA_CTRLREG); outb(HA_CTRL_8HEADS, base + HA_CTRLREG);
outb(command, base + HA_WCOMMAND); outb(command, base + HA_WCOMMAND);
return(FALSE); return (FALSE);
} }
int eata_pio_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) static int eata_pio_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
{ {
uint x, y; uint x, y;
uint base; uint base;
hostdata *hd; hostdata *hd;
struct Scsi_Host *sh; struct Scsi_Host *sh;
struct eata_ccb *cp; struct eata_ccb *cp;
queue_counter++; queue_counter++;
hd = HD(cmd); hd = HD(cmd);
sh = cmd->host; sh = cmd->host;
base = (uint) sh->base; base = (uint) sh->base;
/* use only slot 0, as 2001 can handle only one cmd at a time */ /* use only slot 0, as 2001 can handle only one cmd at a time */
y = x = 0; y = x = 0;
if (hd->ccb[y].status!=FREE) { if (hd->ccb[y].status != FREE) {
DBG(DBG_QUEUE, printk(KERN_EMERG "can_queue %d, x %d, y %d\n", DBG(DBG_QUEUE, printk(KERN_EMERG "can_queue %d, x %d, y %d\n", sh->can_queue, x, y));
sh->can_queue,x,y));
#if DEBUG_EATA #if DEBUG_EATA
panic(KERN_EMERG "eata_pio: run out of queue slots cmdno:%ld " panic(KERN_EMERG "eata_pio: run out of queue slots cmdno:%ld " "intrno: %ld\n", queue_counter, int_counter);
"intrno: %ld\n", queue_counter, int_counter);
#else #else
panic(KERN_EMERG "eata_pio: run out of queue slots....\n"); panic(KERN_EMERG "eata_pio: run out of queue slots....\n");
#endif #endif
} }
cp = &hd->ccb[y]; cp = &hd->ccb[y];
memset(cp, 0, sizeof(struct eata_ccb)); memset(cp, 0, sizeof(struct eata_ccb));
memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
cp->status = USED; /* claim free slot */ cp->status = USED; /* claim free slot */
DBG(DBG_QUEUE, printk(KERN_DEBUG "eata_pio_queue pid %ld, target: %x, lun:" DBG(DBG_QUEUE, printk(KERN_DEBUG "eata_pio_queue pid %ld, target: %x, lun:" " %x, y %d\n", cmd->pid, cmd->target, cmd->lun, y));
" %x, y %d\n", cmd->pid, cmd->target, cmd->lun, y));
cmd->scsi_done = (void *) done;
cmd->scsi_done = (void *)done;
if(cmd->sc_data_direction == SCSI_DATA_WRITE)
/* FIXME: use passed direction flag !! */ cp->DataOut = TRUE; /* Output mode */
switch (cmd->cmnd[0]) { else
case CHANGE_DEFINITION: case COMPARE: case COPY: cp->DataIn = TRUE; /* Input mode */
case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT:
case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER: cp->Interpret = (cmd->target == hd->hostid);
case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: cp->cp_datalen = htonl((unsigned long) cmd->request_bufflen);
case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: cp->Auto_Req_Sen = FALSE;
case WRITE_6: case WRITE_10: case WRITE_VERIFY: cp->cp_reqDMA = htonl(0);
case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME: cp->reqlen = 0;
case SEARCH_HIGH_12: case SEARCH_EQUAL_12: case SEARCH_LOW_12:
case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW: cp->cp_id = cmd->target;
case MEDIUM_SCAN: case SEND_VOLUME_TAG: cp->cp_lun = cmd->lun;
case 0xea: /* alternate number for WRITE LONG */ cp->cp_dispri = FALSE;
cp->DataOut = TRUE; /* Output mode */ cp->cp_identify = TRUE;
break; memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
case TEST_UNIT_READY:
default: cp->cp_statDMA = htonl(0);
cp->DataIn = TRUE; /* Input mode */
} cp->cp_viraddr = cp;
cp->cmd = cmd;
cp->Interpret = (cmd->target == hd->hostid); cmd->host_scribble = (char *) &hd->ccb[y];
cp->cp_datalen = htonl((ulong)cmd->request_bufflen);
cp->Auto_Req_Sen = FALSE; if (cmd->use_sg == 0) {
cp->cp_reqDMA = htonl(0); cmd->SCp.buffers_residual = 1;
cp->reqlen = 0; cmd->SCp.ptr = cmd->request_buffer;
cmd->SCp.this_residual = cmd->request_bufflen;
cp->cp_id = cmd->target; cmd->SCp.buffer = NULL;
cp->cp_lun = cmd->lun; } else {
cp->cp_dispri = FALSE; cmd->SCp.buffer = cmd->request_buffer;
cp->cp_identify = TRUE; cmd->SCp.buffers_residual = cmd->use_sg;
memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
cp->cp_statDMA = htonl(0); }
cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes
cp->cp_viraddr = cp; * are to transfer */
cp->cmd = cmd;
cmd->host_scribble = (char *)&hd->ccb[y]; if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) {
cmd->result = DID_BUS_BUSY << 16;
if (cmd->use_sg == 0) printk(KERN_NOTICE "eata_pio_queue target %d, pid %ld, HBA busy, " "returning DID_BUS_BUSY, done.\n", cmd->target, cmd->pid);
{ done(cmd);
cmd->SCp.buffers_residual=1; cp->status = FREE;
cmd->SCp.ptr = cmd->request_buffer; return (0);
cmd->SCp.this_residual = cmd->request_bufflen; }
cmd->SCp.buffer = NULL; /* FIXME: timeout */
} else { while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
cmd->SCp.buffer = cmd->request_buffer; cpu_relax();
cmd->SCp.buffers_residual = cmd->use_sg; outsw(base + HA_RDATA, cp, hd->cplen);
cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
cmd->SCp.this_residual = cmd->SCp.buffer->length; for (x = 0; x < hd->cppadlen; x++)
} outw(0, base + HA_RDATA);
cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes
* are to transfer */ DBG(DBG_QUEUE, printk(KERN_DEBUG "Queued base %#.4lx pid: %ld target: %x " "lun: %x slot %d irq %d\n", (long) sh->base, cmd->pid, cmd->target, cmd->lun, y, sh->irq));
if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP))
{
cmd->result = DID_BUS_BUSY << 16;
printk(KERN_NOTICE "eata_pio_queue target %d, pid %ld, HBA busy, "
"returning DID_BUS_BUSY, done.\n", cmd->target, cmd->pid);
done(cmd);
cp->status = FREE;
return (0); return (0);
}
while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
cpu_relax();
outsw(base + HA_RDATA, cp, hd->cplen);
outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
for (x = 0; x < hd->cppadlen; x++) outw(0, base + HA_RDATA);
DBG(DBG_QUEUE,printk(KERN_DEBUG "Queued base %#.4lx pid: %ld target: %x "
"lun: %x slot %d irq %d\n", (long)sh->base, cmd->pid,
cmd->target, cmd->lun, y, sh->irq));
return (0);
} }
int eata_pio_abort(Scsi_Cmnd * cmd) static int eata_pio_abort(Scsi_Cmnd * cmd)
{ {
ulong flags; uint loop = HZ;
uint loop = HZ;
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_abort called pid: %ld " "target: %x lun: %x reason %x\n", cmd->pid, cmd->target, cmd->lun, cmd->abort_reason));
spin_lock_irqsave(cmd->host->host_lock, flags);
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_abort called pid: %ld "
"target: %x lun: %x reason %x\n", cmd->pid, while (inb(cmd->host->base + HA_RAUXSTAT) & HA_ABUSY)
cmd->target, cmd->lun, cmd->abort_reason)); if (--loop == 0) {
printk(KERN_WARNING "eata_pio: abort, timeout error.\n");
return FAILED;
while (inb((uint)(cmd->host->base) + HA_RAUXSTAT) & HA_ABUSY) }
if (--loop == 0) { if (CD(cmd)->status == FREE) {
printk(KERN_WARNING "eata_pio: abort, timeout error.\n"); DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_NOT_RUNNING\n"));
spin_unlock_irqrestore(cmd->host->host_lock, flags); return FAILED;
return (SCSI_ABORT_ERROR); }
if (CD(cmd)->status == USED) {
DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_BUSY\n"));
/* We want to sleep a bit more here */
return FAILED; /* SNOOZE */
}
if (CD(cmd)->status == RESET) {
printk(KERN_WARNING "eata_pio: abort, command reset error.\n");
return FAILED;
}
if (CD(cmd)->status == LOCKED) {
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio: abort, queue slot " "locked.\n"));
return FAILED;
} }
if (CD(cmd)->status == FREE) { panic("eata_pio: abort: invalid slot status\n");
DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_NOT_RUNNING\n"));
spin_unlock_irqrestore(cmd->host->host_lock, flags);
return (SCSI_ABORT_NOT_RUNNING);
}
if (CD(cmd)->status == USED) {
DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_BUSY\n"));
spin_unlock_irqrestore(cmd->host->host_lock, flags);
return (SCSI_ABORT_BUSY); /* SNOOZE */
}
if (CD(cmd)->status == RESET) {
spin_unlock_irqrestore(cmd->host->host_lock, flags);
printk(KERN_WARNING "eata_pio: abort, command reset error.\n");
return (SCSI_ABORT_ERROR);
}
if (CD(cmd)->status == LOCKED) {
spin_unlock_irqrestore(cmd->host->host_lock, flags);
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio: abort, queue slot "
"locked.\n"));
return (SCSI_ABORT_NOT_RUNNING);
}
spin_unlock_irqrestore(cmd->host->host_lock, flags);
panic("eata_pio: abort: invalid slot status\n");
} }
int eata_pio_reset(Scsi_Cmnd * cmd, unsigned int dummy) static int eata_pio_host_reset(Scsi_Cmnd * cmd)
{ {
uint x, limit = 0; uint x, limit = 0;
ulong flags; unsigned char success = FALSE;
unchar success = FALSE; Scsi_Cmnd *sp;
Scsi_Cmnd *sp; struct Scsi_Host *host = cmd->host;
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" " %x lun: %x reason %x\n", cmd->pid, cmd->target, cmd->lun, cmd->abort_reason));
" %x lun: %x reason %x\n", cmd->pid, cmd->target,
cmd->lun, cmd->abort_reason)); if (HD(cmd)->state == RESET) {
printk(KERN_WARNING "eata_pio_reset: exit, already in reset.\n");
spin_lock_irqsave(cmd->host->host_lock, flags); return FAILED;
if (HD(cmd)->state == RESET) { }
printk(KERN_WARNING "eata_pio_reset: exit, already in reset.\n");
spin_unlock_irqrestore(cmd->host->host_lock, flags); /* force all slots to be free */
return (SCSI_RESET_ERROR);
} for (x = 0; x < cmd->host->can_queue; x++) {
/* force all slots to be free */ if (HD(cmd)->ccb[x].status == FREE)
continue;
for (x = 0; x < cmd->host->can_queue; x++) {
sp = HD(cmd)->ccb[x].cmd;
if (HD(cmd)->ccb[x].status == FREE) HD(cmd)->ccb[x].status = RESET;
continue; printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->pid);
sp = HD(cmd)->ccb[x].cmd; if (sp == NULL)
HD(cmd)->ccb[x].status = RESET; panic("eata_pio_reset: slot %d, sp==NULL.\n", x);
printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, }
sp->pid);
/* hard reset the HBA */
if (sp == NULL) outb(EATA_CMD_RESET, (uint) cmd->host->base + HA_WCOMMAND);
panic("eata_pio_reset: slot %d, sp==NULL.\n", x);
} DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: board reset done.\n"));
HD(cmd)->state = RESET;
/* hard reset the HBA */
outb(EATA_CMD_RESET, (uint) cmd->host->base+HA_WCOMMAND); spin_unlock_irq(host->host_lock);
set_current_state(TASK_UNINTERRUPTIBLE);
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: board reset done.\n")); schedule_timeout(3 * HZ);
HD(cmd)->state = RESET; spin_lock_irq(host->host_lock);
set_current_state(TASK_UNINTERRUPTIBLE); DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " "loops %d.\n", limit));
schedule_timeout(3*HZ);
for (x = 0; x < cmd->host->can_queue; x++) {
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, "
"loops %d.\n", limit)); /* Skip slots already set free by interrupt */
if (HD(cmd)->ccb[x].status != RESET)
for (x = 0; x < cmd->host->can_queue; x++) { continue;
/* Skip slots already set free by interrupt */ sp = HD(cmd)->ccb[x].cmd;
if (HD(cmd)->ccb[x].status != RESET) sp->result = DID_RESET << 16;
continue;
/* This mailbox is terminated */
sp = HD(cmd)->ccb[x].cmd; printk(KERN_WARNING "eata_pio_reset: reset ccb %d.\n", x);
sp->result = DID_RESET << 16; HD(cmd)->ccb[x].status = FREE;
/* This mailbox is terminated */ sp->scsi_done(sp);
printk(KERN_WARNING "eata_pio_reset: reset ccb %d.\n",x); }
HD(cmd)->ccb[x].status = FREE;
HD(cmd)->state = FALSE;
sp->scsi_done(sp);
} if (success) { /* hmmm... */
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n"));
HD(cmd)->state = FALSE; return SUCCESS;
spin_unlock_irqrestore(cmd->host->host_lock, flags); } else {
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, wakeup.\n"));
if (success) { /* hmmm... */ return FAILED;
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n")); }
return (SCSI_RESET_SUCCESS);
} else {
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, wakeup.\n"));
return (SCSI_RESET_PUNT);
}
} }
char * get_pio_board_data(ulong base, uint irq, uint id, ulong cplen, ushort cppadlen) static char *get_pio_board_data(unsigned long base, uint irq, uint id, unsigned long cplen, unsigned short cppadlen)
{ {
struct eata_ccb cp; struct eata_ccb cp;
static char buff[256]; static char buff[256];
int z; int z;
memset(&cp, 0, sizeof(struct eata_ccb)); memset(&cp, 0, sizeof(struct eata_ccb));
memset(buff, 0, sizeof(buff)); memset(buff, 0, sizeof(buff));
cp.DataIn = TRUE; cp.DataIn = TRUE;
cp.Interpret = TRUE; /* Interpret command */ cp.Interpret = TRUE; /* Interpret command */
cp.cp_datalen = htonl(254); cp.cp_datalen = htonl(254);
cp.cp_dataDMA = htonl(0); cp.cp_dataDMA = htonl(0);
cp.cp_id = id; cp.cp_id = id;
cp.cp_lun = 0; cp.cp_lun = 0;
cp.cp_cdb[0] = INQUIRY; cp.cp_cdb[0] = INQUIRY;
cp.cp_cdb[1] = 0; cp.cp_cdb[1] = 0;
cp.cp_cdb[2] = 0; cp.cp_cdb[2] = 0;
cp.cp_cdb[3] = 0; cp.cp_cdb[3] = 0;
cp.cp_cdb[4] = 254; cp.cp_cdb[4] = 254;
cp.cp_cdb[5] = 0; cp.cp_cdb[5] = 0;
if (eata_pio_send_command((uint) base, EATA_CMD_PIO_SEND_CP)) if (eata_pio_send_command((uint) base, EATA_CMD_PIO_SEND_CP))
return (NULL); return (NULL);
while (!(inb(base + HA_RSTATUS) & HA_SDRQ)); while (!(inb(base + HA_RSTATUS) & HA_SDRQ));
outsw(base + HA_RDATA, &cp, cplen); outsw(base + HA_RDATA, &cp, cplen);
outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND); outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
for (z = 0; z < cppadlen; z++) outw(0, base + HA_RDATA); for (z = 0; z < cppadlen; z++)
outw(0, base + HA_RDATA);
while (inb(base + HA_RSTATUS) & HA_SBUSY);
if (inb(base + HA_RSTATUS) & HA_SERROR) while (inb(base + HA_RSTATUS) & HA_SBUSY);
return (NULL); if (inb(base + HA_RSTATUS) & HA_SERROR)
else if (!(inb(base + HA_RSTATUS) & HA_SDRQ)) return (NULL);
return (NULL); else if (!(inb(base + HA_RSTATUS) & HA_SDRQ))
else return (NULL);
{ else {
insw(base+HA_RDATA, &buff, 127); insw(base + HA_RDATA, &buff, 127);
while (inb(base + HA_RSTATUS)&HA_SDRQ) inw(base + HA_RDATA); while (inb(base + HA_RSTATUS) & HA_SDRQ)
return (buff); inw(base + HA_RDATA);
} return (buff);
}
} }
int get_pio_conf_PIO(u32 base, struct get_conf *buf) static int get_pio_conf_PIO(u32 base, struct get_conf *buf)
{ {
ulong loop = HZ/2; unsigned long loop = HZ / 2;
int z; int z;
ushort *p; unsigned short *p;
if(check_region(base, 9)) if (check_region(base, 9))
return (FALSE);
memset(buf, 0, sizeof(struct get_conf));
while (inb(base + HA_RSTATUS) & HA_SBUSY)
if (--loop == 0)
return (FALSE);
DBG(DBG_PIO && DBG_PROBE,
printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#x\n", base));
eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG);
loop = HZ/2;
for (p = (ushort *) buf;
(long)p <= ((long)buf + (sizeof(struct get_conf) / 2)); p++) {
while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
if (--loop == 0)
return (FALSE); return (FALSE);
loop = HZ/2; memset(buf, 0, sizeof(struct get_conf));
*p = inw(base + HA_RDATA);
} while (inb(base + HA_RSTATUS) & HA_SBUSY)
if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */ if (--loop == 0)
if (htonl(EATA_SIGNATURE) == buf->signature) { return (FALSE);
DBG(DBG_PIO&&DBG_PROBE, printk(KERN_NOTICE "EATA Controller found "
"at %#4x EATA Level: %x\n", base, DBG(DBG_PIO && DBG_PROBE, printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#x\n", base));
(uint) (buf->version))); eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG);
while (inb(base + HA_RSTATUS) & HA_SDRQ) loop = HZ / 2;
inw(base + HA_RDATA); for (p = (unsigned short *) buf; (long) p <= ((long) buf + (sizeof(struct get_conf) / 2)); p++) {
if(ALLOW_DMA_BOARDS == FALSE) { while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
for (z = 0; z < MAXISA; z++) if (--loop == 0)
if (base == ISAbases[z]) { return (FALSE);
buf->IRQ = ISAirqs[z];
break; loop = HZ / 2;
} *p = inw(base + HA_RDATA);
} }
return (TRUE); if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */
} if (htonl(EATA_SIGNATURE) == buf->signature) {
} else { DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found " "at %#4x EATA Level: %x\n", base, (uint) (buf->version)));
DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer "
"for HBA at %x\n", base)); while (inb(base + HA_RSTATUS) & HA_SDRQ)
} inw(base + HA_RDATA);
return (FALSE); if (ALLOW_DMA_BOARDS == FALSE) {
for (z = 0; z < MAXISA; z++)
if (base == ISAbases[z]) {
buf->IRQ = ISAirqs[z];
break;
}
}
return (TRUE);
}
} else {
DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer " "for HBA at %x\n", base));
}
return (FALSE);
} }
void print_pio_config(struct get_conf *gc) static void print_pio_config(struct get_conf *gc)
{ {
printk("Please check values: (read config data)\n"); printk("Please check values: (read config data)\n");
printk("LEN: %d ver:%d OCS:%d TAR:%d TRNXFR:%d MORES:%d\n", printk("LEN: %d ver:%d OCS:%d TAR:%d TRNXFR:%d MORES:%d\n", (uint) ntohl(gc->len), gc->version, gc->OCS_enabled, gc->TAR_support, gc->TRNXFR, gc->MORE_support);
(uint) ntohl(gc->len), gc->version, printk("HAAV:%d SCSIID0:%d ID1:%d ID2:%d QUEUE:%d SG:%d SEC:%d\n", gc->HAA_valid, gc->scsi_id[3], gc->scsi_id[2], gc->scsi_id[1], ntohs(gc->queuesiz), ntohs(gc->SGsiz), gc->SECOND);
gc->OCS_enabled, gc->TAR_support, gc->TRNXFR, gc->MORE_support); printk("IRQ:%d IRQT:%d FORCADR:%d MCH:%d RIDQ:%d\n", gc->IRQ, gc->IRQ_TR, gc->FORCADR, gc->MAX_CHAN, gc->ID_qest);
printk("HAAV:%d SCSIID0:%d ID1:%d ID2:%d QUEUE:%d SG:%d SEC:%d\n",
gc->HAA_valid, gc->scsi_id[3], gc->scsi_id[2],
gc->scsi_id[1], ntohs(gc->queuesiz), ntohs(gc->SGsiz), gc->SECOND);
printk("IRQ:%d IRQT:%d FORCADR:%d MCH:%d RIDQ:%d\n",
gc->IRQ, gc->IRQ_TR, gc->FORCADR,
gc->MAX_CHAN, gc->ID_qest);
} }
static uint print_selftest(uint base) static uint print_selftest(uint base)
{ {
unchar buffer[512]; unsigned char buffer[512];
#ifdef VERBOSE_SETUP #ifdef VERBOSE_SETUP
int z; int z;
#endif #endif
printk("eata_pio: executing controller self test & setup...\n"); printk("eata_pio: executing controller self test & setup...\n");
while (inb(base + HA_RSTATUS) & HA_SBUSY); while (inb(base + HA_RSTATUS) & HA_SBUSY);
outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND); outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND);
do { do {
while (inb(base + HA_RSTATUS) & HA_SBUSY) while (inb(base + HA_RSTATUS) & HA_SBUSY)
/* nothing */ ; /* nothing */ ;
if (inb(base + HA_RSTATUS) & HA_SDRQ) if (inb(base + HA_RSTATUS) & HA_SDRQ) {
{ insw(base + HA_RDATA, &buffer, 256);
insw(base + HA_RDATA, &buffer, 256);
#ifdef VERBOSE_SETUP #ifdef VERBOSE_SETUP
/* no beeps please... */ /* no beeps please... */
for (z = 0; z < 511 && buffer[z]; z++) for (z = 0; z < 511 && buffer[z]; z++)
if (buffer[z] != 7) printk("%c", buffer[z]); if (buffer[z] != 7)
printk("%c", buffer[z]);
#endif #endif
} }
} while (inb(base+HA_RSTATUS) & (HA_SBUSY|HA_SDRQ)); } while (inb(base + HA_RSTATUS) & (HA_SBUSY | HA_SDRQ));
return (!(inb(base+HA_RSTATUS) & HA_SERROR)); return (!(inb(base + HA_RSTATUS) & HA_SERROR));
} }
int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt) static int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
{ {
ulong size = 0; unsigned long size = 0;
char *buff; char *buff;
ulong cplen; unsigned long cplen;
ushort cppadlen; unsigned short cppadlen;
struct Scsi_Host *sh; struct Scsi_Host *sh;
hostdata *hd; hostdata *hd;
DBG(DBG_REGISTER, print_pio_config(gc)); DBG(DBG_REGISTER, print_pio_config(gc));
if (gc->DMA_support == TRUE) { if (gc->DMA_support == TRUE) {
printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n",base); printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n", base);
if(ALLOW_DMA_BOARDS == FALSE) if (ALLOW_DMA_BOARDS == FALSE)
return (FALSE); return (FALSE);
} }
if ((buff = get_pio_board_data((uint)base, gc->IRQ, gc->scsi_id[3], if ((buff = get_pio_board_data((uint) base, gc->IRQ, gc->scsi_id[3], cplen = (htonl(gc->cplen) + 1) / 2, cppadlen = (htons(gc->cppadlen) + 1) / 2)) == NULL) {
cplen =(htonl(gc->cplen )+1)/2, printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (unsigned long) base);
cppadlen=(htons(gc->cppadlen)+1)/2)) == NULL) return (FALSE);
{ }
printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (ulong) base);
return (FALSE); if (print_selftest(base) == FALSE && ALLOW_DMA_BOARDS == FALSE) {
} printk("HBA at %#lx failed while performing self test & setup.\n", (unsigned long) base);
return (FALSE);
if (print_selftest(base) == FALSE && ALLOW_DMA_BOARDS == FALSE) }
{
printk("HBA at %#lx failed while performing self test & setup.\n", request_region(base, 8, "eata_pio");
(ulong) base);
return (FALSE); size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz));
}
sh = scsi_register(tpnt, size);
request_region(base, 8, "eata_pio"); if (sh == NULL) {
release_region(base, 8);
size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)); return FALSE;
}
sh = scsi_register(tpnt, size);
if(sh == NULL) if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */
{ if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", sh)) {
release_region(base, 8); reg_IRQ[gc->IRQ]++;
return FALSE; if (!gc->IRQ_TR)
} reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */
} else {
if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */ printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ);
if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT, release_region(base, 8);
"EATA-PIO", sh)){ return (FALSE);
reg_IRQ[gc->IRQ]++; }
if (!gc->IRQ_TR) } else { /* More than one HBA on this IRQ */
reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */ if (reg_IRQL[gc->IRQ] == TRUE) {
printk("Can't support more than one HBA on this IRQ,\n" " if the IRQ is edge triggered. Sorry.\n");
release_region(base, 8);
return (FALSE);
} else
reg_IRQ[gc->IRQ]++;
}
hd = SD(sh);
memset(hd->ccb, 0, (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)));
memset(hd->reads, 0, sizeof(unsigned long) * 26);
strncpy(SD(sh)->vendor, &buff[8], 8);
SD(sh)->vendor[8] = 0;
strncpy(SD(sh)->name, &buff[16], 17);
SD(sh)->name[17] = 0;
SD(sh)->revision[0] = buff[32];
SD(sh)->revision[1] = buff[33];
SD(sh)->revision[2] = buff[34];
SD(sh)->revision[3] = '.';
SD(sh)->revision[4] = buff[35];
SD(sh)->revision[5] = 0;
switch (ntohl(gc->len)) {
case 0x1c:
SD(sh)->EATA_revision = 'a';
break;
case 0x1e:
SD(sh)->EATA_revision = 'b';
break;
case 0x22:
SD(sh)->EATA_revision = 'c';
break;
case 0x24:
SD(sh)->EATA_revision = 'z';
default:
SD(sh)->EATA_revision = '?';
}
if (ntohl(gc->len) >= 0x22) {
if (gc->is_PCI == TRUE)
hd->bustype = IS_PCI;
else if (gc->is_EISA == TRUE)
hd->bustype = IS_EISA;
else
hd->bustype = IS_ISA;
} else { } else {
printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ); if (buff[21] == '4')
release_region(base, 8); hd->bustype = IS_PCI;
return (FALSE); else if (buff[21] == '2')
hd->bustype = IS_EISA;
else
hd->bustype = IS_ISA;
} }
} else { /* More than one HBA on this IRQ */
if (reg_IRQL[gc->IRQ] == TRUE) { SD(sh)->cplen = cplen;
printk("Can't support more than one HBA on this IRQ,\n" SD(sh)->cppadlen = cppadlen;
" if the IRQ is edge triggered. Sorry.\n"); SD(sh)->hostid = gc->scsi_id[3];
release_region(base, 8); SD(sh)->devflags = 1 << gc->scsi_id[3];
return (FALSE); SD(sh)->moresupport = gc->MORE_support;
} else sh->unique_id = base;
reg_IRQ[gc->IRQ]++; sh->base = base;
} sh->io_port = base;
sh->n_io_port = 8;
hd = SD(sh); sh->irq = gc->IRQ;
sh->dma_channel = PIO;
memset(hd->ccb, 0, (sizeof(struct eata_ccb) * ntohs(gc->queuesiz))); sh->this_id = gc->scsi_id[3];
memset(hd->reads, 0, sizeof(ulong) * 26); sh->can_queue = 1;
sh->cmd_per_lun = 1;
strncpy(SD(sh)->vendor, &buff[8], 8); sh->sg_tablesize = SG_ALL;
SD(sh)->vendor[8] = 0;
strncpy(SD(sh)->name, &buff[16], 17); hd->channel = 0;
SD(sh)->name[17] = 0;
SD(sh)->revision[0] = buff[32]; sh->max_id = 8;
SD(sh)->revision[1] = buff[33]; sh->max_lun = 8;
SD(sh)->revision[2] = buff[34];
SD(sh)->revision[3] = '.'; if (gc->SECOND)
SD(sh)->revision[4] = buff[35]; hd->primary = FALSE;
SD(sh)->revision[5] = 0;
switch (ntohl(gc->len)) {
case 0x1c:
SD(sh)->EATA_revision = 'a';
break;
case 0x1e:
SD(sh)->EATA_revision = 'b';
break;
case 0x22:
SD(sh)->EATA_revision = 'c';
break;
case 0x24:
SD(sh)->EATA_revision = 'z';
default:
SD(sh)->EATA_revision = '?';
}
if(ntohl(gc->len) >= 0x22) {
if (gc->is_PCI == TRUE)
hd->bustype = IS_PCI;
else if (gc->is_EISA == TRUE)
hd->bustype = IS_EISA;
else
hd->bustype = IS_ISA;
} else {
if (buff[21] == '4')
hd->bustype = IS_PCI;
else if (buff[21] == '2')
hd->bustype = IS_EISA;
else else
hd->bustype = IS_ISA; hd->primary = TRUE;
}
sh->unchecked_isa_dma = FALSE; /* We can only do PIO */
SD(sh)->cplen=cplen;
SD(sh)->cppadlen=cppadlen; hd->next = NULL; /* build a linked list of all HBAs */
SD(sh)->hostid=gc->scsi_id[3]; hd->prev = last_HBA;
SD(sh)->devflags=1<<gc->scsi_id[3]; if (hd->prev != NULL)
SD(sh)->moresupport=gc->MORE_support; SD(hd->prev)->next = sh;
sh->unique_id = base; last_HBA = sh;
sh->base = base; if (first_HBA == NULL)
sh->io_port = base; first_HBA = sh;
sh->n_io_port = 8; registered_HBAs++;
sh->irq = gc->IRQ; return (1);
sh->dma_channel = PIO;
sh->this_id = gc->scsi_id[3];
sh->can_queue = 1;
sh->cmd_per_lun = 1;
sh->sg_tablesize = SG_ALL;
hd->channel = 0;
sh->max_id = 8;
sh->max_lun = 8;
if (gc->SECOND)
hd->primary = FALSE;
else
hd->primary = TRUE;
sh->unchecked_isa_dma = FALSE; /* We can only do PIO */
hd->next = NULL; /* build a linked list of all HBAs */
hd->prev = last_HBA;
if(hd->prev != NULL)
SD(hd->prev)->next = sh;
last_HBA = sh;
if (first_HBA == NULL)
first_HBA = sh;
registered_HBAs++;
return (1);
} }
void find_pio_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt) static void find_pio_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt)
{ {
int i; int i;
for (i = 0; i < MAXISA; i++) { for (i = 0; i < MAXISA; i++) {
if (ISAbases[i]) { if (ISAbases[i]) {
if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE){ if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE) {
register_pio_HBA(ISAbases[i], buf, tpnt); register_pio_HBA(ISAbases[i], buf, tpnt);
} }
ISAbases[i] = 0; ISAbases[i] = 0;
}
} }
} return;
return;
} }
void find_pio_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt) static void find_pio_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt)
{ {
u32 base; u32 base;
int i; int i;
#if CHECKPAL #if CHECKPAL
u8 pal1, pal2, pal3; u8 pal1, pal2, pal3;
#endif #endif
for (i = 0; i < MAXEISA; i++) { for (i = 0; i < MAXEISA; i++) {
if (EISAbases[i] == TRUE) { /* Still a possibility ? */ if (EISAbases[i] == TRUE) { /* Still a possibility ? */
base = 0x1c88 + (i * 0x1000); base = 0x1c88 + (i * 0x1000);
#if CHECKPAL #if CHECKPAL
pal1 = inb((u16)base - 8); pal1 = inb((u16) base - 8);
pal2 = inb((u16)base - 7); pal2 = inb((u16) base - 7);
pal3 = inb((u16)base - 6); pal3 = inb((u16) base - 6);
if (((pal1 == 0x12) && (pal2 == 0x14)) || if (((pal1 == 0x12) && (pal2 == 0x14)) || ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || ((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) {
((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: " "%x %x %x \n", (int) pal1, (int) pal2, (int) pal3));
((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) {
DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: "
"%x %x %x \n",
(int)pal1, (int)pal2, (int)pal3));
#endif #endif
if (get_pio_conf_PIO(base, buf) == TRUE) { if (get_pio_conf_PIO(base, buf) == TRUE) {
DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf)); DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf));
if (buf->IRQ) { if (buf->IRQ) {
register_pio_HBA(base, buf, tpnt); register_pio_HBA(base, buf, tpnt);
} else } else
printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " "removed from list\n");
"removed from list\n"); }
} /* Nothing found here so we take it from the list */
/* Nothing found here so we take it from the list */ EISAbases[i] = 0;
EISAbases[i] = 0;
#if CHECKPAL #if CHECKPAL
} }
#endif #endif
}
} }
} return;
return;
} }
void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) static void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt)
{ {
#ifndef CONFIG_PCI #ifndef CONFIG_PCI
printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n");
#else #else
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
u32 base, x; u32 base, x;
while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) { while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) {
DBG(DBG_PROBE && DBG_PCI, DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", dev->name));
printk("eata_pio: find_PCI, HBA at %s\n", dev->name)); if (pci_enable_device(dev))
if (pci_enable_device(dev)) continue;
continue; pci_set_master(dev);
pci_set_master(dev); base = pci_resource_flags(dev, 0);
base = pci_resource_flags(dev, 0); if (base & IORESOURCE_MEM) {
if (base & IORESOURCE_MEM) { printk("eata_pio: invalid base address of device %s\n", dev->name);
printk("eata_pio: invalid base address of device %s\n", dev->name); continue;
continue; }
} base = pci_resource_start(dev, 0);
base = pci_resource_start(dev, 0); /* EISA tag there ? */
/* EISA tag there ? */ if ((inb(base) == 0x12) && (inb(base + 1) == 0x14))
if ((inb(base) == 0x12) && (inb(base + 1) == 0x14)) continue; /* Jep, it's forced, so move on */
continue; /* Jep, it's forced, so move on */ base += 0x10; /* Now, THIS is the real address */
base += 0x10; /* Now, THIS is the real address */ if (base != 0x1f8) {
if (base != 0x1f8) { /* We didn't find it in the primary search */
/* We didn't find it in the primary search */ if (get_pio_conf_PIO(base, buf) == TRUE) {
if (get_pio_conf_PIO(base, buf) == TRUE) { if (buf->FORCADR) /* If the address is forced */
if (buf->FORCADR) /* If the address is forced */ continue; /* we'll find it later */
continue; /* we'll find it later */
/* OK. We made it till here, so we can go now
/* OK. We made it till here, so we can go now * and register it. We only have to check and
* and register it. We only have to check and * eventually remove it from the EISA and ISA list
* eventually remove it from the EISA and ISA list */
*/
register_pio_HBA(base, buf, tpnt);
register_pio_HBA(base, buf, tpnt);
if (base < 0x1000) {
if (base < 0x1000) { for (x = 0; x < MAXISA; ++x) {
for (x = 0; x < MAXISA; ++x) { if (ISAbases[x] == base) {
if (ISAbases[x] == base) { ISAbases[x] = 0;
ISAbases[x] = 0; break;
break; }
} }
} else if ((base & 0x0fff) == 0x0c88) {
x = (base >> 12) & 0x0f;
EISAbases[x] = 0;
}
} }
} else if ((base & 0x0fff) == 0x0c88) {
x = (base >> 12) & 0x0f;
EISAbases[x] = 0;
}
}
#if CHECK_BLINK #if CHECK_BLINK
else if (check_blink_state(base) == TRUE) { else if (check_blink_state(base) == TRUE) {
printk("eata_pio: HBA is in BLINK state.\n" printk("eata_pio: HBA is in BLINK state.\n" "Consult your HBAs manual to correct this.\n");
"Consult your HBAs manual to correct this.\n"); }
}
#endif #endif
} }
} }
#endif /* #ifndef CONFIG_PCI */ #endif /* #ifndef CONFIG_PCI */
} }
int eata_pio_detect(Scsi_Host_Template * tpnt) static int eata_pio_detect(Scsi_Host_Template * tpnt)
{ {
struct Scsi_Host *HBA_ptr; struct Scsi_Host *HBA_ptr;
struct get_conf gc; struct get_conf gc;
int i; int i;
tpnt->proc_name = "eata_pio"; tpnt->proc_name = "eata_pio";
find_pio_PCI(&gc, tpnt); find_pio_PCI(&gc, tpnt);
find_pio_EISA(&gc, tpnt); find_pio_EISA(&gc, tpnt);
find_pio_ISA(&gc, tpnt); find_pio_ISA(&gc, tpnt);
for (i = 0; i <= MAXIRQ; i++) for (i = 0; i <= MAXIRQ; i++)
if (reg_IRQ[i]) if (reg_IRQ[i])
request_irq(i, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", NULL); request_irq(i, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", NULL);
HBA_ptr = first_HBA; HBA_ptr = first_HBA;
if (registered_HBAs != 0) { if (registered_HBAs != 0) {
printk("EATA (Extended Attachment) PIO driver version: %d.%d%s\n" printk("EATA (Extended Attachment) PIO driver version: %d.%d%s\n"
"(c) 1993-95 Michael Neuffer, neuffer@goofy.zdv.uni-mainz.de\n" "(c) 1993-95 Michael Neuffer, neuffer@goofy.zdv.uni-mainz.de\n" " Alfred Arnold, a.arnold@kfa-juelich.de\n" "This release only supports DASD devices (harddisks)\n", VER_MAJOR, VER_MINOR, VER_SUB);
" Alfred Arnold, a.arnold@kfa-juelich.de\n"
"This release only supports DASD devices (harddisks)\n", printk("Registered HBAs:\n");
VER_MAJOR, VER_MINOR, VER_SUB); printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:" " QS: SG: CPL:\n");
for (i = 1; i <= registered_HBAs; i++) {
printk("Registered HBAs:\n"); printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d %d %d %c"
printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:" " %2d %2d %2d\n",
" QS: SG: CPL:\n"); HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
for (i = 1; i <= registered_HBAs; i++) { SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P') ?
printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d %d %d %c" "PCI " : (SD(HBA_ptr)->bustype == 'E') ? "EISA" : "ISA ",
" %2d %2d %2d\n", (uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE) ? 'Y' : 'N', HBA_ptr->can_queue, HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun);
HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision, HBA_ptr = SD(HBA_ptr)->next;
SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')? }
"PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ",
(uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel,
HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N',
HBA_ptr->can_queue, HBA_ptr->sg_tablesize,
HBA_ptr->cmd_per_lun);
HBA_ptr = SD(HBA_ptr)->next;
} }
} return (registered_HBAs);
return (registered_HBAs);
} }
/* Eventually this will go into an include file, but this will be later */ /* Eventually this will go into an include file, but this will be later */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Header file for eata_pio.c Linux EATA-PIO SCSI driver * * Header file for eata_pio.c Linux EATA-PIO SCSI driver *
* (c) 1993-96 Michael Neuffer * * (c) 1993-96 Michael Neuffer *
********************************************************* *********************************************************
* last change: 96/05/05 * * last change: 2002/11/02 *
********************************************************/ ********************************************************/
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "hosts.h" #include "hosts.h"
#include <scsi/scsicam.h> #include <scsi/scsicam.h>
#ifndef HOSTS_C
#include "eata_generic.h" #include "eata_generic.h"
#define VER_MAJOR 0 #define VER_MAJOR 0
...@@ -25,82 +24,55 @@ ...@@ -25,82 +24,55 @@
* Here you can switch parts of the code on and of * * Here you can switch parts of the code on and of *
************************************************************************/ ************************************************************************/
#define VERBOSE_SETUP /* show startup screen of 2001 */ #define VERBOSE_SETUP /* show startup screen of 2001 */
#define ALLOW_DMA_BOARDS 1 #define ALLOW_DMA_BOARDS 1
/************************************************************************ /************************************************************************
* Debug options. * * Debug options. *
* Enable DEBUG and whichever options you require. * * Enable DEBUG and whichever options you require. *
************************************************************************/ ************************************************************************/
#define DEBUG_EATA 1 /* Enable debug code. */ #define DEBUG_EATA 1 /* Enable debug code. */
#define DPT_DEBUG 0 /* Bobs special */ #define DPT_DEBUG 0 /* Bobs special */
#define DBG_DELAY 0 /* Build in delays so debug messages can be #define DBG_DELAY 0 /* Build in delays so debug messages can be
* be read before they vanish of the top of * be read before they vanish of the top of
* the screen! * the screen!
*/ */
#define DBG_PROBE 0 /* Debug probe routines. */ #define DBG_PROBE 0 /* Debug probe routines. */
#define DBG_ISA 0 /* Trace ISA routines */ #define DBG_ISA 0 /* Trace ISA routines */
#define DBG_EISA 0 /* Trace EISA routines */ #define DBG_EISA 0 /* Trace EISA routines */
#define DBG_PCI 0 /* Trace PCI routines */ #define DBG_PCI 0 /* Trace PCI routines */
#define DBG_PIO 0 /* Trace get_config_PIO */ #define DBG_PIO 0 /* Trace get_config_PIO */
#define DBG_COM 0 /* Trace command call */ #define DBG_COM 0 /* Trace command call */
#define DBG_QUEUE 0 /* Trace command queueing. */ #define DBG_QUEUE 0 /* Trace command queueing. */
#define DBG_INTR 0 /* Trace interrupt service routine. */ #define DBG_INTR 0 /* Trace interrupt service routine. */
#define DBG_INTR2 0 /* Trace interrupt service routine. */ #define DBG_INTR2 0 /* Trace interrupt service routine. */
#define DBG_PROC 0 /* Debug proc-fs related statistics */ #define DBG_PROC 0 /* Debug proc-fs related statistics */
#define DBG_PROC_WRITE 0 #define DBG_PROC_WRITE 0
#define DBG_REGISTER 0 /* */ #define DBG_REGISTER 0 /* */
#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */ #define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */
#if DEBUG_EATA #if DEBUG_EATA
#define DBG(x, y) if ((x)) {y;} #define DBG(x, y) if ((x)) {y;}
#else #else
#define DBG(x, y) #define DBG(x, y)
#endif #endif
#endif /* !HOSTS_C */ static int eata_pio_detect(Scsi_Host_Template *);
static int eata_pio_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int eata_pio_abort(Scsi_Cmnd *);
static int eata_pio_host_reset(Scsi_Cmnd *);
static int eata_pio_proc_info(char *, char **, off_t, int, int, int);
static int eata_pio_release(struct Scsi_Host *);
int eata_pio_detect(Scsi_Host_Template *); #define EATA_PIO { \
const char *eata_pio_info(struct Scsi_Host *); proc_info: eata_pio_proc_info, /* procinfo */ \
int eata_pio_command(Scsi_Cmnd *); name: "EATA (Extended Attachment) PIO driver",\
int eata_pio_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); detect: eata_pio_detect, \
int eata_pio_abort(Scsi_Cmnd *); release: eata_pio_release, \
int eata_pio_reset(Scsi_Cmnd *, unsigned int); queuecommand: eata_pio_queue, \
int eata_pio_proc_info(char *, char **, off_t, int, int, int); eh_abort_handler: eata_pio_abort, \
#ifdef MODULE eh_host_reset_handler: eata_pio_host_reset, \
int eata_pio_release(struct Scsi_Host *); use_clustering: ENABLE_CLUSTERING \
#else }
#define eata_pio_release NULL
#endif
#define EATA_PIO { \
proc_info: eata_pio_proc_info, /* procinfo */ \
name: "EATA (Extended Attachment) PIO driver", \
detect: eata_pio_detect, \
release: eata_pio_release, \
queuecommand: eata_pio_queue, \
abort: eata_pio_abort, \
reset: eata_pio_reset, \
unchecked_isa_dma: 1, /* True if ISA */ \
use_clustering: ENABLE_CLUSTERING }
#endif /* _EATA_PIO_H */
/* #endif /* _EATA_PIO_H */
* Overrides for Emacs so that we almost 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: 4
* c-brace-imaginary-offset: 0
* c-brace-offset: -4
* c-argdecl-indent: 4
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* tab-width: 8
* End:
*/
...@@ -1325,118 +1325,115 @@ static int fd_mcs_host_reset(Scsi_Cmnd * SCpnt) ...@@ -1325,118 +1325,115 @@ static int fd_mcs_host_reset(Scsi_Cmnd * SCpnt)
return FAILED; return FAILED;
} }
static int fd_mcs_device_reset(Scsi_Cmnd * SCpnt) { static int fd_mcs_device_reset(Scsi_Cmnd * SCpnt)
return FAILED; {
} return FAILED;
}
static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) { static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
struct Scsi_Host *shpnt = SCpnt->host; struct Scsi_Host *shpnt = SCpnt->host;
unsigned long flags;
#if DEBUG_RESET #if DEBUG_RESET
static int called_once = 0; static int called_once = 0;
#endif #endif
#if ERRORS_ONLY #if ERRORS_ONLY
if (SCpnt) if (SCpnt)
printk("fd_mcs: SCSI Bus Reset\n"); printk("fd_mcs: SCSI Bus Reset\n");
#endif #endif
#if DEBUG_RESET #if DEBUG_RESET
if (called_once) if (called_once)
fd_mcs_print_info(current_SC); fd_mcs_print_info(current_SC);
called_once = 1; called_once = 1;
#endif #endif
spin_lock_irqsave(shpnt->host_lock, flags); outb(1, SCSI_Cntl_port);
do_pause(2);
outb(1, SCSI_Cntl_port); outb(0, SCSI_Cntl_port);
do_pause(2); do_pause(115);
outb(0, SCSI_Cntl_port); outb(0, SCSI_Mode_Cntl_port);
do_pause(115); outb(PARITY_MASK, TMC_Cntl_port);
outb(0, SCSI_Mode_Cntl_port);
outb(PARITY_MASK, TMC_Cntl_port);
/* Unless this is the very first call (i.e., SCPnt == NULL), everything
is probably hosed at this point. We will, however, try to keep
things going by informing the high-level code that we need help. */
spin_unlock_irqrestore(shpnt->host_lock, flags); /* Unless this is the very first call (i.e., SCPnt == NULL), everything
is probably hosed at this point. We will, however, try to keep
things going by informing the high-level code that we need help. */
return SUCCESS; return SUCCESS;
} }
#include <scsi/scsi_ioctl.h> #include <scsi/scsi_ioctl.h>
static int fd_mcs_biosparam(Scsi_Disk * disk, struct block_device *bdev, static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev,
sector_t capacity, int *info_array) { sector_t capacity, int *info_array)
unsigned char buf[512 + sizeof(int) * 2]; {
int size = capacity; unsigned char buf[512 + sizeof(int) * 2];
int *sizes = (int *) buf; int size = capacity;
unsigned char *data = (unsigned char *) (sizes + 2); int *sizes = (int *) buf;
unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 }; unsigned char *data = (unsigned char *) (sizes + 2);
int retcode; unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 };
int retcode;
/* BIOS >= 3.4 for MCA cards */
/* This algorithm was provided by Future Domain (much thanks!). */ /* BIOS >= 3.4 for MCA cards */
/* This algorithm was provided by Future Domain (much thanks!). */
sizes[0] = 0; /* zero bytes out */
sizes[1] = 512; /* one sector in */ sizes[0] = 0; /* zero bytes out */
memcpy(data, do_read, sizeof(do_read)); sizes[1] = 512; /* one sector in */
retcode = kernel_scsi_ioctl(disk->device, SCSI_IOCTL_SEND_COMMAND, (void *) buf); memcpy(data, do_read, sizeof(do_read));
if (!retcode /* SCSI command ok */ retcode = kernel_scsi_ioctl(disk, SCSI_IOCTL_SEND_COMMAND, (void *) buf);
&& data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */ if (!retcode /* SCSI command ok */
&& data[0x1c2]) { /* Partition type */ && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
&& data[0x1c2]) { /* Partition type */
/* The partition table layout is as follows: /* The partition table layout is as follows:
Start: 0x1b3h Start: 0x1b3h
Offset: 0 = partition status Offset: 0 = partition status
1 = starting head 1 = starting head
2 = starting sector and cylinder (word, encoded) 2 = starting sector and cylinder (word, encoded)
4 = partition type 4 = partition type
5 = ending head 5 = ending head
6 = ending sector and cylinder (word, encoded) 6 = ending sector and cylinder (word, encoded)
8 = starting absolute sector (double word) 8 = starting absolute sector (double word)
c = number of sectors (double word) c = number of sectors (double word)
Signature: 0x1fe = 0x55aa Signature: 0x1fe = 0x55aa
So, this algorithm assumes: So, this algorithm assumes:
1) the first partition table is in use, 1) the first partition table is in use,
2) the data in the first entry is correct, and 2) the data in the first entry is correct, and
3) partitions never divide cylinders 3) partitions never divide cylinders
Note that (1) may be FALSE for NetBSD (and other BSD flavors), Note that (1) may be FALSE for NetBSD (and other BSD flavors),
as well as for Linux. Note also, that Linux doesn't pay any as well as for Linux. Note also, that Linux doesn't pay any
attention to the fields that are used by this algorithm -- it attention to the fields that are used by this algorithm -- it
only uses the absolute sector data. Recent versions of Linux's only uses the absolute sector data. Recent versions of Linux's
fdisk(1) will fill this data in correctly, and forthcoming fdisk(1) will fill this data in correctly, and forthcoming
versions will check for consistency. versions will check for consistency.
Checking for a non-zero partition type is not part of the Checking for a non-zero partition type is not part of the
Future Domain algorithm, but it seemed to be a reasonable thing Future Domain algorithm, but it seemed to be a reasonable thing
to do, especially in the Linux and BSD worlds. */ to do, especially in the Linux and BSD worlds. */
info_array[0] = data[0x1c3] + 1; /* heads */ info_array[0] = data[0x1c3] + 1; /* heads */
info_array[1] = data[0x1c4] & 0x3f; /* sectors */ info_array[1] = data[0x1c4] & 0x3f; /* sectors */
} else {
/* Note that this new method guarantees that there will always be
less than 1024 cylinders on a platter. This is good for drives
up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
if ((unsigned int) size >= 0x7e0000U)
{
info_array[0] = 0xff; /* heads = 255 */
info_array[1] = 0x3f; /* sectors = 63 */
} else if ((unsigned int) size >= 0x200000U) {
info_array[0] = 0x80; /* heads = 128 */
info_array[1] = 0x3f; /* sectors = 63 */
} else { } else {
info_array[0] = 0x40; /* heads = 64 */
/* Note that this new method guarantees that there will always be info_array[1] = 0x20; /* sectors = 32 */
less than 1024 cylinders on a platter. This is good for drives
up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
if ((unsigned int) size >= 0x7e0000U) {
info_array[0] = 0xff; /* heads = 255 */
info_array[1] = 0x3f; /* sectors = 63 */
} else if ((unsigned int) size >= 0x200000U) {
info_array[0] = 0x80; /* heads = 128 */
info_array[1] = 0x3f; /* sectors = 63 */
} else {
info_array[0] = 0x40; /* heads = 64 */
info_array[1] = 0x20; /* sectors = 32 */
}
} }
/* For both methods, compute the cylinders */ }
info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]); /* For both methods, compute the cylinders */
info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]);
return 0;
}
/* Eventually this will go into an include file, but this will be later */ /* Eventually this will go into an include file, but this will be later */
static Scsi_Host_Template driver_template = FD_MCS; static Scsi_Host_Template driver_template = FD_MCS;
......
...@@ -30,7 +30,7 @@ static int fd_mcs_bus_reset(Scsi_Cmnd *); ...@@ -30,7 +30,7 @@ static int fd_mcs_bus_reset(Scsi_Cmnd *);
static int fd_mcs_device_reset(Scsi_Cmnd *); static int fd_mcs_device_reset(Scsi_Cmnd *);
static int fd_mcs_host_reset(Scsi_Cmnd *); static int fd_mcs_host_reset(Scsi_Cmnd *);
static int fd_mcs_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); static int fd_mcs_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int fd_mcs_biosparam(Disk *, struct block_device *, static int fd_mcs_biosparam(struct scsi_device *, struct block_device *,
sector_t, int *); sector_t, int *);
static int fd_mcs_proc_info(char *, char **, off_t, int, int, int); static int fd_mcs_proc_info(char *, char **, off_t, int, int, int);
static const char *fd_mcs_info(struct Scsi_Host *); static const char *fd_mcs_info(struct Scsi_Host *);
......
...@@ -54,7 +54,7 @@ static int generic_NCR5380_device_reset(Scsi_Cmnd *); ...@@ -54,7 +54,7 @@ static int generic_NCR5380_device_reset(Scsi_Cmnd *);
static int notyet_generic_proc_info (char *buffer ,char **start, off_t offset, static int notyet_generic_proc_info (char *buffer ,char **start, off_t offset,
int length, int hostno, int inout); int length, int hostno, int inout);
static const char* generic_NCR5380_info(struct Scsi_Host *); static const char* generic_NCR5380_info(struct Scsi_Host *);
static int generic_NCR5380_biosparam(Disk *, struct block_device *, sector_t, int *); static int generic_NCR5380_biosparam(struct scsi_device *, struct block_device *, sector_t, int *);
static int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout); static int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout);
#ifndef CMD_PER_LUN #ifndef CMD_PER_LUN
......
...@@ -192,7 +192,7 @@ typedef struct SHT ...@@ -192,7 +192,7 @@ typedef struct SHT
/* /*
* Old EH handlers, no longer used. Make them warn the user of old * Old EH handlers, no longer used. Make them warn the user of old
* drivers by using a wrogn type * drivers by using a wrong type
*/ */
int (*abort)(int); int (*abort)(int);
int (*reset)(int,int); int (*reset)(int,int);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -10,18 +10,14 @@ ...@@ -10,18 +10,14 @@
/* Common forward declarations for all Linux-versions: */ /* Common forward declarations for all Linux-versions: */
/* Interfaces to the midlevel Linux SCSI driver */ /* Interfaces to the midlevel Linux SCSI driver */
extern int ibmmca_proc_info (char *, char **, off_t, int, int, int); static int ibmmca_proc_info (char *, char **, off_t, int, int, int);
extern int ibmmca_detect (Scsi_Host_Template *); static int ibmmca_detect (Scsi_Host_Template *);
extern int ibmmca_release (struct Scsi_Host *); static int ibmmca_release (struct Scsi_Host *);
extern int ibmmca_command (Scsi_Cmnd *); static int ibmmca_command (Scsi_Cmnd *);
extern int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
extern int ibmmca_abort (Scsi_Cmnd *); static int ibmmca_abort (Scsi_Cmnd *);
extern int ibmmca_reset (Scsi_Cmnd *, unsigned int); static int ibmmca_host_reset (Scsi_Cmnd *);
extern int ibmmca_biosparam (struct scsi_device *, struct block_device *, static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
sector_t, int *);
/*structure for /proc filesystem */
extern struct proc_dir_entry proc_scsi_ibmmca;
/* /*
* 2/8/98 * 2/8/98
...@@ -37,8 +33,8 @@ extern struct proc_dir_entry proc_scsi_ibmmca; ...@@ -37,8 +33,8 @@ extern struct proc_dir_entry proc_scsi_ibmmca;
release: ibmmca_release, /*release fn*/ \ release: ibmmca_release, /*release fn*/ \
command: ibmmca_command, /*command fn*/ \ command: ibmmca_command, /*command fn*/ \
queuecommand: ibmmca_queuecommand, /*queuecommand fn*/ \ queuecommand: ibmmca_queuecommand, /*queuecommand fn*/ \
abort: ibmmca_abort, /*abort fn*/ \ eh_abort_handler:ibmmca_abort, /*abort fn*/ \
reset: ibmmca_reset, /*reset fn*/ \ eh_host_reset_handler:ibmmca_host_reset, /*reset fn*/ \
bios_param: ibmmca_biosparam, /*bios fn*/ \ bios_param: ibmmca_biosparam, /*bios fn*/ \
can_queue: 16, /*can_queue*/ \ can_queue: 16, /*can_queue*/ \
this_id: 7, /*set by detect*/ \ this_id: 7, /*set by detect*/ \
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
***********************************************************************/ ***********************************************************************/
/* $Id: nsp_cs.c,v 1.4 2002/10/15 15:57:01 elca Exp $ */ /* $Id: nsp_cs.c,v 1.5 2002/11/05 12:06:29 elca Exp $ */
#ifdef NSP_KERNEL_2_2 #ifdef NSP_KERNEL_2_2
#include <pcmcia/config.h> #include <pcmcia/config.h>
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
#include "nsp_cs.h" #include "nsp_cs.h"
MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>"); MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>");
MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module $Revision: 1.4 $"); MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module $Revision: 1.5 $");
MODULE_SUPPORTED_DEVICE("sd,sr,sg,st"); MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
#ifdef MODULE_LICENSE #ifdef MODULE_LICENSE
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -77,7 +77,7 @@ MODULE_LICENSE("GPL"); ...@@ -77,7 +77,7 @@ MODULE_LICENSE("GPL");
static int pc_debug = PCMCIA_DEBUG; static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i"); MODULE_PARM(pc_debug, "i");
MODULE_PARM_DESC(pc_debug, "set debug level"); MODULE_PARM_DESC(pc_debug, "set debug level");
static char *version = "$Id: nsp_cs.c,v 1.4 2002/10/15 15:57:01 elca Exp $"; static char *version = "$Id: nsp_cs.c,v 1.5 2002/11/05 12:06:29 elca Exp $";
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
#else #else
#define DEBUG(n, args...) /* */ #define DEBUG(n, args...) /* */
...@@ -129,39 +129,30 @@ MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0 ...@@ -129,39 +129,30 @@ MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0
/* /usr/src/linux/drivers/scsi/hosts.h */ /* /usr/src/linux/drivers/scsi/hosts.h */
static Scsi_Host_Template driver_template = { static Scsi_Host_Template driver_template = {
/* .next = NULL,*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
.proc_name = "nsp_cs", /* kernel 2.4 */ .proc_name = "nsp_cs", /* kernel 2.4 */
#else #else
.proc_dir = &proc_scsi_nsp, /* kernel 2.2 */ .proc_dir = &proc_scsi_nsp, /* kernel 2.2 */
#endif #endif
.proc_info = nsp_proc_info, .proc_info = nsp_proc_info,
.name = "WorkBit NinjaSCSI-3/32Bi", .name = "WorkBit NinjaSCSI-3/32Bi(16bit)",
.detect = nsp_detect, .detect = nsp_detect,
.release = nsp_release, .release = nsp_release,
.info = nsp_info, .info = nsp_info,
/* .command = NULL,*/
.queuecommand = nsp_queuecommand, .queuecommand = nsp_queuecommand,
/* .eh_strategy_handler = nsp_eh_strategy,*/ /* .eh_strategy_handler = nsp_eh_strategy,*/
/* .eh_abort_handler = nsp_eh_abort,*/ /* .eh_abort_handler = nsp_eh_abort,*/
/* .eh_device_reset_handler = nsp_eh_device_reset,*/ /* .eh_device_reset_handler = nsp_eh_device_reset,*/
.eh_bus_reset_handler = nsp_eh_bus_reset, .eh_bus_reset_handler = nsp_eh_bus_reset,
.eh_host_reset_handler = nsp_eh_host_reset, .eh_host_reset_handler = nsp_eh_host_reset,
.abort = nsp_abort,
.reset = nsp_reset,
/* .slave_attach = NULL,*/
/* .bios_param = NULL,*/
.can_queue = 1, .can_queue = 1,
.this_id = NSP_INITIATOR_ID, .this_id = NSP_INITIATOR_ID,
.sg_tablesize = SG_ALL, .sg_tablesize = SG_ALL,
.cmd_per_lun = 1, .cmd_per_lun = 1,
/* .present = 0,*/
/* .unchecked_isa_dma = 0,*/
.use_clustering = DISABLE_CLUSTERING, .use_clustering = DISABLE_CLUSTERING,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
.use_new_eh_code = 1, .use_new_eh_code = 1,
#endif #endif
/* .emulated = 0,*/
}; };
static dev_link_t *dev_list = NULL; static dev_link_t *dev_list = NULL;
...@@ -180,12 +171,12 @@ static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -180,12 +171,12 @@ static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
#endif #endif
nsp_hw_data *data = &nsp_data; nsp_hw_data *data = &nsp_data;
DEBUG(0, "%s() SCpnt=0x%p target=%d lun=%d buff=0x%p bufflen=%d use_sg=%d\n", DEBUG(0, "%s: SCpnt=0x%p target=%d lun=%d buff=0x%p bufflen=%d use_sg=%d\n",
__FUNCTION__, SCpnt, target, SCpnt->lun, SCpnt->request_buffer, SCpnt->request_bufflen, SCpnt->use_sg); __FUNCTION__, SCpnt, target, SCpnt->lun, SCpnt->request_buffer, SCpnt->request_bufflen, SCpnt->use_sg);
//DEBUG(0, " before CurrentSC=0x%p\n", data->CurrentSC); //DEBUG(0, " before CurrentSC=0x%p\n", data->CurrentSC);
if(data->CurrentSC != NULL) { if(data->CurrentSC != NULL) {
printk(KERN_DEBUG " %s() CurrentSC!=NULL cannot happen!\n", __FUNCTION__); printk(KERN_DEBUG " %s: CurrentSC!=NULL this can't be happen\n", __FUNCTION__);
data->CurrentSC = NULL; data->CurrentSC = NULL;
SCpnt->result = DID_BAD_TARGET << 16; SCpnt->result = DID_BAD_TARGET << 16;
done(SCpnt); done(SCpnt);
...@@ -231,7 +222,7 @@ static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -231,7 +222,7 @@ static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
} }
//DEBUG(0, __func__ "() out\n"); //DEBUG(0, "%s: out\n", __FUNCTION__);
return 0; return 0;
} }
...@@ -243,7 +234,7 @@ static void nsp_setup_fifo(nsp_hw_data *data, int enabled) ...@@ -243,7 +234,7 @@ static void nsp_setup_fifo(nsp_hw_data *data, int enabled)
unsigned int base = data->BaseAddress; unsigned int base = data->BaseAddress;
unsigned char transfer_mode_reg; unsigned char transfer_mode_reg;
//DEBUG(0, __func__ "() enabled=%d\n", enabled); //DEBUG(0, "%s: enabled=%d\n", __FUNCTION__, enabled);
if (enabled != FALSE) { if (enabled != FALSE) {
transfer_mode_reg = TRANSFER_GO | BRAIND; transfer_mode_reg = TRANSFER_GO | BRAIND;
...@@ -265,7 +256,7 @@ static void nsphw_init_sync(nsp_hw_data *data) ...@@ -265,7 +256,7 @@ static void nsphw_init_sync(nsp_hw_data *data)
int i; int i;
/* setup sync data */ /* setup sync data */
for ( i = 0; i < N_TARGET; i++ ) { for ( i = 0; i < NUMBER(data->Sync); i++ ) {
data->Sync[i] = tmp_sync; data->Sync[i] = tmp_sync;
} }
} }
...@@ -277,7 +268,7 @@ static int nsphw_init(nsp_hw_data *data) ...@@ -277,7 +268,7 @@ static int nsphw_init(nsp_hw_data *data)
{ {
unsigned int base = data->BaseAddress; unsigned int base = data->BaseAddress;
DEBUG(0, "%s() in base=0x%x\n", __FUNCTION__, base); DEBUG(0, "%s: in base=0x%x\n", __FUNCTION__, base);
data->ScsiClockDiv = CLOCK_40M | FAST_20; data->ScsiClockDiv = CLOCK_40M | FAST_20;
data->CurrentSC = NULL; data->CurrentSC = NULL;
...@@ -340,7 +331,7 @@ static unsigned int nsphw_start_selection(Scsi_Cmnd *SCpnt, ...@@ -340,7 +331,7 @@ static unsigned int nsphw_start_selection(Scsi_Cmnd *SCpnt,
int time_out; int time_out;
unsigned char phase, arbit; unsigned char phase, arbit;
//DEBUG(0, __func__ "()in\n"); //DEBUG(0, "%s:in\n", __FUNCTION__);
phase = nsp_index_read(base, SCSIBUSMON); phase = nsp_index_read(base, SCSIBUSMON);
if(phase != BUSMON_BUS_FREE) { if(phase != BUSMON_BUS_FREE) {
...@@ -422,7 +413,7 @@ static int nsp_msg(Scsi_Cmnd *SCpnt, nsp_hw_data *data) ...@@ -422,7 +413,7 @@ static int nsp_msg(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
int i; int i;
DEBUG(0, "%s()\n", __FUNCTION__); DEBUG(0, "%s:\n", __FUNCTION__);
period = sync->SyncPeriod; period = sync->SyncPeriod;
offset = sync->SyncOffset; offset = sync->SyncOffset;
...@@ -473,7 +464,7 @@ static void nsp_start_timer(Scsi_Cmnd *SCpnt, nsp_hw_data *data, int time) ...@@ -473,7 +464,7 @@ static void nsp_start_timer(Scsi_Cmnd *SCpnt, nsp_hw_data *data, int time)
{ {
unsigned int base = SCpnt->host->io_port; unsigned int base = SCpnt->host->io_port;
//DEBUG(0, __func__ "() in SCpnt=0x%p, time=%d\n", SCpnt, time); //DEBUG(0, "%s: in SCpnt=0x%p, time=%d\n", __FUNCTION__, SCpnt, time);
data->TimerCount = time; data->TimerCount = time;
nsp_index_write(base, TIMERCOUNT, time); nsp_index_write(base, TIMERCOUNT, time);
} }
...@@ -487,7 +478,7 @@ static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str) ...@@ -487,7 +478,7 @@ static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str)
unsigned char reg; unsigned char reg;
int time_out; int time_out;
//DEBUG(0, __func__ "()\n"); //DEBUG(0, "%s:\n", __FUNCTION__);
time_out = 100; time_out = 100;
...@@ -499,7 +490,7 @@ static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str) ...@@ -499,7 +490,7 @@ static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str)
} while ((time_out-- != 0) && (reg & mask) != 0); } while ((time_out-- != 0) && (reg & mask) != 0);
if (time_out == 0) { if (time_out == 0) {
printk(KERN_DEBUG "%s: %s signal off timeut\n", __FUNCTION__, str); printk(KERN_DEBUG "%s:: %s signal off timeut\n", __FUNCTION__, str);
} }
return 0; return 0;
...@@ -516,7 +507,7 @@ static int nsp_expect_signal(Scsi_Cmnd *SCpnt, ...@@ -516,7 +507,7 @@ static int nsp_expect_signal(Scsi_Cmnd *SCpnt,
int time_out; int time_out;
unsigned char phase, i_src; unsigned char phase, i_src;
//DEBUG(0, __func__ "() current_phase=0x%x, mask=0x%x\n", current_phase, mask); //DEBUG(0, "%s: current_phase=0x%x, mask=0x%x\n", __FUNCTION__, current_phase, mask);
time_out = 100; time_out = 100;
do { do {
...@@ -536,7 +527,7 @@ static int nsp_expect_signal(Scsi_Cmnd *SCpnt, ...@@ -536,7 +527,7 @@ static int nsp_expect_signal(Scsi_Cmnd *SCpnt,
} }
} while(time_out-- != 0); } while(time_out-- != 0);
//DEBUG(0, __func__ " : " __func__ " timeout\n"); //DEBUG(0, "%s: timeout\n", __FUNCTION__);
return -1; return -1;
} }
...@@ -551,7 +542,7 @@ static int nsp_xfer(Scsi_Cmnd *SCpnt, nsp_hw_data *data, int phase) ...@@ -551,7 +542,7 @@ static int nsp_xfer(Scsi_Cmnd *SCpnt, nsp_hw_data *data, int phase)
int ptr; int ptr;
int ret; int ret;
//DEBUG(0, __func__ "()\n"); //DEBUG(0, "%s:\n", __FUNCTION__);
for (ptr = 0; len > 0; len --, ptr ++) { for (ptr = 0; len > 0; len --, ptr ++) {
ret = nsp_expect_signal(SCpnt, phase, BUSMON_REQ); ret = nsp_expect_signal(SCpnt, phase, BUSMON_REQ);
...@@ -586,7 +577,7 @@ static int nsp_dataphase_bypass(Scsi_Cmnd *SCpnt, nsp_hw_data *data) ...@@ -586,7 +577,7 @@ static int nsp_dataphase_bypass(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
{ {
unsigned int count; unsigned int count;
//DEBUG(0, __func__ "()\n"); //DEBUG(0, "%s:\n", __FUNCTION__);
if (SCpnt->SCp.have_data_in != IO_IN) { if (SCpnt->SCp.have_data_in != IO_IN) {
return 0; return 0;
...@@ -618,7 +609,7 @@ static int nsp_reselected(Scsi_Cmnd *SCpnt, nsp_hw_data *data) ...@@ -618,7 +609,7 @@ static int nsp_reselected(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
unsigned int base = SCpnt->host->io_port; unsigned int base = SCpnt->host->io_port;
unsigned char reg; unsigned char reg;
//DEBUG(0, __func__ "()\n"); //DEBUG(0, "%s:\n", __FUNCTION__);
nsp_negate_signal(SCpnt, BUSMON_SEL, "reselect<SEL>"); nsp_negate_signal(SCpnt, BUSMON_SEL, "reselect<SEL>");
...@@ -648,7 +639,7 @@ static int nsp_fifo_count(Scsi_Cmnd *SCpnt) ...@@ -648,7 +639,7 @@ static int nsp_fifo_count(Scsi_Cmnd *SCpnt)
count = (h << 16) | (m << 8) | (l << 0); count = (h << 16) | (m << 8) | (l << 0);
//DEBUG(0, __func__ "() =0x%x\n", count); //DEBUG(0, "%s: =0x%x\n", __FUNCTION__, count);
return count; return count;
} }
...@@ -670,8 +661,8 @@ static void nsp_pio_read(Scsi_Cmnd *SCpnt, nsp_hw_data *data) ...@@ -670,8 +661,8 @@ static void nsp_pio_read(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
ocount = data->FifoCount; ocount = data->FifoCount;
DEBUG(0, "%s() in SCpnt=0x%p resid=%d ocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d\n", DEBUG(0, "%s: in SCpnt=0x%p resid=%d ocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d\n",
__FUNCTION__, SCpnt, RESID, ocount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual); __FUNCTION__, SCpnt, RESID, ocount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual);
time_out = 1000; time_out = 1000;
...@@ -744,8 +735,8 @@ static void nsp_pio_read(Scsi_Cmnd *SCpnt, nsp_hw_data *data) ...@@ -744,8 +735,8 @@ static void nsp_pio_read(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
data->FifoCount = ocount; data->FifoCount = ocount;
if (time_out == 0) { if (time_out == 0) {
printk(KERN_DEBUG "%s() pio read timeout resid=%d this_residual=%d buffers_residual=%d\n", printk(KERN_DEBUG "%s: pio read timeout resid=%d this_residual=%d buffers_residual=%d\n",
__FUNCTION__, RESID, SCpnt->SCp.this_residual, SCpnt->SCp.buffers_residual); __FUNCTION__, RESID, SCpnt->SCp.this_residual, SCpnt->SCp.buffers_residual);
} }
DEBUG(0, " read ocount=0x%x\n", ocount); DEBUG(0, " read ocount=0x%x\n", ocount);
} }
...@@ -763,7 +754,8 @@ static void nsp_pio_write(Scsi_Cmnd *SCpnt, nsp_hw_data *data) ...@@ -763,7 +754,8 @@ static void nsp_pio_write(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
ocount = data->FifoCount; ocount = data->FifoCount;
DEBUG(0, "%s() in fifocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d resid=0x%x\n", __FUNCTION__, data->FifoCount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual, RESID); DEBUG(0, "%s: in fifocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d resid=0x%x\n",
__FUNCTION__, data->FifoCount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual, RESID);
time_out = 1000; time_out = 1000;
...@@ -833,7 +825,7 @@ static void nsp_pio_write(Scsi_Cmnd *SCpnt, nsp_hw_data *data) ...@@ -833,7 +825,7 @@ static void nsp_pio_write(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
data->FifoCount = ocount; data->FifoCount = ocount;
if (time_out == 0) { if (time_out == 0) {
printk(KERN_DEBUG "%s() pio write timeout resid=0x%x\n", __FUNCTION__, RESID); printk(KERN_DEBUG "%s: pio write timeout resid=0x%x\n", __FUNCTION__, RESID);
} }
DEBUG(0, " write ocount=0x%x\n", ocount); DEBUG(0, " write ocount=0x%x\n", ocount);
} }
...@@ -851,7 +843,7 @@ static int nsp_nexus(Scsi_Cmnd *SCpnt, nsp_hw_data *data) ...@@ -851,7 +843,7 @@ static int nsp_nexus(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
// unsigned char lun = SCpnt->lun; // unsigned char lun = SCpnt->lun;
sync_data *sync = &(data->Sync[target]); sync_data *sync = &(data->Sync[target]);
//DEBUG(0, __func__ "() in SCpnt=0x%p\n", SCpnt); //DEBUG(0, "%s: in SCpnt=0x%p\n", __FUNCTION__, SCpnt);
/* setup synch transfer registers */ /* setup synch transfer registers */
nsp_index_write(base, SYNCREG, sync->SyncRegister); nsp_index_write(base, SYNCREG, sync->SyncRegister);
...@@ -948,7 +940,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -948,7 +940,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs)
nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR | IRQCONTROL_FIFO_CLEAR); nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR | IRQCONTROL_FIFO_CLEAR);
if (data->CurrentSC == NULL) { if (data->CurrentSC == NULL) {
printk(KERN_DEBUG "%s: CurrentSC==NULL irq_status=0x%x phase=0x%x irq_phase=0x%x cannot happen\n", __FUNCTION__, i_src, phase, irq_phase); printk(KERN_DEBUG "%s: CurrentSC==NULL irq_status=0x%x phase=0x%x irq_phase=0x%x this can't be happen\n", __FUNCTION__, i_src, phase, irq_phase);
return; return;
} else { } else {
tmpSC = data->CurrentSC; tmpSC = data->CurrentSC;
...@@ -962,7 +954,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -962,7 +954,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs)
*/ */
if ((i_src & IRQSTATUS_SCSI) != 0) { if ((i_src & IRQSTATUS_SCSI) != 0) {
if ((irq_phase & SCSI_RESET_IRQ) != 0) { if ((irq_phase & SCSI_RESET_IRQ) != 0) {
printk(KERN_DEBUG " %s() bus reset (power off?)\n", __FUNCTION__); printk(KERN_DEBUG " %s: bus reset (power off?)\n", __FUNCTION__);
*sync_neg = SYNC_NOT_YET; *sync_neg = SYNC_NOT_YET;
data->CurrentSC = NULL; data->CurrentSC = NULL;
tmpSC->result = (DID_RESET << 16) | tmpSC->result = (DID_RESET << 16) |
...@@ -1064,7 +1056,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1064,7 +1056,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs)
/* check unexpected bus free state */ /* check unexpected bus free state */
if (phase == 0) { if (phase == 0) {
printk(KERN_DEBUG "%s: unexpected bus free. i_src=0x%x, phase=0x%x, irq_phase=0x%x\n", __FUNCTION__, i_src, phase, irq_phase); printk(KERN_DEBUG " %s: unexpected bus free. i_src=0x%x, phase=0x%x, irq_phase=0x%x\n", __FUNCTION__, i_src, phase, irq_phase);
*sync_neg = SYNC_NOT_YET; *sync_neg = SYNC_NOT_YET;
data->CurrentSC = NULL; data->CurrentSC = NULL;
...@@ -1208,7 +1200,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1208,7 +1200,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs)
break; break;
} }
//DEBUG(0, __func__ "() out\n"); //DEBUG(0, "%s: out\n", __FUNCTION__);
return; return;
timer_out: timer_out:
...@@ -1246,7 +1238,7 @@ static int nsp_detect(Scsi_Host_Template *sht) ...@@ -1246,7 +1238,7 @@ static int nsp_detect(Scsi_Host_Template *sht)
snprintf(data->nspinfo, snprintf(data->nspinfo,
sizeof(data->nspinfo), sizeof(data->nspinfo),
"NinjaSCSI-3/32Bi Driver $Revision: 1.4 $ IO:0x%04lx-0x%04lx MMIO(virt addr):0x%04lx IRQ:%02d", "NinjaSCSI-3/32Bi Driver $Revision: 1.5 $ IO:0x%04lx-0x%04lx MMIO(virt addr):0x%04lx IRQ:%02d",
host->io_port, host->io_port + host->n_io_port - 1, host->io_port, host->io_port + host->n_io_port - 1,
host->base, host->base,
host->irq); host->irq);
...@@ -1303,16 +1295,28 @@ static int nsp_proc_info(char *buffer, ...@@ -1303,16 +1295,28 @@ static int nsp_proc_info(char *buffer,
int speed; int speed;
unsigned long flags; unsigned long flags;
nsp_hw_data *data = &nsp_data; nsp_hw_data *data = &nsp_data;
struct Scsi_Host *host; struct Scsi_Host *host = NULL;
if (inout) { if (inout) {
return -EINVAL; return -EINVAL;
} }
/* search this HBA host */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45))
host = scsi_host_hn_get(hostno); host = scsi_host_hn_get(hostno);
#else
for (host=scsi_hostlist; host; host=host->next) {
if (host->host_no == hostno) {
break;
}
}
#endif
if (host == NULL) {
return -ESRCH;
}
SPRINTF("NinjaSCSI status\n\n"); SPRINTF("NinjaSCSI status\n\n");
SPRINTF("Driver version: $Revision: 1.4 $\n"); SPRINTF("Driver version: $Revision: 1.5 $\n");
SPRINTF("SCSI host No.: %d\n", hostno); SPRINTF("SCSI host No.: %d\n", hostno);
SPRINTF("IRQ: %d\n", host->irq); SPRINTF("IRQ: %d\n", host->irq);
SPRINTF("IO: 0x%lx-0x%lx\n", host->io_port, host->io_port + host->n_io_port - 1); SPRINTF("IO: 0x%lx-0x%lx\n", host->io_port, host->io_port + host->n_io_port - 1);
...@@ -1393,45 +1397,6 @@ static int nsp_proc_info(char *buffer, ...@@ -1393,45 +1397,6 @@ static int nsp_proc_info(char *buffer,
} }
#undef SPRINTF #undef SPRINTF
/*---------------------------------------------------------------*/
/* error handler */
/*---------------------------------------------------------------*/
static int nsp_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
{
nsp_hw_data *data = &nsp_data;
int ret = 0;
DEBUG(0, "%s: SCpnt=0x%p why=%d\n", __FUNCTION__, SCpnt, reset_flags);
if (reset_flags & SCSI_RESET_SUGGEST_BUS_RESET) {
nsp_eh_bus_reset(SCpnt);
ret |= SCSI_RESET_BUS_RESET;
}
if (reset_flags & SCSI_RESET_SUGGEST_HOST_RESET) {
nsp_eh_host_reset(SCpnt);
ret |= SCSI_RESET_HOST_RESET;
}
if (ret != 0) {
return SCSI_RESET_SUCCESS | ret;
} else {
nsphw_init_sync(data);
return SCSI_RESET_PUNT;
}
}
static int nsp_abort(Scsi_Cmnd *SCpnt)
{
DEBUG(0, "%s: SCpnt=0x%p\n", __FUNCTION__, SCpnt);
nsp_eh_host_reset(SCpnt);
nsp_eh_bus_reset(SCpnt);
return SCSI_ABORT_SUCCESS;
}
/*static int nsp_eh_strategy(struct Scsi_Host *Shost) /*static int nsp_eh_strategy(struct Scsi_Host *Shost)
{ {
...@@ -1460,7 +1425,7 @@ static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt) ...@@ -1460,7 +1425,7 @@ static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt)
unsigned int base = SCpnt->host->io_port; unsigned int base = SCpnt->host->io_port;
int i; int i;
DEBUG(0, "%s() SCpnt=0x%p base=0x%x\n", __FUNCTION__, SCpnt, base); DEBUG(0, "%s: SCpnt=0x%p base=0x%x\n", __FUNCTION__, SCpnt, base);
nsp_write(base, IRQCONTROL, IRQCONTROL_ALLMASK); nsp_write(base, IRQCONTROL, IRQCONTROL_ALLMASK);
...@@ -1482,7 +1447,7 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt) ...@@ -1482,7 +1447,7 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
{ {
nsp_hw_data *data = &nsp_data; nsp_hw_data *data = &nsp_data;
DEBUG(0, "%s\n", __FUNCTION__); DEBUG(0, "%s:\n", __FUNCTION__);
nsphw_init(data); nsphw_init(data);
...@@ -1517,7 +1482,7 @@ static dev_link_t *nsp_cs_attach(void) ...@@ -1517,7 +1482,7 @@ static dev_link_t *nsp_cs_attach(void)
dev_link_t *link; dev_link_t *link;
int ret, i; int ret, i;
DEBUG(0, "%s()\n", __FUNCTION__); DEBUG(0, "%s:\n", __FUNCTION__);
/* Create new SCSI device */ /* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kmalloc(sizeof(*info), GFP_KERNEL);
...@@ -1607,7 +1572,7 @@ static void nsp_cs_detach(dev_link_t *link) ...@@ -1607,7 +1572,7 @@ static void nsp_cs_detach(dev_link_t *link)
return; return;
} }
del_timer_sync(&link->release); del_timer(&link->release);
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
nsp_cs_release((u_long)link); nsp_cs_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) { if (link->state & DEV_STALE_CONFIG) {
...@@ -1659,7 +1624,7 @@ static void nsp_cs_config(dev_link_t *link) ...@@ -1659,7 +1624,7 @@ static void nsp_cs_config(dev_link_t *link)
nsp_hw_data *data = &nsp_data; nsp_hw_data *data = &nsp_data;
DEBUG(0, "%s() in\n", __FUNCTION__); DEBUG(0, "%s: in\n", __FUNCTION__);
tuple.DesiredTuple = CISTPL_CONFIG; tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0; tuple.Attributes = 0;
...@@ -1764,7 +1729,7 @@ static void nsp_cs_config(dev_link_t *link) ...@@ -1764,7 +1729,7 @@ static void nsp_cs_config(dev_link_t *link)
break; break;
next_entry: next_entry:
DEBUG(0, "%s next\n", __FUNCTION__); DEBUG(0, "%s: next\n", __FUNCTION__);
if (link->io.NumPorts1) if (link->io.NumPorts1)
CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIO, link->handle, &link->io);
...@@ -1787,9 +1752,8 @@ static void nsp_cs_config(dev_link_t *link) ...@@ -1787,9 +1752,8 @@ static void nsp_cs_config(dev_link_t *link)
data->NumAddress = link->io.NumPorts1; data->NumAddress = link->io.NumPorts1;
data->IrqNumber = link->irq.AssignedIRQ; data->IrqNumber = link->irq.AssignedIRQ;
DEBUG(0, "%s I/O[0x%x+0x%x] IRQ %d\n", DEBUG(0, "%s: I/O[0x%x+0x%x] IRQ %d\n",
__FUNCTION__, __FUNCTION__, data->BaseAddress, data->NumAddress, data->IrqNumber);
data->BaseAddress, data->NumAddress, data->IrqNumber);
if(nsphw_init(data) == FALSE) { if(nsphw_init(data) == FALSE) {
goto cs_failed; goto cs_failed;
...@@ -1804,8 +1768,13 @@ static void nsp_cs_config(dev_link_t *link) ...@@ -1804,8 +1768,13 @@ static void nsp_cs_config(dev_link_t *link)
DEBUG(0, "GET_SCSI_INFO\n"); DEBUG(0, "GET_SCSI_INFO\n");
tail = &link->dev; tail = &link->dev;
info->ndev = 0; info->ndev = 0;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45))
for (host = scsi_host_get_next(NULL); host; for (host = scsi_host_get_next(NULL); host;
host = scsi_host_get_next(host)) { host = scsi_host_get_next(host)) {
#else
for (host = scsi_hostlist; host != NULL; host = host->next) {
#endif
if (host->hostt == &driver_template) { if (host->hostt == &driver_template) {
for (dev = host->host_queue; dev != NULL; dev = dev->next) { for (dev = host->host_queue; dev != NULL; dev = dev->next) {
u_long arg[2], id; u_long arg[2], id;
...@@ -1998,7 +1967,7 @@ static int nsp_cs_event(event_t event, ...@@ -1998,7 +1967,7 @@ static int nsp_cs_event(event_t event,
DEBUG(0, " event: unknown\n"); DEBUG(0, " event: unknown\n");
break; break;
} }
DEBUG(0, "%s end\n", __FUNCTION__); DEBUG(0, "%s: end\n", __FUNCTION__);
return 0; return 0;
} /* nsp_cs_event */ } /* nsp_cs_event */
...@@ -2009,7 +1978,7 @@ static int __init nsp_cs_init(void) ...@@ -2009,7 +1978,7 @@ static int __init nsp_cs_init(void)
{ {
servinfo_t serv; servinfo_t serv;
DEBUG(0, "%s() in\n", __FUNCTION__); DEBUG(0, "%s: in\n", __FUNCTION__);
DEBUG(0, "%s\n", version); DEBUG(0, "%s\n", version);
CardServices(GetCardServicesInfo, &serv); CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) { if (serv.Revision != CS_RELEASE_CODE) {
...@@ -2019,14 +1988,14 @@ static int __init nsp_cs_init(void) ...@@ -2019,14 +1988,14 @@ static int __init nsp_cs_init(void)
} }
register_pcmcia_driver(&dev_info, &nsp_cs_attach, &nsp_cs_detach); register_pcmcia_driver(&dev_info, &nsp_cs_attach, &nsp_cs_detach);
DEBUG(0, "%s() out\n", __FUNCTION__); DEBUG(0, "%s: out\n", __FUNCTION__);
return 0; return 0;
} }
static void __exit nsp_cs_cleanup(void) static void __exit nsp_cs_cleanup(void)
{ {
DEBUG(0, "%s() unloading\n", __FUNCTION__); DEBUG(0, "%s: unloading\n", __FUNCTION__);
unregister_pcmcia_driver(&dev_info); unregister_pcmcia_driver(&dev_info);
while (dev_list != NULL) { while (dev_list != NULL) {
if (dev_list->state & DEV_CONFIG) { if (dev_list->state & DEV_CONFIG) {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
=========================================================*/ =========================================================*/
/* $Id: nsp_cs.h,v 1.3 2002/10/10 11:07:52 elca Exp $ */ /* $Id: nsp_cs.h,v 1.4 2002/11/05 12:06:29 elca Exp $ */
#ifndef __nsp_cs__ #ifndef __nsp_cs__
#define __nsp_cs__ #define __nsp_cs__
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
/************************************ /************************************
* Some useful macros... * Some useful macros...
*/ */
#define Number(arr) ((int) (sizeof(arr) / sizeof(arr[0]))) #define NUMBER(arr) ((int) (sizeof(arr) / sizeof(arr[0]))) /* from XtNumber() in /usr/X11R6/include/X11/Intrinsic.h */
#define BIT(x) (1L << (x)) #define BIT(x) (1L << (x))
#define MIN(a,b) ((a) > (b) ? (b) : (a)) #define MIN(a,b) ((a) > (b) ? (b) : (a))
...@@ -270,10 +270,10 @@ typedef struct _nsp_hw_data { ...@@ -270,10 +270,10 @@ typedef struct _nsp_hw_data {
static void nsp_cs_release(u_long arg); static void nsp_cs_release(u_long arg);
static int nsp_cs_event(event_t event, int priority, event_callback_args_t *args); static int nsp_cs_event(event_t event, int priority, event_callback_args_t *args);
static dev_link_t *nsp_cs_attach(void); static dev_link_t *nsp_cs_attach(void);
static void nsp_cs_detach(dev_link_t *); static void nsp_cs_detach(dev_link_t *);
static unsigned int nsphw_start_selection(Scsi_Cmnd *SCpnt, nsp_hw_data *data); static unsigned int nsphw_start_selection(Scsi_Cmnd *SCpnt, nsp_hw_data *data);
static void nsp_start_timer(Scsi_Cmnd *SCpnt, nsp_hw_data *data, int time); static void nsp_start_timer(Scsi_Cmnd *SCpnt, nsp_hw_data *data, int time);
...@@ -285,9 +285,6 @@ static int nsp_proc_info(char *buffer, char **start, off_t offset, ...@@ -285,9 +285,6 @@ static int nsp_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int inout); int length, int hostno, int inout);
static int nsp_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); static int nsp_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
static int nsp_abort(Scsi_Cmnd *);
static int nsp_reset(Scsi_Cmnd *, unsigned int);
/*static int nsp_eh_abort(Scsi_Cmnd * SCpnt);*/ /*static int nsp_eh_abort(Scsi_Cmnd * SCpnt);*/
/*static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt);*/ /*static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt);*/
static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt); static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt);
......
...@@ -64,7 +64,7 @@ static void nsp_message_out(Scsi_Cmnd *SCpnt, nsp_hw_data *data) ...@@ -64,7 +64,7 @@ static void nsp_message_out(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
DEBUG(0, " msgout loop\n"); DEBUG(0, " msgout loop\n");
do { do {
if (nsp_xfer(SCpnt, data, BUSPHASE_MESSAGE_OUT)) { if (nsp_xfer(SCpnt, data, BUSPHASE_MESSAGE_OUT)) {
printk(KERN_DEBUG " %s msgout: xfer short\n", __FUNCTION__); printk(KERN_DEBUG " %s: msgout: xfer short\n", __FUNCTION__);
} }
/* catch a next signal */ /* catch a next signal */
......
...@@ -613,7 +613,7 @@ int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -613,7 +613,7 @@ int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
#ifdef PCMCIA #ifdef PCMCIA
/* /*
* Allow PCMCIA code to preset the port */ * Allow PCMCIA code to preset the port
* port should be 0 and irq to -1 respectively for autoprobing * port should be 0 and irq to -1 respectively for autoprobing
*/ */
......
...@@ -1486,16 +1486,16 @@ static int u14_34f_eh_host_reset(Scsi_Cmnd *SCarg) { ...@@ -1486,16 +1486,16 @@ static int u14_34f_eh_host_reset(Scsi_Cmnd *SCarg) {
return SUCCESS; return SUCCESS;
} }
static int u14_34f_bios_param(Disk *disk, struct block_device *bdev, static int u14_34f_bios_param(struct scsi_device *disk, struct block_device *bdev,
int *dkinfo) { sector_t capacity, int *dkinfo) {
unsigned int j = 0; unsigned int j = 0;
int size = disk->capacity; unsigned int size = capacity;
dkinfo[0] = HD(j)->heads; dkinfo[0] = HD(j)->heads;
dkinfo[1] = HD(j)->sectors; dkinfo[1] = HD(j)->sectors;
dkinfo[2] = size / (HD(j)->heads * HD(j)->sectors); dkinfo[2] = size / (HD(j)->heads * HD(j)->sectors);
if (ext_tran && (scsicam_bios_param(disk, bdev, dkinfo) < 0)) { if (ext_tran && (scsicam_bios_param(bdev, capacity, dkinfo) < 0)) {
dkinfo[0] = 255; dkinfo[0] = 255;
dkinfo[1] = 63; dkinfo[1] = 63;
dkinfo[2] = size / (dkinfo[0] * dkinfo[1]); dkinfo[2] = size / (dkinfo[0] * dkinfo[1]);
......
...@@ -7,7 +7,7 @@ static int u14_34f_release(struct Scsi_Host *); ...@@ -7,7 +7,7 @@ static int u14_34f_release(struct Scsi_Host *);
static int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
static int u14_34f_eh_abort(Scsi_Cmnd *); static int u14_34f_eh_abort(Scsi_Cmnd *);
static int u14_34f_eh_host_reset(Scsi_Cmnd *); static int u14_34f_eh_host_reset(Scsi_Cmnd *);
static int u14_34f_bios_param(Disk *, struct block_device *, int *); static int u14_34f_bios_param(struct scsi_device *, struct block_device *, sector_t, int *);
static int u14_34f_slave_attach(Scsi_Device *); static int u14_34f_slave_attach(Scsi_Device *);
#define U14_34F_VERSION "8.00.00" #define U14_34F_VERSION "8.00.00"
...@@ -17,8 +17,6 @@ static int u14_34f_slave_attach(Scsi_Device *); ...@@ -17,8 +17,6 @@ static int u14_34f_slave_attach(Scsi_Device *);
detect: u14_34f_detect, \ detect: u14_34f_detect, \
release: u14_34f_release, \ release: u14_34f_release, \
queuecommand: u14_34f_queuecommand, \ queuecommand: u14_34f_queuecommand, \
abort: NULL, \
reset: NULL, \
eh_abort_handler: u14_34f_eh_abort, \ eh_abort_handler: u14_34f_eh_abort, \
eh_device_reset_handler: NULL, \ eh_device_reset_handler: NULL, \
eh_bus_reset_handler: NULL, \ eh_bus_reset_handler: NULL, \
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
* John's work modified by Caleb Epstein (cae@jpmorgan.com) and * John's work modified by Caleb Epstein (cae@jpmorgan.com) and
* Eric Youngdale (ericy@cais.com). * Eric Youngdale (ericy@cais.com).
* Thanks to UltraStor for providing the necessary documentation * Thanks to UltraStor for providing the necessary documentation
*
* This is an old driver, for the 14F and 34F you should be using the
* u14-34f driver instead.
*/ */
/* /*
...@@ -164,8 +167,8 @@ ...@@ -164,8 +167,8 @@
packed structure. */ packed structure. */
typedef struct { typedef struct {
unsigned int address; u32 address;
unsigned int num_bytes; u32 num_bytes;
} ultrastor_sg_list; } ultrastor_sg_list;
...@@ -190,7 +193,7 @@ struct mscp { ...@@ -190,7 +193,7 @@ struct mscp {
unsigned char scsi_cdbs[12]; /* SCSI commands */ unsigned char scsi_cdbs[12]; /* SCSI commands */
unsigned char adapter_status; /* non-zero indicates HA error */ unsigned char adapter_status; /* non-zero indicates HA error */
unsigned char target_status; /* non-zero indicates target error */ unsigned char target_status; /* non-zero indicates target error */
unsigned int sense_data PACKED; u32 sense_data PACKED;
/* The following fields are for software only. They are included in /* The following fields are for software only. They are included in
the MSCP structure because they are associated with SCSI requests. */ the MSCP structure because they are associated with SCSI requests. */
void (*done)(Scsi_Cmnd *); void (*done)(Scsi_Cmnd *);
...@@ -289,17 +292,15 @@ static void do_ultrastor_interrupt(int, void *, struct pt_regs *); ...@@ -289,17 +292,15 @@ static void do_ultrastor_interrupt(int, void *, struct pt_regs *);
static inline void build_sg_list(struct mscp *, Scsi_Cmnd *SCpnt); static inline void build_sg_list(struct mscp *, Scsi_Cmnd *SCpnt);
/* Always called with host lock held */
static inline int find_and_clear_bit_16(unsigned short *field) static inline int find_and_clear_bit_16(unsigned short *field)
{ {
int rv; int rv;
unsigned long flags;
save_flags(flags);
cli();
if (*field == 0) panic("No free mscp"); if (*field == 0) panic("No free mscp");
asm("xorl %0,%0\n0:\tbsfw %1,%w0\n\tbtr %0,%1\n\tjnc 0b" asm("xorl %0,%0\n0:\tbsfw %1,%w0\n\tbtr %0,%1\n\tjnc 0b"
: "=&r" (rv), "=m" (*field) : "1" (*field)); : "=&r" (rv), "=m" (*field) : "1" (*field));
restore_flags(flags);
return rv; return rv;
} }
...@@ -320,14 +321,12 @@ static inline unsigned char xchgb(unsigned char reg, ...@@ -320,14 +321,12 @@ static inline unsigned char xchgb(unsigned char reg,
#if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT) #if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT)
static void log_ultrastor_abort(register struct ultrastor_config *config, /* Always called with the host lock held */
static void log_ultrastor_abort(struct ultrastor_config *config,
int command) int command)
{ {
static char fmt[80] = "abort %d (%x); MSCP free pool: %x;"; static char fmt[80] = "abort %d (%x); MSCP free pool: %x;";
register int i; int i;
unsigned long flags;
save_flags(flags);
cli();
for (i = 0; i < ULTRASTOR_MAX_CMDS; i++) for (i = 0; i < ULTRASTOR_MAX_CMDS; i++)
{ {
...@@ -340,7 +339,7 @@ static void log_ultrastor_abort(register struct ultrastor_config *config, ...@@ -340,7 +339,7 @@ static void log_ultrastor_abort(register struct ultrastor_config *config,
fmt[20 + ULTRASTOR_MAX_CMDS * 2] = '\n'; fmt[20 + ULTRASTOR_MAX_CMDS * 2] = '\n';
fmt[21 + ULTRASTOR_MAX_CMDS * 2] = 0; fmt[21 + ULTRASTOR_MAX_CMDS * 2] = 0;
printk(fmt, command, &config->mscp[command], config->mscp_free); printk(fmt, command, &config->mscp[command], config->mscp_free);
restore_flags(flags);
} }
#endif #endif
...@@ -528,7 +527,7 @@ static int ultrastor_14f_detect(Scsi_Host_Template * tpnt) ...@@ -528,7 +527,7 @@ static int ultrastor_14f_detect(Scsi_Host_Template * tpnt)
static int ultrastor_24f_detect(Scsi_Host_Template * tpnt) static int ultrastor_24f_detect(Scsi_Host_Template * tpnt)
{ {
register int i; int i;
struct Scsi_Host * shpnt = NULL; struct Scsi_Host * shpnt = NULL;
#if (ULTRASTOR_DEBUG & UD_DETECT) #if (ULTRASTOR_DEBUG & UD_DETECT)
...@@ -638,13 +637,13 @@ static int ultrastor_24f_detect(Scsi_Host_Template * tpnt) ...@@ -638,13 +637,13 @@ static int ultrastor_24f_detect(Scsi_Host_Template * tpnt)
return FALSE; return FALSE;
} }
int ultrastor_detect(Scsi_Host_Template * tpnt) static int ultrastor_detect(Scsi_Host_Template * tpnt)
{ {
tpnt->proc_name = "ultrastor"; tpnt->proc_name = "ultrastor";
return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt); return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt);
} }
const char *ultrastor_info(struct Scsi_Host * shpnt) static const char *ultrastor_info(struct Scsi_Host * shpnt)
{ {
static char buf[64]; static char buf[64];
...@@ -662,7 +661,7 @@ const char *ultrastor_info(struct Scsi_Host * shpnt) ...@@ -662,7 +661,7 @@ const char *ultrastor_info(struct Scsi_Host * shpnt)
return buf; return buf;
} }
static inline void build_sg_list(register struct mscp *mscp, Scsi_Cmnd *SCpnt) static inline void build_sg_list(struct mscp *mscp, Scsi_Cmnd *SCpnt)
{ {
struct scatterlist *sl; struct scatterlist *sl;
long transfer_length = 0; long transfer_length = 0;
...@@ -683,14 +682,13 @@ static inline void build_sg_list(register struct mscp *mscp, Scsi_Cmnd *SCpnt) ...@@ -683,14 +682,13 @@ static inline void build_sg_list(register struct mscp *mscp, Scsi_Cmnd *SCpnt)
mscp->transfer_data_length = transfer_length; mscp->transfer_data_length = transfer_length;
} }
int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) static int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{ {
register struct mscp *my_mscp; struct mscp *my_mscp;
#if ULTRASTOR_MAX_CMDS > 1 #if ULTRASTOR_MAX_CMDS > 1
int mscp_index; int mscp_index;
#endif #endif
unsigned int status; unsigned int status;
unsigned long flags;
/* Next test is for debugging; "can't happen" */ /* Next test is for debugging; "can't happen" */
if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0) if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0)
...@@ -706,14 +704,8 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -706,14 +704,8 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
my_mscp = &config.mscp[mscp_index]; my_mscp = &config.mscp[mscp_index];
#if 1
/* This way is faster. */
*(unsigned char *)my_mscp = OP_SCSI | (DTD_SCSI << 3); *(unsigned char *)my_mscp = OP_SCSI | (DTD_SCSI << 3);
#else
my_mscp->opcode = OP_SCSI;
my_mscp->xdir = DTD_SCSI;
my_mscp->dcn = FALSE;
#endif
/* Tape drives don't work properly if the cache is used. The SCSI /* Tape drives don't work properly if the cache is used. The SCSI
READ command for a tape doesn't have a block offset, and the adapter READ command for a tape doesn't have a block offset, and the adapter
incorrectly assumes that all reads from the tape read the same incorrectly assumes that all reads from the tape read the same
...@@ -748,35 +740,31 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -748,35 +740,31 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
SCpnt->host_scribble = (unsigned char *)my_mscp; SCpnt->host_scribble = (unsigned char *)my_mscp;
/* Find free OGM slot. On 24F, look for OGM status byte == 0. /* Find free OGM slot. On 24F, look for OGM status byte == 0.
On 14F and 34F, wait for local interrupt pending flag to clear. */ On 14F and 34F, wait for local interrupt pending flag to clear.
FIXME: now we are using new_eh we should punt here and let the
midlayer sort it out */
retry: retry:
if (config.slot) if (config.slot)
while (inb(config.ogm_address - 1) != 0 && while (inb(config.ogm_address - 1) != 0 && config.aborted[mscp_index] == 0xff)
config.aborted[mscp_index] == 0xff) barrier(); barrier();
/* else??? */ /* else??? */
while ((inb(LCL_DOORBELL_INTR(config.doorbell_address)) & while ((inb(LCL_DOORBELL_INTR(config.doorbell_address)) & (config.slot ? 2 : 1)) && config.aborted[mscp_index] == 0xff)
(config.slot ? 2 : 1)) barrier();
&& config.aborted[mscp_index] == 0xff) barrier();
/* To avoid race conditions, make the code to write to the adapter
atomic. This simplifies the abort code. */
save_flags(flags); /* To avoid race conditions, keep the code to write to the adapter
cli(); atomic. This simplifies the abort code. Right now the
scsi mid layer has the host_lock already held
*/
if (inb(LCL_DOORBELL_INTR(config.doorbell_address)) & if (inb(LCL_DOORBELL_INTR(config.doorbell_address)) & (config.slot ? 2 : 1))
(config.slot ? 2 : 1))
{
restore_flags(flags);
goto retry; goto retry;
}
status = xchgb(0, &config.aborted[mscp_index]); status = xchgb(0, &config.aborted[mscp_index]);
if (status != 0xff) { if (status != 0xff) {
restore_flags(flags);
#if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT) #if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT)
printk("USx4F: queuecommand: aborted\n"); printk("USx4F: queuecommand: aborted\n");
...@@ -811,8 +799,6 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -811,8 +799,6 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
outb(0x1, LCL_DOORBELL_INTR(config.doorbell_address)); outb(0x1, LCL_DOORBELL_INTR(config.doorbell_address));
} }
restore_flags(flags);
#if (ULTRASTOR_DEBUG & UD_COMMAND) #if (ULTRASTOR_DEBUG & UD_COMMAND)
printk("USx4F: queuecommand: returning\n"); printk("USx4F: queuecommand: returning\n");
#endif #endif
...@@ -835,7 +821,7 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -835,7 +821,7 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
*/ */
int ultrastor_abort(Scsi_Cmnd *SCpnt) static int ultrastor_abort(Scsi_Cmnd *SCpnt)
{ {
#if ULTRASTOR_DEBUG & UD_ABORT #if ULTRASTOR_DEBUG & UD_ABORT
char out[108]; char out[108];
...@@ -844,14 +830,16 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) ...@@ -844,14 +830,16 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
#endif #endif
unsigned int mscp_index; unsigned int mscp_index;
unsigned char old_aborted; unsigned char old_aborted;
unsigned long flags;
void (*done)(Scsi_Cmnd *); void (*done)(Scsi_Cmnd *);
struct Scsi_Host *host = SCpnt->host;
if(config.slot) if(config.slot)
return SCSI_ABORT_SNOOZE; /* Do not attempt an abort for the 24f */ return FAILED; /* Do not attempt an abort for the 24f */
/* Simple consistency checking */ /* Simple consistency checking */
if(!SCpnt->host_scribble) if(!SCpnt->host_scribble)
return SCSI_ABORT_NOT_RUNNING; return FAILED;
mscp_index = ((struct mscp *)SCpnt->host_scribble) - config.mscp; mscp_index = ((struct mscp *)SCpnt->host_scribble) - config.mscp;
if (mscp_index >= ULTRASTOR_MAX_CMDS) if (mscp_index >= ULTRASTOR_MAX_CMDS)
...@@ -863,8 +851,8 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) ...@@ -863,8 +851,8 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
int port0 = (config.slot << 12) | 0xc80; int port0 = (config.slot << 12) | 0xc80;
int i; int i;
unsigned long flags; unsigned long flags;
save_flags(flags);
cli(); spin_lock_irqsave(host->host_lock, flags);
strcpy(out, "OGM %d:%x ICM %d:%x ports: "); strcpy(out, "OGM %d:%x ICM %d:%x ports: ");
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
...@@ -879,7 +867,7 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) ...@@ -879,7 +867,7 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
ogm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 23)); ogm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 23));
icm_status = inb(port0 + 27); icm_status = inb(port0 + 27);
icm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 28)); icm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 28));
restore_flags(flags); spin_lock_irqsave(host->host_lock, flags);
} }
/* First check to see if an interrupt is pending. I suspect the SiS /* First check to see if an interrupt is pending. I suspect the SiS
...@@ -888,14 +876,13 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) ...@@ -888,14 +876,13 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
if (config.slot ? inb(config.icm_address - 1) == 2 : if (config.slot ? inb(config.icm_address - 1) == 2 :
(inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1)) (inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1))
{ {
unsigned long flags;
save_flags(flags);
printk("Ux4F: abort while completed command pending\n"); printk("Ux4F: abort while completed command pending\n");
restore_flags(flags);
cli(); spin_lock_irqsave(host->host_lock, flags);
/* FIXME: Ewww... need to think about passing host around properly */
ultrastor_interrupt(0, NULL, NULL); ultrastor_interrupt(0, NULL, NULL);
restore_flags(flags); spin_unlock_irqrestore(host->host_lock, flags);
return SCSI_ABORT_SUCCESS; /* FIXME - is this correct? -ERY */ return SUCCESS;
} }
#endif #endif
...@@ -904,7 +891,7 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) ...@@ -904,7 +891,7 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
/* aborted == 0xff is the signal that queuecommand has not yet sent /* aborted == 0xff is the signal that queuecommand has not yet sent
the command. It will notice the new abort flag and fail. */ the command. It will notice the new abort flag and fail. */
if (old_aborted == 0xff) if (old_aborted == 0xff)
return SCSI_ABORT_SUCCESS; return SUCCESS;
/* On 24F, send an abort MSCP request. The adapter will interrupt /* On 24F, send an abort MSCP request. The adapter will interrupt
and the interrupt handler will call done. */ and the interrupt handler will call done. */
...@@ -912,18 +899,18 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) ...@@ -912,18 +899,18 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
{ {
unsigned long flags; unsigned long flags;
save_flags(flags); spin_lock_irqsave(host->host_lock, flags);
cli();
outl(isa_virt_to_bus(&config.mscp[mscp_index]), config.ogm_address); outl(isa_virt_to_bus(&config.mscp[mscp_index]), config.ogm_address);
inb(0xc80); /* delay */ udelay(8);
outb(0x80, config.ogm_address - 1); outb(0x80, config.ogm_address - 1);
outb(0x2, LCL_DOORBELL_INTR(config.doorbell_address)); outb(0x2, LCL_DOORBELL_INTR(config.doorbell_address));
#if ULTRASTOR_DEBUG & UD_ABORT #if ULTRASTOR_DEBUG & UD_ABORT
log_ultrastor_abort(&config, mscp_index); log_ultrastor_abort(&config, mscp_index);
printk(out, ogm_status, ogm_addr, icm_status, icm_addr); printk(out, ogm_status, ogm_addr, icm_status, icm_addr);
#endif #endif
restore_flags(flags); spin_unlock_irqrestore(host->host_lock, flags);
return SCSI_ABORT_PENDING; /* FIXME: add a wait for the abort to complete */
return SUCCESS;
} }
#if ULTRASTOR_DEBUG & UD_ABORT #if ULTRASTOR_DEBUG & UD_ABORT
...@@ -953,27 +940,30 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) ...@@ -953,27 +940,30 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
done = config.mscp[mscp_index].done; done = config.mscp[mscp_index].done;
config.mscp[mscp_index].done = 0; config.mscp[mscp_index].done = 0;
SCpnt->result = DID_ABORT << 16; SCpnt->result = DID_ABORT << 16;
/* I worry about reentrancy in scsi.c */
/* Take the host lock to guard against scsi layer re-entry */
spin_lock_irqsave(host->host_lock, flags);
done(SCpnt); done(SCpnt);
spin_unlock_irqrestore(host->host_lock, flags);
/* Need to set a timeout here in case command never completes. */ /* Need to set a timeout here in case command never completes. */
return SCSI_ABORT_SUCCESS; return SUCCESS;
} }
int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) static int ultrastor_host_reset(Scsi_Cmnd * SCpnt)
{ {
unsigned long flags; unsigned long flags;
register int i; int i;
struct Scsi_Host *host = SCpnt->host;
#if (ULTRASTOR_DEBUG & UD_RESET) #if (ULTRASTOR_DEBUG & UD_RESET)
printk("US14F: reset: called\n"); printk("US14F: reset: called\n");
#endif #endif
if(config.slot) if(config.slot)
return SCSI_RESET_PUNT; /* Do not attempt a reset for the 24f */ return FAILED;
save_flags(flags);
cli();
spin_lock_irqsave(host->host_lock, flags);
/* Reset the adapter and SCSI bus. The SCSI bus reset can be /* Reset the adapter and SCSI bus. The SCSI bus reset can be
inhibited by clearing ultrastor_bus_reset before probe. */ inhibited by clearing ultrastor_bus_reset before probe. */
outb(0xc0, LCL_DOORBELL_INTR(config.doorbell_address)); outb(0xc0, LCL_DOORBELL_INTR(config.doorbell_address));
...@@ -1005,7 +995,10 @@ int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) ...@@ -1005,7 +995,10 @@ int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
#endif #endif
/* FIXME - if the device implements soft resets, then the command /* FIXME - if the device implements soft resets, then the command
will still be running. ERY */ will still be running. ERY
Even bigger deal with new_eh!
*/
memset((unsigned char *)config.aborted, 0, sizeof config.aborted); memset((unsigned char *)config.aborted, 0, sizeof config.aborted);
#if ULTRASTOR_MAX_CMDS == 1 #if ULTRASTOR_MAX_CMDS == 1
...@@ -1014,7 +1007,7 @@ int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) ...@@ -1014,7 +1007,7 @@ int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
config.mscp_free = ~0; config.mscp_free = ~0;
#endif #endif
restore_flags(flags); spin_unlock_irqrestore(host->host_lock, flags);
return SCSI_RESET_SUCCESS; return SCSI_RESET_SUCCESS;
} }
...@@ -1041,7 +1034,7 @@ static void ultrastor_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1041,7 +1034,7 @@ static void ultrastor_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if ULTRASTOR_MAX_CMDS > 1 #if ULTRASTOR_MAX_CMDS > 1
unsigned int mscp_index; unsigned int mscp_index;
#endif #endif
register struct mscp *mscp; struct mscp *mscp;
void (*done)(Scsi_Cmnd *); void (*done)(Scsi_Cmnd *);
Scsi_Cmnd *SCtmp; Scsi_Cmnd *SCtmp;
......
...@@ -13,13 +13,12 @@ ...@@ -13,13 +13,12 @@
#ifndef _ULTRASTOR_H #ifndef _ULTRASTOR_H
#define _ULTRASTOR_H #define _ULTRASTOR_H
int ultrastor_detect(Scsi_Host_Template *); static int ultrastor_detect(Scsi_Host_Template *);
const char *ultrastor_info(struct Scsi_Host * shpnt); static const char *ultrastor_info(struct Scsi_Host * shpnt);
int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int ultrastor_abort(Scsi_Cmnd *); static int ultrastor_abort(Scsi_Cmnd *);
int ultrastor_reset(Scsi_Cmnd *, unsigned int); static int ultrastor_host_reset(Scsi_Cmnd *);
int ultrastor_biosparam(struct scsi_device *, struct block_device *, static int ultrastor_biosparam(struct scsi_device *, struct block_device *, sector_t, int *);
sector_t, int *);
#define ULTRASTOR_14F_MAX_SG 16 #define ULTRASTOR_14F_MAX_SG 16
...@@ -35,8 +34,8 @@ int ultrastor_biosparam(struct scsi_device *, struct block_device *, ...@@ -35,8 +34,8 @@ int ultrastor_biosparam(struct scsi_device *, struct block_device *,
detect: ultrastor_detect, \ detect: ultrastor_detect, \
info: ultrastor_info, \ info: ultrastor_info, \
queuecommand: ultrastor_queuecommand, \ queuecommand: ultrastor_queuecommand, \
abort: ultrastor_abort, \ eh_abort_handler: ultrastor_abort, \
reset: ultrastor_reset, \ eh_host_reset_handler: ultrastor_host_reset, \
bios_param: ultrastor_biosparam, \ bios_param: ultrastor_biosparam, \
can_queue: ULTRASTOR_MAX_CMDS, \ can_queue: ULTRASTOR_MAX_CMDS, \
this_id: 0, \ this_id: 0, \
......
...@@ -1240,7 +1240,7 @@ static int wd7000_adapter_reset(Adapter * host) ...@@ -1240,7 +1240,7 @@ static int wd7000_adapter_reset(Adapter * host)
host->control = 0; /* this must always shadow ASC_CONTROL */ host->control = 0; /* this must always shadow ASC_CONTROL */
if (WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { if (WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) {
printk("wd7000_init: WAIT timed out.\n"); printk(KERN_ERR "wd7000_init: WAIT timed out.\n");
return -1; /* -1 = not ok */ return -1; /* -1 = not ok */
} }
...@@ -1249,25 +1249,25 @@ static int wd7000_adapter_reset(Adapter * host) ...@@ -1249,25 +1249,25 @@ static int wd7000_adapter_reset(Adapter * host)
switch (diag) { switch (diag) {
case 2: case 2:
printk("RAM failure.\n"); printk(KERN_ERR "RAM failure.\n");
break; break;
case 3: case 3:
printk("FIFO R/W failed\n"); printk(KERN_ERR "FIFO R/W failed\n");
break; break;
case 4: case 4:
printk("SBIC register R/W failed\n"); printk(KERN_ERR "SBIC register R/W failed\n");
break; break;
case 5: case 5:
printk("Initialization D-FF failed.\n"); printk(KERN_ERR "Initialization D-FF failed.\n");
break; break;
case 6: case 6:
printk("Host IRQ D-FF failed.\n"); printk(KERN_ERR "Host IRQ D-FF failed.\n");
break; break;
case 7: case 7:
printk("ROM checksum error.\n"); printk(KERN_ERR "ROM checksum error.\n");
break; break;
default: default:
printk("diagnostic code 0x%02Xh received.\n", diag); printk(KERN_ERR "diagnostic code 0x%02Xh received.\n", diag);
} }
return -1; return -1;
} }
......
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
#ifdef CONFIG_FS_EXT_ATTR #ifdef CONFIG_FS_EXT_ATTR
# include <linux/ext_attr.h> # include <linux/ext_attr.h>
# ifdef CONFIG_FS_POSIX_ACL # if 0 /* was a broken check for Posix ACLs */
# include <linux/posix_acl.h> # include <linux/posix_acl.h>
# endif # endif
#endif #endif
...@@ -466,7 +466,7 @@ int lento_setattr(const char *name, struct iattr *iattr, ...@@ -466,7 +466,7 @@ int lento_setattr(const char *name, struct iattr *iattr,
struct dentry *dentry; struct dentry *dentry;
struct presto_file_set *fset; struct presto_file_set *fset;
int error; int error;
#ifdef CONFIG_FS_POSIX_ACL #if 0 /* was a broken check for Posix ACLs */
int (*set_posix_acl)(struct inode *, int type, posix_acl_t *)=NULL; int (*set_posix_acl)(struct inode *, int type, posix_acl_t *)=NULL;
#endif #endif
...@@ -507,7 +507,7 @@ int lento_setattr(const char *name, struct iattr *iattr, ...@@ -507,7 +507,7 @@ int lento_setattr(const char *name, struct iattr *iattr,
(dentry->d_inode->i_mode & ~S_IALLUGO); (dentry->d_inode->i_mode & ~S_IALLUGO);
CDEBUG(D_PIOCTL, "chmod: orig %#o, set %#o, result %#o\n", CDEBUG(D_PIOCTL, "chmod: orig %#o, set %#o, result %#o\n",
dentry->d_inode->i_mode, set_mode, iattr->ia_mode); dentry->d_inode->i_mode, set_mode, iattr->ia_mode);
#ifdef CONFIG_FS_POSIX_ACL #if 0 /* was a broken check for Posix ACLs */
/* ACl code interacts badly with setattr /* ACl code interacts badly with setattr
* since it tries to modify the ACL using * since it tries to modify the ACL using
* set_ext_attr which recurses back into presto. * set_ext_attr which recurses back into presto.
...@@ -535,7 +535,7 @@ int lento_setattr(const char *name, struct iattr *iattr, ...@@ -535,7 +535,7 @@ int lento_setattr(const char *name, struct iattr *iattr,
} }
} }
#ifdef CONFIG_FS_POSIX_ACL #if 0 /* was a broken check for Posix ACLs */
/* restore the inode_operations if we changed them*/ /* restore the inode_operations if we changed them*/
if (iattr->ia_valid & ATTR_MODE) if (iattr->ia_valid & ATTR_MODE)
dentry->d_inode->i_op->set_posix_acl=set_posix_acl; dentry->d_inode->i_op->set_posix_acl=set_posix_acl;
...@@ -2252,7 +2252,7 @@ int lento_iopen(const char *name, ino_t ino, unsigned int generation, ...@@ -2252,7 +2252,7 @@ int lento_iopen(const char *name, ino_t ino, unsigned int generation,
#ifdef CONFIG_FS_EXT_ATTR #ifdef CONFIG_FS_EXT_ATTR
#ifdef CONFIG_FS_POSIX_ACL #if 0 /* was a broken check for Posix ACLs */
/* Posix ACL code changes i_mode without using a notify_change (or /* Posix ACL code changes i_mode without using a notify_change (or
* a mark_inode_dirty!). We need to duplicate this at the reintegrator * a mark_inode_dirty!). We need to duplicate this at the reintegrator
* which is done by this function. This function also takes care of * which is done by this function. This function also takes care of
...@@ -2395,7 +2395,7 @@ int presto_do_set_ext_attr(struct presto_file_set *fset, ...@@ -2395,7 +2395,7 @@ int presto_do_set_ext_attr(struct presto_file_set *fset,
goto exit; goto exit;
} }
#ifdef CONFIG_FS_POSIX_ACL #if 0 /* was a broken check for Posix ACLs */
/* Reset mode if specified*/ /* Reset mode if specified*/
/* XXX: when we do native acl support, move this code out! */ /* XXX: when we do native acl support, move this code out! */
if (mode != NULL) { if (mode != NULL) {
......
...@@ -1401,6 +1401,7 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l) ...@@ -1401,6 +1401,7 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l)
inode = filp->f_dentry->d_inode; inode = filp->f_dentry->d_inode;
#ifdef CONFIG_MMU
/* Don't allow mandatory locks on files that may be memory mapped /* Don't allow mandatory locks on files that may be memory mapped
* and shared. * and shared.
*/ */
...@@ -1413,6 +1414,7 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l) ...@@ -1413,6 +1414,7 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l)
goto out; goto out;
} }
} }
#endif
error = flock_to_posix_lock(filp, file_lock, &flock); error = flock_to_posix_lock(filp, file_lock, &flock);
if (error) if (error)
......
...@@ -96,8 +96,8 @@ int vfs_fstat(unsigned int fd, struct kstat *stat) ...@@ -96,8 +96,8 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
} }
#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) \ #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) \
&& !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) \ && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) \
&& !defined(__arm__) && !defined(__arm__) && !defined(CONFIG_V850)
/* /*
* For backward compatibility? Maybe this should be moved * For backward compatibility? Maybe this should be moved
......
...@@ -19,4 +19,8 @@ struct timer_opts{ ...@@ -19,4 +19,8 @@ struct timer_opts{
#define TICK_SIZE (tick_nsec / 1000) #define TICK_SIZE (tick_nsec / 1000)
extern struct timer_opts* select_timer(void); extern struct timer_opts* select_timer(void);
/* Modifiers for buggy PIT handling */
extern int pit_latch_buggy;
#endif #endif
...@@ -17,8 +17,8 @@ config CRC32 ...@@ -17,8 +17,8 @@ config CRC32
# #
config ZLIB_INFLATE config ZLIB_INFLATE
tristate tristate
default m if CRAMFS!=y && PPP_DEFLATE!=y && JFFS2_FS!=y && ZISOFS_FS!=y && (CRAMFS=m || PPP_DEFLATE=m || JFFS2_FS=m || ZISOFS_FS=m) default y if CRAMFS=y || PPP_DEFLATE=y || JFFS2_FS=y || ZISOFS_FS=y || BINFMT_ZFLAT=y
default y if CRAMFS=y || PPP_DEFLATE=y || JFFS2_FS=y || ZISOFS_FS=y default m if CRAMFS=m || PPP_DEFLATE=m || JFFS2_FS=m || ZISOFS_FS=m || BINFMT_ZFLAT=m
config ZLIB_DEFLATE config ZLIB_DEFLATE
tristate tristate
......
...@@ -11,6 +11,6 @@ $(obj)/initramfs_data.o: $(src)/initramfs_data.scr $(obj)/initramfs_data.cpio.gz ...@@ -11,6 +11,6 @@ $(obj)/initramfs_data.o: $(src)/initramfs_data.scr $(obj)/initramfs_data.cpio.gz
$(call if_changed,ld) $(call if_changed,ld)
$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio
( cd $(obj) ; ./$< | gzip -9c > $@ ) ./$< | gzip -9c > $@
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