Commit d68780fb authored by Jeff Garzik's avatar Jeff Garzik

Merge redhat.com:/home/jgarzik/repo/linus-2.5

into redhat.com:/home/jgarzik/repo/net-drivers-2.5
parents c5265e0f eb0ad91a
......@@ -12,7 +12,7 @@ NM := $(NM) -B
LDFLAGS_vmlinux = -static -N #-relax
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.
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
.init.ramfs ALIGN(8192): {
__initramfs_start = .;
*(.init.initramfs)
*(.init.ramfs)
__initramfs_end = .;
}
......
......@@ -337,7 +337,6 @@ config PREEMPT
config X86_UP_APIC
bool "Local APIC support on uniprocessors" if !SMP
default y if SMP
---help---
A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU
......@@ -447,7 +446,7 @@ config X86_MCE
the 386 and 486, so nearly everyone can say Y here.
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
help
Enabling this feature starts a timer that triggers every 5 seconds which
......@@ -456,12 +455,12 @@ config X86_MCE_NONFATAL
Disable this if you don't want to see these messages.
Seeing the messages this option prints out may be indicative of dying hardware,
or out-of-spec (ie, overclocked) hardware.
This option only does something on hardware with Intel P6 style MCE.
(Pentium Pro and above, AMD Athlon/Duron)
This option only does something on certain CPUs.
(AMD Athlon/Duron and Intel Pentium 4)
config X86_MCE_P4THERMAL
bool "check for P4 thermal throttling interrupt."
depends on X86_MCE && X86_UP_APIC
depends on X86_MCE && (X86_UP_APIC || SMP)
help
Enabling this feature will cause a message to be printed when the P4
enters thermal throttling.
......
......@@ -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_MWINCHIP2) += $(call check_gcc,-march=winchip2,-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)
......
......@@ -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 \
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 \
bootflag.o
pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o
obj-y += cpu/
obj-y += timers/
......
......@@ -13,7 +13,10 @@ obj-y += rise.o
obj-y += nexgen.o
obj-y += umc.o
obj-$(CONFIG_X86_MCE) += mcheck/
obj-$(CONFIG_MTRR) += mtrr/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
include $(TOPDIR)/Rules.make
......@@ -358,7 +358,9 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
boot_cpu_data.x86_capability[3]);
/* Init Machine Check Exception if available. */
#ifdef CONFIG_X86_MCE
mcheck_init(c);
#endif
}
/*
* Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
......
......@@ -5,6 +5,7 @@
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/timer.h>
#include "cpu.h"
......@@ -170,7 +171,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
c->coma_bug = 1;
break;
case 4: /* MediaGX/GXm */
case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
#ifdef CONFIG_PCI
/* It isn't really a PCI quirk directly, but the cure is 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)
isa_dma_bridge_buggy = 2;
#endif
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 */
if (c->cpuid_level == 2) {
/* Enable Natsemi MMX extensions */
setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1);
/* Enable cxMMX extensions (GX1 Datasheet 54) */
setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
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;
}
else { /* MediaGX */
Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
p = Cx86_cb+2;
c->x86_model = (dir1 & 0x20) ? 1 : 2;
#ifndef CONFIG_CS5520
clear_bit(X86_FEATURE_TSC, c->x86_capability);
#endif
}
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/types.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/smp.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 <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 */
struct intel_mce_extended_msrs {
......@@ -37,17 +32,16 @@ struct intel_mce_extended_msrs {
/* u32 *reserved[]; */
};
static int mce_disabled __initdata = 0;
static int mce_num_extended_msrs = 0;
static int banks;
#ifdef CONFIG_X86_MCE_P4THERMAL
/*
* P4/Xeon Thermal transition interrupt handler
*/
static void unexpected_thermal_interrupt(struct pt_regs *regs)
{
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)
{
u32 l, h;
......@@ -55,7 +49,7 @@ static void intel_thermal_interrupt(struct pt_regs *regs)
ack_APIC_irq();
rdmsr(MSR_IA32_THERM_STATUS, l, h);
rdmsr (MSR_IA32_THERM_STATUS, l, h);
if (l & 1) {
printk(KERN_EMERG "CPU#%d: Temperature above threshold\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)
}
}
static void unexpected_thermal_interrupt(struct pt_regs *regs)
{
printk(KERN_ERR "CPU#%d: Unexpected LVT TMR interrupt!\n", smp_processor_id());
}
/*
* Thermal interrupt handler for this CPU setup
*/
/* Thermal interrupt handler for this CPU setup */
static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt;
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 */
static void __init intel_init_thermal(struct cpuinfo_x86 *c)
{
u32 l, h;
......@@ -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
* 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);
if ((l & (1<<3)) && (h & APIC_DM_SMI)) {
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)
h |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */
apic_write_around(APIC_LVTTHMR, h);
rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03 , h);
rdmsr (MSR_IA32_THERM_INTERRUPT, l, h);
wrmsr (MSR_IA32_THERM_INTERRUPT, l | 0x03 , h);
/* ok we're good to go... */
vendor_thermal_interrupt = intel_thermal_interrupt;
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h);
rdmsr (MSR_IA32_MISC_ENABLE, l, h);
wrmsr (MSR_IA32_MISC_ENABLE, l | (1<<3), h);
l = apic_read(APIC_LVTTHMR);
apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
printk(KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu);
l = apic_read (APIC_LVTTHMR);
apic_write_around (APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
printk (KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu);
return;
}
#endif /* CONFIG_X86_MCE_P4THERMAL */
/* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */
static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
{
u32 h;
......@@ -146,16 +130,16 @@ static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
if (mce_num_extended_msrs == 0)
goto done;
rdmsr(MSR_IA32_MCG_EAX, r->eax, h);
rdmsr(MSR_IA32_MCG_EBX, r->ebx, h);
rdmsr(MSR_IA32_MCG_ECX, r->ecx, h);
rdmsr(MSR_IA32_MCG_EDX, r->edx, h);
rdmsr(MSR_IA32_MCG_ESI, r->esi, h);
rdmsr(MSR_IA32_MCG_EDI, r->edi, h);
rdmsr(MSR_IA32_MCG_EBP, r->ebp, h);
rdmsr(MSR_IA32_MCG_ESP, r->esp, h);
rdmsr(MSR_IA32_MCG_EFLAGS, r->eflags, h);
rdmsr(MSR_IA32_MCG_EIP, r->eip, h);
rdmsr (MSR_IA32_MCG_EAX, r->eax, h);
rdmsr (MSR_IA32_MCG_EBX, r->ebx, h);
rdmsr (MSR_IA32_MCG_ECX, r->ecx, h);
rdmsr (MSR_IA32_MCG_EDX, r->edx, h);
rdmsr (MSR_IA32_MCG_ESI, r->esi, h);
rdmsr (MSR_IA32_MCG_EDI, r->edi, h);
rdmsr (MSR_IA32_MCG_EBP, r->ebp, h);
rdmsr (MSR_IA32_MCG_ESP, r->esp, h);
rdmsr (MSR_IA32_MCG_EFLAGS, r->eflags, h);
rdmsr (MSR_IA32_MCG_EIP, r->eip, h);
/* can we rely on kmalloc to do a dynamic
* allocation for the reserved registers?
......@@ -164,10 +148,6 @@ static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
return mce_num_extended_msrs;
}
/*
* Machine Check Handler For PII/PIII
*/
static void intel_machine_check(struct pt_regs * regs, long error_code)
{
int recover=1;
......@@ -176,329 +156,106 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
int i;
struct intel_mce_extended_msrs dbg;
rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
if(mcgstl&(1<<0)) /* Recoverable ? */
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);
printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
smp_processor_id(), mcgsth, mcgstl);
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);
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);
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);
}
for (i=0;i<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);
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);
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();
printk ("\n");
}
}
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);
}
/*
* 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);
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++) {
u32 msr;
msr = MSR_IA32_MC0_STATUS+i*4;
rdmsr (msr, low, high);
if (high&(1<<31)) {
/* Clear it */
wrmsr(msr, 0UL, 0UL);
/* Serialize */
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);
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)
void __init intel_p4_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
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;
wmb();
if(done==0)
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);
banks = l&0xff;
/* Don't enable bank 0 on intel P6 cores, it goes bang quickly. */
if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 == 6) {
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);
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);
}
for(i=0; i<banks; i++)
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());
set_in_cr4(X86_CR4_MCE);
printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
/* 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);
/*
* 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
/* Check for P4/Xeon Thermal monitor */
intel_init_thermal(c);
#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
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");
}
init_nonfatal_mce_checker();
#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)
pushl $do_page_fault
jmp error_code
#ifdef CONFIG_X86_MCE
ENTRY(machine_check)
pushl $0
pushl $do_machine_check
jmp error_code
#endif
ENTRY(spurious_interrupt_bug)
pushl $0
......
......@@ -61,6 +61,7 @@
#include <asm/arch_hooks.h>
extern spinlock_t i8259A_lock;
int pit_latch_buggy; /* extern */
#include "do_timer.h"
......
......@@ -60,6 +60,8 @@ static unsigned long get_offset_tsc(void)
static void mark_offset_tsc(void)
{
int count;
int countmp;
static int count1=0, count2=LATCH;
/*
* It is important that these two operations happen almost at
* the same time. We do the RDTSC stuff first, since it's
......@@ -83,6 +85,20 @@ static void mark_offset_tsc(void)
count |= inb(0x40) << 8;
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;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
}
......@@ -111,10 +127,12 @@ static unsigned long __init calibrate_tsc(void)
* Set the Gate high, program CTC channel 2 for mode 0,
* (interrupt on terminal count mode), binary count,
* 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(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
outb_p(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
outb_p(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
{
unsigned long startlow, starthigh;
......@@ -238,8 +256,6 @@ static int init_tsc(void)
* moaned if you have the only one in the world - you fix it!
*/
dodgy_tsc();
if (cpu_has_tsc) {
unsigned long tsc_quotient = calibrate_tsc();
if (tsc_quotient) {
......
......@@ -906,7 +906,9 @@ void __init trap_init(void)
set_trap_gate(15,&spurious_interrupt_bug);
set_trap_gate(16,&coprocessor_error);
set_trap_gate(17,&alignment_check);
#ifdef CONFIG_X86_MCE
set_trap_gate(18,&machine_check);
#endif
set_trap_gate(19,&simd_coprocessor_error);
set_system_gate(SYSCALL_VECTOR,&system_call);
......
......@@ -3139,12 +3139,12 @@ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt)
*/
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44)
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
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[])
{
sector_t capacy = disk->capacity;
sector_t capacity = disk->capacity;
#endif
int heads, sectors, cylinders;
......
......@@ -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 const char *sbp2scsi_info (struct Scsi_Host *host);
void sbp2scsi_setup(char *str, int *ints);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28)
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44)
static int sbp2scsi_biosparam (struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int geom[]);
#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
static int sbp2scsi_abort (Scsi_Cmnd *SCpnt);
static int sbp2scsi_reset (Scsi_Cmnd *SCpnt);
......
......@@ -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 {
unsigned char value;
const char *name;
......@@ -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);
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(INITIATOR_COMMAND_REG, ICR_BASE);
......@@ -1026,11 +1074,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
case 5:
printk(KERN_INFO "scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no);
timeout = jiffies + 5 * HZ;
while (time_before(jiffies, timeout) && (NCR5380_read(STATUS_REG) & SR_BSY))
{
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, 0, 5*HZ);
break;
case 2:
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)
* twiddling done to the host specific fields of cmd. If the
* main coroutine is not running, it is restarted.
*
* Locks: host lock taken by caller. Called functions drop and
* retake this lock. Called functions take dma lock.
* Locks: host lock taken by caller
*/
static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
......@@ -1164,7 +1207,8 @@ static void NCR5380_main(void *p)
instance = hostdata->host;
spin_lock_irqsave(instance->host_lock, flags);
if(instance->irq != IRQ_NONE)
spin_lock_irqsave(instance->host_lock, flags);
do {
/* Lock held here */
......@@ -1243,12 +1287,9 @@ static void NCR5380_main(void *p)
do not respond to commands immediately
after a scan */
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);
tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
hostdata->issue_queue = tmp;
//spin_unlock_irq(&io_request_lock);
hostdata->time_expires = jiffies + USLEEP_WAITLONG;
NCR5380_set_timer(instance);
}
......@@ -1267,7 +1308,8 @@ static void NCR5380_main(void *p)
break;
} 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
......@@ -1341,24 +1383,9 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
hostdata->dmalen = 0;
(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 */
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK)
cpu_relax();
#endif
/* FIXME: we need to poll briefly then defer a workqueue task ! */
NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2*HZ);
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
......@@ -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
* 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)
......@@ -1451,8 +1478,11 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
unsigned long timeout;
unsigned char value;
NCR5380_setup(instance);
int err;
if (hostdata->selecting) {
if(instance->irq != IRQ_NONE)
spin_unlock_irq(instance->host_lock);
goto part2; /* RvC: sorry prof. Dijkstra, but it keeps the
rest of the code nearly the same */
}
......@@ -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(MODE_REG, MR_ARBITRATE);
/* Wait for arbitration logic to complete */
#if NCR_TIMEOUT
{
unsigned long timeout = jiffies + 2 * NCR_TIMEOUT;
if(instance->irq != IRQ_NONE)
spin_unlock_irq(instance->host_lock);
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
&& time_before(jiffies, timeout))
cpu_relax();
/* We can be relaxed here, interrupts are on, we are
in workqueue context, the birds are singing in the trees */
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);
if (time_after_eq(jiffies, timeout)) {
printk("scsi: arbitration timeout at %d\n", __LINE__);
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1;
}
if (err < 0) {
printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__);
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
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));
......@@ -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)) {
NCR5380_write(MODE_REG, MR_BASE);
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);
......@@ -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(INITIATOR_COMMAND_REG, ICR_BASE);
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
......@@ -1613,8 +1636,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
we poll only once ech clock tick */
value = NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO);
/* FIXME HZ=100 assumption ? */
if (!value && (hostdata->select_time < 25)) {
if (!value && (hostdata->select_time < HZ/4)) {
/* RvC: we still must wait for a device response */
hostdata->select_time++; /* after 25 ticks the device has failed */
hostdata->time_expires = jiffies + 1;
......@@ -1627,6 +1649,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
waiting period */
if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
if(instance->irq != IRQ_NONE)
spin_lock_irq(instance->host_lock);
NCR5380_reselect(instance);
printk("scsi%d : reselection after won arbitration?\n", instance->host_no);
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)
if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
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)
printk("\trestart select\n");
printk(KERN_DEBUG "\trestart select\n");
NCR5380_dprint(NDEBUG_SELECTION, instance);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1;
}
if(instance->irq != IRQ_NONE)
spin_lock_irq(instance->host_lock);
cmd->result = DID_BAD_TARGET << 16;
collect_stats(hostdata, cmd);
cmd->scsi_done(cmd);
......@@ -1678,29 +1704,21 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
*/
/* Wait for start of REQ/ACK handshake */
#ifdef NCR_TIMEOUT
{
unsigned long timeout = jiffies + NCR_TIMEOUT;
spin_unlock_irq(instance->host_lock);
while (!(NCR5380_read(STATUS_REG) & SR_REQ) && 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", instance->host_no, __LINE__);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1;
}
err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
if(err)
{ printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
goto failed;
}
#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));
tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun);
if(instance->irq != IRQ_NONE)
spin_lock_irq(instance->host_lock);
len = 1;
cmd->tag = 0;
......@@ -1717,6 +1735,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
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
* if breaking is not allowed, we keep polling as long as needed
*/
/* FIXME */
while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed);
if (!(tmp & SR_REQ)) {
/* timeout condition */
......@@ -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);
}
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));
/*
......@@ -1905,8 +1931,9 @@ static void do_reset(struct Scsi_Host *host) {
static int do_abort(struct Scsi_Host *host) {
NCR5380_local_declare();
unsigned char tmp, *msgptr, phase;
unsigned char *msgptr, phase, tmp;
int len;
int rc;
NCR5380_setup(host);
......@@ -1923,15 +1950,21 @@ static int do_abort(struct Scsi_Host *host) {
* the target sees, so we just handshake.
*/
while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ)
cpu_relax();
rc = NCR5380_poll_politely(host, STATUS_REG, SR_REQ, SR_REQ, 60 * HZ);
if(rc < 0)
return -1;
tmp = (unsigned char)rc;
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
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);
if(rc == -1)
return -1;
}
tmp = ABORT;
msgptr = &tmp;
......@@ -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
* 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) {
......@@ -2503,7 +2536,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
/* Enable reselect interrupts */
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)
barrier();
return;
......@@ -2658,7 +2692,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
*
* 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) {
......@@ -2696,16 +2730,19 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
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);
/*
* 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))
cpu_relax();
if(NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 2*HZ))
abort = 1;
len = 1;
data = msg;
......@@ -2713,7 +2750,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
NCR5380_transfer_pio(instance, &phase, &len, &data);
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);
abort = 1;
} else {
......@@ -2747,7 +2784,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
break;
}
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,
* we must abort it.
......@@ -2790,9 +2827,11 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
*
* We should use the Last Byte Sent bit, unfortunately this is
* 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(INITIATOR_COMMAND_REG, ICR_BASE);
......@@ -2827,21 +2866,15 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
* a problem, we could implement longjmp() / setjmp(), setjmp()
* called where the loop started in NCR5380_main().
*
* Locks: host lock taken by function
* Locks: host lock taken by caller
*/
#ifndef NCR5380_abort
static
#endif
int NCR5380_abort(Scsi_Cmnd * cmd) {
static int NCR5380_abort(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
struct Scsi_Host *instance = cmd->host;
unsigned long flags;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
Scsi_Cmnd *tmp, **prev;
spin_lock_irqsave(instance->host_lock, flags);
printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no);
print_Scsi_Cmnd(cmd);
......@@ -2884,7 +2917,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* aborted flag and get back into our main loop.
*/
spin_unlock_irqrestore(instance->host_lock, flags);
return 0;
}
#endif
......@@ -2894,8 +2926,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* 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));
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) {
......@@ -2905,7 +2935,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
tmp->result = DID_ABORT << 16;
dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
tmp->done(tmp);
spin_unlock_irqrestore(instance->host_lock, flags);
return SUCCESS;
}
#if (NDEBUG & NDEBUG_ABORT)
......@@ -2927,7 +2956,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
if (hostdata->connected) {
dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no));
spin_unlock_irqrestore(instance->host_lock, flags);
return FAILED;
}
/*
......@@ -2972,7 +3000,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
tmp->host_scribble = NULL;
tmp->result = DID_ABORT << 16;
tmp->done(tmp);
spin_unlock_irqrestore(instance->host_lock, flags);
return SUCCESS;
}
}
......@@ -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
* broke.
*/
spin_unlock_irqrestore(instance->host_lock, flags);
printk(KERN_WARNING "scsi%d : warning : SCSI command probably completed successfully\n"
" before abortion\n", instance->host_no);
return FAILED;
......@@ -2999,22 +3025,15 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
*
* Returns : SUCCESS
*
* Locks: host lock taken by function
* Locks: host lock taken by caller
*/
#ifndef NCR5380_bus_reset
static
#endif
int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
unsigned long flags;
struct Scsi_Host *instance = cmd->host;
static int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
NCR5380_setup(cmd->host);
spin_lock_irqsave(instance->host_lock, flags);
NCR5380_print_status(cmd->host);
do_reset(cmd->host);
spin_unlock_irqrestore(instance->host_lock, flags);
return SUCCESS;
}
......@@ -3028,12 +3047,7 @@ int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
* Locks: io_request_lock held by caller
*/
#ifndef NCR5380_device_reset
static
#endif
int NCR5380_device_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
NCR5380_setup(cmd->host);
static int NCR5380_device_reset(Scsi_Cmnd * cmd) {
return FAILED;
}
......@@ -3047,11 +3061,6 @@ int NCR5380_device_reset(Scsi_Cmnd * cmd) {
* Locks: io_request_lock held by caller
*/
#ifndef NCR5380_host_reset
static
#endif
int NCR5380_host_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
NCR5380_setup(cmd->host);
static int NCR5380_host_reset(Scsi_Cmnd * cmd) {
return FAILED;
}
......@@ -677,22 +677,6 @@ static void wait_intr(void)
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 *))
{
int i;
......@@ -726,6 +710,21 @@ static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
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)
{
DEB(printk("NCR53c406a_abort called\n"));
......@@ -755,7 +754,7 @@ static int NCR53c406a_bus_reset(Scsi_Cmnd * SCpnt)
return FAILED;
}
static int NCR53c406a_biosparm(struct scsi_disk *disk,
static int NCR53c406a_biosparm(struct scsi_device *disk,
struct block_device *dev,
sector_t capacity, int *info_array)
{
......@@ -1065,8 +1064,30 @@ static void __init calc_port_addr(void)
MODULE_LICENSE("GPL");
/* Eventually this will go into an include file, but this will be later */
static Scsi_Host_Template driver_template = NCR53c406a;
/* NOTE: scatter-gather support only works in PIO mode.
* 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"
......
#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 @@
*
* aha1740_makecode may still need even more work
* 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>
......@@ -68,7 +76,7 @@ static spinlock_t aha1740_lock = SPIN_LOCK_UNLOCKED;
/* One for each IRQ level (9-15) */
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 len;
......@@ -76,7 +84,7 @@ int aha1740_proc_info(char *buffer, char **start, off_t offset,
struct aha1740_hostdata *host;
if (inout)
return(-ENOSYS);
return-ENOSYS;
for (len = 0; len < 8; len++) {
shpnt = aha_host[len];
......@@ -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
{
......@@ -179,7 +187,7 @@ int aha1740_makecode(unchar *sense, unchar *status)
return status[3] | retval << 16;
}
int aha1740_test_port(unsigned int base)
static int aha1740_test_port(unsigned int base)
{
char name[4], tmp;
......@@ -212,7 +220,7 @@ int aha1740_test_port(unsigned int base)
}
/* 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];
void (*my_done)(Scsi_Cmnd *);
......@@ -303,7 +311,7 @@ void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
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 *cmd = (unchar *) SCpnt->cmnd;
......@@ -317,16 +325,6 @@ int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
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;
done(SCpnt);
return 0;
......@@ -486,7 +484,7 @@ static void internal_done(Scsi_Cmnd * SCpnt)
SCpnt->SCp.Status++;
}
int aha1740_command(Scsi_Cmnd * SCpnt)
static int aha1740_command(Scsi_Cmnd * SCpnt)
{
aha1740_queuecommand(SCpnt, internal_done);
SCpnt->SCp.Status = 0;
......@@ -501,7 +499,7 @@ int aha1740_command(Scsi_Cmnd * SCpnt)
/* Query the board for its irq_level. Nothing else matters
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)
{
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,
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;
......@@ -540,8 +538,8 @@ int aha1740_detect(Scsi_Host_Template * tpnt)
outb(G2CNTRL_HRST, G2CNTRL(slotbase));
outb(0, G2CNTRL(slotbase));
}
printk("Configuring aha174x at IO:%x, IRQ %d\n", slotbase, irq_level);
printk("aha174x: Extended translation %sabled.\n",
printk(KERN_INFO "Configuring aha174x at IO:%x, IRQ %d\n", slotbase, irq_level);
printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
translation ? "en" : "dis");
DEB(printk("aha1740_detect: enable interrupt channel %d\n",irq_level));
if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",NULL)) {
......@@ -572,31 +570,7 @@ int aha1740_detect(Scsi_Host_Template * tpnt)
return count;
}
/* Note: They following two functions do not apply very well to the Adaptec,
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,
static int aha1740_biosparam(struct scsi_device *sdev, struct block_device *dev,
sector_t capacity, int* ip)
{
int size = capacity;
......
......@@ -13,8 +13,8 @@
#include <linux/types.h>
/* 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 MAXEISA 8 /* Just took my machine's specifications. Adjust to fit.*/
#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. */
/* I just saw an ad, and bumped this from 6 to 8 */
#define SLOTBASE(x) ((x << 12) + 0xc80)
#define SLOTSIZE 0x5c
......@@ -75,14 +75,14 @@
#define ATTN_START 0x40 /* Start CCB */
#define ATTN_ABORT 0x50 /* Abort CCB */
#define G2CNTRL_HRST 0x80 /* Hard Reset */
#define G2CNTRL_IRST 0x40 /* Clear EISA Interrupt */
#define G2CNTRL_HRDY 0x20 /* Sets HOST ready */
#define G2CNTRL_HRST 0x80 /* Hard Reset */
#define G2CNTRL_IRST 0x40 /* Clear EISA Interrupt */
#define G2CNTRL_HRDY 0x20 /* Sets HOST ready */
/* This is used with scatter-gather */
struct aha1740_chain {
u32 dataptr; /* Location of data */
u32 datalen; /* Size of this part of chain */
u32 dataptr; /* Location of data */
u32 datalen; /* Size of this part of chain */
};
/* These belong in scsi.h */
......@@ -107,40 +107,40 @@ struct aha1740_chain {
#define MAX_STATUS 32
struct ecb { /* Enhanced Control Block 6.1 */
u16 cmdw; /* Command Word */
/* Flag Word 1 */
u16 cne:1, /* Control Block Chaining */
:6, di:1, /* Disable Interrupt */
:2, ses:1, /* Suppress Underrun error */
:1, sg:1, /* Scatter/Gather */
:1, dsb:1, /* Disable Status Block */
ars:1; /* Automatic Request Sense */
/* Flag Word 2 */
u16 lun:3, /* Logical Unit */
tag:1, /* Tagged Queuing */
tt:2, /* Tag Type */
nd:1, /* No Disconnect */
:1, dat:1, /* Data transfer - check direction */
dir:1, /* Direction of transfer 1 = datain */
st:1, /* Suppress Transfer */
chk:1, /* Calculate Checksum */
:2, rec:1, :1; /* Error Recovery */
u16 nil0; /* nothing */
u32 dataptr; /* Data or Scatter List ptr */
u32 datalen; /* Data or Scatter List len */
u32 statusptr; /* Status Block ptr */
u32 linkptr; /* Chain Address */
u32 nil1; /* nothing */
u32 senseptr; /* Sense Info Pointer */
u8 senselen; /* Sense Length */
u8 cdblen; /* CDB Length */
u16 datacheck; /* Data checksum */
u8 cdb[MAX_CDB]; /* CDB area */
u16 cmdw; /* Command Word */
/* Flag Word 1 */
u16 cne:1, /* Control Block Chaining */
:6, di:1, /* Disable Interrupt */
:2, ses:1, /* Suppress Underrun error */
:1, sg:1, /* Scatter/Gather */
:1, dsb:1, /* Disable Status Block */
ars:1; /* Automatic Request Sense */
/* Flag Word 2 */
u16 lun:3, /* Logical Unit */
tag:1, /* Tagged Queuing */
tt:2, /* Tag Type */
nd:1, /* No Disconnect */
:1, dat:1, /* Data transfer - check direction */
dir:1, /* Direction of transfer 1 = datain */
st:1, /* Suppress Transfer */
chk:1, /* Calculate Checksum */
:2, rec:1,:1; /* Error Recovery */
u16 nil0; /* nothing */
u32 dataptr; /* Data or Scatter List ptr */
u32 datalen; /* Data or Scatter List len */
u32 statusptr; /* Status Block ptr */
u32 linkptr; /* Chain Address */
u32 nil1; /* nothing */
u32 senseptr; /* Sense Info Pointer */
u8 senselen; /* Sense Length */
u8 cdblen; /* CDB Length */
u16 datacheck; /* Data checksum */
u8 cdb[MAX_CDB]; /* CDB area */
/* Hardware defined portion ends here, rest is driver defined */
u8 sense[MAX_SENSE]; /* Sense area */
u8 status[MAX_STATUS]; /* Status area */
Scsi_Cmnd *SCpnt; /* Link to the SCSI Command Block */
void (*done)(Scsi_Cmnd *); /* Completion Function */
u8 sense[MAX_SENSE]; /* Sense area */
u8 status[MAX_STATUS]; /* Status area */
Scsi_Cmnd *SCpnt; /* Link to the SCSI Command Block */
void (*done) (Scsi_Cmnd *); /* Completion Function */
};
#define AHA1740CMD_NOP 0x00 /* No OP */
......@@ -152,32 +152,22 @@ struct ecb { /* Enhanced Control Block 6.1 */
#define AHA1740CMD_RINQ 0x0a /* Read Host Adapter Inquiry Data */
#define AHA1740CMD_TARG 0x10 /* Target SCSI Command */
int aha1740_detect(Scsi_Host_Template *);
int aha1740_command(Scsi_Cmnd *);
int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int aha1740_abort(Scsi_Cmnd *);
int aha1740_reset(Scsi_Cmnd *, unsigned int);
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);
static int aha1740_detect(Scsi_Host_Template *);
static int aha1740_command(Scsi_Cmnd *);
static int aha1740_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int aha1740_biosparam(struct scsi_device *, struct block_device *, sector_t, int *);
static int aha1740_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout);
#define AHA1740_ECBS 32
#define AHA1740_SCATTER 16
#define AHA1740_CMDLUN 1
#ifndef NULL
#define NULL 0
#endif
#define AHA1740 { proc_name: "aha1740", \
proc_info: aha1740_proc_info, \
name: "Adaptec 174x (EISA)", \
detect: aha1740_detect, \
command: aha1740_command, \
queuecommand: aha1740_queuecommand, \
abort: aha1740_abort, \
reset: aha1740_reset, \
bios_param: aha1740_biosparam, \
can_queue: AHA1740_ECBS, \
this_id: 7, \
......
......@@ -476,7 +476,6 @@ MODULE_AUTHOR("Dario Ballabio");
#include <linux/blk.h>
#include "scsi.h"
#include "hosts.h"
#include "sd.h"
#include <asm/dma.h>
#include <asm/irq.h>
#include "eata.h"
......@@ -1838,7 +1837,7 @@ int eata2x_bios_param(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int *dkinfo) {
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[1] = 63;
dkinfo[2] = size / (dkinfo[0] * dkinfo[1]);
......
......@@ -18,8 +18,6 @@ static int eata2x_slave_attach(Scsi_Device *);
detect: eata2x_detect, \
release: eata2x_release, \
queuecommand: eata2x_queuecommand, \
abort: NULL, \
reset: NULL, \
eh_abort_handler: eata2x_eh_abort, \
eh_device_reset_handler: NULL, \
eh_bus_reset_handler: NULL, \
......
......@@ -14,6 +14,9 @@
* neuffer@goofy.zdv.uni-mainz.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 *
* and/or modify it under the terms of the GNU General *
* Public License as published by the Free Software *
......@@ -30,15 +33,23 @@
* Public License along with this kernel; if not, write to *
* the Free Software Foundation, Inc., 675 Mass Ave, *
* 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 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
......@@ -57,902 +68,830 @@
#include <linux/blk.h>
#include <linux/spinlock.h>
static uint ISAbases[MAXISA] =
{0x1F0, 0x170, 0x330, 0x230};
static uint ISAirqs[MAXISA] =
{14,12,15,11};
static unchar EISAbases[] =
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
static uint ISAbases[MAXISA] = {
0x1F0, 0x170, 0x330, 0x230
};
static uint ISAirqs[MAXISA] = {
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 struct Scsi_Host *last_HBA = NULL;
static struct Scsi_Host *first_HBA = NULL;
static unchar reg_IRQ[] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static unchar reg_IRQL[] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static struct Scsi_Host *last_HBA;
static struct Scsi_Host *first_HBA;
static unsigned char reg_IRQ[];
static unsigned char reg_IRQL[];
static ulong int_counter = 0;
static ulong queue_counter = 0;
static unsigned long int_counter = 0;
static unsigned long queue_counter = 0;
#include "eata_pio_proc.c"
#ifdef MODULE
int eata_pio_release(struct Scsi_Host *sh)
static int eata_pio_release(struct Scsi_Host *sh)
{
if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq, NULL);
else reg_IRQ[sh->irq]--;
if (SD(sh)->channel == 0) {
if (sh->io_port && sh->n_io_port)
release_region(sh->io_port, sh->n_io_port);
}
return(TRUE);
if (sh->irq && reg_IRQ[sh->irq] == 1)
free_irq(sh->irq, NULL);
else
reg_IRQ[sh->irq]--;
if (SD(sh)->channel == 0) {
if (sh->io_port && sh->n_io_port)
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;
if ((SCp->this_residual-=Increment)==0)
{
if ((--SCp->buffers_residual)==0) SCp->Status=FALSE;
else
{
SCp->buffer++;
SCp->ptr=page_address(SCp->buffer->page) + SCp->buffer->offset;
SCp->this_residual=SCp->buffer->length;
SCp->ptr += Increment;
if ((SCp->this_residual -= Increment) == 0) {
if ((--SCp->buffers_residual) == 0)
SCp->Status = FALSE;
else {
SCp->buffer++;
SCp->ptr = page_address(SCp->buffer->page) + SCp->buffer->offset;
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;
struct Scsi_Host *dev = dev_id;
spin_lock_irqsave(dev->host_lock, flags);
eata_pio_int_handler(irq, dev_id, regs);
spin_unlock_irqrestore(dev->host_lock, flags);
unsigned long flags;
struct Scsi_Host *dev = dev_id;
spin_lock_irqsave(dev->host_lock, flags);
eata_pio_int_handler(irq, dev_id, regs);
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;
Scsi_Cmnd *cmd;
hostdata *hd;
struct eata_ccb *cp;
uint base;
uint x,z;
struct Scsi_Host *sh;
ushort zwickel=0;
unchar stat,odd;
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
uint eata_stat = 0xfffff;
Scsi_Cmnd *cmd;
hostdata *hd;
struct eata_ccb *cp;
uint base;
uint x, z;
struct Scsi_Host *sh;
unsigned short zwickel = 0;
unsigned char stat, odd;
for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev)
{
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;
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 (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 */
{
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;
}
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;
}
}
}
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 (stat != 0x50)
printk(KERN_DEBUG "stat: %#.2x, result: %#.8x\n", stat,
cmd->result);
if (stat != 0x50)
printk(KERN_DEBUG "stat: %#.2x, result: %#.8x\n", stat, cmd->result);
#endif
cp->status = FREE; /* now we can release the slot */
cmd->scsi_done(cmd);
}
return;
cp->status = FREE; /* now we can release the slot */
cmd->scsi_done(cmd);
}
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;
while (inb(base + HA_RSTATUS) & HA_SBUSY)
if (--loop == 0)
return(TRUE);
/* 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
* initialization this way */
outb(HA_CTRL_8HEADS,base+HA_CTRLREG);
outb(command, base + HA_WCOMMAND);
return(FALSE);
uint loop = HZ / 2;
while (inb(base + HA_RSTATUS) & HA_SBUSY)
if (--loop == 0)
return (TRUE);
/* 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
* initialization this way */
outb(HA_CTRL_8HEADS, base + HA_CTRLREG);
outb(command, base + HA_WCOMMAND);
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 base;
hostdata *hd;
struct Scsi_Host *sh;
struct eata_ccb *cp;
queue_counter++;
hd = HD(cmd);
sh = cmd->host;
base = (uint) sh->base;
/* use only slot 0, as 2001 can handle only one cmd at a time */
y = x = 0;
if (hd->ccb[y].status!=FREE) {
DBG(DBG_QUEUE, printk(KERN_EMERG "can_queue %d, x %d, y %d\n",
sh->can_queue,x,y));
uint x, y;
uint base;
hostdata *hd;
struct Scsi_Host *sh;
struct eata_ccb *cp;
queue_counter++;
hd = HD(cmd);
sh = cmd->host;
base = (uint) sh->base;
/* use only slot 0, as 2001 can handle only one cmd at a time */
y = x = 0;
if (hd->ccb[y].status != FREE) {
DBG(DBG_QUEUE, printk(KERN_EMERG "can_queue %d, x %d, y %d\n", sh->can_queue, x, y));
#if DEBUG_EATA
panic(KERN_EMERG "eata_pio: run out of queue slots cmdno:%ld "
"intrno: %ld\n", queue_counter, int_counter);
panic(KERN_EMERG "eata_pio: run out of queue slots cmdno:%ld " "intrno: %ld\n", queue_counter, int_counter);
#else
panic(KERN_EMERG "eata_pio: run out of queue slots....\n");
panic(KERN_EMERG "eata_pio: run out of queue slots....\n");
#endif
}
cp = &hd->ccb[y];
memset(cp, 0, sizeof(struct eata_ccb));
memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
cp->status = USED; /* claim free slot */
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));
cmd->scsi_done = (void *)done;
/* FIXME: use passed direction flag !! */
switch (cmd->cmnd[0]) {
case CHANGE_DEFINITION: case COMPARE: case COPY:
case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT:
case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER:
case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE:
case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
case WRITE_6: case WRITE_10: case WRITE_VERIFY:
case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME:
case SEARCH_HIGH_12: case SEARCH_EQUAL_12: case SEARCH_LOW_12:
case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW:
case MEDIUM_SCAN: case SEND_VOLUME_TAG:
case 0xea: /* alternate number for WRITE LONG */
cp->DataOut = TRUE; /* Output mode */
break;
case TEST_UNIT_READY:
default:
cp->DataIn = TRUE; /* Input mode */
}
cp->Interpret = (cmd->target == hd->hostid);
cp->cp_datalen = htonl((ulong)cmd->request_bufflen);
cp->Auto_Req_Sen = FALSE;
cp->cp_reqDMA = htonl(0);
cp->reqlen = 0;
cp->cp_id = cmd->target;
cp->cp_lun = cmd->lun;
cp->cp_dispri = FALSE;
cp->cp_identify = TRUE;
memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
cp->cp_statDMA = htonl(0);
cp->cp_viraddr = cp;
cp->cmd = cmd;
cmd->host_scribble = (char *)&hd->ccb[y];
if (cmd->use_sg == 0)
{
cmd->SCp.buffers_residual=1;
cmd->SCp.ptr = cmd->request_buffer;
cmd->SCp.this_residual = cmd->request_bufflen;
cmd->SCp.buffer = NULL;
} else {
cmd->SCp.buffer = cmd->request_buffer;
cmd->SCp.buffers_residual = cmd->use_sg;
cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
}
cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes
* are to transfer */
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;
}
cp = &hd->ccb[y];
memset(cp, 0, sizeof(struct eata_ccb));
memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
cp->status = USED; /* claim free slot */
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));
cmd->scsi_done = (void *) done;
if(cmd->sc_data_direction == SCSI_DATA_WRITE)
cp->DataOut = TRUE; /* Output mode */
else
cp->DataIn = TRUE; /* Input mode */
cp->Interpret = (cmd->target == hd->hostid);
cp->cp_datalen = htonl((unsigned long) cmd->request_bufflen);
cp->Auto_Req_Sen = FALSE;
cp->cp_reqDMA = htonl(0);
cp->reqlen = 0;
cp->cp_id = cmd->target;
cp->cp_lun = cmd->lun;
cp->cp_dispri = FALSE;
cp->cp_identify = TRUE;
memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
cp->cp_statDMA = htonl(0);
cp->cp_viraddr = cp;
cp->cmd = cmd;
cmd->host_scribble = (char *) &hd->ccb[y];
if (cmd->use_sg == 0) {
cmd->SCp.buffers_residual = 1;
cmd->SCp.ptr = cmd->request_buffer;
cmd->SCp.this_residual = cmd->request_bufflen;
cmd->SCp.buffer = NULL;
} else {
cmd->SCp.buffer = cmd->request_buffer;
cmd->SCp.buffers_residual = cmd->use_sg;
cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
}
cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes
* are to transfer */
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);
}
/* FIXME: timeout */
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);
}
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;
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,
cmd->target, cmd->lun, cmd->abort_reason));
while (inb((uint)(cmd->host->base) + HA_RAUXSTAT) & HA_ABUSY)
if (--loop == 0) {
printk(KERN_WARNING "eata_pio: abort, timeout error.\n");
spin_unlock_irqrestore(cmd->host->host_lock, flags);
return (SCSI_ABORT_ERROR);
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));
while (inb(cmd->host->base + HA_RAUXSTAT) & HA_ABUSY)
if (--loop == 0) {
printk(KERN_WARNING "eata_pio: abort, timeout error.\n");
return FAILED;
}
if (CD(cmd)->status == FREE) {
DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_NOT_RUNNING\n"));
return FAILED;
}
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) {
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");
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;
ulong flags;
unchar success = FALSE;
Scsi_Cmnd *sp;
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));
spin_lock_irqsave(cmd->host->host_lock, flags);
if (HD(cmd)->state == RESET) {
printk(KERN_WARNING "eata_pio_reset: exit, already in reset.\n");
spin_unlock_irqrestore(cmd->host->host_lock, flags);
return (SCSI_RESET_ERROR);
}
/* force all slots to be free */
for (x = 0; x < cmd->host->can_queue; x++) {
if (HD(cmd)->ccb[x].status == FREE)
continue;
sp = HD(cmd)->ccb[x].cmd;
HD(cmd)->ccb[x].status = RESET;
printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x,
sp->pid);
if (sp == NULL)
panic("eata_pio_reset: slot %d, sp==NULL.\n", x);
}
/* hard reset the HBA */
outb(EATA_CMD_RESET, (uint) cmd->host->base+HA_WCOMMAND);
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: board reset done.\n"));
HD(cmd)->state = RESET;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(3*HZ);
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, "
"loops %d.\n", limit));
for (x = 0; x < cmd->host->can_queue; x++) {
/* Skip slots already set free by interrupt */
if (HD(cmd)->ccb[x].status != RESET)
continue;
sp = HD(cmd)->ccb[x].cmd;
sp->result = DID_RESET << 16;
/* This mailbox is terminated */
printk(KERN_WARNING "eata_pio_reset: reset ccb %d.\n",x);
HD(cmd)->ccb[x].status = FREE;
sp->scsi_done(sp);
}
HD(cmd)->state = FALSE;
spin_unlock_irqrestore(cmd->host->host_lock, flags);
if (success) { /* hmmm... */
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);
}
uint x, limit = 0;
unsigned char success = FALSE;
Scsi_Cmnd *sp;
struct Scsi_Host *host = cmd->host;
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));
if (HD(cmd)->state == RESET) {
printk(KERN_WARNING "eata_pio_reset: exit, already in reset.\n");
return FAILED;
}
/* force all slots to be free */
for (x = 0; x < cmd->host->can_queue; x++) {
if (HD(cmd)->ccb[x].status == FREE)
continue;
sp = HD(cmd)->ccb[x].cmd;
HD(cmd)->ccb[x].status = RESET;
printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->pid);
if (sp == NULL)
panic("eata_pio_reset: slot %d, sp==NULL.\n", x);
}
/* hard reset the HBA */
outb(EATA_CMD_RESET, (uint) cmd->host->base + HA_WCOMMAND);
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: board reset done.\n"));
HD(cmd)->state = RESET;
spin_unlock_irq(host->host_lock);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(3 * HZ);
spin_lock_irq(host->host_lock);
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " "loops %d.\n", limit));
for (x = 0; x < cmd->host->can_queue; x++) {
/* Skip slots already set free by interrupt */
if (HD(cmd)->ccb[x].status != RESET)
continue;
sp = HD(cmd)->ccb[x].cmd;
sp->result = DID_RESET << 16;
/* This mailbox is terminated */
printk(KERN_WARNING "eata_pio_reset: reset ccb %d.\n", x);
HD(cmd)->ccb[x].status = FREE;
sp->scsi_done(sp);
}
HD(cmd)->state = FALSE;
if (success) { /* hmmm... */
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n"));
return SUCCESS;
} else {
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, wakeup.\n"));
return FAILED;
}
}
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;
static char buff[256];
int z;
memset(&cp, 0, sizeof(struct eata_ccb));
memset(buff, 0, sizeof(buff));
cp.DataIn = TRUE;
cp.Interpret = TRUE; /* Interpret command */
cp.cp_datalen = htonl(254);
cp.cp_dataDMA = htonl(0);
cp.cp_id = id;
cp.cp_lun = 0;
cp.cp_cdb[0] = INQUIRY;
cp.cp_cdb[1] = 0;
cp.cp_cdb[2] = 0;
cp.cp_cdb[3] = 0;
cp.cp_cdb[4] = 254;
cp.cp_cdb[5] = 0;
if (eata_pio_send_command((uint) base, EATA_CMD_PIO_SEND_CP))
return (NULL);
while (!(inb(base + HA_RSTATUS) & HA_SDRQ));
outsw(base + HA_RDATA, &cp, cplen);
outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
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)
return (NULL);
else if (!(inb(base + HA_RSTATUS) & HA_SDRQ))
return (NULL);
else
{
insw(base+HA_RDATA, &buff, 127);
while (inb(base + HA_RSTATUS)&HA_SDRQ) inw(base + HA_RDATA);
return (buff);
}
struct eata_ccb cp;
static char buff[256];
int z;
memset(&cp, 0, sizeof(struct eata_ccb));
memset(buff, 0, sizeof(buff));
cp.DataIn = TRUE;
cp.Interpret = TRUE; /* Interpret command */
cp.cp_datalen = htonl(254);
cp.cp_dataDMA = htonl(0);
cp.cp_id = id;
cp.cp_lun = 0;
cp.cp_cdb[0] = INQUIRY;
cp.cp_cdb[1] = 0;
cp.cp_cdb[2] = 0;
cp.cp_cdb[3] = 0;
cp.cp_cdb[4] = 254;
cp.cp_cdb[5] = 0;
if (eata_pio_send_command((uint) base, EATA_CMD_PIO_SEND_CP))
return (NULL);
while (!(inb(base + HA_RSTATUS) & HA_SDRQ));
outsw(base + HA_RDATA, &cp, cplen);
outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
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)
return (NULL);
else if (!(inb(base + HA_RSTATUS) & HA_SDRQ))
return (NULL);
else {
insw(base + HA_RDATA, &buff, 127);
while (inb(base + HA_RSTATUS) & HA_SDRQ)
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;
int z;
ushort *p;
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)
unsigned long loop = HZ / 2;
int z;
unsigned short *p;
if (check_region(base, 9))
return (FALSE);
loop = HZ/2;
*p = inw(base + HA_RDATA);
}
if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */
if (htonl(EATA_SIGNATURE) == buf->signature) {
DBG(DBG_PIO&&DBG_PROBE, printk(KERN_NOTICE "EATA Controller found "
"at %#4x EATA Level: %x\n", base,
(uint) (buf->version)));
while (inb(base + HA_RSTATUS) & HA_SDRQ)
inw(base + HA_RDATA);
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);
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 = (unsigned short *) buf; (long) p <= ((long) buf + (sizeof(struct get_conf) / 2)); p++) {
while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
if (--loop == 0)
return (FALSE);
loop = HZ / 2;
*p = inw(base + HA_RDATA);
}
if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */
if (htonl(EATA_SIGNATURE) == buf->signature) {
DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found " "at %#4x EATA Level: %x\n", base, (uint) (buf->version)));
while (inb(base + HA_RSTATUS) & HA_SDRQ)
inw(base + HA_RDATA);
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("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);
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);
printk("Please check values: (read config data)\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);
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)
{
unchar buffer[512];
unsigned char buffer[512];
#ifdef VERBOSE_SETUP
int z;
int z;
#endif
printk("eata_pio: executing controller self test & setup...\n");
while (inb(base + HA_RSTATUS) & HA_SBUSY);
outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND);
do {
while (inb(base + HA_RSTATUS) & HA_SBUSY)
/* nothing */ ;
if (inb(base + HA_RSTATUS) & HA_SDRQ)
{
insw(base + HA_RDATA, &buffer, 256);
printk("eata_pio: executing controller self test & setup...\n");
while (inb(base + HA_RSTATUS) & HA_SBUSY);
outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND);
do {
while (inb(base + HA_RSTATUS) & HA_SBUSY)
/* nothing */ ;
if (inb(base + HA_RSTATUS) & HA_SDRQ) {
insw(base + HA_RDATA, &buffer, 256);
#ifdef VERBOSE_SETUP
/* no beeps please... */
for (z = 0; z < 511 && buffer[z]; z++)
if (buffer[z] != 7) printk("%c", buffer[z]);
/* no beeps please... */
for (z = 0; z < 511 && buffer[z]; z++)
if (buffer[z] != 7)
printk("%c", buffer[z]);
#endif
}
} while (inb(base+HA_RSTATUS) & (HA_SBUSY|HA_SDRQ));
return (!(inb(base+HA_RSTATUS) & HA_SERROR));
}
} while (inb(base + HA_RSTATUS) & (HA_SBUSY | HA_SDRQ));
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;
char *buff;
ulong cplen;
ushort cppadlen;
struct Scsi_Host *sh;
hostdata *hd;
DBG(DBG_REGISTER, print_pio_config(gc));
if (gc->DMA_support == TRUE) {
printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n",base);
if(ALLOW_DMA_BOARDS == FALSE)
return (FALSE);
}
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)
{
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",
(ulong) base);
return (FALSE);
}
request_region(base, 8, "eata_pio");
size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz));
sh = scsi_register(tpnt, size);
if(sh == NULL)
{
release_region(base, 8);
return FALSE;
}
if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */
if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT,
"EATA-PIO", sh)){
reg_IRQ[gc->IRQ]++;
if (!gc->IRQ_TR)
reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */
unsigned long size = 0;
char *buff;
unsigned long cplen;
unsigned short cppadlen;
struct Scsi_Host *sh;
hostdata *hd;
DBG(DBG_REGISTER, print_pio_config(gc));
if (gc->DMA_support == TRUE) {
printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n", base);
if (ALLOW_DMA_BOARDS == FALSE)
return (FALSE);
}
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) {
printk("HBA at %#lx didn't react on INQUIRY. Sorry.\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", (unsigned long) base);
return (FALSE);
}
request_region(base, 8, "eata_pio");
size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz));
sh = scsi_register(tpnt, size);
if (sh == NULL) {
release_region(base, 8);
return FALSE;
}
if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */
if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", sh)) {
reg_IRQ[gc->IRQ]++;
if (!gc->IRQ_TR)
reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */
} else {
printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ);
release_region(base, 8);
return (FALSE);
}
} else { /* More than one HBA on this IRQ */
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 {
printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ);
release_region(base, 8);
return (FALSE);
if (buff[21] == '4')
hd->bustype = IS_PCI;
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) {
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(ulong) * 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 {
if (buff[21] == '4')
hd->bustype = IS_PCI;
else if (buff[21] == '2')
hd->bustype = IS_EISA;
SD(sh)->cplen = cplen;
SD(sh)->cppadlen = cppadlen;
SD(sh)->hostid = gc->scsi_id[3];
SD(sh)->devflags = 1 << gc->scsi_id[3];
SD(sh)->moresupport = gc->MORE_support;
sh->unique_id = base;
sh->base = base;
sh->io_port = base;
sh->n_io_port = 8;
sh->irq = gc->IRQ;
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->bustype = IS_ISA;
}
SD(sh)->cplen=cplen;
SD(sh)->cppadlen=cppadlen;
SD(sh)->hostid=gc->scsi_id[3];
SD(sh)->devflags=1<<gc->scsi_id[3];
SD(sh)->moresupport=gc->MORE_support;
sh->unique_id = base;
sh->base = base;
sh->io_port = base;
sh->n_io_port = 8;
sh->irq = gc->IRQ;
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);
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;
for (i = 0; i < MAXISA; i++) {
if (ISAbases[i]) {
if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE){
register_pio_HBA(ISAbases[i], buf, tpnt);
}
ISAbases[i] = 0;
int i;
for (i = 0; i < MAXISA; i++) {
if (ISAbases[i]) {
if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE) {
register_pio_HBA(ISAbases[i], buf, tpnt);
}
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;
int i;
u32 base;
int i;
#if CHECKPAL
u8 pal1, pal2, pal3;
u8 pal1, pal2, pal3;
#endif
for (i = 0; i < MAXEISA; i++) {
if (EISAbases[i] == TRUE) { /* Still a possibility ? */
for (i = 0; i < MAXEISA; i++) {
if (EISAbases[i] == TRUE) { /* Still a possibility ? */
base = 0x1c88 + (i * 0x1000);
base = 0x1c88 + (i * 0x1000);
#if CHECKPAL
pal1 = inb((u16)base - 8);
pal2 = inb((u16)base - 7);
pal3 = inb((u16)base - 6);
if (((pal1 == 0x12) && (pal2 == 0x14)) ||
((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) ||
((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));
pal1 = inb((u16) base - 8);
pal2 = inb((u16) base - 7);
pal3 = inb((u16) base - 6);
if (((pal1 == 0x12) && (pal2 == 0x14)) || ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || ((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
if (get_pio_conf_PIO(base, buf) == TRUE) {
DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf));
if (buf->IRQ) {
register_pio_HBA(base, buf, tpnt);
} else
printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA "
"removed from list\n");
}
/* Nothing found here so we take it from the list */
EISAbases[i] = 0;
if (get_pio_conf_PIO(base, buf) == TRUE) {
DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf));
if (buf->IRQ) {
register_pio_HBA(base, buf, tpnt);
} else
printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " "removed from list\n");
}
/* Nothing found here so we take it from the list */
EISAbases[i] = 0;
#if CHECKPAL
}
}
#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
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
struct pci_dev *dev = NULL;
u32 base, x;
while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) {
DBG(DBG_PROBE && DBG_PCI,
printk("eata_pio: find_PCI, HBA at %s\n", dev->name));
if (pci_enable_device(dev))
continue;
pci_set_master(dev);
base = pci_resource_flags(dev, 0);
if (base & IORESOURCE_MEM) {
printk("eata_pio: invalid base address of device %s\n", dev->name);
continue;
}
base = pci_resource_start(dev, 0);
/* EISA tag there ? */
if ((inb(base) == 0x12) && (inb(base + 1) == 0x14))
continue; /* Jep, it's forced, so move on */
base += 0x10; /* Now, THIS is the real address */
if (base != 0x1f8) {
/* We didn't find it in the primary search */
if (get_pio_conf_PIO(base, buf) == TRUE) {
if (buf->FORCADR) /* If the address is forced */
continue; /* we'll find it later */
/* OK. We made it till here, so we can go now
* and register it. We only have to check and
* eventually remove it from the EISA and ISA list
*/
register_pio_HBA(base, buf, tpnt);
if (base < 0x1000) {
for (x = 0; x < MAXISA; ++x) {
if (ISAbases[x] == base) {
ISAbases[x] = 0;
break;
}
struct pci_dev *dev = NULL;
u32 base, x;
while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) {
DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", dev->name));
if (pci_enable_device(dev))
continue;
pci_set_master(dev);
base = pci_resource_flags(dev, 0);
if (base & IORESOURCE_MEM) {
printk("eata_pio: invalid base address of device %s\n", dev->name);
continue;
}
base = pci_resource_start(dev, 0);
/* EISA tag there ? */
if ((inb(base) == 0x12) && (inb(base + 1) == 0x14))
continue; /* Jep, it's forced, so move on */
base += 0x10; /* Now, THIS is the real address */
if (base != 0x1f8) {
/* We didn't find it in the primary search */
if (get_pio_conf_PIO(base, buf) == TRUE) {
if (buf->FORCADR) /* If the address is forced */
continue; /* we'll find it later */
/* OK. We made it till here, so we can go now
* and register it. We only have to check and
* eventually remove it from the EISA and ISA list
*/
register_pio_HBA(base, buf, tpnt);
if (base < 0x1000) {
for (x = 0; x < MAXISA; ++x) {
if (ISAbases[x] == base) {
ISAbases[x] = 0;
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
else if (check_blink_state(base) == TRUE) {
printk("eata_pio: HBA is in BLINK state.\n"
"Consult your HBAs manual to correct this.\n");
}
else if (check_blink_state(base) == TRUE) {
printk("eata_pio: HBA is in BLINK state.\n" "Consult your HBAs manual to correct this.\n");
}
#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 get_conf gc;
int i;
tpnt->proc_name = "eata_pio";
find_pio_PCI(&gc, tpnt);
find_pio_EISA(&gc, tpnt);
find_pio_ISA(&gc, tpnt);
for (i = 0; i <= MAXIRQ; i++)
if (reg_IRQ[i])
request_irq(i, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", NULL);
HBA_ptr = first_HBA;
if (registered_HBAs != 0) {
printk("EATA (Extended Attachment) PIO driver version: %d.%d%s\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);
printk("Registered HBAs:\n");
printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:"
" QS: SG: CPL:\n");
for (i = 1; i <= registered_HBAs; i++) {
printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d %d %d %c"
" %2d %2d %2d\n",
HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
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;
struct Scsi_Host *HBA_ptr;
struct get_conf gc;
int i;
tpnt->proc_name = "eata_pio";
find_pio_PCI(&gc, tpnt);
find_pio_EISA(&gc, tpnt);
find_pio_ISA(&gc, tpnt);
for (i = 0; i <= MAXIRQ; i++)
if (reg_IRQ[i])
request_irq(i, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", NULL);
HBA_ptr = first_HBA;
if (registered_HBAs != 0) {
printk("EATA (Extended Attachment) PIO driver version: %d.%d%s\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);
printk("Registered HBAs:\n");
printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:" " QS: SG: CPL:\n");
for (i = 1; i <= registered_HBAs; i++) {
printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d %d %d %c"
" %2d %2d %2d\n",
HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
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 */
......
......@@ -2,7 +2,7 @@
* Header file for eata_pio.c Linux EATA-PIO SCSI driver *
* (c) 1993-96 Michael Neuffer *
*********************************************************
* last change: 96/05/05 *
* last change: 2002/11/02 *
********************************************************/
......@@ -14,7 +14,6 @@
#include "hosts.h"
#include <scsi/scsicam.h>
#ifndef HOSTS_C
#include "eata_generic.h"
#define VER_MAJOR 0
......@@ -25,82 +24,55 @@
* 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
/************************************************************************
* Debug options. *
* Enable DEBUG and whichever options you require. *
************************************************************************/
#define DEBUG_EATA 1 /* Enable debug code. */
#define DPT_DEBUG 0 /* Bobs special */
#define DBG_DELAY 0 /* Build in delays so debug messages can be
* be read before they vanish of the top of
* the screen!
*/
#define DBG_PROBE 0 /* Debug probe routines. */
#define DBG_ISA 0 /* Trace ISA routines */
#define DBG_EISA 0 /* Trace EISA routines */
#define DBG_PCI 0 /* Trace PCI routines */
#define DBG_PIO 0 /* Trace get_config_PIO */
#define DBG_COM 0 /* Trace command call */
#define DBG_QUEUE 0 /* Trace command queueing. */
#define DBG_INTR 0 /* Trace interrupt service routine. */
#define DBG_INTR2 0 /* Trace interrupt service routine. */
#define DBG_PROC 0 /* Debug proc-fs related statistics */
#define DEBUG_EATA 1 /* Enable debug code. */
#define DPT_DEBUG 0 /* Bobs special */
#define DBG_DELAY 0 /* Build in delays so debug messages can be
* be read before they vanish of the top of
* the screen!
*/
#define DBG_PROBE 0 /* Debug probe routines. */
#define DBG_ISA 0 /* Trace ISA routines */
#define DBG_EISA 0 /* Trace EISA routines */
#define DBG_PCI 0 /* Trace PCI routines */
#define DBG_PIO 0 /* Trace get_config_PIO */
#define DBG_COM 0 /* Trace command call */
#define DBG_QUEUE 0 /* Trace command queueing. */
#define DBG_INTR 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_WRITE 0
#define DBG_REGISTER 0 /* */
#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */
#define DBG_REGISTER 0 /* */
#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */
#if DEBUG_EATA
#define DBG(x, y) if ((x)) {y;}
#if DEBUG_EATA
#define DBG(x, y) if ((x)) {y;}
#else
#define DBG(x, y)
#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 *);
const char *eata_pio_info(struct Scsi_Host *);
int eata_pio_command(Scsi_Cmnd *);
int eata_pio_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int eata_pio_abort(Scsi_Cmnd *);
int eata_pio_reset(Scsi_Cmnd *, unsigned int);
int eata_pio_proc_info(char *, char **, off_t, int, int, int);
#ifdef MODULE
int eata_pio_release(struct Scsi_Host *);
#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 */
#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, \
eh_abort_handler: eata_pio_abort, \
eh_host_reset_handler: eata_pio_host_reset, \
use_clustering: ENABLE_CLUSTERING \
}
/*
* 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:
*/
#endif /* _EATA_PIO_H */
......@@ -1325,118 +1325,115 @@ static int fd_mcs_host_reset(Scsi_Cmnd * SCpnt)
return FAILED;
}
static int fd_mcs_device_reset(Scsi_Cmnd * SCpnt) {
return FAILED;
}
static int fd_mcs_device_reset(Scsi_Cmnd * SCpnt)
{
return FAILED;
}
static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
struct Scsi_Host *shpnt = SCpnt->host;
unsigned long flags;
static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
struct Scsi_Host *shpnt = SCpnt->host;
#if DEBUG_RESET
static int called_once = 0;
static int called_once = 0;
#endif
#if ERRORS_ONLY
if (SCpnt)
printk("fd_mcs: SCSI Bus Reset\n");
if (SCpnt)
printk("fd_mcs: SCSI Bus Reset\n");
#endif
#if DEBUG_RESET
if (called_once)
fd_mcs_print_info(current_SC);
called_once = 1;
if (called_once)
fd_mcs_print_info(current_SC);
called_once = 1;
#endif
spin_lock_irqsave(shpnt->host_lock, flags);
outb(1, SCSI_Cntl_port);
do_pause(2);
outb(0, SCSI_Cntl_port);
do_pause(115);
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. */
outb(1, SCSI_Cntl_port);
do_pause(2);
outb(0, SCSI_Cntl_port);
do_pause(115);
outb(0, SCSI_Mode_Cntl_port);
outb(PARITY_MASK, TMC_Cntl_port);
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;
}
}
#include <scsi/scsi_ioctl.h>
static int fd_mcs_biosparam(Scsi_Disk * disk, struct block_device *bdev,
sector_t capacity, int *info_array) {
unsigned char buf[512 + sizeof(int) * 2];
int size = capacity;
int *sizes = (int *) buf;
unsigned char *data = (unsigned char *) (sizes + 2);
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!). */
sizes[0] = 0; /* zero bytes out */
sizes[1] = 512; /* one sector in */
memcpy(data, do_read, sizeof(do_read));
retcode = kernel_scsi_ioctl(disk->device, SCSI_IOCTL_SEND_COMMAND, (void *) buf);
if (!retcode /* SCSI command ok */
&& data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
&& data[0x1c2]) { /* Partition type */
/* The partition table layout is as follows:
Start: 0x1b3h
Offset: 0 = partition status
1 = starting head
2 = starting sector and cylinder (word, encoded)
4 = partition type
5 = ending head
6 = ending sector and cylinder (word, encoded)
8 = starting absolute sector (double word)
c = number of sectors (double word)
Signature: 0x1fe = 0x55aa
So, this algorithm assumes:
1) the first partition table is in use,
2) the data in the first entry is correct, and
3) partitions never divide cylinders
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
attention to the fields that are used by this algorithm -- it
only uses the absolute sector data. Recent versions of Linux's
fdisk(1) will fill this data in correctly, and forthcoming
versions will check for consistency.
Checking for a non-zero partition type is not part of the
Future Domain algorithm, but it seemed to be a reasonable thing
to do, especially in the Linux and BSD worlds. */
info_array[0] = data[0x1c3] + 1; /* heads */
info_array[1] = data[0x1c4] & 0x3f; /* sectors */
static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev,
sector_t capacity, int *info_array)
{
unsigned char buf[512 + sizeof(int) * 2];
int size = capacity;
int *sizes = (int *) buf;
unsigned char *data = (unsigned char *) (sizes + 2);
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!). */
sizes[0] = 0; /* zero bytes out */
sizes[1] = 512; /* one sector in */
memcpy(data, do_read, sizeof(do_read));
retcode = kernel_scsi_ioctl(disk, SCSI_IOCTL_SEND_COMMAND, (void *) buf);
if (!retcode /* SCSI command ok */
&& data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
&& data[0x1c2]) { /* Partition type */
/* The partition table layout is as follows:
Start: 0x1b3h
Offset: 0 = partition status
1 = starting head
2 = starting sector and cylinder (word, encoded)
4 = partition type
5 = ending head
6 = ending sector and cylinder (word, encoded)
8 = starting absolute sector (double word)
c = number of sectors (double word)
Signature: 0x1fe = 0x55aa
So, this algorithm assumes:
1) the first partition table is in use,
2) the data in the first entry is correct, and
3) partitions never divide cylinders
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
attention to the fields that are used by this algorithm -- it
only uses the absolute sector data. Recent versions of Linux's
fdisk(1) will fill this data in correctly, and forthcoming
versions will check for consistency.
Checking for a non-zero partition type is not part of the
Future Domain algorithm, but it seemed to be a reasonable thing
to do, especially in the Linux and BSD worlds. */
info_array[0] = data[0x1c3] + 1; /* heads */
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 {
/* 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 {
info_array[0] = 0x40; /* heads = 64 */
info_array[1] = 0x20; /* sectors = 32 */
}
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 */
static Scsi_Host_Template driver_template = FD_MCS;
......
......@@ -30,7 +30,7 @@ static int fd_mcs_bus_reset(Scsi_Cmnd *);
static int fd_mcs_device_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_biosparam(Disk *, struct block_device *,
static int fd_mcs_biosparam(struct scsi_device *, struct block_device *,
sector_t, int *);
static int fd_mcs_proc_info(char *, char **, off_t, int, int, int);
static const char *fd_mcs_info(struct Scsi_Host *);
......
......@@ -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,
int length, int hostno, int inout);
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);
#ifndef CMD_PER_LUN
......
......@@ -192,7 +192,7 @@ typedef struct SHT
/*
* 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 (*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 @@
/* Common forward declarations for all Linux-versions: */
/* Interfaces to the midlevel Linux SCSI driver */
extern int ibmmca_proc_info (char *, char **, off_t, int, int, int);
extern int ibmmca_detect (Scsi_Host_Template *);
extern int ibmmca_release (struct Scsi_Host *);
extern int ibmmca_command (Scsi_Cmnd *);
extern int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
extern int ibmmca_abort (Scsi_Cmnd *);
extern int ibmmca_reset (Scsi_Cmnd *, unsigned int);
extern int ibmmca_biosparam (struct scsi_device *, struct block_device *,
sector_t, int *);
/*structure for /proc filesystem */
extern struct proc_dir_entry proc_scsi_ibmmca;
static int ibmmca_proc_info (char *, char **, off_t, int, int, int);
static int ibmmca_detect (Scsi_Host_Template *);
static int ibmmca_release (struct Scsi_Host *);
static int ibmmca_command (Scsi_Cmnd *);
static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int ibmmca_abort (Scsi_Cmnd *);
static int ibmmca_host_reset (Scsi_Cmnd *);
static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
/*
* 2/8/98
......@@ -37,8 +33,8 @@ extern struct proc_dir_entry proc_scsi_ibmmca;
release: ibmmca_release, /*release fn*/ \
command: ibmmca_command, /*command fn*/ \
queuecommand: ibmmca_queuecommand, /*queuecommand fn*/ \
abort: ibmmca_abort, /*abort fn*/ \
reset: ibmmca_reset, /*reset fn*/ \
eh_abort_handler:ibmmca_abort, /*abort fn*/ \
eh_host_reset_handler:ibmmca_host_reset, /*reset fn*/ \
bios_param: ibmmca_biosparam, /*bios fn*/ \
can_queue: 16, /*can_queue*/ \
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 @@
***********************************************************************/
/* $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
#include <pcmcia/config.h>
......@@ -67,7 +67,7 @@
#include "nsp_cs.h"
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");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
......@@ -77,7 +77,7 @@ MODULE_LICENSE("GPL");
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
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)
#else
#define DEBUG(n, args...) /* */
......@@ -129,39 +129,30 @@ MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0
/* /usr/src/linux/drivers/scsi/hosts.h */
static Scsi_Host_Template driver_template = {
/* .next = NULL,*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
.proc_name = "nsp_cs", /* kernel 2.4 */
#else
.proc_dir = &proc_scsi_nsp, /* kernel 2.2 */
#endif
.proc_info = nsp_proc_info,
.name = "WorkBit NinjaSCSI-3/32Bi",
.name = "WorkBit NinjaSCSI-3/32Bi(16bit)",
.detect = nsp_detect,
.release = nsp_release,
.info = nsp_info,
/* .command = NULL,*/
.queuecommand = nsp_queuecommand,
/* .eh_strategy_handler = nsp_eh_strategy,*/
/* .eh_abort_handler = nsp_eh_abort,*/
/* .eh_device_reset_handler = nsp_eh_device_reset,*/
.eh_bus_reset_handler = nsp_eh_bus_reset,
.eh_host_reset_handler = nsp_eh_host_reset,
.abort = nsp_abort,
.reset = nsp_reset,
/* .slave_attach = NULL,*/
/* .bios_param = NULL,*/
.can_queue = 1,
.this_id = NSP_INITIATOR_ID,
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
/* .present = 0,*/
/* .unchecked_isa_dma = 0,*/
.use_clustering = DISABLE_CLUSTERING,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
.use_new_eh_code = 1,
#endif
/* .emulated = 0,*/
};
static dev_link_t *dev_list = NULL;
......@@ -180,12 +171,12 @@ static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
#endif
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",
__FUNCTION__, SCpnt, target, SCpnt->lun, SCpnt->request_buffer, SCpnt->request_bufflen, SCpnt->use_sg);
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);
//DEBUG(0, " before CurrentSC=0x%p\n", data->CurrentSC);
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;
SCpnt->result = DID_BAD_TARGET << 16;
done(SCpnt);
......@@ -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;
}
......@@ -243,7 +234,7 @@ static void nsp_setup_fifo(nsp_hw_data *data, int enabled)
unsigned int base = data->BaseAddress;
unsigned char transfer_mode_reg;
//DEBUG(0, __func__ "() enabled=%d\n", enabled);
//DEBUG(0, "%s: enabled=%d\n", __FUNCTION__, enabled);
if (enabled != FALSE) {
transfer_mode_reg = TRANSFER_GO | BRAIND;
......@@ -265,7 +256,7 @@ static void nsphw_init_sync(nsp_hw_data *data)
int i;
/* setup sync data */
for ( i = 0; i < N_TARGET; i++ ) {
for ( i = 0; i < NUMBER(data->Sync); i++ ) {
data->Sync[i] = tmp_sync;
}
}
......@@ -277,7 +268,7 @@ static int nsphw_init(nsp_hw_data *data)
{
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->CurrentSC = NULL;
......@@ -340,7 +331,7 @@ static unsigned int nsphw_start_selection(Scsi_Cmnd *SCpnt,
int time_out;
unsigned char phase, arbit;
//DEBUG(0, __func__ "()in\n");
//DEBUG(0, "%s:in\n", __FUNCTION__);
phase = nsp_index_read(base, SCSIBUSMON);
if(phase != BUSMON_BUS_FREE) {
......@@ -422,7 +413,7 @@ static int nsp_msg(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
int i;
DEBUG(0, "%s()\n", __FUNCTION__);
DEBUG(0, "%s:\n", __FUNCTION__);
period = sync->SyncPeriod;
offset = sync->SyncOffset;
......@@ -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;
//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;
nsp_index_write(base, TIMERCOUNT, time);
}
......@@ -487,7 +478,7 @@ static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str)
unsigned char reg;
int time_out;
//DEBUG(0, __func__ "()\n");
//DEBUG(0, "%s:\n", __FUNCTION__);
time_out = 100;
......@@ -499,7 +490,7 @@ static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str)
} while ((time_out-- != 0) && (reg & mask) != 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;
......@@ -516,7 +507,7 @@ static int nsp_expect_signal(Scsi_Cmnd *SCpnt,
int time_out;
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;
do {
......@@ -536,7 +527,7 @@ static int nsp_expect_signal(Scsi_Cmnd *SCpnt,
}
} while(time_out-- != 0);
//DEBUG(0, __func__ " : " __func__ " timeout\n");
//DEBUG(0, "%s: timeout\n", __FUNCTION__);
return -1;
}
......@@ -551,7 +542,7 @@ static int nsp_xfer(Scsi_Cmnd *SCpnt, nsp_hw_data *data, int phase)
int ptr;
int ret;
//DEBUG(0, __func__ "()\n");
//DEBUG(0, "%s:\n", __FUNCTION__);
for (ptr = 0; len > 0; len --, ptr ++) {
ret = nsp_expect_signal(SCpnt, phase, BUSMON_REQ);
......@@ -586,7 +577,7 @@ static int nsp_dataphase_bypass(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
{
unsigned int count;
//DEBUG(0, __func__ "()\n");
//DEBUG(0, "%s:\n", __FUNCTION__);
if (SCpnt->SCp.have_data_in != IO_IN) {
return 0;
......@@ -618,7 +609,7 @@ static int nsp_reselected(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
unsigned int base = SCpnt->host->io_port;
unsigned char reg;
//DEBUG(0, __func__ "()\n");
//DEBUG(0, "%s:\n", __FUNCTION__);
nsp_negate_signal(SCpnt, BUSMON_SEL, "reselect<SEL>");
......@@ -648,7 +639,7 @@ static int nsp_fifo_count(Scsi_Cmnd *SCpnt)
count = (h << 16) | (m << 8) | (l << 0);
//DEBUG(0, __func__ "() =0x%x\n", count);
//DEBUG(0, "%s: =0x%x\n", __FUNCTION__, count);
return count;
}
......@@ -670,8 +661,8 @@ static void nsp_pio_read(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
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",
__FUNCTION__, SCpnt, RESID, ocount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual);
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);
time_out = 1000;
......@@ -744,8 +735,8 @@ static void nsp_pio_read(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
data->FifoCount = ocount;
if (time_out == 0) {
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);
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);
}
DEBUG(0, " read ocount=0x%x\n", ocount);
}
......@@ -763,7 +754,8 @@ static void nsp_pio_write(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
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;
......@@ -833,7 +825,7 @@ static void nsp_pio_write(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
data->FifoCount = ocount;
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);
}
......@@ -851,7 +843,7 @@ static int nsp_nexus(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
// unsigned char lun = SCpnt->lun;
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 */
nsp_index_write(base, SYNCREG, sync->SyncRegister);
......@@ -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);
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;
} else {
tmpSC = data->CurrentSC;
......@@ -962,7 +954,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs)
*/
if ((i_src & IRQSTATUS_SCSI) != 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;
data->CurrentSC = NULL;
tmpSC->result = (DID_RESET << 16) |
......@@ -1064,7 +1056,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs)
/* check unexpected bus free state */
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;
data->CurrentSC = NULL;
......@@ -1208,7 +1200,7 @@ static void nspintr(int irq, void *dev_id, struct pt_regs *regs)
break;
}
//DEBUG(0, __func__ "() out\n");
//DEBUG(0, "%s: out\n", __FUNCTION__);
return;
timer_out:
......@@ -1246,7 +1238,7 @@ static int nsp_detect(Scsi_Host_Template *sht)
snprintf(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->base,
host->irq);
......@@ -1303,16 +1295,28 @@ static int nsp_proc_info(char *buffer,
int speed;
unsigned long flags;
nsp_hw_data *data = &nsp_data;
struct Scsi_Host *host;
struct Scsi_Host *host = NULL;
if (inout) {
return -EINVAL;
}
/* search this HBA host */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45))
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("Driver version: $Revision: 1.4 $\n");
SPRINTF("Driver version: $Revision: 1.5 $\n");
SPRINTF("SCSI host No.: %d\n", hostno);
SPRINTF("IRQ: %d\n", host->irq);
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,
}
#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)
{
......@@ -1460,7 +1425,7 @@ static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt)
unsigned int base = SCpnt->host->io_port;
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);
......@@ -1482,7 +1447,7 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
{
nsp_hw_data *data = &nsp_data;
DEBUG(0, "%s\n", __FUNCTION__);
DEBUG(0, "%s:\n", __FUNCTION__);
nsphw_init(data);
......@@ -1517,7 +1482,7 @@ static dev_link_t *nsp_cs_attach(void)
dev_link_t *link;
int ret, i;
DEBUG(0, "%s()\n", __FUNCTION__);
DEBUG(0, "%s:\n", __FUNCTION__);
/* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
......@@ -1607,7 +1572,7 @@ static void nsp_cs_detach(dev_link_t *link)
return;
}
del_timer_sync(&link->release);
del_timer(&link->release);
if (link->state & DEV_CONFIG) {
nsp_cs_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
......@@ -1659,7 +1624,7 @@ static void nsp_cs_config(dev_link_t *link)
nsp_hw_data *data = &nsp_data;
DEBUG(0, "%s() in\n", __FUNCTION__);
DEBUG(0, "%s: in\n", __FUNCTION__);
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
......@@ -1764,7 +1729,7 @@ static void nsp_cs_config(dev_link_t *link)
break;
next_entry:
DEBUG(0, "%s next\n", __FUNCTION__);
DEBUG(0, "%s: next\n", __FUNCTION__);
if (link->io.NumPorts1)
CardServices(ReleaseIO, link->handle, &link->io);
......@@ -1787,9 +1752,8 @@ static void nsp_cs_config(dev_link_t *link)
data->NumAddress = link->io.NumPorts1;
data->IrqNumber = link->irq.AssignedIRQ;
DEBUG(0, "%s I/O[0x%x+0x%x] IRQ %d\n",
__FUNCTION__,
data->BaseAddress, data->NumAddress, data->IrqNumber);
DEBUG(0, "%s: I/O[0x%x+0x%x] IRQ %d\n",
__FUNCTION__, data->BaseAddress, data->NumAddress, data->IrqNumber);
if(nsphw_init(data) == FALSE) {
goto cs_failed;
......@@ -1804,8 +1768,13 @@ static void nsp_cs_config(dev_link_t *link)
DEBUG(0, "GET_SCSI_INFO\n");
tail = &link->dev;
info->ndev = 0;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45))
for (host = scsi_host_get_next(NULL); host;
host = scsi_host_get_next(host)) {
#else
for (host = scsi_hostlist; host != NULL; host = host->next) {
#endif
if (host->hostt == &driver_template) {
for (dev = host->host_queue; dev != NULL; dev = dev->next) {
u_long arg[2], id;
......@@ -1998,7 +1967,7 @@ static int nsp_cs_event(event_t event,
DEBUG(0, " event: unknown\n");
break;
}
DEBUG(0, "%s end\n", __FUNCTION__);
DEBUG(0, "%s: end\n", __FUNCTION__);
return 0;
} /* nsp_cs_event */
......@@ -2009,7 +1978,7 @@ static int __init nsp_cs_init(void)
{
servinfo_t serv;
DEBUG(0, "%s() in\n", __FUNCTION__);
DEBUG(0, "%s: in\n", __FUNCTION__);
DEBUG(0, "%s\n", version);
CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) {
......@@ -2019,14 +1988,14 @@ static int __init nsp_cs_init(void)
}
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;
}
static void __exit nsp_cs_cleanup(void)
{
DEBUG(0, "%s() unloading\n", __FUNCTION__);
DEBUG(0, "%s: unloading\n", __FUNCTION__);
unregister_pcmcia_driver(&dev_info);
while (dev_list != NULL) {
if (dev_list->state & DEV_CONFIG) {
......
......@@ -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__
#define __nsp_cs__
......@@ -26,7 +26,7 @@
/************************************
* 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 MIN(a,b) ((a) > (b) ? (b) : (a))
......@@ -270,10 +270,10 @@ typedef struct _nsp_hw_data {
static void nsp_cs_release(u_long arg);
static int nsp_cs_event(event_t event, int priority, event_callback_args_t *args);
static void nsp_cs_release(u_long arg);
static int nsp_cs_event(event_t event, int priority, event_callback_args_t *args);
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 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,
int length, int hostno, int inout);
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_device_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)
DEBUG(0, " msgout loop\n");
do {
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 */
......
......@@ -613,7 +613,7 @@ int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
#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
*/
......
......@@ -1486,16 +1486,16 @@ static int u14_34f_eh_host_reset(Scsi_Cmnd *SCarg) {
return SUCCESS;
}
static int u14_34f_bios_param(Disk *disk, struct block_device *bdev,
int *dkinfo) {
static int u14_34f_bios_param(struct scsi_device *disk, struct block_device *bdev,
sector_t capacity, int *dkinfo) {
unsigned int j = 0;
int size = disk->capacity;
unsigned int size = capacity;
dkinfo[0] = HD(j)->heads;
dkinfo[1] = 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[1] = 63;
dkinfo[2] = size / (dkinfo[0] * dkinfo[1]);
......
......@@ -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_eh_abort(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 *);
#define U14_34F_VERSION "8.00.00"
......@@ -17,8 +17,6 @@ static int u14_34f_slave_attach(Scsi_Device *);
detect: u14_34f_detect, \
release: u14_34f_release, \
queuecommand: u14_34f_queuecommand, \
abort: NULL, \
reset: NULL, \
eh_abort_handler: u14_34f_eh_abort, \
eh_device_reset_handler: NULL, \
eh_bus_reset_handler: NULL, \
......
......@@ -8,6 +8,9 @@
* John's work modified by Caleb Epstein (cae@jpmorgan.com) and
* Eric Youngdale (ericy@cais.com).
* 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 @@
packed structure. */
typedef struct {
unsigned int address;
unsigned int num_bytes;
u32 address;
u32 num_bytes;
} ultrastor_sg_list;
......@@ -190,7 +193,7 @@ struct mscp {
unsigned char scsi_cdbs[12]; /* SCSI commands */
unsigned char adapter_status; /* non-zero indicates HA 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 MSCP structure because they are associated with SCSI requests. */
void (*done)(Scsi_Cmnd *);
......@@ -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);
/* Always called with host lock held */
static inline int find_and_clear_bit_16(unsigned short *field)
{
int rv;
unsigned long flags;
save_flags(flags);
cli();
if (*field == 0) panic("No free mscp");
asm("xorl %0,%0\n0:\tbsfw %1,%w0\n\tbtr %0,%1\n\tjnc 0b"
: "=&r" (rv), "=m" (*field) : "1" (*field));
restore_flags(flags);
return rv;
}
......@@ -320,14 +321,12 @@ static inline unsigned char xchgb(unsigned char reg,
#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)
{
static char fmt[80] = "abort %d (%x); MSCP free pool: %x;";
register int i;
unsigned long flags;
save_flags(flags);
cli();
int i;
for (i = 0; i < ULTRASTOR_MAX_CMDS; i++)
{
......@@ -340,7 +339,7 @@ static void log_ultrastor_abort(register struct ultrastor_config *config,
fmt[20 + ULTRASTOR_MAX_CMDS * 2] = '\n';
fmt[21 + ULTRASTOR_MAX_CMDS * 2] = 0;
printk(fmt, command, &config->mscp[command], config->mscp_free);
restore_flags(flags);
}
#endif
......@@ -528,7 +527,7 @@ static int ultrastor_14f_detect(Scsi_Host_Template * tpnt)
static int ultrastor_24f_detect(Scsi_Host_Template * tpnt)
{
register int i;
int i;
struct Scsi_Host * shpnt = NULL;
#if (ULTRASTOR_DEBUG & UD_DETECT)
......@@ -638,13 +637,13 @@ static int ultrastor_24f_detect(Scsi_Host_Template * tpnt)
return FALSE;
}
int ultrastor_detect(Scsi_Host_Template * tpnt)
static int ultrastor_detect(Scsi_Host_Template * tpnt)
{
tpnt->proc_name = "ultrastor";
return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt);
tpnt->proc_name = "ultrastor";
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];
......@@ -662,7 +661,7 @@ const char *ultrastor_info(struct Scsi_Host * shpnt)
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;
long transfer_length = 0;
......@@ -683,14 +682,13 @@ static inline void build_sg_list(register struct mscp *mscp, Scsi_Cmnd *SCpnt)
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
int mscp_index;
#endif
unsigned int status;
unsigned long flags;
/* Next test is for debugging; "can't happen" */
if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0)
......@@ -706,14 +704,8 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
my_mscp = &config.mscp[mscp_index];
#if 1
/* This way is faster. */
*(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
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
......@@ -748,35 +740,31 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
SCpnt->host_scribble = (unsigned char *)my_mscp;
/* 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)
while (inb(config.ogm_address - 1) != 0 &&
config.aborted[mscp_index] == 0xff) barrier();
while (inb(config.ogm_address - 1) != 0 && config.aborted[mscp_index] == 0xff)
barrier();
/* else??? */
while ((inb(LCL_DOORBELL_INTR(config.doorbell_address)) &
(config.slot ? 2 : 1))
&& config.aborted[mscp_index] == 0xff) barrier();
/* To avoid race conditions, make the code to write to the adapter
atomic. This simplifies the abort code. */
while ((inb(LCL_DOORBELL_INTR(config.doorbell_address)) & (config.slot ? 2 : 1)) && config.aborted[mscp_index] == 0xff)
barrier();
save_flags(flags);
cli();
/* To avoid race conditions, keep the code to write to the adapter
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)) &
(config.slot ? 2 : 1))
{
restore_flags(flags);
if (inb(LCL_DOORBELL_INTR(config.doorbell_address)) & (config.slot ? 2 : 1))
goto retry;
}
status = xchgb(0, &config.aborted[mscp_index]);
if (status != 0xff) {
restore_flags(flags);
#if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT)
printk("USx4F: queuecommand: aborted\n");
......@@ -811,8 +799,6 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
outb(0x1, LCL_DOORBELL_INTR(config.doorbell_address));
}
restore_flags(flags);
#if (ULTRASTOR_DEBUG & UD_COMMAND)
printk("USx4F: queuecommand: returning\n");
#endif
......@@ -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
char out[108];
......@@ -844,14 +830,16 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
#endif
unsigned int mscp_index;
unsigned char old_aborted;
unsigned long flags;
void (*done)(Scsi_Cmnd *);
struct Scsi_Host *host = SCpnt->host;
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 */
if(!SCpnt->host_scribble)
return SCSI_ABORT_NOT_RUNNING;
return FAILED;
mscp_index = ((struct mscp *)SCpnt->host_scribble) - config.mscp;
if (mscp_index >= ULTRASTOR_MAX_CMDS)
......@@ -863,8 +851,8 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
int port0 = (config.slot << 12) | 0xc80;
int i;
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(host->host_lock, flags);
strcpy(out, "OGM %d:%x ICM %d:%x ports: ");
for (i = 0; i < 16; i++)
{
......@@ -879,7 +867,7 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
ogm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 23));
icm_status = inb(port0 + 27);
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
......@@ -888,14 +876,13 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
if (config.slot ? inb(config.icm_address - 1) == 2 :
(inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1))
{
unsigned long flags;
save_flags(flags);
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);
restore_flags(flags);
return SCSI_ABORT_SUCCESS; /* FIXME - is this correct? -ERY */
spin_unlock_irqrestore(host->host_lock, flags);
return SUCCESS;
}
#endif
......@@ -904,7 +891,7 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
/* aborted == 0xff is the signal that queuecommand has not yet sent
the command. It will notice the new abort flag and fail. */
if (old_aborted == 0xff)
return SCSI_ABORT_SUCCESS;
return SUCCESS;
/* On 24F, send an abort MSCP request. The adapter will interrupt
and the interrupt handler will call done. */
......@@ -912,18 +899,18 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
{
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(host->host_lock, flags);
outl(isa_virt_to_bus(&config.mscp[mscp_index]), config.ogm_address);
inb(0xc80); /* delay */
udelay(8);
outb(0x80, config.ogm_address - 1);
outb(0x2, LCL_DOORBELL_INTR(config.doorbell_address));
#if ULTRASTOR_DEBUG & UD_ABORT
log_ultrastor_abort(&config, mscp_index);
printk(out, ogm_status, ogm_addr, icm_status, icm_addr);
#endif
restore_flags(flags);
return SCSI_ABORT_PENDING;
spin_unlock_irqrestore(host->host_lock, flags);
/* FIXME: add a wait for the abort to complete */
return SUCCESS;
}
#if ULTRASTOR_DEBUG & UD_ABORT
......@@ -953,27 +940,30 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
done = config.mscp[mscp_index].done;
config.mscp[mscp_index].done = 0;
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);
spin_unlock_irqrestore(host->host_lock, flags);
/* 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;
register int i;
int i;
struct Scsi_Host *host = SCpnt->host;
#if (ULTRASTOR_DEBUG & UD_RESET)
printk("US14F: reset: called\n");
#endif
if(config.slot)
return SCSI_RESET_PUNT; /* Do not attempt a reset for the 24f */
save_flags(flags);
cli();
return FAILED;
spin_lock_irqsave(host->host_lock, flags);
/* Reset the adapter and SCSI bus. The SCSI bus reset can be
inhibited by clearing ultrastor_bus_reset before probe. */
outb(0xc0, LCL_DOORBELL_INTR(config.doorbell_address));
......@@ -1005,7 +995,10 @@ int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
#endif
/* 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);
#if ULTRASTOR_MAX_CMDS == 1
......@@ -1014,7 +1007,7 @@ int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
config.mscp_free = ~0;
#endif
restore_flags(flags);
spin_unlock_irqrestore(host->host_lock, flags);
return SCSI_RESET_SUCCESS;
}
......@@ -1041,7 +1034,7 @@ static void ultrastor_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if ULTRASTOR_MAX_CMDS > 1
unsigned int mscp_index;
#endif
register struct mscp *mscp;
struct mscp *mscp;
void (*done)(Scsi_Cmnd *);
Scsi_Cmnd *SCtmp;
......
......@@ -13,13 +13,12 @@
#ifndef _ULTRASTOR_H
#define _ULTRASTOR_H
int ultrastor_detect(Scsi_Host_Template *);
const char *ultrastor_info(struct Scsi_Host * shpnt);
int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int ultrastor_abort(Scsi_Cmnd *);
int ultrastor_reset(Scsi_Cmnd *, unsigned int);
int ultrastor_biosparam(struct scsi_device *, struct block_device *,
sector_t, int *);
static int ultrastor_detect(Scsi_Host_Template *);
static const char *ultrastor_info(struct Scsi_Host * shpnt);
static int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
static int ultrastor_abort(Scsi_Cmnd *);
static int ultrastor_host_reset(Scsi_Cmnd *);
static int ultrastor_biosparam(struct scsi_device *, struct block_device *, sector_t, int *);
#define ULTRASTOR_14F_MAX_SG 16
......@@ -35,8 +34,8 @@ int ultrastor_biosparam(struct scsi_device *, struct block_device *,
detect: ultrastor_detect, \
info: ultrastor_info, \
queuecommand: ultrastor_queuecommand, \
abort: ultrastor_abort, \
reset: ultrastor_reset, \
eh_abort_handler: ultrastor_abort, \
eh_host_reset_handler: ultrastor_host_reset, \
bios_param: ultrastor_biosparam, \
can_queue: ULTRASTOR_MAX_CMDS, \
this_id: 0, \
......
......@@ -1240,7 +1240,7 @@ static int wd7000_adapter_reset(Adapter * host)
host->control = 0; /* this must always shadow ASC_CONTROL */
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 */
}
......@@ -1249,25 +1249,25 @@ static int wd7000_adapter_reset(Adapter * host)
switch (diag) {
case 2:
printk("RAM failure.\n");
printk(KERN_ERR "RAM failure.\n");
break;
case 3:
printk("FIFO R/W failed\n");
printk(KERN_ERR "FIFO R/W failed\n");
break;
case 4:
printk("SBIC register R/W failed\n");
printk(KERN_ERR "SBIC register R/W failed\n");
break;
case 5:
printk("Initialization D-FF failed.\n");
printk(KERN_ERR "Initialization D-FF failed.\n");
break;
case 6:
printk("Host IRQ D-FF failed.\n");
printk(KERN_ERR "Host IRQ D-FF failed.\n");
break;
case 7:
printk("ROM checksum error.\n");
printk(KERN_ERR "ROM checksum error.\n");
break;
default:
printk("diagnostic code 0x%02Xh received.\n", diag);
printk(KERN_ERR "diagnostic code 0x%02Xh received.\n", diag);
}
return -1;
}
......
......@@ -74,7 +74,7 @@
#ifdef CONFIG_FS_EXT_ATTR
# include <linux/ext_attr.h>
# ifdef CONFIG_FS_POSIX_ACL
# if 0 /* was a broken check for Posix ACLs */
# include <linux/posix_acl.h>
# endif
#endif
......@@ -466,7 +466,7 @@ int lento_setattr(const char *name, struct iattr *iattr,
struct dentry *dentry;
struct presto_file_set *fset;
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;
#endif
......@@ -507,7 +507,7 @@ int lento_setattr(const char *name, struct iattr *iattr,
(dentry->d_inode->i_mode & ~S_IALLUGO);
CDEBUG(D_PIOCTL, "chmod: orig %#o, set %#o, result %#o\n",
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
* since it tries to modify the ACL using
* set_ext_attr which recurses back into presto.
......@@ -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*/
if (iattr->ia_valid & ATTR_MODE)
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,
#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
* a mark_inode_dirty!). We need to duplicate this at the reintegrator
* 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,
goto exit;
}
#ifdef CONFIG_FS_POSIX_ACL
#if 0 /* was a broken check for Posix ACLs */
/* Reset mode if specified*/
/* XXX: when we do native acl support, move this code out! */
if (mode != NULL) {
......
......@@ -1401,6 +1401,7 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l)
inode = filp->f_dentry->d_inode;
#ifdef CONFIG_MMU
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
*/
......@@ -1413,6 +1414,7 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l)
goto out;
}
}
#endif
error = flock_to_posix_lock(filp, file_lock, &flock);
if (error)
......
......@@ -96,8 +96,8 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
}
#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) \
&& !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) \
&& !defined(__arm__)
&& !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) \
&& !defined(__arm__) && !defined(CONFIG_V850)
/*
* For backward compatibility? Maybe this should be moved
......
......@@ -19,4 +19,8 @@ struct timer_opts{
#define TICK_SIZE (tick_nsec / 1000)
extern struct timer_opts* select_timer(void);
/* Modifiers for buggy PIT handling */
extern int pit_latch_buggy;
#endif
......@@ -17,8 +17,8 @@ config CRC32
#
config ZLIB_INFLATE
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
default y if CRAMFS=y || PPP_DEFLATE=y || JFFS2_FS=y || ZISOFS_FS=y || BINFMT_ZFLAT=y
default m if CRAMFS=m || PPP_DEFLATE=m || JFFS2_FS=m || ZISOFS_FS=m || BINFMT_ZFLAT=m
config ZLIB_DEFLATE
tristate
......
......@@ -11,6 +11,6 @@ $(obj)/initramfs_data.o: $(src)/initramfs_data.scr $(obj)/initramfs_data.cpio.gz
$(call if_changed,ld)
$(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