Commit 994b3fb0 authored by Benjamin LaHaise's avatar Benjamin LaHaise

Merge redhat.com:/md0/linus-2.5 into redhat.com:/md0/aio-2.5

parents ecb796f5 469d2810
...@@ -738,7 +738,7 @@ S: Maintained ...@@ -738,7 +738,7 @@ S: Maintained
IBM ServeRAID RAID DRIVER IBM ServeRAID RAID DRIVER
P: Jack Hammer P: Jack Hammer
P: Dave Jeffrey P: Dave Jeffery
M: ipslinux@adaptec.com M: ipslinux@adaptec.com
W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html
S: Supported S: Supported
......
...@@ -251,6 +251,10 @@ CONFIG_ALPHA_PRIMO ...@@ -251,6 +251,10 @@ CONFIG_ALPHA_PRIMO
CONFIG_ALPHA_GAMMA CONFIG_ALPHA_GAMMA
Say Y if you have an AS 2000 5/xxx or an AS 2100 5/xxx. Say Y if you have an AS 2000 5/xxx or an AS 2100 5/xxx.
CONFIG_ALPHA_EV67
Is this a machine based on the EV67 core? If in doubt, select N here
and the machine will be treated as an EV6.
CONFIG_ALPHA_SRM CONFIG_ALPHA_SRM
There are two different types of booting firmware on Alphas: SRM, There are two different types of booting firmware on Alphas: SRM,
which is command line driven, and ARC, which uses menus and arrow which is command line driven, and ARC, which uses menus and arrow
...@@ -610,3 +614,14 @@ CONFIG_DEBUG_SPINLOCK ...@@ -610,3 +614,14 @@ CONFIG_DEBUG_SPINLOCK
best used in conjunction with the NMI watchdog so that spinlock best used in conjunction with the NMI watchdog so that spinlock
deadlocks are also debuggable. deadlocks are also debuggable.
CONFIG_DEBUG_RWLOCK
If you say Y here then read-write lock processing will count how many
times it has tried to get the lock and issue an error message after
too many attempts. If you suspect a rwlock problem or a kernel
hacker asks for this option then say Y. Otherwise say N.
CONFIG_DEBUG_SEMAPHORE
If you say Y here then semaphore processing will issue lots of
verbose debugging messages. If you suspect a semaphore problem or a
kernel hacker asks for this option then say Y. Otherwise say N.
...@@ -99,30 +99,32 @@ export libs-y ...@@ -99,30 +99,32 @@ export libs-y
MAKEBOOT = $(MAKE) -C arch/alpha/boot MAKEBOOT = $(MAKE) -C arch/alpha/boot
rawboot: rawboot: vmlinux
@$(MAKEBOOT) rawboot @$(MAKEBOOT) rawboot
boot: vmlinux
@$(MAKEBOOT)
# #
# My boot writes directly to a specific disk partition, I doubt most # My boot writes directly to a specific disk partition, I doubt most
# people will want to do that without changes.. # people will want to do that without changes..
# #
msb my-special-boot: msb my-special-boot: vmlinux
@$(MAKEBOOT) msb @$(MAKEBOOT) msb
bootimage: bootimage: vmlinux
@$(MAKEBOOT) bootimage @$(MAKEBOOT) bootimage
srmboot: srmboot: vmlinux
@$(MAKEBOOT) srmboot @$(MAKEBOOT) srmboot
archclean: archclean:
@$(MAKE) -C arch/alpha/kernel clean
@$(MAKEBOOT) clean @$(MAKEBOOT) clean
archmrproper: archmrproper:
rm -f include/asm-alpha/asm_offsets.h rm -f include/asm-alpha/asm_offsets.h
bootpfile: bootpfile: vmlinux
@$(MAKEBOOT) bootpfile @$(MAKEBOOT) bootpfile
......
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
# Copyright (C) 1994 by Linus Torvalds # Copyright (C) 1994 by Linus Torvalds
# #
LINKFLAGS = -static -T bootloader.lds #-N -relax LINKFLAGS = -static -T bootloader.lds -uvsprintf #-N -relax
CFLAGS := $(CFLAGS) -I$(TOPDIR)/include
.S.s: .S.s:
$(CPP) $(AFLAGS) -traditional -o $*.o $< $(CPP) $(AFLAGS) -traditional -o $*.o $<
......
...@@ -8,8 +8,9 @@ EXTRA_AFLAGS := $(CFLAGS) ...@@ -8,8 +8,9 @@ EXTRA_AFLAGS := $(CFLAGS)
export-objs := alpha_ksyms.o export-objs := alpha_ksyms.o
obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o irq_alpha.o \ obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
signal.o setup.o ptrace.o time.o semaphore.o alpha_ksyms.o irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
alpha_ksyms.o systbls.o
# #
# FIXME! # FIXME!
......
...@@ -161,7 +161,6 @@ EXPORT_SYMBOL(sys_read); ...@@ -161,7 +161,6 @@ EXPORT_SYMBOL(sys_read);
EXPORT_SYMBOL(sys_lseek); EXPORT_SYMBOL(sys_lseek);
EXPORT_SYMBOL(__kernel_execve); EXPORT_SYMBOL(__kernel_execve);
EXPORT_SYMBOL(sys_setsid); EXPORT_SYMBOL(sys_setsid);
EXPORT_SYMBOL(sys_sync);
EXPORT_SYMBOL(sys_wait4); EXPORT_SYMBOL(sys_wait4);
/* Networking helper routines. */ /* Networking helper routines. */
......
...@@ -9,8 +9,7 @@ ...@@ -9,8 +9,7 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/asm_offsets.h> #include <asm/asm_offsets.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/unistd.h>
#define NR_SYSCALLS 381
/* /*
* stack offsets * stack offsets
...@@ -677,6 +676,7 @@ ret_success: ...@@ -677,6 +676,7 @@ ret_success:
.end entSys .end entSys
.align 3 .align 3
.globl sys_sigreturn
.ent sys_sigreturn .ent sys_sigreturn
sys_sigreturn: sys_sigreturn:
mov $30,$17 mov $30,$17
...@@ -688,6 +688,7 @@ sys_sigreturn: ...@@ -688,6 +688,7 @@ sys_sigreturn:
.end sys_sigreturn .end sys_sigreturn
.align 3 .align 3
.globl sys_rt_sigreturn
.ent sys_rt_sigreturn .ent sys_rt_sigreturn
sys_rt_sigreturn: sys_rt_sigreturn:
mov $30,$17 mov $30,$17
...@@ -699,6 +700,7 @@ sys_rt_sigreturn: ...@@ -699,6 +700,7 @@ sys_rt_sigreturn:
.end sys_rt_sigreturn .end sys_rt_sigreturn
.align 3 .align 3
.globl sys_sigsuspend
.ent sys_sigsuspend .ent sys_sigsuspend
sys_sigsuspend: sys_sigsuspend:
mov $30,$17 mov $30,$17
...@@ -713,6 +715,7 @@ sys_sigsuspend: ...@@ -713,6 +715,7 @@ sys_sigsuspend:
.end sys_sigsuspend .end sys_sigsuspend
.align 3 .align 3
.globl sys_rt_sigsuspend
.ent sys_rt_sigsuspend .ent sys_rt_sigsuspend
sys_rt_sigsuspend: sys_rt_sigsuspend:
mov $30,$18 mov $30,$18
...@@ -725,421 +728,3 @@ sys_rt_sigsuspend: ...@@ -725,421 +728,3 @@ sys_rt_sigsuspend:
lda $30,SWITCH_STACK_SIZE+16($30) lda $30,SWITCH_STACK_SIZE+16($30)
ret $31,($26),1 ret $31,($26),1
.end sys_rt_sigsuspend .end sys_rt_sigsuspend
.data
.align 3
.globl sys_call_table
sys_call_table:
.quad alpha_ni_syscall /* 0 */
.quad sys_exit
.quad sys_fork
.quad sys_read
.quad sys_write
.quad alpha_ni_syscall /* 5 */
.quad sys_close
.quad osf_wait4
.quad alpha_ni_syscall
.quad sys_link
.quad sys_unlink /* 10 */
.quad alpha_ni_syscall
.quad sys_chdir
.quad sys_fchdir
.quad sys_mknod
.quad sys_chmod /* 15 */
.quad sys_chown
.quad osf_brk
.quad alpha_ni_syscall
.quad sys_lseek
.quad sys_getxpid /* 20 */
.quad osf_mount
.quad sys_umount
.quad sys_setuid
.quad sys_getxuid
.quad alpha_ni_syscall /* 25 */
.quad sys_ptrace
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 30 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_access
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 35 */
.quad sys_sync
.quad sys_kill
.quad alpha_ni_syscall
.quad sys_setpgid
.quad alpha_ni_syscall /* 40 */
.quad sys_dup
.quad sys_pipe
.quad osf_set_program_attributes
.quad alpha_ni_syscall
.quad sys_open /* 45 */
.quad alpha_ni_syscall
.quad sys_getxgid
.quad osf_sigprocmask
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 50 */
.quad sys_acct
.quad sys_sigpending
.quad alpha_ni_syscall
.quad sys_ioctl
.quad alpha_ni_syscall /* 55 */
.quad alpha_ni_syscall
.quad sys_symlink
.quad sys_readlink
.quad sys_execve
.quad sys_umask /* 60 */
.quad sys_chroot
.quad alpha_ni_syscall
.quad sys_getpgrp
.quad sys_getpagesize
.quad alpha_ni_syscall /* 65 */
.quad sys_vfork
.quad sys_newstat
.quad sys_newlstat
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 70 */
.quad osf_mmap
.quad alpha_ni_syscall
.quad sys_munmap
.quad sys_mprotect
.quad sys_madvise /* 75 */
.quad sys_vhangup
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_getgroups
/* map BSD's setpgrp to sys_setpgid for binary compatibility: */
.quad sys_setgroups /* 80 */
.quad alpha_ni_syscall
.quad sys_setpgid
.quad osf_setitimer
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 85 */
.quad osf_getitimer
.quad sys_gethostname
.quad sys_sethostname
.quad sys_getdtablesize
.quad sys_dup2 /* 90 */
.quad sys_newfstat
.quad sys_fcntl
.quad osf_select
.quad sys_poll
.quad sys_fsync /* 95 */
.quad sys_setpriority
.quad sys_socket
.quad sys_connect
.quad sys_accept
.quad osf_getpriority /* 100 */
.quad sys_send
.quad sys_recv
.quad sys_sigreturn
.quad sys_bind
.quad sys_setsockopt /* 105 */
.quad sys_listen
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 110 */
.quad sys_sigsuspend
.quad osf_sigstack
.quad sys_recvmsg
.quad sys_sendmsg
.quad alpha_ni_syscall /* 115 */
.quad osf_gettimeofday
.quad osf_getrusage
.quad sys_getsockopt
.quad alpha_ni_syscall
#ifdef CONFIG_OSF4_COMPAT
.quad osf_readv /* 120 */
.quad osf_writev
#else
.quad sys_readv /* 120 */
.quad sys_writev
#endif
.quad osf_settimeofday
.quad sys_fchown
.quad sys_fchmod
.quad sys_recvfrom /* 125 */
.quad sys_setreuid
.quad sys_setregid
.quad sys_rename
.quad sys_truncate
.quad sys_ftruncate /* 130 */
.quad sys_flock
.quad sys_setgid
.quad sys_sendto
.quad sys_shutdown
.quad sys_socketpair /* 135 */
.quad sys_mkdir
.quad sys_rmdir
.quad osf_utimes
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 140 */
.quad sys_getpeername
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_getrlimit
.quad sys_setrlimit /* 145 */
.quad alpha_ni_syscall
.quad sys_setsid
.quad sys_quotactl
.quad alpha_ni_syscall
.quad sys_getsockname /* 150 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 155 */
.quad osf_sigaction
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad osf_getdirentries
.quad osf_statfs /* 160 */
.quad osf_fstatfs
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad osf_getdomainname /* 165 */
.quad sys_setdomainname
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 170 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 175 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 180 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 185 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 190 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 195 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad osf_swapon
.quad sys_msgctl /* 200 */
.quad sys_msgget
.quad sys_msgrcv
.quad sys_msgsnd
.quad sys_semctl
.quad sys_semget /* 205 */
.quad sys_semop
.quad osf_utsname
.quad sys_lchown
.quad osf_shmat
.quad sys_shmctl /* 210 */
.quad sys_shmdt
.quad sys_shmget
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 215 */
.quad alpha_ni_syscall
.quad sys_msync
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 220 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 225 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 230 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_getpgid
.quad sys_getsid
.quad sys_sigaltstack /* 235 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 240 */
.quad osf_sysinfo
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad osf_proplist_syscall
.quad alpha_ni_syscall /* 245 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 250 */
.quad osf_usleep_thread
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_sysfs
.quad alpha_ni_syscall /* 255 */
.quad osf_getsysinfo
.quad osf_setsysinfo
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 260 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 265 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 270 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 275 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 280 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 285 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 290 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 295 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
/* linux-specific system calls start at 300 */
.quad sys_bdflush /* 300 */
.quad sys_sethae
.quad sys_mount
.quad sys_old_adjtimex
.quad sys_swapoff
.quad sys_getdents /* 305 */
.quad alpha_create_module
.quad sys_init_module
.quad sys_delete_module
.quad sys_get_kernel_syms
.quad sys_syslog /* 310 */
.quad sys_reboot
.quad sys_clone
.quad sys_uselib
.quad sys_mlock
.quad sys_munlock /* 315 */
.quad sys_mlockall
.quad sys_munlockall
.quad sys_sysinfo
.quad sys_sysctl
.quad sys_ni_syscall /* 320 */
.quad sys_oldumount
.quad sys_swapon
.quad sys_times
.quad sys_personality
.quad sys_setfsuid /* 325 */
.quad sys_setfsgid
.quad sys_ustat
.quad sys_statfs
.quad sys_fstatfs
.quad sys_sched_setparam /* 330 */
.quad sys_sched_getparam
.quad sys_sched_setscheduler
.quad sys_sched_getscheduler
.quad sys_sched_yield
.quad sys_sched_get_priority_max /* 335 */
.quad sys_sched_get_priority_min
.quad sys_sched_rr_get_interval
.quad sys_ni_syscall /* sys_afs_syscall */
.quad sys_newuname
.quad sys_nanosleep /* 340 */
.quad sys_mremap
.quad sys_nfsservctl
.quad sys_setresuid
.quad sys_getresuid
.quad sys_pciconfig_read /* 345 */
.quad sys_pciconfig_write
.quad sys_query_module
.quad sys_prctl
.quad sys_pread64
.quad sys_pwrite64 /* 350 */
.quad sys_rt_sigreturn
.quad sys_rt_sigaction
.quad sys_rt_sigprocmask
.quad sys_rt_sigpending
.quad sys_rt_sigtimedwait /* 355 */
.quad sys_rt_sigqueueinfo
.quad sys_rt_sigsuspend
.quad sys_select
.quad sys_gettimeofday
.quad sys_settimeofday /* 360 */
.quad sys_getitimer
.quad sys_setitimer
.quad sys_utimes
.quad sys_getrusage
.quad sys_wait4 /* 365 */
.quad sys_adjtimex
.quad sys_getcwd
.quad sys_capget
.quad sys_capset
.quad sys_sendfile /* 370 */
.quad sys_setresgid
.quad sys_getresgid
.quad sys_ni_syscall /* sys_dipc */
.quad sys_pivot_root
.quad sys_mincore /* 375 */
.quad sys_pciconfig_iobase
.quad sys_getdents64
.quad sys_gettid
.quad sys_readahead
.quad sys_ni_syscall /* 380, sys_security */
.quad sys_tkill
.quad sys_setxattr
.quad sys_lsetxattr
.quad sys_fsetxattr
.quad sys_getxattr
.quad sys_lgetxattr
.quad sys_fgetxattr
.quad sys_listxattr
.quad sys_llistxattr
.quad sys_flistxattr /* 390 */
.quad sys_removexattr
.quad sys_lremovexattr
.quad sys_fremovexattr
.quad sys_futex
.quad sys_sched_setaffinity
.quad sys_sched_getaffinity
.quad sys_ni_syscall /* 397, tux */
.quad sys_io_setup
.quad sys_io_destroy
.quad sys_io_getevents /* 400 */
.quad sys_io_submit
.quad sys_io_cancel
.quad sys_ni_syscall /* 403, sys_alloc_hugepages */
.quad sys_ni_syscall /* 404, sys_free_hugepages */
.quad sys_exit_group
...@@ -44,8 +44,9 @@ ...@@ -44,8 +44,9 @@
#include <asm/processor.h> #include <asm/processor.h>
extern int do_pipe(int *); extern int do_pipe(int *);
extern asmlinkage unsigned long sys_brk(unsigned long); extern asmlinkage unsigned long sys_brk(unsigned long);
extern int sys_getpriority(int, int);
extern asmlinkage unsigned long sys_create_module(char *, unsigned long);
/* /*
* Brk needs to return an error. Still support Linux's brk(0) query idiom, * Brk needs to return an error. Still support Linux's brk(0) query idiom,
...@@ -53,7 +54,8 @@ extern asmlinkage unsigned long sys_brk(unsigned long); ...@@ -53,7 +54,8 @@ extern asmlinkage unsigned long sys_brk(unsigned long);
* identical to OSF as we don't return 0 on success, but doing otherwise * identical to OSF as we don't return 0 on success, but doing otherwise
* would require changes to libc. Hopefully this is good enough. * would require changes to libc. Hopefully this is good enough.
*/ */
asmlinkage unsigned long osf_brk(unsigned long brk) asmlinkage unsigned long
osf_brk(unsigned long brk)
{ {
unsigned long retval = sys_brk(brk); unsigned long retval = sys_brk(brk);
if (brk && brk != retval) if (brk && brk != retval)
...@@ -64,9 +66,9 @@ asmlinkage unsigned long osf_brk(unsigned long brk) ...@@ -64,9 +66,9 @@ asmlinkage unsigned long osf_brk(unsigned long brk)
/* /*
* This is pure guess-work.. * This is pure guess-work..
*/ */
asmlinkage int osf_set_program_attributes( asmlinkage int
unsigned long text_start, unsigned long text_len, osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
unsigned long bss_start, unsigned long bss_len) unsigned long bss_start, unsigned long bss_len)
{ {
struct mm_struct *mm; struct mm_struct *mm;
...@@ -106,8 +108,9 @@ struct osf_dirent_callback { ...@@ -106,8 +108,9 @@ struct osf_dirent_callback {
int error; int error;
}; };
static int osf_filldir(void *__buf, const char *name, int namlen, loff_t offset, static int
ino_t ino, unsigned int d_type) osf_filldir(void *__buf, const char *name, int namlen, loff_t offset,
ino_t ino, unsigned int d_type)
{ {
struct osf_dirent *dirent; struct osf_dirent *dirent;
struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf; struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;
...@@ -134,8 +137,9 @@ static int osf_filldir(void *__buf, const char *name, int namlen, loff_t offset, ...@@ -134,8 +137,9 @@ static int osf_filldir(void *__buf, const char *name, int namlen, loff_t offset,
return 0; return 0;
} }
asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent, asmlinkage int
unsigned int count, long *basep) osf_getdirentries(unsigned int fd, struct osf_dirent *dirent,
unsigned int count, long *basep)
{ {
int error; int error;
struct file *file; struct file *file;
...@@ -159,9 +163,9 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent, ...@@ -159,9 +163,9 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent,
if (count != buf.count) if (count != buf.count)
error = count - buf.count; error = count - buf.count;
out_putf: out_putf:
fput(file); fput(file);
out: out:
return error; return error;
} }
...@@ -172,8 +176,9 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent, ...@@ -172,8 +176,9 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent,
* Alpha syscall convention has no problem returning negative * Alpha syscall convention has no problem returning negative
* values: * values:
*/ */
asmlinkage int osf_getpriority(int which, int who, int a2, int a3, int a4, asmlinkage int
int a5, struct pt_regs regs) osf_getpriority(int which, int who,
int a2, int a3, int a4, int a5, struct pt_regs regs)
{ {
extern int sys_getpriority(int, int); extern int sys_getpriority(int, int);
int prio; int prio;
...@@ -194,24 +199,24 @@ asmlinkage int osf_getpriority(int which, int who, int a2, int a3, int a4, ...@@ -194,24 +199,24 @@ asmlinkage int osf_getpriority(int which, int who, int a2, int a3, int a4,
/* /*
* No need to acquire the kernel lock, we're local.. * No need to acquire the kernel lock, we're local..
*/ */
asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, asmlinkage unsigned long
int a5, struct pt_regs regs) sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5, struct pt_regs regs)
{ {
struct task_struct * tsk = current; struct task_struct * tsk = current;
(&regs)->r20 = tsk->euid; (&regs)->r20 = tsk->euid;
return tsk->uid; return tsk->uid;
} }
asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, asmlinkage unsigned long
int a5, struct pt_regs regs) sys_getxgid(int a0, int a1, int a2, int a3, int a4, int a5, struct pt_regs regs)
{ {
struct task_struct * tsk = current; struct task_struct * tsk = current;
(&regs)->r20 = tsk->egid; (&regs)->r20 = tsk->egid;
return tsk->gid; return tsk->gid;
} }
asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, asmlinkage unsigned long
int a5, struct pt_regs regs) sys_getxpid(int a0, int a1, int a2, int a3, int a4, int a5, struct pt_regs regs)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
...@@ -226,9 +231,9 @@ asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, ...@@ -226,9 +231,9 @@ asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4,
return tsk->tgid; return tsk->tgid;
} }
asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len, asmlinkage unsigned long
unsigned long prot, unsigned long flags, unsigned long fd, osf_mmap(unsigned long addr, unsigned long len, unsigned long prot,
unsigned long off) unsigned long flags, unsigned long fd, unsigned long off)
{ {
struct file *file = NULL; struct file *file = NULL;
unsigned long ret = -EBADF; unsigned long ret = -EBADF;
...@@ -249,7 +254,7 @@ asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len, ...@@ -249,7 +254,7 @@ asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
up_write(&current->mm->mmap_sem); up_write(&current->mm->mmap_sem);
if (file) if (file)
fput(file); fput(file);
out: out:
return ret; return ret;
} }
...@@ -271,7 +276,9 @@ struct osf_statfs { ...@@ -271,7 +276,9 @@ struct osf_statfs {
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
} *osf_stat; } *osf_stat;
static int linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf_stat, unsigned long bufsiz) static int
linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf_stat,
unsigned long bufsiz)
{ {
struct osf_statfs tmp_stat; struct osf_statfs tmp_stat;
...@@ -291,7 +298,9 @@ static int linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf ...@@ -291,7 +298,9 @@ static int linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf
return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0; return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;
} }
static int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsigned long bufsiz) static int
do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer,
unsigned long bufsiz)
{ {
struct statfs linux_stat; struct statfs linux_stat;
int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat); int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat);
...@@ -300,7 +309,8 @@ static int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsi ...@@ -300,7 +309,8 @@ static int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsi
return error; return error;
} }
asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long bufsiz) asmlinkage int
osf_statfs(char *path, struct osf_statfs *buffer, unsigned long bufsiz)
{ {
struct nameidata nd; struct nameidata nd;
int retval; int retval;
...@@ -313,7 +323,8 @@ asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long b ...@@ -313,7 +323,8 @@ asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long b
return retval; return retval;
} }
asmlinkage int osf_fstatfs(unsigned long fd, struct osf_statfs *buffer, unsigned long bufsiz) asmlinkage int
osf_fstatfs(unsigned long fd, struct osf_statfs *buffer, unsigned long bufsiz)
{ {
struct file *file; struct file *file;
int retval; int retval;
...@@ -342,10 +353,9 @@ struct cdfs_args { ...@@ -342,10 +353,9 @@ struct cdfs_args {
char *devname; char *devname;
int flags; int flags;
uid_t exroot; uid_t exroot;
/*
* This has lots more here, which Linux handles with the option block /* This has lots more here, which Linux handles with the option block
* but I'm too lazy to do the translation into ASCII. but I'm too lazy to do the translation into ASCII. */
*/
}; };
struct procfs_args { struct procfs_args {
...@@ -362,7 +372,8 @@ struct procfs_args { ...@@ -362,7 +372,8 @@ struct procfs_args {
* Just how long ago was it written? OTOH our UFS driver may be still * Just how long ago was it written? OTOH our UFS driver may be still
* unhappy with OSF UFS. [CHECKME] * unhappy with OSF UFS. [CHECKME]
*/ */
static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags) static int
osf_ufs_mount(char *dirname, struct ufs_args *args, int flags)
{ {
int retval; int retval;
struct cdfs_args tmp; struct cdfs_args tmp;
...@@ -377,11 +388,12 @@ static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags) ...@@ -377,11 +388,12 @@ static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags)
goto out; goto out;
retval = do_mount(devname, dirname, "ext2", flags, NULL); retval = do_mount(devname, dirname, "ext2", flags, NULL);
putname(devname); putname(devname);
out: out:
return retval; return retval;
} }
static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags) static int
osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags)
{ {
int retval; int retval;
struct cdfs_args tmp; struct cdfs_args tmp;
...@@ -396,11 +408,12 @@ static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags) ...@@ -396,11 +408,12 @@ static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags)
goto out; goto out;
retval = do_mount(devname, dirname, "iso9660", flags, NULL); retval = do_mount(devname, dirname, "iso9660", flags, NULL);
putname(devname); putname(devname);
out: out:
return retval; return retval;
} }
static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags) static int
osf_procfs_mount(char *dirname, struct procfs_args *args, int flags)
{ {
struct procfs_args tmp; struct procfs_args tmp;
...@@ -410,7 +423,8 @@ static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags) ...@@ -410,7 +423,8 @@ static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags)
return do_mount("", dirname, "proc", flags, NULL); return do_mount("", dirname, "proc", flags, NULL);
} }
asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data) asmlinkage int
osf_mount(unsigned long typenr, char *path, int flag, void *data)
{ {
int retval = -EINVAL; int retval = -EINVAL;
char *name; char *name;
...@@ -435,12 +449,13 @@ asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data) ...@@ -435,12 +449,13 @@ asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data)
printk("osf_mount(%ld, %x)\n", typenr, flag); printk("osf_mount(%ld, %x)\n", typenr, flag);
} }
putname(name); putname(name);
out: out:
unlock_kernel(); unlock_kernel();
return retval; return retval;
} }
asmlinkage int osf_utsname(char *name) asmlinkage int
osf_utsname(char *name)
{ {
int error; int error;
...@@ -458,12 +473,13 @@ asmlinkage int osf_utsname(char *name) ...@@ -458,12 +473,13 @@ asmlinkage int osf_utsname(char *name)
goto out; goto out;
error = 0; error = 0;
out: out:
up_read(&uts_sem); up_read(&uts_sem);
return error; return error;
} }
asmlinkage int osf_swapon(const char *path, int flags, int lowat, int hiwat) asmlinkage int
osf_swapon(const char *path, int flags, int lowat, int hiwat)
{ {
int ret; int ret;
...@@ -474,35 +490,36 @@ asmlinkage int osf_swapon(const char *path, int flags, int lowat, int hiwat) ...@@ -474,35 +490,36 @@ asmlinkage int osf_swapon(const char *path, int flags, int lowat, int hiwat)
return ret; return ret;
} }
asmlinkage unsigned long sys_getpagesize(void) asmlinkage unsigned long
sys_getpagesize(void)
{ {
return PAGE_SIZE; return PAGE_SIZE;
} }
asmlinkage unsigned long sys_getdtablesize(void) asmlinkage unsigned long
sys_getdtablesize(void)
{ {
return NR_OPEN; return NR_OPEN;
} }
asmlinkage int sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5, asmlinkage int
struct pt_regs regs) sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5, struct pt_regs regs)
{ {
int fd[2]; int fd[2], error;
int error;
error = do_pipe(fd); error = do_pipe(fd);
if (error) if (!error) {
goto out; regs.r20 = fd[1];
(&regs)->r20 = fd[1]; error = fd[0];
error = fd[0]; }
out:
return error; return error;
} }
/* /*
* For compatibility with OSF/1 only. Use utsname(2) instead. * For compatibility with OSF/1 only. Use utsname(2) instead.
*/ */
asmlinkage int osf_getdomainname(char *name, int namelen) asmlinkage int
osf_getdomainname(char *name, int namelen)
{ {
unsigned len; unsigned len;
int i, error; int i, error;
...@@ -522,12 +539,12 @@ asmlinkage int osf_getdomainname(char *name, int namelen) ...@@ -522,12 +539,12 @@ asmlinkage int osf_getdomainname(char *name, int namelen)
break; break;
} }
up_read(&uts_sem); up_read(&uts_sem);
out: out:
return error; return error;
} }
asmlinkage long
asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg) osf_shmat(int shmid, void *shmaddr, int shmflg)
{ {
unsigned long raddr; unsigned long raddr;
long err; long err;
...@@ -541,7 +558,7 @@ asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg) ...@@ -541,7 +558,7 @@ asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg)
* non-negative longs! * non-negative longs!
*/ */
err = raddr; err = raddr;
out: out:
unlock_kernel(); unlock_kernel();
return err; return err;
} }
...@@ -612,7 +629,8 @@ enum pl_code { ...@@ -612,7 +629,8 @@ enum pl_code {
PL_DEL = 5, PL_FDEL = 6 PL_DEL = 5, PL_FDEL = 6
}; };
asmlinkage long osf_proplist_syscall(enum pl_code code, union pl_args *args) asmlinkage long
osf_proplist_syscall(enum pl_code code, union pl_args *args)
{ {
long error; long error;
int *min_buf_size_ptr; int *min_buf_size_ptr;
...@@ -655,7 +673,8 @@ asmlinkage long osf_proplist_syscall(enum pl_code code, union pl_args *args) ...@@ -655,7 +673,8 @@ asmlinkage long osf_proplist_syscall(enum pl_code code, union pl_args *args)
return error; return error;
} }
asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss) asmlinkage int
osf_sigstack(struct sigstack *uss, struct sigstack *uoss)
{ {
unsigned long usp = rdusp(); unsigned long usp = rdusp();
unsigned long oss_sp = current->sas_ss_sp + current->sas_ss_size; unsigned long oss_sp = current->sas_ss_sp + current->sas_ss_size;
...@@ -691,7 +710,7 @@ asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss) ...@@ -691,7 +710,7 @@ asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss)
} }
error = 0; error = 0;
out: out:
return error; return error;
} }
...@@ -702,32 +721,28 @@ asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss) ...@@ -702,32 +721,28 @@ asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss)
* create_module() because it's one of the few system calls * create_module() because it's one of the few system calls
* that return kernel addresses (which are negative). * that return kernel addresses (which are negative).
*/ */
asmlinkage unsigned long alpha_create_module(char *module_name, unsigned long size,
int a3, int a4, int a5, int a6, asmlinkage unsigned long
struct pt_regs regs) alpha_create_module(char *module_name, unsigned long size,
int a3, int a4, int a5, int a6, struct pt_regs regs)
{ {
asmlinkage unsigned long sys_create_module(char *, unsigned long);
long retval; long retval;
lock_kernel(); lock_kernel();
retval = sys_create_module(module_name, size); retval = sys_create_module(module_name, size);
/*
* we get either a module address or an error number,
* and we know the error number is a small negative
* number, while the address is always negative but
* much larger.
*/
if (retval + 1000 > 0)
goto out;
/* tell entry.S:syscall_error that this is NOT an error: */ /* We get either a module address or an error number, and we know
regs.r0 = 0; the error number is a small negative number, while the address
out: is always negative but much larger. */
unlock_kernel(); if (retval + 1000 < 0)
regs.r0 = 0;
unlock_kernel();
return retval; return retval;
} }
asmlinkage long osf_sysinfo(int command, char *buf, long count) asmlinkage long
osf_sysinfo(int command, char *buf, long count)
{ {
static char * sysinfo_table[] = { static char * sysinfo_table[] = {
system_utsname.sysname, system_utsname.sysname,
...@@ -761,13 +776,13 @@ asmlinkage long osf_sysinfo(int command, char *buf, long count) ...@@ -761,13 +776,13 @@ asmlinkage long osf_sysinfo(int command, char *buf, long count)
else else
err = 0; err = 0;
up_read(&uts_sem); up_read(&uts_sem);
out: out:
return err; return err;
} }
asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, asmlinkage unsigned long
unsigned long nbytes, osf_getsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
int *start, void *arg) int *start, void *arg)
{ {
unsigned long w; unsigned long w;
struct percpu_struct *cpu; struct percpu_struct *cpu;
...@@ -823,9 +838,9 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, ...@@ -823,9 +838,9 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, asmlinkage unsigned long
unsigned long nbytes, osf_setsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
int *start, void *arg) int *start, void *arg)
{ {
switch (op) { switch (op) {
case SSI_IEEE_FP_CONTROL: { case SSI_IEEE_FP_CONTROL: {
...@@ -925,21 +940,24 @@ struct itimerval32 ...@@ -925,21 +940,24 @@ struct itimerval32
struct timeval32 it_value; struct timeval32 it_value;
}; };
static inline long get_tv32(struct timeval *o, struct timeval32 *i) static inline long
get_tv32(struct timeval *o, struct timeval32 *i)
{ {
return (!access_ok(VERIFY_READ, i, sizeof(*i)) || return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
(__get_user(o->tv_sec, &i->tv_sec) | (__get_user(o->tv_sec, &i->tv_sec) |
__get_user(o->tv_usec, &i->tv_usec))); __get_user(o->tv_usec, &i->tv_usec)));
} }
static inline long put_tv32(struct timeval32 *o, struct timeval *i) static inline long
put_tv32(struct timeval32 *o, struct timeval *i)
{ {
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->tv_sec, &o->tv_sec) | (__put_user(i->tv_sec, &o->tv_sec) |
__put_user(i->tv_usec, &o->tv_usec))); __put_user(i->tv_usec, &o->tv_usec)));
} }
static inline long get_it32(struct itimerval *o, struct itimerval32 *i) static inline long
get_it32(struct itimerval *o, struct itimerval32 *i)
{ {
return (!access_ok(VERIFY_READ, i, sizeof(*i)) || return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) | (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
...@@ -948,7 +966,8 @@ static inline long get_it32(struct itimerval *o, struct itimerval32 *i) ...@@ -948,7 +966,8 @@ static inline long get_it32(struct itimerval *o, struct itimerval32 *i)
__get_user(o->it_value.tv_usec, &i->it_value.tv_usec))); __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
} }
static inline long put_it32(struct itimerval32 *o, struct itimerval *i) static inline long
put_it32(struct itimerval32 *o, struct itimerval *i)
{ {
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) | (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
...@@ -964,7 +983,8 @@ jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value) ...@@ -964,7 +983,8 @@ jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value)
value->tv_sec = jiffies / HZ; value->tv_sec = jiffies / HZ;
} }
asmlinkage int osf_gettimeofday(struct timeval32 *tv, struct timezone *tz) asmlinkage int
osf_gettimeofday(struct timeval32 *tv, struct timezone *tz)
{ {
if (tv) { if (tv) {
struct timeval ktv; struct timeval ktv;
...@@ -979,7 +999,8 @@ asmlinkage int osf_gettimeofday(struct timeval32 *tv, struct timezone *tz) ...@@ -979,7 +999,8 @@ asmlinkage int osf_gettimeofday(struct timeval32 *tv, struct timezone *tz)
return 0; return 0;
} }
asmlinkage int osf_settimeofday(struct timeval32 *tv, struct timezone *tz) asmlinkage int
osf_settimeofday(struct timeval32 *tv, struct timezone *tz)
{ {
struct timeval ktv; struct timeval ktv;
struct timezone ktz; struct timezone ktz;
...@@ -996,7 +1017,8 @@ asmlinkage int osf_settimeofday(struct timeval32 *tv, struct timezone *tz) ...@@ -996,7 +1017,8 @@ asmlinkage int osf_settimeofday(struct timeval32 *tv, struct timezone *tz)
return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
} }
asmlinkage int osf_getitimer(int which, struct itimerval32 *it) asmlinkage int
osf_getitimer(int which, struct itimerval32 *it)
{ {
struct itimerval kit; struct itimerval kit;
int error; int error;
...@@ -1008,8 +1030,8 @@ asmlinkage int osf_getitimer(int which, struct itimerval32 *it) ...@@ -1008,8 +1030,8 @@ asmlinkage int osf_getitimer(int which, struct itimerval32 *it)
return error; return error;
} }
asmlinkage int osf_setitimer(int which, struct itimerval32 *in, asmlinkage int
struct itimerval32 *out) osf_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
{ {
struct itimerval kin, kout; struct itimerval kin, kout;
int error; int error;
...@@ -1031,7 +1053,8 @@ asmlinkage int osf_setitimer(int which, struct itimerval32 *in, ...@@ -1031,7 +1053,8 @@ asmlinkage int osf_setitimer(int which, struct itimerval32 *in,
} }
asmlinkage int osf_utimes(const char *filename, struct timeval32 *tvs) asmlinkage int
osf_utimes(const char *filename, struct timeval32 *tvs)
{ {
char *kfilename; char *kfilename;
struct timeval ktvs[2]; struct timeval ktvs[2];
...@@ -1136,9 +1159,9 @@ osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, ...@@ -1136,9 +1159,9 @@ osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
set_fd_set(n, outp->fds_bits, fds.res_out); set_fd_set(n, outp->fds_bits, fds.res_out);
set_fd_set(n, exp->fds_bits, fds.res_ex); set_fd_set(n, exp->fds_bits, fds.res_ex);
out: out:
kfree(bits); kfree(bits);
out_nofds: out_nofds:
return ret; return ret;
} }
...@@ -1161,7 +1184,8 @@ struct rusage32 { ...@@ -1161,7 +1184,8 @@ struct rusage32 {
long ru_nivcsw; /* involuntary " */ long ru_nivcsw; /* involuntary " */
}; };
asmlinkage int osf_getrusage(int who, struct rusage32 *ru) asmlinkage int
osf_getrusage(int who, struct rusage32 *ru)
{ {
struct rusage32 r; struct rusage32 r;
...@@ -1198,8 +1222,8 @@ asmlinkage int osf_getrusage(int who, struct rusage32 *ru) ...@@ -1198,8 +1222,8 @@ asmlinkage int osf_getrusage(int who, struct rusage32 *ru)
return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
} }
asmlinkage int osf_wait4(pid_t pid, int *ustatus, int options, asmlinkage int
struct rusage32 *ur) osf_wait4(pid_t pid, int *ustatus, int options, struct rusage32 *ur)
{ {
if (!ur) { if (!ur) {
return sys_wait4(pid, ustatus, options, NULL); return sys_wait4(pid, ustatus, options, NULL);
...@@ -1245,7 +1269,8 @@ asmlinkage int osf_wait4(pid_t pid, int *ustatus, int options, ...@@ -1245,7 +1269,8 @@ asmlinkage int osf_wait4(pid_t pid, int *ustatus, int options,
* seems to be a timeval pointer, and I suspect the second * seems to be a timeval pointer, and I suspect the second
* one is the time remaining.. Ho humm.. No documentation. * one is the time remaining.. Ho humm.. No documentation.
*/ */
asmlinkage int osf_usleep_thread(struct timeval32 *sleep, struct timeval32 *remain) asmlinkage int
osf_usleep_thread(struct timeval32 *sleep, struct timeval32 *remain)
{ {
struct timeval tmp; struct timeval tmp;
unsigned long ticks; unsigned long ticks;
...@@ -1268,7 +1293,7 @@ asmlinkage int osf_usleep_thread(struct timeval32 *sleep, struct timeval32 *rema ...@@ -1268,7 +1293,7 @@ asmlinkage int osf_usleep_thread(struct timeval32 *sleep, struct timeval32 *rema
} }
return 0; return 0;
fault: fault:
return -EFAULT; return -EFAULT;
} }
...@@ -1302,7 +1327,8 @@ struct timex32 { ...@@ -1302,7 +1327,8 @@ struct timex32 {
int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32;
}; };
asmlinkage int sys_old_adjtimex(struct timex32 *txc_p) asmlinkage int
sys_old_adjtimex(struct timex32 *txc_p)
{ {
struct timex txc; struct timex txc;
int ret; int ret;
......
...@@ -191,26 +191,13 @@ machine_power_off(void) ...@@ -191,26 +191,13 @@ machine_power_off(void)
common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL); common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL);
} }
/* Used by sysrq-p, among others. I don't believe r9-r15 are ever
saved in the context it's used. */
void void
show_regs(struct pt_regs * regs) show_regs(struct pt_regs *regs)
{ {
printk("\n"); dik_show_regs(regs, 0);
printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
printk("ps: %04lx pc: [<%016lx>] CPU %d %s\n",
regs->ps, regs->pc, smp_processor_id(), print_tainted());
printk("rp: [<%016lx>] sp: %p\n", regs->r26, regs+1);
printk(" r0: %016lx r1: %016lx r2: %016lx r3: %016lx\n",
regs->r0, regs->r1, regs->r2, regs->r3);
printk(" r4: %016lx r5: %016lx r6: %016lx r7: %016lx\n",
regs->r4, regs->r5, regs->r6, regs->r7);
printk(" r8: %016lx r16: %016lx r17: %016lx r18: %016lx\n",
regs->r8, regs->r16, regs->r17, regs->r18);
printk("r19: %016lx r20: %016lx r21: %016lx r22: %016lx\n",
regs->r19, regs->r20, regs->r21, regs->r22);
printk("r23: %016lx r24: %016lx r25: %016lx r26: %016lx\n",
regs->r23, regs->r24, regs->r25, regs->r26);
printk("r27: %016lx r28: %016lx r29: %016lx hae: %016lx\n",
regs->r27, regs->r28, regs->gp, regs->hae);
} }
/* /*
......
...@@ -37,6 +37,11 @@ ...@@ -37,6 +37,11 @@
#include <linux/blk.h> #include <linux/blk.h>
#endif #endif
#ifdef CONFIG_MAGIC_SYSRQ
#include <linux/sysrq.h>
#include <linux/reboot.h>
#endif
#include <linux/notifier.h> #include <linux/notifier.h>
extern struct notifier_block *panic_notifier_list; extern struct notifier_block *panic_notifier_list;
static int alpha_panic_event(struct notifier_block *, unsigned long, void *); static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
...@@ -539,6 +544,15 @@ setup_arch(char **cmdline_p) ...@@ -539,6 +544,15 @@ setup_arch(char **cmdline_p)
register_srm_console(); register_srm_console();
} }
#ifdef CONFIG_MAGIC_SYSRQ
/* If we're using SRM, make sysrq-b halt back to the prom,
not auto-reboot. */
if (alpha_using_srm) {
struct sysrq_key_op *op = __sysrq_get_key_op('b');
op->handler = (void *) machine_halt;
}
#endif
/* /*
* Indentify and reconfigure for the current system. * Indentify and reconfigure for the current system.
*/ */
......
/*
* arch/alpha/kernel/systbls.S
*
* The system call table.
*/
#include <asm/unistd.h>
.data
.align 3
.globl sys_call_table
sys_call_table:
.quad alpha_ni_syscall /* 0 */
.quad sys_exit
.quad sys_fork
.quad sys_read
.quad sys_write
.quad alpha_ni_syscall /* 5 */
.quad sys_close
.quad osf_wait4
.quad alpha_ni_syscall
.quad sys_link
.quad sys_unlink /* 10 */
.quad alpha_ni_syscall
.quad sys_chdir
.quad sys_fchdir
.quad sys_mknod
.quad sys_chmod /* 15 */
.quad sys_chown
.quad osf_brk
.quad alpha_ni_syscall
.quad sys_lseek
.quad sys_getxpid /* 20 */
.quad osf_mount
.quad sys_umount
.quad sys_setuid
.quad sys_getxuid
.quad alpha_ni_syscall /* 25 */
.quad sys_ptrace
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 30 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_access
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 35 */
.quad sys_sync
.quad sys_kill
.quad alpha_ni_syscall
.quad sys_setpgid
.quad alpha_ni_syscall /* 40 */
.quad sys_dup
.quad sys_pipe
.quad osf_set_program_attributes
.quad alpha_ni_syscall
.quad sys_open /* 45 */
.quad alpha_ni_syscall
.quad sys_getxgid
.quad osf_sigprocmask
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 50 */
.quad sys_acct
.quad sys_sigpending
.quad alpha_ni_syscall
.quad sys_ioctl
.quad alpha_ni_syscall /* 55 */
.quad alpha_ni_syscall
.quad sys_symlink
.quad sys_readlink
.quad sys_execve
.quad sys_umask /* 60 */
.quad sys_chroot
.quad alpha_ni_syscall
.quad sys_getpgrp
.quad sys_getpagesize
.quad alpha_ni_syscall /* 65 */
.quad sys_vfork
.quad sys_newstat
.quad sys_newlstat
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 70 */
.quad osf_mmap
.quad alpha_ni_syscall
.quad sys_munmap
.quad sys_mprotect
.quad sys_madvise /* 75 */
.quad sys_vhangup
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_getgroups
/* map BSD's setpgrp to sys_setpgid for binary compatibility: */
.quad sys_setgroups /* 80 */
.quad alpha_ni_syscall
.quad sys_setpgid
.quad osf_setitimer
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 85 */
.quad osf_getitimer
.quad sys_gethostname
.quad sys_sethostname
.quad sys_getdtablesize
.quad sys_dup2 /* 90 */
.quad sys_newfstat
.quad sys_fcntl
.quad osf_select
.quad sys_poll
.quad sys_fsync /* 95 */
.quad sys_setpriority
.quad sys_socket
.quad sys_connect
.quad sys_accept
.quad osf_getpriority /* 100 */
.quad sys_send
.quad sys_recv
.quad sys_sigreturn
.quad sys_bind
.quad sys_setsockopt /* 105 */
.quad sys_listen
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 110 */
.quad sys_sigsuspend
.quad osf_sigstack
.quad sys_recvmsg
.quad sys_sendmsg
.quad alpha_ni_syscall /* 115 */
.quad osf_gettimeofday
.quad osf_getrusage
.quad sys_getsockopt
.quad alpha_ni_syscall
#ifdef CONFIG_OSF4_COMPAT
.quad osf_readv /* 120 */
.quad osf_writev
#else
.quad sys_readv /* 120 */
.quad sys_writev
#endif
.quad osf_settimeofday
.quad sys_fchown
.quad sys_fchmod
.quad sys_recvfrom /* 125 */
.quad sys_setreuid
.quad sys_setregid
.quad sys_rename
.quad sys_truncate
.quad sys_ftruncate /* 130 */
.quad sys_flock
.quad sys_setgid
.quad sys_sendto
.quad sys_shutdown
.quad sys_socketpair /* 135 */
.quad sys_mkdir
.quad sys_rmdir
.quad osf_utimes
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 140 */
.quad sys_getpeername
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_getrlimit
.quad sys_setrlimit /* 145 */
.quad alpha_ni_syscall
.quad sys_setsid
.quad sys_quotactl
.quad alpha_ni_syscall
.quad sys_getsockname /* 150 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 155 */
.quad osf_sigaction
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad osf_getdirentries
.quad osf_statfs /* 160 */
.quad osf_fstatfs
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad osf_getdomainname /* 165 */
.quad sys_setdomainname
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 170 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 175 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 180 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 185 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 190 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 195 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad osf_swapon
.quad sys_msgctl /* 200 */
.quad sys_msgget
.quad sys_msgrcv
.quad sys_msgsnd
.quad sys_semctl
.quad sys_semget /* 205 */
.quad sys_semop
.quad osf_utsname
.quad sys_lchown
.quad osf_shmat
.quad sys_shmctl /* 210 */
.quad sys_shmdt
.quad sys_shmget
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 215 */
.quad alpha_ni_syscall
.quad sys_msync
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 220 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 225 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 230 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_getpgid
.quad sys_getsid
.quad sys_sigaltstack /* 235 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 240 */
.quad osf_sysinfo
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad osf_proplist_syscall
.quad alpha_ni_syscall /* 245 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 250 */
.quad osf_usleep_thread
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_sysfs
.quad alpha_ni_syscall /* 255 */
.quad osf_getsysinfo
.quad osf_setsysinfo
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 260 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 265 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 270 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 275 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 280 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 285 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 290 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 295 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
/* linux-specific system calls start at 300 */
.quad sys_bdflush /* 300 */
.quad sys_sethae
.quad sys_mount
.quad sys_old_adjtimex
.quad sys_swapoff
.quad sys_getdents /* 305 */
.quad alpha_create_module
.quad sys_init_module
.quad sys_delete_module
.quad sys_get_kernel_syms
.quad sys_syslog /* 310 */
.quad sys_reboot
.quad sys_clone
.quad sys_uselib
.quad sys_mlock
.quad sys_munlock /* 315 */
.quad sys_mlockall
.quad sys_munlockall
.quad sys_sysinfo
.quad sys_sysctl
.quad sys_ni_syscall /* 320 */
.quad sys_oldumount
.quad sys_swapon
.quad sys_times
.quad sys_personality
.quad sys_setfsuid /* 325 */
.quad sys_setfsgid
.quad sys_ustat
.quad sys_statfs
.quad sys_fstatfs
.quad sys_sched_setparam /* 330 */
.quad sys_sched_getparam
.quad sys_sched_setscheduler
.quad sys_sched_getscheduler
.quad sys_sched_yield
.quad sys_sched_get_priority_max /* 335 */
.quad sys_sched_get_priority_min
.quad sys_sched_rr_get_interval
.quad sys_ni_syscall /* sys_afs_syscall */
.quad sys_newuname
.quad sys_nanosleep /* 340 */
.quad sys_mremap
.quad sys_nfsservctl
.quad sys_setresuid
.quad sys_getresuid
.quad sys_pciconfig_read /* 345 */
.quad sys_pciconfig_write
.quad sys_query_module
.quad sys_prctl
.quad sys_pread64
.quad sys_pwrite64 /* 350 */
.quad sys_rt_sigreturn
.quad sys_rt_sigaction
.quad sys_rt_sigprocmask
.quad sys_rt_sigpending
.quad sys_rt_sigtimedwait /* 355 */
.quad sys_rt_sigqueueinfo
.quad sys_rt_sigsuspend
.quad sys_select
.quad sys_gettimeofday
.quad sys_settimeofday /* 360 */
.quad sys_getitimer
.quad sys_setitimer
.quad sys_utimes
.quad sys_getrusage
.quad sys_wait4 /* 365 */
.quad sys_adjtimex
.quad sys_getcwd
.quad sys_capget
.quad sys_capset
.quad sys_sendfile /* 370 */
.quad sys_setresgid
.quad sys_getresgid
.quad sys_ni_syscall /* sys_dipc */
.quad sys_pivot_root
.quad sys_mincore /* 375 */
.quad sys_pciconfig_iobase
.quad sys_getdents64
.quad sys_gettid
.quad sys_readahead
.quad sys_ni_syscall /* 380, sys_security */
.quad sys_tkill
.quad sys_setxattr
.quad sys_lsetxattr
.quad sys_fsetxattr
.quad sys_getxattr /* 385 */
.quad sys_lgetxattr
.quad sys_fgetxattr
.quad sys_listxattr
.quad sys_llistxattr
.quad sys_flistxattr /* 390 */
.quad sys_removexattr
.quad sys_lremovexattr
.quad sys_fremovexattr
.quad sys_futex
.quad sys_sched_setaffinity /* 395 */
.quad sys_sched_getaffinity
.quad sys_ni_syscall /* 397, tux */
.quad sys_io_setup
.quad sys_io_destroy
.quad sys_io_getevents /* 400 */
.quad sys_io_submit
.quad sys_io_cancel
.quad sys_ni_syscall /* 403, sys_alloc_hugepages */
.quad sys_ni_syscall /* 404, sys_free_hugepages */
.quad sys_exit_group
.size sys_call_table, . - sys_call_table
.type sys_call_table, @object
/* Remember to update everything, kids. */
.ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
.err
.endif
...@@ -51,14 +51,16 @@ obj-$(CONFIG_SMP) += dec_and_lock.o ...@@ -51,14 +51,16 @@ obj-$(CONFIG_SMP) += dec_and_lock.o
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
__divqu.o: $(ev6)divide.S $(obj)/__divqu.o: $(obj)/$(ev6)divide.S
$(CC) $(AFLAGS) -DDIV -c -o __divqu.o $(ev6)divide.S $(CC) $(AFLAGS) -DDIV -c -o $(obj)/__divqu.o $(obj)/$(ev6)divide.S
__remqu.o: $(ev6)divide.S $(obj)/__remqu.o: $(obj)/$(ev6)divide.S
$(CC) $(AFLAGS) -DREM -c -o __remqu.o $(ev6)divide.S $(CC) $(AFLAGS) -DREM -c -o $(obj)/__remqu.o $(obj)/$(ev6)divide.S
__divlu.o: $(ev6)divide.S $(obj)/__divlu.o: $(obj)/$(ev6)divide.S
$(CC) $(AFLAGS) -DDIV -DINTSIZE -c -o __divlu.o $(ev6)divide.S $(CC) $(AFLAGS) -DDIV -DINTSIZE \
-c -o $(obj)/__divlu.o $(obj)/$(ev6)divide.S
__remlu.o: $(ev6)divide.S $(obj)/__remlu.o: $(obj)/$(ev6)divide.S
$(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o $(ev6)divide.S $(CC) $(AFLAGS) -DREM -DINTSIZE \
-c -o $(obj)/__remlu.o $(obj)/$(ev6)divide.S
...@@ -278,7 +278,7 @@ $u_eoc: ...@@ -278,7 +278,7 @@ $u_eoc:
extqh t2, a1, t0 # e0 : extract low bits for last word extqh t2, a1, t0 # e0 : extract low bits for last word
or t1, t0, t1 # e1 : or t1, t0, t1 # e1 :
1: cmpbge zero, t1, t7 1: cmpbge zero, t1, t8
mov t1, t0 mov t1, t0
$u_eocfin: # end-of-count, final word $u_eocfin: # end-of-count, final word
......
...@@ -125,11 +125,10 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -125,11 +125,10 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
goto bad_area; goto bad_area;
if (expand_stack(vma, address)) if (expand_stack(vma, address))
goto bad_area; goto bad_area;
/*
* Ok, we have a good vm_area for this memory access, so /* Ok, we have a good vm_area for this memory access, so
* we can handle it.. we can handle it. */
*/ good_area:
good_area:
if (cause < 0) { if (cause < 0) {
if (!(vma->vm_flags & VM_EXEC)) if (!(vma->vm_flags & VM_EXEC))
goto bad_area; goto bad_area;
...@@ -143,11 +142,9 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -143,11 +142,9 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
} }
survive: survive:
/* /* If for any reason at all we couldn't handle the fault,
* If for any reason at all we couldn't handle the fault, make sure we exit gracefully rather than endlessly redo
* make sure we exit gracefully rather than endlessly redo the fault. */
* the fault.
*/
fault = handle_mm_fault(mm, vma, address, cause > 0); fault = handle_mm_fault(mm, vma, address, cause > 0);
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
...@@ -155,14 +152,11 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -155,14 +152,11 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
goto out_of_memory; goto out_of_memory;
if (fault == 0) if (fault == 0)
goto do_sigbus; goto do_sigbus;
return; return;
/* /* Something tried to access memory that isn't in our memory map.
* Something tried to access memory that isn't in our memory map.. Fix it, but check if it's kernel or user first. */
* Fix it, but check if it's kernel or user first.. bad_area:
*/
bad_area:
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
if (user_mode(regs)) { if (user_mode(regs)) {
...@@ -170,7 +164,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -170,7 +164,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
return; return;
} }
no_context: no_context:
/* Are we prepared to handle this fault as an exception? */ /* Are we prepared to handle this fault as an exception? */
if ((fixup = search_exception_table(regs->pc, regs->gp)) != 0) { if ((fixup = search_exception_table(regs->pc, regs->gp)) != 0) {
unsigned long newpc; unsigned long newpc;
...@@ -183,20 +177,16 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -183,20 +177,16 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
return; return;
} }
/* /* Oops. The kernel tried to access some bad page. We'll have to
* Oops. The kernel tried to access some bad page. We'll have to terminate things with extreme prejudice. */
* terminate things with extreme prejudice.
*/
printk(KERN_ALERT "Unable to handle kernel paging request at " printk(KERN_ALERT "Unable to handle kernel paging request at "
"virtual address %016lx\n", address); "virtual address %016lx\n", address);
die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16); die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16);
do_exit(SIGKILL); do_exit(SIGKILL);
/* /* We ran out of memory, or some other thing happened to us that
* We ran out of memory, or some other thing happened to us that made made us unable to handle the page fault gracefully. */
* us unable to handle the page fault gracefully. out_of_memory:
*/
out_of_memory:
if (current->pid == 1) { if (current->pid == 1) {
yield(); yield();
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
...@@ -208,18 +198,16 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -208,18 +198,16 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
goto no_context; goto no_context;
do_exit(SIGKILL); do_exit(SIGKILL);
do_sigbus: do_sigbus:
/* /* Send a sigbus, regardless of whether we were in kernel
* Send a sigbus, regardless of whether we were in kernel or user mode. */
* or user mode.
*/
force_sig(SIGBUS, current); force_sig(SIGBUS, current);
if (!user_mode(regs)) if (!user_mode(regs))
goto no_context; goto no_context;
return; return;
#ifdef CONFIG_ALPHA_LARGE_VMALLOC #ifdef CONFIG_ALPHA_LARGE_VMALLOC
vmalloc_fault: vmalloc_fault:
if (user_mode(regs)) { if (user_mode(regs)) {
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
return; return;
......
...@@ -58,10 +58,11 @@ SECTIONS ...@@ -58,10 +58,11 @@ SECTIONS
__initcall_end = .; __initcall_end = .;
} }
. = ALIGN(64); .data.percpu ALIGN(64): {
__per_cpu_start = .; __per_cpu_start = .;
.data.percpu : { *(.data.percpu) } *(.data.percpu)
__per_cpu_end = .; __per_cpu_end = .;
}
/* The initial task and kernel stack */ /* The initial task and kernel stack */
.data.init_thread ALIGN(2*8192) : { .data.init_thread ALIGN(2*8192) : {
......
...@@ -1664,14 +1664,6 @@ static int idedisk_resume(struct device *dev, u32 level) ...@@ -1664,14 +1664,6 @@ static int idedisk_resume(struct device *dev, u32 level)
/* This is just a hook for the overall driver tree. /* This is just a hook for the overall driver tree.
*/ */
static struct device_driver idedisk_devdrv = {
.bus = &ide_bus_type,
.name = "IDE disk driver",
.suspend = idedisk_suspend,
.resume = idedisk_resume,
};
static int idedisk_ioctl (ide_drive_t *drive, struct inode *inode, static int idedisk_ioctl (ide_drive_t *drive, struct inode *inode,
struct file *file, unsigned int cmd, unsigned long arg) struct file *file, unsigned int cmd, unsigned long arg)
{ {
...@@ -1717,12 +1709,6 @@ static void idedisk_setup (ide_drive_t *drive) ...@@ -1717,12 +1709,6 @@ static void idedisk_setup (ide_drive_t *drive)
drive->doorlocking = 1; drive->doorlocking = 1;
} }
} }
{
sprintf(drive->disk->disk_dev.name, "ide-disk");
drive->disk->disk_dev.driver = &idedisk_devdrv;
drive->disk->disk_dev.driver_data = drive;
}
#if 1 #if 1
(void) probe_lba_addressing(drive, 1); (void) probe_lba_addressing(drive, 1);
#else #else
...@@ -1806,7 +1792,6 @@ static int idedisk_cleanup (ide_drive_t *drive) ...@@ -1806,7 +1792,6 @@ static int idedisk_cleanup (ide_drive_t *drive)
{ {
struct gendisk *g = drive->disk; struct gendisk *g = drive->disk;
device_unregister(&drive->disk->disk_dev);
if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
if (do_idedisk_flushcache(drive)) if (do_idedisk_flushcache(drive))
printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
...@@ -1905,7 +1890,6 @@ static void __exit idedisk_exit (void) ...@@ -1905,7 +1890,6 @@ static void __exit idedisk_exit (void)
static int idedisk_init (void) static int idedisk_init (void)
{ {
ide_register_driver(&idedisk_driver); ide_register_driver(&idedisk_driver);
driver_register(&idedisk_devdrv);
return 0; return 0;
} }
......
...@@ -998,15 +998,6 @@ static void init_gendisk (ide_hwif_t *hwif) ...@@ -998,15 +998,6 @@ static void init_gendisk (ide_hwif_t *hwif)
sprintf(disk->disk_name,"hd%c",'a'+hwif->index*MAX_DRIVES+unit); sprintf(disk->disk_name,"hd%c",'a'+hwif->index*MAX_DRIVES+unit);
disk->minor_shift = PARTN_BITS; disk->minor_shift = PARTN_BITS;
disk->fops = ide_fops; disk->fops = ide_fops;
snprintf(disk->disk_dev.bus_id,BUS_ID_SIZE,"%u.%u",
hwif->index,unit);
snprintf(disk->disk_dev.name,DEVICE_NAME_SIZE,
"%s","IDE Drive");
disk->disk_dev.parent = &hwif->gendev;
disk->disk_dev.bus = &ide_bus_type;
if (hwif->drives[unit].present)
device_register(&disk->disk_dev);
hwif->drives[unit].disk = disk; hwif->drives[unit].disk = disk;
} }
...@@ -1020,6 +1011,20 @@ static void init_gendisk (ide_hwif_t *hwif) ...@@ -1020,6 +1011,20 @@ static void init_gendisk (ide_hwif_t *hwif)
if (hwif->drives[unit].present) if (hwif->drives[unit].present)
hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL); hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
} }
for (unit = 0; unit < units; ++unit) {
ide_drive_t * drive = &hwif->drives[unit];
snprintf(drive->gendev.bus_id,BUS_ID_SIZE,"%u.%u",
hwif->index,unit);
snprintf(drive->gendev.name,DEVICE_NAME_SIZE,
"%s","IDE Drive");
drive->gendev.parent = &hwif->gendev;
drive->gendev.bus = &ide_bus_type;
if (drive->present)
device_register(&drive->gendev);
}
return; return;
err_kmalloc_gd: err_kmalloc_gd:
......
...@@ -2463,6 +2463,7 @@ int ata_attach(ide_drive_t *drive) ...@@ -2463,6 +2463,7 @@ int ata_attach(ide_drive_t *drive)
if (driver->attach(drive) == 0) { if (driver->attach(drive) == 0) {
if (driver->owner) if (driver->owner)
__MOD_DEC_USE_COUNT(driver->owner); __MOD_DEC_USE_COUNT(driver->owner);
drive->gendev.driver = &driver->gen_driver;
return 0; return 0;
} }
spin_lock(&drivers_lock); spin_lock(&drivers_lock);
...@@ -3422,6 +3423,21 @@ int ide_unregister_subdriver (ide_drive_t *drive) ...@@ -3422,6 +3423,21 @@ int ide_unregister_subdriver (ide_drive_t *drive)
EXPORT_SYMBOL(ide_unregister_subdriver); EXPORT_SYMBOL(ide_unregister_subdriver);
static int ide_drive_remove(struct device * dev)
{
ide_drive_t * drive = container_of(dev,ide_drive_t,gendev);
ide_driver_t * driver = drive->driver;
if (driver) {
if (driver->standby)
driver->standby(drive);
if (driver->cleanup)
driver->cleanup(drive);
}
return 0;
}
int ide_register_driver(ide_driver_t *driver) int ide_register_driver(ide_driver_t *driver)
{ {
struct list_head list; struct list_head list;
...@@ -3440,7 +3456,10 @@ int ide_register_driver(ide_driver_t *driver) ...@@ -3440,7 +3456,10 @@ int ide_register_driver(ide_driver_t *driver)
list_del_init(&drive->list); list_del_init(&drive->list);
ata_attach(drive); ata_attach(drive);
} }
return 0; driver->gen_driver.name = driver->name;
driver->gen_driver.bus = &ide_bus_type;
driver->gen_driver.remove = ide_drive_remove;
return driver_register(&driver->gen_driver);
} }
EXPORT_SYMBOL(ide_register_driver); EXPORT_SYMBOL(ide_register_driver);
...@@ -3491,52 +3510,6 @@ EXPORT_SYMBOL(ide_lock); ...@@ -3491,52 +3510,6 @@ EXPORT_SYMBOL(ide_lock);
EXPORT_SYMBOL(ide_probe); EXPORT_SYMBOL(ide_probe);
EXPORT_SYMBOL(ide_devfs_handle); EXPORT_SYMBOL(ide_devfs_handle);
static int ide_notify_reboot (struct notifier_block *this, unsigned long event, void *x)
{
ide_hwif_t *hwif;
ide_drive_t *drive;
int i, unit;
switch (event) {
case SYS_HALT:
case SYS_POWER_OFF:
case SYS_RESTART:
break;
default:
return NOTIFY_DONE;
}
printk(KERN_INFO "flushing ide devices: ");
for (i = 0; i < MAX_HWIFS; i++) {
hwif = &ide_hwifs[i];
if (!hwif->present)
continue;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
drive = &hwif->drives[unit];
if (!drive->present)
continue;
/* set the drive to standby */
printk("%s ", drive->name);
if (event != SYS_RESTART)
if (drive->driver != NULL && DRIVER(drive)->standby(drive))
continue;
if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
continue;
}
}
printk("\n");
return NOTIFY_DONE;
}
static struct notifier_block ide_notifier = {
ide_notify_reboot,
NULL,
5
};
struct bus_type ide_bus_type = { struct bus_type ide_bus_type = {
.name = "ide", .name = "ide",
}; };
...@@ -3562,7 +3535,6 @@ int __init ide_init (void) ...@@ -3562,7 +3535,6 @@ int __init ide_init (void)
ide_init_builtin_drivers(); ide_init_builtin_drivers();
initializing = 0; initializing = 0;
register_reboot_notifier(&ide_notifier);
return 0; return 0;
} }
...@@ -3597,7 +3569,6 @@ void cleanup_module (void) ...@@ -3597,7 +3569,6 @@ void cleanup_module (void)
{ {
int index; int index;
unregister_reboot_notifier(&ide_notifier);
for (index = 0; index < MAX_HWIFS; ++index) { for (index = 0; index < MAX_HWIFS; ++index) {
ide_unregister(index); ide_unregister(index);
#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) #if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
......
...@@ -11,12 +11,11 @@ ...@@ -11,12 +11,11 @@
Do not purchase this card, even as a joke. It's performance is horrible, Do not purchase this card, even as a joke. It's performance is horrible,
and it breaks in many ways. and it breaks in many ways.
The author may be reached as becker@scyld.com, or C/O The original author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation Scyld Computing Corporation
410 Severn Ave., Suite 210 410 Severn Ave., Suite 210
Annapolis MD 21403 Annapolis MD 21403
Fixed (again!) the missing interrupt locking on TX/RX shifting. Fixed (again!) the missing interrupt locking on TX/RX shifting.
Alan Cox <Alan.Cox@linux.org> Alan Cox <Alan.Cox@linux.org>
...@@ -34,7 +33,16 @@ ...@@ -34,7 +33,16 @@
Cleaned up for 2.3.x because we broke SMP now. Cleaned up for 2.3.x because we broke SMP now.
20000208 Alan Cox <alan@redhat.com> 20000208 Alan Cox <alan@redhat.com>
Check up pass for 2.5. Nothing significant changed
20021009 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.
*/ */
...@@ -88,7 +96,7 @@ ...@@ -88,7 +96,7 @@
*/ */
#define DRV_NAME "3c501" #define DRV_NAME "3c501"
#define DRV_VERSION "2001/11/17" #define DRV_VERSION "2002/10/09"
static const char version[] = static const char version[] =
...@@ -122,113 +130,21 @@ static const char version[] = ...@@ -122,113 +130,21 @@ static const char version[] =
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/init.h> #include <linux/init.h>
#include "3c501.h"
/* A zero-terminated list of I/O addresses to be probed. /* A zero-terminated list of I/O addresses to be probed.
The 3c501 can be at many locations, but here are the popular ones. */ The 3c501 can be at many locations, but here are the popular ones. */
static unsigned int netcard_portlist[] __initdata = { static unsigned int netcard_portlist[] __initdata = {
0x280, 0x300, 0 0x280, 0x300, 0
}; };
/*
* Index to functions.
*/
int el1_probe(struct net_device *dev);
static int el1_probe1(struct net_device *dev, int ioaddr);
static int el_open(struct net_device *dev);
static void el_timeout(struct net_device *dev);
static int el_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void el_receive(struct net_device *dev);
static void el_reset(struct net_device *dev);
static int el1_close(struct net_device *dev);
static struct net_device_stats *el1_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
#define EL1_IO_EXTENT 16
#ifndef EL_DEBUG
#define EL_DEBUG 0 /* use 0 for production, 1 for devel., >2 for debug */
#endif /* Anything above 5 is wordy death! */
#define debug el_debug
static int el_debug = EL_DEBUG;
/*
* Board-specific info in dev->priv.
*/
struct net_local
{
struct net_device_stats stats;
int tx_pkt_start; /* The length of the current Tx packet. */
int collisions; /* Tx collisions this packet */
int loading; /* Spot buffer load collisions */
int txing; /* True if card is in TX mode */
spinlock_t lock; /* Serializing lock */
};
#define RX_STATUS (ioaddr + 0x06)
#define RX_CMD RX_STATUS
#define TX_STATUS (ioaddr + 0x07)
#define TX_CMD TX_STATUS
#define GP_LOW (ioaddr + 0x08)
#define GP_HIGH (ioaddr + 0x09)
#define RX_BUF_CLR (ioaddr + 0x0A)
#define RX_LOW (ioaddr + 0x0A)
#define RX_HIGH (ioaddr + 0x0B)
#define SAPROM (ioaddr + 0x0C)
#define AX_STATUS (ioaddr + 0x0E)
#define AX_CMD AX_STATUS
#define DATAPORT (ioaddr + 0x0F)
#define TX_RDY 0x08 /* In TX_STATUS */
#define EL1_DATAPTR 0x08
#define EL1_RXPTR 0x0A
#define EL1_SAPROM 0x0C
#define EL1_DATAPORT 0x0f
/*
* Writes to the ax command register.
*/
#define AX_OFF 0x00 /* Irq off, buffer access on */
#define AX_SYS 0x40 /* Load the buffer */
#define AX_XMIT 0x44 /* Transmit a packet */
#define AX_RX 0x48 /* Receive a packet */
#define AX_LOOP 0x0C /* Loopback mode */
#define AX_RESET 0x80
/*
* Normal receive mode written to RX_STATUS. We must intr on short packets
* to avoid bogus rx lockups.
*/
#define RX_NORM 0xA8 /* 0x68 == all addrs, 0xA8 only to me. */
#define RX_PROM 0x68 /* Senior Prom, uhmm promiscuous mode. */
#define RX_MULT 0xE8 /* Accept multicast packets. */
#define TX_NORM 0x0A /* Interrupt on everything that might hang the chip */
/*
* TX_STATUS register.
*/
#define TX_COLLISION 0x02
#define TX_16COLLISIONS 0x04
#define TX_READY 0x08
#define RX_RUNT 0x08
#define RX_MISSED 0x01 /* Missed a packet due to 3c501 braindamage. */
#define RX_GOOD 0x30 /* Good packet 0x20, or simple overflow 0x10. */
/* /*
* The boilerplate probe code. * The boilerplate probe code.
*/ */
/** /**
* el1_probe: * el1_probe: - probe for a 3c501
* @dev: The device structure passed in to probe. * @dev: The device structure passed in to probe.
* *
* This can be called from two places. The network layer will probe using * This can be called from two places. The network layer will probe using
...@@ -556,7 +472,6 @@ static int el_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -556,7 +472,6 @@ static int el_start_xmit(struct sk_buff *skb, struct net_device *dev)
while(1); while(1);
} }
/** /**
* el_interrupt: * el_interrupt:
...@@ -1072,12 +987,8 @@ void cleanup_module(void) ...@@ -1072,12 +987,8 @@ void cleanup_module(void)
} }
#endif /* MODULE */ #endif /* MODULE */
MODULE_AUTHOR("Donald Becker, Alan Cox");
MODULE_DESCRIPTION("Support for the ancient 3Com 3c501 ethernet card");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -m486 -c -o 3c501.o 3c501.c"
* kept-new-versions: 5
* End:
*/
/*
* Index to functions.
*/
int el1_probe(struct net_device *dev);
static int el1_probe1(struct net_device *dev, int ioaddr);
static int el_open(struct net_device *dev);
static void el_timeout(struct net_device *dev);
static int el_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void el_receive(struct net_device *dev);
static void el_reset(struct net_device *dev);
static int el1_close(struct net_device *dev);
static struct net_device_stats *el1_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
#define EL1_IO_EXTENT 16
#ifndef EL_DEBUG
#define EL_DEBUG 0 /* use 0 for production, 1 for devel., >2 for debug */
#endif /* Anything above 5 is wordy death! */
#define debug el_debug
static int el_debug = EL_DEBUG;
/*
* Board-specific info in dev->priv.
*/
struct net_local
{
struct net_device_stats stats;
int tx_pkt_start; /* The length of the current Tx packet. */
int collisions; /* Tx collisions this packet */
int loading; /* Spot buffer load collisions */
int txing; /* True if card is in TX mode */
spinlock_t lock; /* Serializing lock */
};
#define RX_STATUS (ioaddr + 0x06)
#define RX_CMD RX_STATUS
#define TX_STATUS (ioaddr + 0x07)
#define TX_CMD TX_STATUS
#define GP_LOW (ioaddr + 0x08)
#define GP_HIGH (ioaddr + 0x09)
#define RX_BUF_CLR (ioaddr + 0x0A)
#define RX_LOW (ioaddr + 0x0A)
#define RX_HIGH (ioaddr + 0x0B)
#define SAPROM (ioaddr + 0x0C)
#define AX_STATUS (ioaddr + 0x0E)
#define AX_CMD AX_STATUS
#define DATAPORT (ioaddr + 0x0F)
#define TX_RDY 0x08 /* In TX_STATUS */
#define EL1_DATAPTR 0x08
#define EL1_RXPTR 0x0A
#define EL1_SAPROM 0x0C
#define EL1_DATAPORT 0x0f
/*
* Writes to the ax command register.
*/
#define AX_OFF 0x00 /* Irq off, buffer access on */
#define AX_SYS 0x40 /* Load the buffer */
#define AX_XMIT 0x44 /* Transmit a packet */
#define AX_RX 0x48 /* Receive a packet */
#define AX_LOOP 0x0C /* Loopback mode */
#define AX_RESET 0x80
/*
* Normal receive mode written to RX_STATUS. We must intr on short packets
* to avoid bogus rx lockups.
*/
#define RX_NORM 0xA8 /* 0x68 == all addrs, 0xA8 only to me. */
#define RX_PROM 0x68 /* Senior Prom, uhmm promiscuous mode. */
#define RX_MULT 0xE8 /* Accept multicast packets. */
#define TX_NORM 0x0A /* Interrupt on everything that might hang the chip */
/*
* TX_STATUS register.
*/
#define TX_COLLISION 0x02
#define TX_16COLLISIONS 0x04
#define TX_READY 0x08
#define RX_RUNT 0x08
#define RX_MISSED 0x01 /* Missed a packet due to 3c501 braindamage. */
#define RX_GOOD 0x30 /* Good packet 0x20, or simple overflow 0x10. */
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#define CPQFCTSSTRUCTS_H #define CPQFCTSSTRUCTS_H
#include <linux/timer.h> // timer declaration in our host data #include <linux/timer.h> // timer declaration in our host data
#include <linux/tqueue.h> // task queue sched
#include <asm/atomic.h> #include <asm/atomic.h>
#include "cpqfcTSioctl.h" #include "cpqfcTSioctl.h"
......
...@@ -317,13 +317,15 @@ uchar result; ...@@ -317,13 +317,15 @@ uchar result;
static void in2000_execute(struct Scsi_Host *instance); static void in2000_execute(struct Scsi_Host *instance);
int in2000_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) static int in2000_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
{ {
struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata; struct IN2000_hostdata *hostdata;
Scsi_Cmnd *tmp; Scsi_Cmnd *tmp;
unsigned long flags; unsigned long flags;
hostdata = (struct IN2000_hostdata *)cmd->host->hostdata; instance = cmd->host;
hostdata = (struct IN2000_hostdata *)instance->hostdata;
DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid)) DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
...@@ -355,7 +357,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid)) ...@@ -355,7 +357,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
if (cmd->use_sg) { if (cmd->use_sg) {
cmd->SCp.buffer = (struct scatterlist *)cmd->buffer; cmd->SCp.buffer = (struct scatterlist *)cmd->buffer;
cmd->SCp.buffers_residual = cmd->use_sg - 1; cmd->SCp.buffers_residual = cmd->use_sg - 1;
cmd->SCp.ptr = (char *)cmd->SCp.buffer->address; cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+cmd->SCp.buffer->offset;
cmd->SCp.this_residual = cmd->SCp.buffer->length; cmd->SCp.this_residual = cmd->SCp.buffer->length;
} }
else { else {
...@@ -391,9 +393,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid)) ...@@ -391,9 +393,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
* queue and calling in2000_execute(). * queue and calling in2000_execute().
*/ */
save_flags(flags); spin_lock_irqsave(instance->host_lock, flags);
cli();
/* /*
* Add the cmd to the end of 'input_Q'. Note that REQUEST_SENSE * Add the cmd to the end of 'input_Q'. Note that REQUEST_SENSE
* commands are added to the head of the queue so that the desired * commands are added to the head of the queue so that the desired
...@@ -418,8 +418,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid)) ...@@ -418,8 +418,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
in2000_execute(cmd->host); in2000_execute(cmd->host);
DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid)) DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
spin_unlock_irqrestore(instance->host_lock, flags);
restore_flags(flags);
return 0; return 0;
} }
...@@ -762,7 +761,7 @@ int i; ...@@ -762,7 +761,7 @@ int i;
++cmd->SCp.buffer; ++cmd->SCp.buffer;
--cmd->SCp.buffers_residual; --cmd->SCp.buffers_residual;
cmd->SCp.this_residual = cmd->SCp.buffer->length; cmd->SCp.this_residual = cmd->SCp.buffer->length;
cmd->SCp.ptr = cmd->SCp.buffer->address; cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
} }
/* Set up hardware registers */ /* Set up hardware registers */
...@@ -855,7 +854,7 @@ unsigned long flags; ...@@ -855,7 +854,7 @@ unsigned long flags;
/* Get the spin_lock and disable further ints, for SMP */ /* Get the spin_lock and disable further ints, for SMP */
CLISPIN_LOCK(instance, flags); spin_lock_irqsave(instance->host_lock, flags);
#ifdef PROC_STATISTICS #ifdef PROC_STATISTICS
hostdata->int_cnt++; hostdata->int_cnt++;
...@@ -993,7 +992,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT))) ...@@ -993,7 +992,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
write1_io(0, IO_LED_OFF); write1_io(0, IO_LED_OFF);
/* release the SMP spin_lock and restore irq state */ /* release the SMP spin_lock and restore irq state */
CLISPIN_UNLOCK(instance, flags); spin_unlock_irqrestore(instance->host_lock, flags);
return; return;
} }
...@@ -1011,7 +1010,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT))) ...@@ -1011,7 +1010,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
write1_io(0, IO_LED_OFF); write1_io(0, IO_LED_OFF);
/* release the SMP spin_lock and restore irq state */ /* release the SMP spin_lock and restore irq state */
CLISPIN_UNLOCK(instance, flags); spin_unlock_irqrestore(instance->host_lock, flags);
return; return;
} }
...@@ -1433,7 +1432,7 @@ DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0])) ...@@ -1433,7 +1432,7 @@ DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
hostdata->state = S_UNCONNECTED; hostdata->state = S_UNCONNECTED;
/* release the SMP spin_lock and restore irq state */ /* release the SMP spin_lock and restore irq state */
CLISPIN_UNLOCK(instance, flags); spin_unlock_irqrestore(instance->host_lock, flags);
return; return;
} }
DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid)) DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
...@@ -1609,7 +1608,7 @@ DB(DB_INTR,printk("-%ld",cmd->pid)) ...@@ -1609,7 +1608,7 @@ DB(DB_INTR,printk("-%ld",cmd->pid))
DB(DB_INTR,printk("} ")) DB(DB_INTR,printk("} "))
/* release the SMP spin_lock and restore irq state */ /* release the SMP spin_lock and restore irq state */
CLISPIN_UNLOCK(instance, flags); spin_unlock_irqrestore(instance->host_lock, flags);
} }
...@@ -1619,11 +1618,14 @@ DB(DB_INTR,printk("} ")) ...@@ -1619,11 +1618,14 @@ DB(DB_INTR,printk("} "))
#define RESET_CARD_AND_BUS 1 #define RESET_CARD_AND_BUS 1
#define B_FLAG 0x80 #define B_FLAG 0x80
/*
* Caller must hold instance lock!
*/
static int reset_hardware(struct Scsi_Host *instance, int type) static int reset_hardware(struct Scsi_Host *instance, int type)
{ {
struct IN2000_hostdata *hostdata; struct IN2000_hostdata *hostdata;
int qt,x; int qt,x;
unsigned long flags;
hostdata = (struct IN2000_hostdata *)instance->hostdata; hostdata = (struct IN2000_hostdata *)instance->hostdata;
...@@ -1638,16 +1640,16 @@ unsigned long flags; ...@@ -1638,16 +1640,16 @@ unsigned long flags;
write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER, write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER,
calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF)); calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF));
save_flags(flags);
cli();
write1_io(0,IO_FIFO_WRITE); /* clear fifo counter */ write1_io(0,IO_FIFO_WRITE); /* clear fifo counter */
write1_io(0,IO_FIFO_READ); /* start fifo out in read mode */ write1_io(0,IO_FIFO_READ); /* start fifo out in read mode */
write_3393(hostdata,WD_COMMAND, WD_CMD_RESET); write_3393(hostdata,WD_COMMAND, WD_CMD_RESET);
/* FIXME: timeout ?? */
while (!(READ_AUX_STAT() & ASR_INT)) while (!(READ_AUX_STAT() & ASR_INT))
; /* wait for RESET to complete */ cpu_relax(); /* wait for RESET to complete */
x = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */ x = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */
restore_flags(flags);
write_3393(hostdata,WD_QUEUE_TAG,0xa5); /* any random number */ write_3393(hostdata,WD_QUEUE_TAG,0xa5); /* any random number */
qt = read_3393(hostdata,WD_QUEUE_TAG); qt = read_3393(hostdata,WD_QUEUE_TAG);
if (qt == 0xa5) { if (qt == 0xa5) {
...@@ -1662,7 +1664,7 @@ unsigned long flags; ...@@ -1662,7 +1664,7 @@ unsigned long flags;
int in2000_reset(Scsi_Cmnd *cmd, unsigned int reset_flags) static int in2000_bus_reset(Scsi_Cmnd *cmd)
{ {
unsigned long flags; unsigned long flags;
struct Scsi_Host *instance; struct Scsi_Host *instance;
...@@ -1672,10 +1674,9 @@ int x; ...@@ -1672,10 +1674,9 @@ int x;
instance = cmd->host; instance = cmd->host;
hostdata = (struct IN2000_hostdata *)instance->hostdata; hostdata = (struct IN2000_hostdata *)instance->hostdata;
printk("scsi%d: Reset. ", instance->host_no); printk(KERN_WARNING "scsi%d: Reset. ", instance->host_no);
save_flags(flags);
cli();
spin_lock_irqsave(instance->host_lock, flags);
/* do scsi-reset here */ /* do scsi-reset here */
reset_hardware(instance, RESET_CARD_AND_BUS); reset_hardware(instance, RESET_CARD_AND_BUS);
...@@ -1694,13 +1695,22 @@ int x; ...@@ -1694,13 +1695,22 @@ int x;
hostdata->outgoing_len = 0; hostdata->outgoing_len = 0;
cmd->result = DID_RESET << 16; cmd->result = DID_RESET << 16;
restore_flags(flags); spin_unlock_irqrestore(instance->host_lock, flags);
return 0; return SUCCESS;
} }
static int in2000_host_reset(Scsi_Cmnd *cmd)
{
return FAILED;
}
static int in2000_device_reset(Scsi_Cmnd *cmd)
{
return FAILED;
}
int in2000_abort (Scsi_Cmnd *cmd)
static int in2000_abort (Scsi_Cmnd *cmd)
{ {
struct Scsi_Host *instance; struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata; struct IN2000_hostdata *hostdata;
...@@ -1709,13 +1719,10 @@ unsigned long flags; ...@@ -1709,13 +1719,10 @@ unsigned long flags;
uchar sr, asr; uchar sr, asr;
unsigned long timeout; unsigned long timeout;
save_flags (flags);
cli();
instance = cmd->host; instance = cmd->host;
hostdata = (struct IN2000_hostdata *)instance->hostdata; hostdata = (struct IN2000_hostdata *)instance->hostdata;
printk ("scsi%d: Abort-", instance->host_no); printk(KERN_DEBUG "scsi%d: Abort-", instance->host_no);
printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ", printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ",
READ_AUX_STAT(),read_3393_count(hostdata),cmd->SCp.this_residual,cmd->SCp.buffers_residual, READ_AUX_STAT(),read_3393_count(hostdata),cmd->SCp.this_residual,cmd->SCp.buffers_residual,
cmd->SCp.have_data_in,read1_io(IO_FIFO_COUNT)); cmd->SCp.have_data_in,read1_io(IO_FIFO_COUNT));
...@@ -1725,6 +1732,7 @@ unsigned long timeout; ...@@ -1725,6 +1732,7 @@ unsigned long timeout;
* from the inout_Q. * from the inout_Q.
*/ */
spin_lock_irqsave(instance->host_lock, flags);
tmp = (Scsi_Cmnd *)hostdata->input_Q; tmp = (Scsi_Cmnd *)hostdata->input_Q;
prev = 0; prev = 0;
while (tmp) { while (tmp) {
...@@ -1733,11 +1741,11 @@ unsigned long timeout; ...@@ -1733,11 +1741,11 @@ unsigned long timeout;
prev->host_scribble = cmd->host_scribble; prev->host_scribble = cmd->host_scribble;
cmd->host_scribble = NULL; cmd->host_scribble = NULL;
cmd->result = DID_ABORT << 16; cmd->result = DID_ABORT << 16;
printk("scsi%d: Abort - removing command %ld from input_Q. ", printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ",
instance->host_no, cmd->pid); instance->host_no, cmd->pid);
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
restore_flags(flags); spin_unlock_irqrestore(instance->host_lock, flags);
return SCSI_ABORT_SUCCESS; return SUCCESS;
} }
prev = tmp; prev = tmp;
tmp = (Scsi_Cmnd *)tmp->host_scribble; tmp = (Scsi_Cmnd *)tmp->host_scribble;
...@@ -1756,7 +1764,7 @@ unsigned long timeout; ...@@ -1756,7 +1764,7 @@ unsigned long timeout;
if (hostdata->connected == cmd) { if (hostdata->connected == cmd) {
printk("scsi%d: Aborting connected command %ld - ", printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ",
instance->host_no, cmd->pid); instance->host_no, cmd->pid);
printk("sending wd33c93 ABORT command - "); printk("sending wd33c93 ABORT command - ");
...@@ -1800,7 +1808,6 @@ unsigned long timeout; ...@@ -1800,7 +1808,6 @@ unsigned long timeout;
in2000_execute (instance); in2000_execute (instance);
restore_flags(flags);
return SCSI_ABORT_SUCCESS; return SCSI_ABORT_SUCCESS;
} }
...@@ -1813,9 +1820,9 @@ unsigned long timeout; ...@@ -1813,9 +1820,9 @@ unsigned long timeout;
for (tmp=(Scsi_Cmnd *)hostdata->disconnected_Q; tmp; for (tmp=(Scsi_Cmnd *)hostdata->disconnected_Q; tmp;
tmp=(Scsi_Cmnd *)tmp->host_scribble) tmp=(Scsi_Cmnd *)tmp->host_scribble)
if (cmd == tmp) { if (cmd == tmp) {
restore_flags(flags); spin_unlock_irqrestore(instance->host_lock, flags);
printk("Sending ABORT_SNOOZE. "); printk(KERN_DEBUG "scsi%d: unable to abort disconnected command.\n", instance->host_no);
return SCSI_ABORT_SNOOZE; return FAILED;
} }
/* /*
...@@ -1830,10 +1837,10 @@ unsigned long timeout; ...@@ -1830,10 +1837,10 @@ unsigned long timeout;
in2000_execute (instance); in2000_execute (instance);
restore_flags(flags); spin_unlock_irqrestore(instance->host_lock, flags);
printk("scsi%d: warning : SCSI command probably completed successfully" printk("scsi%d: warning : SCSI command probably completed successfully"
" before abortion. ", instance->host_no); " before abortion. ", instance->host_no);
return SCSI_ABORT_NOT_RUNNING; return SUCCESS;
} }
...@@ -1845,7 +1852,7 @@ static char setup_buffer[SETUP_BUFFER_SIZE]; ...@@ -1845,7 +1852,7 @@ static char setup_buffer[SETUP_BUFFER_SIZE];
static char setup_used[MAX_SETUP_ARGS]; static char setup_used[MAX_SETUP_ARGS];
static int done_setup = 0; static int done_setup = 0;
void __init in2000_setup (char *str, int *ints) static void __init in2000_setup (char *str, int *ints)
{ {
int i; int i;
char *p1,*p2; char *p1,*p2;
...@@ -1931,7 +1938,7 @@ static const int int_tab[] in2000__INITDATA = { ...@@ -1931,7 +1938,7 @@ static const int int_tab[] in2000__INITDATA = {
}; };
int __init in2000_detect(Scsi_Host_Template * tpnt) static int __init in2000_detect(Scsi_Host_Template * tpnt)
{ {
struct Scsi_Host *instance; struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata; struct IN2000_hostdata *hostdata;
...@@ -2115,7 +2122,11 @@ char buf[32]; ...@@ -2115,7 +2122,11 @@ char buf[32];
#endif #endif
/* FIXME: not strictly needed I think but the called code expects
to be locked */
spin_lock_irqsave(instance->host_lock, flags);
x = reset_hardware(instance,(hostdata->args & A_NO_SCSI_RESET)?RESET_CARD:RESET_CARD_AND_BUS); x = reset_hardware(instance,(hostdata->args & A_NO_SCSI_RESET)?RESET_CARD:RESET_CARD_AND_BUS);
spin_unlock_irqrestore(instance->host_lock, flags);
hostdata->microcode = read_3393(hostdata,WD_CDB_1); hostdata->microcode = read_3393(hostdata,WD_CDB_1);
if (x & 0x01) { if (x & 0x01) {
...@@ -2158,7 +2169,7 @@ char buf[32]; ...@@ -2158,7 +2169,7 @@ char buf[32];
* supposed to do... * supposed to do...
*/ */
int in2000_biosparam(Disk *disk, struct block_device *dev, int *iinfo) static int in2000_biosparam(Disk *disk, struct block_device *dev, int *iinfo)
{ {
int size; int size;
...@@ -2190,7 +2201,7 @@ int size; ...@@ -2190,7 +2201,7 @@ int size;
} }
int in2000_proc_info(char *buf, char **start, off_t off, int len, int hn, int in) static int in2000_proc_info(char *buf, char **start, off_t off, int len, int hn, int in)
{ {
#ifdef PROC_INTERFACE #ifdef PROC_INTERFACE
...@@ -2260,8 +2271,7 @@ static int stop = 0; ...@@ -2260,8 +2271,7 @@ static int stop = 0;
return len; return len;
} }
save_flags(flags); spin_lock_irqsave(instance->host_lock, flags);
cli();
bp = buf; bp = buf;
*bp = '\0'; *bp = '\0';
if (hd->proc & PR_VERSION) { if (hd->proc & PR_VERSION) {
...@@ -2340,7 +2350,7 @@ static int stop = 0; ...@@ -2340,7 +2350,7 @@ static int stop = 0;
; /* insert your own custom function here */ ; /* insert your own custom function here */
} }
strcat(bp,"\n"); strcat(bp,"\n");
restore_flags(flags); spin_unlock_irqrestore(instance->host_lock, flags);
*start = buf; *start = buf;
if (stop) { if (stop) {
stop = 0; stop = 0;
......
...@@ -397,13 +397,15 @@ struct IN2000_hostdata { ...@@ -397,13 +397,15 @@ struct IN2000_hostdata {
# define CLISPIN_UNLOCK(host,flags) spin_unlock_irqrestore(host->host_lock, \ # define CLISPIN_UNLOCK(host,flags) spin_unlock_irqrestore(host->host_lock, \
flags) flags)
int in2000_detect(Scsi_Host_Template *) in2000__INIT; static int in2000_detect(Scsi_Host_Template *) in2000__INIT;
int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int in2000_abort(Scsi_Cmnd *); static int in2000_abort(Scsi_Cmnd *);
void in2000_setup(char *, int *) in2000__INIT; static void in2000_setup(char *, int *) in2000__INIT;
int in2000_proc_info(char *, char **, off_t, int, int, int); static int in2000_proc_info(char *, char **, off_t, int, int, int);
int in2000_biosparam(struct scsi_disk *, struct block_device *, int *); static int in2000_biosparam(struct scsi_disk *, struct block_device *, int *);
int in2000_reset(Scsi_Cmnd *, unsigned int); static int in2000_host_reset(Scsi_Cmnd *);
static int in2000_bus_reset(Scsi_Cmnd *);
static int in2000_device_reset(Scsi_Cmnd *);
#define IN2000_CAN_Q 16 #define IN2000_CAN_Q 16
...@@ -411,19 +413,21 @@ int in2000_reset(Scsi_Cmnd *, unsigned int); ...@@ -411,19 +413,21 @@ int in2000_reset(Scsi_Cmnd *, unsigned int);
#define IN2000_CPL 2 #define IN2000_CPL 2
#define IN2000_HOST_ID 7 #define IN2000_HOST_ID 7
#define IN2000 { proc_name: "in2000", /* name of /proc/scsi directory entry */ \ #define IN2000 { proc_name: "in2000", /* name of /proc/scsi directory entry */ \
proc_info: in2000_proc_info, /* pointer to proc info function */ \ proc_info: in2000_proc_info, /* pointer to proc info function */ \
name: "Always IN2000", /* device name */ \ name: "Always IN2000", /* device name */ \
detect: in2000_detect, /* returns number of in2000's found */ \ detect: in2000_detect, /* returns number of in2000's found */ \
queuecommand: in2000_queuecommand, /* queue scsi command, don't wait */ \ queuecommand: in2000_queuecommand, /* queue scsi command, don't wait */ \
abort: in2000_abort, /* abort current command */ \ eh_abort_handler: in2000_abort, /* abort current command */ \
reset: in2000_reset, /* reset scsi bus */ \ eh_bus_reset_handler: in2000_bus_reset, /* reset scsi bus */ \
bios_param: in2000_biosparam, /* figures out BIOS parameters for lilo, etc */ \ eh_device_reset_handler: in2000_device_reset, /* reset scsi device */ \
can_queue: IN2000_CAN_Q, /* max commands we can queue up */ \ eh_host_reset_handler: in2000_host_reset, /* reset scsi hba */ \
this_id: IN2000_HOST_ID, /* host-adapter scsi id */ \ bios_param: in2000_biosparam, /* figures out BIOS parameters for lilo, etc */ \
sg_tablesize: IN2000_SG, /* scatter-gather table size */ \ can_queue: IN2000_CAN_Q, /* max commands we can queue up */ \
cmd_per_lun: IN2000_CPL, /* commands per lun */ \ this_id: IN2000_HOST_ID, /* host-adapter scsi id */ \
use_clustering: DISABLE_CLUSTERING, /* ENABLE_CLUSTERING may speed things up */ \ sg_tablesize: IN2000_SG, /* scatter-gather table size */ \
cmd_per_lun: IN2000_CPL, /* commands per lun */ \
use_clustering: DISABLE_CLUSTERING, /* ENABLE_CLUSTERING may speed things up */ \
} }
#endif /* IN2000_H */ #endif /* IN2000_H */
/*****************************************************************************/ /*****************************************************************************/
/* ips.c -- driver for the IBM ServeRAID controller */ /* ips.c -- driver for the Adaptec / IBM ServeRAID controller */
/* */ /* */
/* Written By: Keith Mitchell, IBM Corporation */ /* Written By: Keith Mitchell, IBM Corporation */
/* Jack Hammer, Adaptec, Inc. */ /* Jack Hammer, Adaptec, Inc. */
/* David Jeffery, Adaptec, Inc. */ /* David Jeffery, Adaptec, Inc. */
/* */ /* */
/* Copyright (C) 2000 IBM Corporation */ /* Copyright (C) 2000 IBM Corporation */
/* Copyright (C) 2002 Adaptec, Inc. */
/* */ /* */
/* This program is free software; you can redistribute it and/or modify */ /* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */ /* it under the terms of the GNU General Public License as published by */
...@@ -42,7 +43,7 @@ ...@@ -42,7 +43,7 @@
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */ /* */
/* Bugs/Comments/Suggestions about this driver should be mailed to: */ /* Bugs/Comments/Suggestions about this driver should be mailed to: */
/* ipslinux@us.ibm.com */ /* ipslinux@adaptec.com */
/* */ /* */
/* For system support issues, contact your local IBM Customer support. */ /* For system support issues, contact your local IBM Customer support. */
/* Directions to find IBM Customer Support for each country can be found at: */ /* Directions to find IBM Customer Support for each country can be found at: */
...@@ -66,9 +67,8 @@ ...@@ -66,9 +67,8 @@
/* 0.99.05 - Fix an oops when we get certain passthru commands */ /* 0.99.05 - Fix an oops when we get certain passthru commands */
/* 1.00.00 - Initial Public Release */ /* 1.00.00 - Initial Public Release */
/* Functionally equivalent to 0.99.05 */ /* Functionally equivalent to 0.99.05 */
/* 3.60.00 - Bump max commands to 128 for use with ServeRAID firmware 3.60 */ /* 3.60.00 - Bump max commands to 128 for use with firmware 3.60 */
/* - Change version to 3.60 to coincide with ServeRAID release */ /* - Change version to 3.60 to coincide with release numbering. */
/* numbering. */
/* 3.60.01 - Remove bogus error check in passthru routine */ /* 3.60.01 - Remove bogus error check in passthru routine */
/* 3.60.02 - Make DCDB direction based on lookup table */ /* 3.60.02 - Make DCDB direction based on lookup table */
/* - Only allow one DCDB command to a SCSI ID at a time */ /* - Only allow one DCDB command to a SCSI ID at a time */
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
/* 4.00.01 - Add support for First Failure Data Capture */ /* 4.00.01 - Add support for First Failure Data Capture */
/* 4.00.02 - Fix problem with PT DCDB with no buffer */ /* 4.00.02 - Fix problem with PT DCDB with no buffer */
/* 4.00.03 - Add alternative passthru interface */ /* 4.00.03 - Add alternative passthru interface */
/* - Add ability to flash ServeRAID BIOS */ /* - Add ability to flash BIOS */
/* 4.00.04 - Rename structures/constants to be prefixed with IPS_ */ /* 4.00.04 - Rename structures/constants to be prefixed with IPS_ */
/* 4.00.05 - Remove wish_block from init routine */ /* 4.00.05 - Remove wish_block from init routine */
/* - Use linux/spinlock.h instead of asm/spinlock.h for kernels */ /* - Use linux/spinlock.h instead of asm/spinlock.h for kernels */
...@@ -158,9 +158,7 @@ ...@@ -158,9 +158,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/sched.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/reboot.h> #include <linux/reboot.h>
...@@ -222,7 +220,7 @@ struct proc_dir_entry proc_scsi_ips = { ...@@ -222,7 +220,7 @@ struct proc_dir_entry proc_scsi_ips = {
dma_addr_t *dmahandle) { dma_addr_t *dmahandle) {
void * ptr = kmalloc(size, GFP_ATOMIC); void * ptr = kmalloc(size, GFP_ATOMIC);
if(ptr){ if(ptr){
*dmahandle = VIRT_TO_BUS(ptr); *dmahandle = (uint32_t)virt_to_bus(ptr);
} }
return ptr; return ptr;
} }
...@@ -231,10 +229,10 @@ struct proc_dir_entry proc_scsi_ips = { ...@@ -231,10 +229,10 @@ struct proc_dir_entry proc_scsi_ips = {
#define pci_map_sg(a,b,n,z) (n) #define pci_map_sg(a,b,n,z) (n)
#define pci_unmap_sg(a,b,c,d) #define pci_unmap_sg(a,b,c,d)
#define pci_map_single(a,b,c,d) (VIRT_TO_BUS(b)) #define pci_map_single(a,b,c,d) ((uint32_t)virt_to_bus(b))
#define pci_unmap_single(a,b,c,d) #define pci_unmap_single(a,b,c,d)
#ifndef sg_dma_address #ifndef sg_dma_address
#define sg_dma_address(x) (VIRT_TO_BUS((x)->address)) #define sg_dma_address(x) ((uint32_t)virt_to_bus((x)->address))
#define sg_dma_len(x) ((x)->length) #define sg_dma_len(x) ((x)->length)
#endif #endif
#define pci_unregister_driver(x) #define pci_unregister_driver(x)
...@@ -242,18 +240,16 @@ struct proc_dir_entry proc_scsi_ips = { ...@@ -242,18 +240,16 @@ struct proc_dir_entry proc_scsi_ips = {
#if LINUX_VERSION_CODE <= LinuxVersionCode(2,5,0) #if LINUX_VERSION_CODE <= LinuxVersionCode(2,5,0)
#define IPS_SG_ADDRESS(sg) ((sg)->address) #define IPS_SG_ADDRESS(sg) ((sg)->address)
#define IPS_LOCK_IRQ(lock) spin_lock_irq(&io_request_lock)
#define IPS_UNLOCK_IRQ(lock) spin_unlock_irq(&io_request_lock)
#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags) #define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
#define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags) #define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
#ifndef __devexit_p
#define __devexit_p(x) x
#endif
#else #else
#define IPS_SG_ADDRESS(sg) (page_address((sg)->page) ? \ #define IPS_SG_ADDRESS(sg) (page_address((sg)->page) ? \
page_address((sg)->page)+(sg)->offset : 0) page_address((sg)->page)+(sg)->offset : 0)
#define IPS_LOCK_IRQ(lock) spin_lock_irq(lock) #define IPS_LOCK_SAVE(lock,flags) spin_lock(lock)
#define IPS_UNLOCK_IRQ(lock) spin_unlock_irq(lock) #define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock(lock)
#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(lock,flags)
#define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(lock,flags)
#endif #endif
#define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \ #define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \
...@@ -532,6 +528,7 @@ static void copy_mem_info(IPS_INFOSTR *, char *, int); ...@@ -532,6 +528,7 @@ static void copy_mem_info(IPS_INFOSTR *, char *, int);
static int copy_info(IPS_INFOSTR *, char *, ...); static int copy_info(IPS_INFOSTR *, char *, ...);
static int ips_get_version_info(ips_ha_t *ha, IPS_VERSION_DATA *Buffer, int intr ); static int ips_get_version_info(ips_ha_t *ha, IPS_VERSION_DATA *Buffer, int intr );
static void ips_version_check(ips_ha_t *ha, int intr); static void ips_version_check(ips_ha_t *ha, int intr);
static int ips_abort_init(ips_ha_t *ha, struct Scsi_Host *sh, int index);
static int ips_init_phase2( int index ); static int ips_init_phase2( int index );
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
...@@ -962,14 +959,6 @@ ips_detect(Scsi_Host_Template *SHT) { ...@@ -962,14 +959,6 @@ ips_detect(Scsi_Host_Template *SHT) {
ha = IPS_HA(sh); ha = IPS_HA(sh);
memset(ha, 0, sizeof(ips_ha_t)); memset(ha, 0, sizeof(ips_ha_t));
/* Initialize spin lock */
spin_lock_init(&ha->scb_lock);
spin_lock_init(&ha->copp_lock);
spin_lock_init(&ha->ips_lock);
spin_lock_init(&ha->copp_waitlist.lock);
spin_lock_init(&ha->scb_waitlist.lock);
spin_lock_init(&ha->scb_activelist.lock);
ips_sh[ips_next_controller] = sh; ips_sh[ips_next_controller] = sh;
ips_ha[ips_next_controller] = ha; ips_ha[ips_next_controller] = ha;
ips_num_controllers++; ips_num_controllers++;
...@@ -1416,12 +1405,13 @@ ips_halt(struct notifier_block *nb, ulong event, void *buf) { ...@@ -1416,12 +1405,13 @@ ips_halt(struct notifier_block *nb, ulong event, void *buf) {
/* Routine Description: */ /* Routine Description: */
/* */ /* */
/* Abort a command (using the new error code stuff) */ /* Abort a command (using the new error code stuff) */
/* */ /* Note: this routine is called under the io_request_lock */
/****************************************************************************/ /****************************************************************************/
int int
ips_eh_abort(Scsi_Cmnd *SC) { ips_eh_abort(Scsi_Cmnd *SC) {
ips_ha_t *ha; ips_ha_t *ha;
ips_copp_wait_item_t *item; ips_copp_wait_item_t *item;
int ret;
METHOD_TRACE("ips_eh_abort", 1); METHOD_TRACE("ips_eh_abort", 1);
...@@ -1443,36 +1433,25 @@ ips_eh_abort(Scsi_Cmnd *SC) { ...@@ -1443,36 +1433,25 @@ ips_eh_abort(Scsi_Cmnd *SC) {
return (FAILED); return (FAILED);
} }
if (test_and_set_bit(IPS_IN_ABORT, &ha->flags))
return (FAILED);
/* See if the command is on the copp queue */ /* See if the command is on the copp queue */
IPS_QUEUE_LOCK(&ha->copp_waitlist);
item = ha->copp_waitlist.head; item = ha->copp_waitlist.head;
while ((item) && (item->scsi_cmd != SC)) while ((item) && (item->scsi_cmd != SC))
item = item->next; item = item->next;
IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
if (item) { if (item) {
/* Found it */ /* Found it */
ips_removeq_copp(&ha->copp_waitlist, item); ips_removeq_copp(&ha->copp_waitlist, item);
clear_bit(IPS_IN_ABORT, &ha->flags); ret = (SUCCESS);
return (SUCCESS);
}
/* See if the command is on the wait queue */ /* See if the command is on the wait queue */
if (ips_removeq_wait(&ha->scb_waitlist, SC)) { } else if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
/* command not sent yet */ /* command not sent yet */
clear_bit(IPS_IN_ABORT, &ha->flags); ret = (SUCCESS);
return (SUCCESS);
} else { } else {
/* command must have already been sent */ /* command must have already been sent */
clear_bit(IPS_IN_ABORT, &ha->flags); ret = (FAILED);
return (FAILED);
} }
return ret;
} }
/****************************************************************************/ /****************************************************************************/
...@@ -1493,7 +1472,6 @@ ips_eh_reset(Scsi_Cmnd *SC) { ...@@ -1493,7 +1472,6 @@ ips_eh_reset(Scsi_Cmnd *SC) {
ips_ha_t *ha; ips_ha_t *ha;
ips_scb_t *scb; ips_scb_t *scb;
ips_copp_wait_item_t *item; ips_copp_wait_item_t *item;
unsigned long cpu_flags;
METHOD_TRACE("ips_eh_reset", 1); METHOD_TRACE("ips_eh_reset", 1);
...@@ -1518,36 +1496,27 @@ ips_eh_reset(Scsi_Cmnd *SC) { ...@@ -1518,36 +1496,27 @@ ips_eh_reset(Scsi_Cmnd *SC) {
if (!ha->active) if (!ha->active)
return (FAILED); return (FAILED);
if (test_and_set_bit(IPS_IN_RESET, &ha->flags))
return (FAILED);
/* See if the command is on the copp queue */ /* See if the command is on the copp queue */
IPS_QUEUE_LOCK(&ha->copp_waitlist);
item = ha->copp_waitlist.head; item = ha->copp_waitlist.head;
while ((item) && (item->scsi_cmd != SC)) while ((item) && (item->scsi_cmd != SC))
item = item->next; item = item->next;
IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
if (item) { if (item) {
/* Found it */ /* Found it */
ips_removeq_copp(&ha->copp_waitlist, item); ips_removeq_copp(&ha->copp_waitlist, item);
clear_bit(IPS_IN_RESET, &ha->flags);
return (SUCCESS); return (SUCCESS);
} }
/* See if the command is on the wait queue */ /* See if the command is on the wait queue */
if (ips_removeq_wait(&ha->scb_waitlist, SC)) { if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
/* command not sent yet */ /* command not sent yet */
clear_bit(IPS_IN_RESET, &ha->flags);
return (SUCCESS); return (SUCCESS);
} }
/* An explanation for the casual observer: */ /* An explanation for the casual observer: */
/* Part of the function of a RAID controller is automatic error */ /* Part of the function of a RAID controller is automatic error */
/* detection and recovery. As such, the only problem that physically */ /* detection and recovery. As such, the only problem that physically */
/* resetting a ServeRAID adapter will ever fix is when, for some reason,*/ /* resetting an adapter will ever fix is when, for some reason, */
/* the driver is not successfully communicating with the adapter. */ /* the driver is not successfully communicating with the adapter. */
/* Therefore, we will attempt to flush this adapter. If that succeeds, */ /* Therefore, we will attempt to flush this adapter. If that succeeds, */
/* then there's no real purpose in a physical reset. This will complete */ /* then there's no real purpose in a physical reset. This will complete */
...@@ -1574,13 +1543,12 @@ ips_eh_reset(Scsi_Cmnd *SC) { ...@@ -1574,13 +1543,12 @@ ips_eh_reset(Scsi_Cmnd *SC) {
ret = ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_IORL); ret = ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_IORL);
if (ret == IPS_SUCCESS) { if (ret == IPS_SUCCESS) {
printk(KERN_NOTICE "(%s%d) Reset Request - Flushed Cache\n", ips_name, ha->host_num); printk(KERN_NOTICE "(%s%d) Reset Request - Flushed Cache\n", ips_name, ha->host_num);
clear_bit(IPS_IN_RESET, &ha->flags);
return (SUCCESS); return (SUCCESS);
} }
} }
/* Either we can't communicate with the adapter or it's an IOCTL request */ /* Either we can't communicate with the adapter or it's an IOCTL request */
/* from a ServeRAID utility. A physical reset is needed at this point. */ /* from a utility. A physical reset is needed at this point. */
ha->ioctl_reset = 0; /* Reset the IOCTL Requested Reset Flag */ ha->ioctl_reset = 0; /* Reset the IOCTL Requested Reset Flag */
...@@ -1619,8 +1587,6 @@ ips_eh_reset(Scsi_Cmnd *SC) { ...@@ -1619,8 +1587,6 @@ ips_eh_reset(Scsi_Cmnd *SC) {
} }
ha->active = FALSE; ha->active = FALSE;
clear_bit(IPS_IN_RESET, &ha->flags);
return (FAILED); return (FAILED);
} }
...@@ -1651,8 +1617,6 @@ ips_eh_reset(Scsi_Cmnd *SC) { ...@@ -1651,8 +1617,6 @@ ips_eh_reset(Scsi_Cmnd *SC) {
} }
ha->active = FALSE; ha->active = FALSE;
clear_bit(IPS_IN_RESET, &ha->flags);
return (FAILED); return (FAILED);
} }
...@@ -1661,10 +1625,8 @@ ips_eh_reset(Scsi_Cmnd *SC) { ...@@ -1661,10 +1625,8 @@ ips_eh_reset(Scsi_Cmnd *SC) {
struct timeval tv; struct timeval tv;
do_gettimeofday(&tv); do_gettimeofday(&tv);
IPS_HA_LOCK(cpu_flags);
ha->last_ffdc = tv.tv_sec; ha->last_ffdc = tv.tv_sec;
ha->reset_count++; ha->reset_count++;
IPS_HA_UNLOCK(cpu_flags);
ips_ffdc_reset(ha, IPS_INTR_IORL); ips_ffdc_reset(ha, IPS_INTR_IORL);
} }
...@@ -1683,25 +1645,11 @@ ips_eh_reset(Scsi_Cmnd *SC) { ...@@ -1683,25 +1645,11 @@ ips_eh_reset(Scsi_Cmnd *SC) {
ha->dcdb_active[i-1] = 0; ha->dcdb_active[i-1] = 0;
/* Reset the number of active IOCTLs */ /* Reset the number of active IOCTLs */
IPS_HA_LOCK(cpu_flags);
ha->num_ioctl = 0; ha->num_ioctl = 0;
IPS_HA_UNLOCK(cpu_flags);
clear_bit(IPS_IN_RESET, &ha->flags); ips_next(ha, IPS_INTR_IORL);
if (!test_bit(IPS_IN_INTR, &ha->flags)) {
/*
* Only execute the next command when
* we are not being called from the
* interrupt handler. The interrupt
* handler wants to do this and since
* interrupts are turned off here....
*/
ips_next(ha, IPS_INTR_IORL);
}
return (SUCCESS); return (SUCCESS);
#endif /* NO_IPS_RESET */ #endif /* NO_IPS_RESET */
} }
...@@ -1721,7 +1669,6 @@ ips_eh_reset(Scsi_Cmnd *SC) { ...@@ -1721,7 +1669,6 @@ ips_eh_reset(Scsi_Cmnd *SC) {
int int
ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) { ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
ips_ha_t *ha; ips_ha_t *ha;
unsigned long cpu_flags;
ips_passthru_t *pt; ips_passthru_t *pt;
METHOD_TRACE("ips_queue", 1); METHOD_TRACE("ips_queue", 1);
...@@ -1735,28 +1682,17 @@ ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) { ...@@ -1735,28 +1682,17 @@ ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
return (DID_ERROR); return (DID_ERROR);
if (ips_is_passthru(SC)) { if (ips_is_passthru(SC)) {
IPS_QUEUE_LOCK(&ha->copp_waitlist);
if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) { if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {
IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
SC->result = DID_BUS_BUSY << 16;
done(SC);
return (0);
} else {
IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
}
} else {
IPS_QUEUE_LOCK(&ha->scb_waitlist);
if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
IPS_QUEUE_UNLOCK(&ha->scb_waitlist);
SC->result = DID_BUS_BUSY << 16; SC->result = DID_BUS_BUSY << 16;
done(SC); done(SC);
return (0); return (0);
} else {
IPS_QUEUE_UNLOCK(&ha->scb_waitlist);
} }
} else if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
SC->result = DID_BUS_BUSY << 16;
done(SC);
return (0);
} }
SC->scsi_done = done; SC->scsi_done = done;
...@@ -1810,27 +1746,15 @@ ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) { ...@@ -1810,27 +1746,15 @@ ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
} }
scratch->scsi_cmd = SC; scratch->scsi_cmd = SC;
sema_init(&ha->ioctl_sem, 0);
scratch->sem = &ha->ioctl_sem;
scratch->next = NULL; scratch->next = NULL;
ips_putq_copp_tail(&ha->copp_waitlist, scratch); ips_putq_copp_tail(&ha->copp_waitlist, scratch);
} }
else else {
ips_putq_wait_tail(&ha->scb_waitlist, SC); ips_putq_wait_tail(&ha->scb_waitlist, SC);
if(ha->scb_waitlist.count + ha->scb_activelist.count > 32)
mod_timer(&SC->eh_timeout, jiffies + 120 * HZ);
IPS_HA_LOCK(cpu_flags);
if ((!test_bit(IPS_IN_INTR, &ha->flags)) &&
(!test_bit(IPS_IN_ABORT, &ha->flags)) &&
(!test_bit(IPS_IN_RESET, &ha->flags))) {
IPS_HA_UNLOCK(cpu_flags);
ips_next(ha, IPS_INTR_IORL);
} else {
IPS_HA_UNLOCK(cpu_flags);
} }
ips_next(ha, IPS_INTR_IORL);
/* If We were using the CD Boot Flash Buffer, Restore the Old Values */ /* If We were using the CD Boot Flash Buffer, Restore the Old Values */
if ( ips_FlashData == ha->ioctl_data ) { if ( ips_FlashData == ha->ioctl_data ) {
...@@ -1960,20 +1884,13 @@ do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -1960,20 +1884,13 @@ do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
host = ips_sh[ha->host_num]; host = ips_sh[ha->host_num];
IPS_LOCK_SAVE(host->host_lock, cpu_flags); IPS_LOCK_SAVE(host->host_lock, cpu_flags);
if (test_and_set_bit(IPS_IN_INTR, &ha->flags)) {
IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
return ;
}
if (!ha->active) { if (!ha->active) {
clear_bit(IPS_IN_INTR, &ha->flags);
IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
return; return;
} }
(*ha->func.intr)(ha); (*ha->func.intr)(ha);
clear_bit(IPS_IN_INTR, &ha->flags);
IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
/* start the next command */ /* start the next command */
...@@ -1997,7 +1914,6 @@ ips_intr_copperhead(ips_ha_t *ha) { ...@@ -1997,7 +1914,6 @@ ips_intr_copperhead(ips_ha_t *ha) {
ips_scb_t *scb; ips_scb_t *scb;
IPS_STATUS cstatus; IPS_STATUS cstatus;
int intrstatus; int intrstatus;
unsigned long cpu_flags;
METHOD_TRACE("ips_intr", 2); METHOD_TRACE("ips_intr", 2);
...@@ -2007,15 +1923,12 @@ ips_intr_copperhead(ips_ha_t *ha) { ...@@ -2007,15 +1923,12 @@ ips_intr_copperhead(ips_ha_t *ha) {
if (!ha->active) if (!ha->active)
return; return;
IPS_HA_LOCK(cpu_flags);
intrstatus = (*ha->func.isintr)(ha); intrstatus = (*ha->func.isintr)(ha);
if (!intrstatus) { if (!intrstatus) {
/* /*
* Unexpected/Shared interrupt * Unexpected/Shared interrupt
*/ */
IPS_HA_UNLOCK(cpu_flags);
return; return;
} }
...@@ -2042,12 +1955,8 @@ ips_intr_copperhead(ips_ha_t *ha) { ...@@ -2042,12 +1955,8 @@ ips_intr_copperhead(ips_ha_t *ha) {
* use the callback function to finish things up * use the callback function to finish things up
* NOTE: interrupts are OFF for this * NOTE: interrupts are OFF for this
*/ */
IPS_HA_UNLOCK(cpu_flags);
(*scb->callback) (ha, scb); (*scb->callback) (ha, scb);
IPS_HA_LOCK(cpu_flags);
} /* end while */ } /* end while */
IPS_HA_UNLOCK(cpu_flags);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -2067,7 +1976,6 @@ ips_intr_morpheus(ips_ha_t *ha) { ...@@ -2067,7 +1976,6 @@ ips_intr_morpheus(ips_ha_t *ha) {
ips_scb_t *scb; ips_scb_t *scb;
IPS_STATUS cstatus; IPS_STATUS cstatus;
int intrstatus; int intrstatus;
unsigned long cpu_flags;
METHOD_TRACE("ips_intr_morpheus", 2); METHOD_TRACE("ips_intr_morpheus", 2);
...@@ -2077,15 +1985,12 @@ ips_intr_morpheus(ips_ha_t *ha) { ...@@ -2077,15 +1985,12 @@ ips_intr_morpheus(ips_ha_t *ha) {
if (!ha->active) if (!ha->active)
return; return;
IPS_HA_LOCK(cpu_flags);
intrstatus = (*ha->func.isintr)(ha); intrstatus = (*ha->func.isintr)(ha);
if (!intrstatus) { if (!intrstatus) {
/* /*
* Unexpected/Shared interrupt * Unexpected/Shared interrupt
*/ */
IPS_HA_UNLOCK(cpu_flags);
return; return;
} }
...@@ -2118,12 +2023,8 @@ ips_intr_morpheus(ips_ha_t *ha) { ...@@ -2118,12 +2023,8 @@ ips_intr_morpheus(ips_ha_t *ha) {
* use the callback function to finish things up * use the callback function to finish things up
* NOTE: interrupts are OFF for this * NOTE: interrupts are OFF for this
*/ */
IPS_HA_UNLOCK(cpu_flags);
(*scb->callback) (ha, scb); (*scb->callback) (ha, scb);
IPS_HA_LOCK(cpu_flags);
} /* end while */ } /* end while */
IPS_HA_UNLOCK(cpu_flags);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -3235,8 +3136,7 @@ ips_next(ips_ha_t *ha, int intr) { ...@@ -3235,8 +3136,7 @@ ips_next(ips_ha_t *ha, int intr) {
Scsi_Cmnd *q; Scsi_Cmnd *q;
ips_copp_wait_item_t *item; ips_copp_wait_item_t *item;
int ret; int ret;
unsigned long cpu_flags; unsigned long cpu_flags = 0;
unsigned long cpu_flags2 = 0;
struct Scsi_Host *host; struct Scsi_Host *host;
METHOD_TRACE("ips_next", 1); METHOD_TRACE("ips_next", 1);
...@@ -3247,27 +3147,20 @@ ips_next(ips_ha_t *ha, int intr) { ...@@ -3247,27 +3147,20 @@ ips_next(ips_ha_t *ha, int intr) {
* Block access to the queue function so * Block access to the queue function so
* this command won't time out * this command won't time out
*/ */
if (intr == IPS_INTR_ON) if(intr == IPS_INTR_ON)
IPS_LOCK_SAVE(host->host_lock, cpu_flags2); IPS_LOCK_SAVE(host->host_lock, cpu_flags);
if ((ha->subsys->param[3] & 0x300000) && ( ha->scb_activelist.count == 0 )) { if ((ha->subsys->param[3] & 0x300000) && ( ha->scb_activelist.count == 0 )) {
struct timeval tv; struct timeval tv;
do_gettimeofday(&tv); do_gettimeofday(&tv);
IPS_HA_LOCK(cpu_flags);
if (tv.tv_sec - ha->last_ffdc > IPS_SECS_8HOURS) { if (tv.tv_sec - ha->last_ffdc > IPS_SECS_8HOURS) {
ha->last_ffdc = tv.tv_sec; ha->last_ffdc = tv.tv_sec;
IPS_HA_UNLOCK(cpu_flags);
ips_ffdc_time(ha); ips_ffdc_time(ha);
} else {
IPS_HA_UNLOCK(cpu_flags);
} }
} }
if (intr == IPS_INTR_ON)
IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags2);
/* /*
* Send passthru commands * Send passthru commands
* These have priority over normal I/O * These have priority over normal I/O
...@@ -3275,22 +3168,21 @@ ips_next(ips_ha_t *ha, int intr) { ...@@ -3275,22 +3168,21 @@ ips_next(ips_ha_t *ha, int intr) {
* since we limit the number that can be active * since we limit the number that can be active
* on the card at any one time * on the card at any one time
*/ */
IPS_HA_LOCK(cpu_flags);
IPS_QUEUE_LOCK(&ha->copp_waitlist);
while ((ha->num_ioctl < IPS_MAX_IOCTL) && while ((ha->num_ioctl < IPS_MAX_IOCTL) &&
(ha->copp_waitlist.head) && (ha->copp_waitlist.head) &&
(scb = ips_getscb(ha))) { (scb = ips_getscb(ha))) {
IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
item = ips_removeq_copp_head(&ha->copp_waitlist); item = ips_removeq_copp_head(&ha->copp_waitlist);
ha->num_ioctl++; ha->num_ioctl++;
IPS_HA_UNLOCK(cpu_flags); if(intr == IPS_INTR_ON)
IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
scb->scsi_cmd = item->scsi_cmd; scb->scsi_cmd = item->scsi_cmd;
scb->sem = item->sem;
kfree(item); kfree(item);
ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr); ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
if(intr == IPS_INTR_ON)
IPS_LOCK_SAVE(host->host_lock, cpu_flags);
switch (ret) { switch (ret) {
case IPS_FAILURE: case IPS_FAILURE:
if (scb->scsi_cmd) { if (scb->scsi_cmd) {
...@@ -3313,8 +3205,6 @@ ips_next(ips_ha_t *ha, int intr) { ...@@ -3313,8 +3205,6 @@ ips_next(ips_ha_t *ha, int intr) {
} /* end case */ } /* end case */
if (ret != IPS_SUCCESS) { if (ret != IPS_SUCCESS) {
IPS_HA_LOCK(cpu_flags);
IPS_QUEUE_LOCK(&ha->copp_waitlist);
ha->num_ioctl--; ha->num_ioctl--;
continue; continue;
} }
...@@ -3341,20 +3231,14 @@ ips_next(ips_ha_t *ha, int intr) { ...@@ -3341,20 +3231,14 @@ ips_next(ips_ha_t *ha, int intr) {
break; break;
} /* end case */ } /* end case */
IPS_HA_LOCK(cpu_flags);
IPS_QUEUE_LOCK(&ha->copp_waitlist);
} }
IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
IPS_HA_UNLOCK(cpu_flags);
/* /*
* Send "Normal" I/O commands * Send "Normal" I/O commands
*/ */
IPS_HA_LOCK(cpu_flags);
IPS_QUEUE_LOCK(&ha->scb_waitlist);
p = ha->scb_waitlist.head; p = ha->scb_waitlist.head;
IPS_QUEUE_UNLOCK(&ha->scb_waitlist);
while ((p) && (scb = ips_getscb(ha))) { while ((p) && (scb = ips_getscb(ha))) {
if ((p->channel > 0) && (ha->dcdb_active[p->channel-1] & (1 << p->target))) { if ((p->channel > 0) && (ha->dcdb_active[p->channel-1] & (1 << p->target))) {
ips_freescb(ha, scb); ips_freescb(ha, scb);
...@@ -3364,10 +3248,9 @@ ips_next(ips_ha_t *ha, int intr) { ...@@ -3364,10 +3248,9 @@ ips_next(ips_ha_t *ha, int intr) {
q = p; q = p;
SC = ips_removeq_wait(&ha->scb_waitlist, q); SC = ips_removeq_wait(&ha->scb_waitlist, q);
if (SC == NULL) /* Should never happen, but good to check anyway */
continue;
IPS_HA_UNLOCK(cpu_flags); /* Unlock HA after command is taken off queue */ if(intr == IPS_INTR_ON)
IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); /* Unlock HA after command is taken off queue */
SC->result = DID_OK; SC->result = DID_OK;
SC->host_scribble = NULL; SC->host_scribble = NULL;
...@@ -3475,13 +3358,15 @@ ips_next(ips_ha_t *ha, int intr) { ...@@ -3475,13 +3358,15 @@ ips_next(ips_ha_t *ha, int intr) {
scb->dcdb.cmd_attribute |= IPS_TRANSFER64K; scb->dcdb.cmd_attribute |= IPS_TRANSFER64K;
scb->dcdb.transfer_length = 0; scb->dcdb.transfer_length = 0;
} }
if(intr == IPS_INTR_ON)
IPS_LOCK_SAVE(host->host_lock, cpu_flags);
ret = ips_send_cmd(ha, scb); ret = ips_send_cmd(ha, scb);
if (ret == IPS_SUCCESS)
ips_putq_scb_head(&ha->scb_activelist, scb);
switch(ret) { switch(ret) {
case IPS_SUCCESS:
ips_putq_scb_head(&ha->scb_activelist, scb);
break;
case IPS_FAILURE: case IPS_FAILURE:
if (scb->scsi_cmd) { if (scb->scsi_cmd) {
scb->scsi_cmd->result = DID_ERROR << 16; scb->scsi_cmd->result = DID_ERROR << 16;
...@@ -3508,10 +3393,10 @@ ips_next(ips_ha_t *ha, int intr) { ...@@ -3508,10 +3393,10 @@ ips_next(ips_ha_t *ha, int intr) {
p = (Scsi_Cmnd *) p->host_scribble; p = (Scsi_Cmnd *) p->host_scribble;
IPS_HA_LOCK(cpu_flags);
} /* end while */ } /* end while */
IPS_HA_UNLOCK(cpu_flags); if(intr == IPS_INTR_ON)
IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -3522,7 +3407,7 @@ ips_next(ips_ha_t *ha, int intr) { ...@@ -3522,7 +3407,7 @@ ips_next(ips_ha_t *ha, int intr) {
/* */ /* */
/* Add an item to the head of the queue */ /* Add an item to the head of the queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline void static inline void
...@@ -3532,8 +3417,6 @@ ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) { ...@@ -3532,8 +3417,6 @@ ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) {
if (!item) if (!item)
return ; return ;
IPS_QUEUE_LOCK(queue);
item->q_next = queue->head; item->q_next = queue->head;
queue->head = item; queue->head = item;
...@@ -3541,8 +3424,6 @@ ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) { ...@@ -3541,8 +3424,6 @@ ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) {
queue->tail = item; queue->tail = item;
queue->count++; queue->count++;
IPS_QUEUE_UNLOCK(queue);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -3553,7 +3434,7 @@ ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) { ...@@ -3553,7 +3434,7 @@ ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) {
/* */ /* */
/* Add an item to the tail of the queue */ /* Add an item to the tail of the queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline void static inline void
...@@ -3563,8 +3444,6 @@ ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) { ...@@ -3563,8 +3444,6 @@ ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) {
if (!item) if (!item)
return ; return ;
IPS_QUEUE_LOCK(queue);
item->q_next = NULL; item->q_next = NULL;
if (queue->tail) if (queue->tail)
...@@ -3576,8 +3455,6 @@ ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) { ...@@ -3576,8 +3455,6 @@ ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) {
queue->head = item; queue->head = item;
queue->count++; queue->count++;
IPS_QUEUE_UNLOCK(queue);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -3588,7 +3465,7 @@ ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) { ...@@ -3588,7 +3465,7 @@ ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) {
/* */ /* */
/* Remove the head of the queue */ /* Remove the head of the queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline ips_scb_t * static inline ips_scb_t *
...@@ -3597,13 +3474,9 @@ ips_removeq_scb_head(ips_scb_queue_t *queue) { ...@@ -3597,13 +3474,9 @@ ips_removeq_scb_head(ips_scb_queue_t *queue) {
METHOD_TRACE("ips_removeq_scb_head", 1); METHOD_TRACE("ips_removeq_scb_head", 1);
IPS_QUEUE_LOCK(queue);
item = queue->head; item = queue->head;
if (!item) { if (!item) {
IPS_QUEUE_UNLOCK(queue);
return (NULL); return (NULL);
} }
...@@ -3615,8 +3488,6 @@ ips_removeq_scb_head(ips_scb_queue_t *queue) { ...@@ -3615,8 +3488,6 @@ ips_removeq_scb_head(ips_scb_queue_t *queue) {
queue->count--; queue->count--;
IPS_QUEUE_UNLOCK(queue);
return (item); return (item);
} }
...@@ -3628,7 +3499,7 @@ ips_removeq_scb_head(ips_scb_queue_t *queue) { ...@@ -3628,7 +3499,7 @@ ips_removeq_scb_head(ips_scb_queue_t *queue) {
/* */ /* */
/* Remove an item from a queue */ /* Remove an item from a queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline ips_scb_t * static inline ips_scb_t *
...@@ -3640,11 +3511,7 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) { ...@@ -3640,11 +3511,7 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) {
if (!item) if (!item)
return (NULL); return (NULL);
IPS_QUEUE_LOCK(queue);
if (item == queue->head) { if (item == queue->head) {
IPS_QUEUE_UNLOCK(queue);
return (ips_removeq_scb_head(queue)); return (ips_removeq_scb_head(queue));
} }
...@@ -3663,13 +3530,9 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) { ...@@ -3663,13 +3530,9 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) {
item->q_next = NULL; item->q_next = NULL;
queue->count--; queue->count--;
IPS_QUEUE_UNLOCK(queue);
return (item); return (item);
} }
IPS_QUEUE_UNLOCK(queue);
return (NULL); return (NULL);
} }
...@@ -3681,7 +3544,7 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) { ...@@ -3681,7 +3544,7 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) {
/* */ /* */
/* Add an item to the head of the queue */ /* Add an item to the head of the queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline void static inline void
...@@ -3691,8 +3554,6 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) { ...@@ -3691,8 +3554,6 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
if (!item) if (!item)
return ; return ;
IPS_QUEUE_LOCK(queue);
item->host_scribble = (char *) queue->head; item->host_scribble = (char *) queue->head;
queue->head = item; queue->head = item;
...@@ -3700,8 +3561,6 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) { ...@@ -3700,8 +3561,6 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
queue->tail = item; queue->tail = item;
queue->count++; queue->count++;
IPS_QUEUE_UNLOCK(queue);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -3712,7 +3571,7 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) { ...@@ -3712,7 +3571,7 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
/* */ /* */
/* Add an item to the tail of the queue */ /* Add an item to the tail of the queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline void static inline void
...@@ -3722,8 +3581,6 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { ...@@ -3722,8 +3581,6 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
if (!item) if (!item)
return ; return ;
IPS_QUEUE_LOCK(queue);
item->host_scribble = NULL; item->host_scribble = NULL;
if (queue->tail) if (queue->tail)
...@@ -3735,8 +3592,6 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { ...@@ -3735,8 +3592,6 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
queue->head = item; queue->head = item;
queue->count++; queue->count++;
IPS_QUEUE_UNLOCK(queue);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -3747,7 +3602,7 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { ...@@ -3747,7 +3602,7 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
/* */ /* */
/* Remove the head of the queue */ /* Remove the head of the queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline Scsi_Cmnd * static inline Scsi_Cmnd *
...@@ -3756,13 +3611,9 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) { ...@@ -3756,13 +3611,9 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) {
METHOD_TRACE("ips_removeq_wait_head", 1); METHOD_TRACE("ips_removeq_wait_head", 1);
IPS_QUEUE_LOCK(queue);
item = queue->head; item = queue->head;
if (!item) { if (!item) {
IPS_QUEUE_UNLOCK(queue);
return (NULL); return (NULL);
} }
...@@ -3774,8 +3625,6 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) { ...@@ -3774,8 +3625,6 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) {
queue->count--; queue->count--;
IPS_QUEUE_UNLOCK(queue);
return (item); return (item);
} }
...@@ -3787,7 +3636,7 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) { ...@@ -3787,7 +3636,7 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) {
/* */ /* */
/* Remove an item from a queue */ /* Remove an item from a queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline Scsi_Cmnd * static inline Scsi_Cmnd *
...@@ -3799,11 +3648,7 @@ ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) { ...@@ -3799,11 +3648,7 @@ ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
if (!item) if (!item)
return (NULL); return (NULL);
IPS_QUEUE_LOCK(queue);
if (item == queue->head) { if (item == queue->head) {
IPS_QUEUE_UNLOCK(queue);
return (ips_removeq_wait_head(queue)); return (ips_removeq_wait_head(queue));
} }
...@@ -3822,13 +3667,9 @@ ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) { ...@@ -3822,13 +3667,9 @@ ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
item->host_scribble = NULL; item->host_scribble = NULL;
queue->count--; queue->count--;
IPS_QUEUE_UNLOCK(queue);
return (item); return (item);
} }
IPS_QUEUE_UNLOCK(queue);
return (NULL); return (NULL);
} }
...@@ -3840,7 +3681,7 @@ ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) { ...@@ -3840,7 +3681,7 @@ ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
/* */ /* */
/* Add an item to the head of the queue */ /* Add an item to the head of the queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline void static inline void
...@@ -3850,8 +3691,6 @@ ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { ...@@ -3850,8 +3691,6 @@ ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
if (!item) if (!item)
return ; return ;
IPS_QUEUE_LOCK(queue);
item->next = queue->head; item->next = queue->head;
queue->head = item; queue->head = item;
...@@ -3859,8 +3698,6 @@ ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { ...@@ -3859,8 +3698,6 @@ ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
queue->tail = item; queue->tail = item;
queue->count++; queue->count++;
IPS_QUEUE_UNLOCK(queue);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -3871,7 +3708,7 @@ ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { ...@@ -3871,7 +3708,7 @@ ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
/* */ /* */
/* Add an item to the tail of the queue */ /* Add an item to the tail of the queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline void static inline void
...@@ -3881,8 +3718,6 @@ ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { ...@@ -3881,8 +3718,6 @@ ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
if (!item) if (!item)
return ; return ;
IPS_QUEUE_LOCK(queue);
item->next = NULL; item->next = NULL;
if (queue->tail) if (queue->tail)
...@@ -3894,8 +3729,6 @@ ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { ...@@ -3894,8 +3729,6 @@ ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
queue->head = item; queue->head = item;
queue->count++; queue->count++;
IPS_QUEUE_UNLOCK(queue);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -3906,7 +3739,7 @@ ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { ...@@ -3906,7 +3739,7 @@ ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
/* */ /* */
/* Remove the head of the queue */ /* Remove the head of the queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline ips_copp_wait_item_t * static inline ips_copp_wait_item_t *
...@@ -3915,13 +3748,9 @@ ips_removeq_copp_head(ips_copp_queue_t *queue) { ...@@ -3915,13 +3748,9 @@ ips_removeq_copp_head(ips_copp_queue_t *queue) {
METHOD_TRACE("ips_removeq_copp_head", 1); METHOD_TRACE("ips_removeq_copp_head", 1);
IPS_QUEUE_LOCK(queue);
item = queue->head; item = queue->head;
if (!item) { if (!item) {
IPS_QUEUE_UNLOCK(queue);
return (NULL); return (NULL);
} }
...@@ -3933,8 +3762,6 @@ ips_removeq_copp_head(ips_copp_queue_t *queue) { ...@@ -3933,8 +3762,6 @@ ips_removeq_copp_head(ips_copp_queue_t *queue) {
queue->count--; queue->count--;
IPS_QUEUE_UNLOCK(queue);
return (item); return (item);
} }
...@@ -3946,7 +3773,7 @@ ips_removeq_copp_head(ips_copp_queue_t *queue) { ...@@ -3946,7 +3773,7 @@ ips_removeq_copp_head(ips_copp_queue_t *queue) {
/* */ /* */
/* Remove an item from a queue */ /* Remove an item from a queue */
/* */ /* */
/* ASSUMED to be called from within a lock */ /* ASSUMED to be called from within the HA lock */
/* */ /* */
/****************************************************************************/ /****************************************************************************/
static inline ips_copp_wait_item_t * static inline ips_copp_wait_item_t *
...@@ -3958,11 +3785,7 @@ ips_removeq_copp(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { ...@@ -3958,11 +3785,7 @@ ips_removeq_copp(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
if (!item) if (!item)
return (NULL); return (NULL);
IPS_QUEUE_LOCK(queue);
if (item == queue->head) { if (item == queue->head) {
IPS_QUEUE_UNLOCK(queue);
return (ips_removeq_copp_head(queue)); return (ips_removeq_copp_head(queue));
} }
...@@ -3981,13 +3804,9 @@ ips_removeq_copp(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { ...@@ -3981,13 +3804,9 @@ ips_removeq_copp(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
item->next = NULL; item->next = NULL;
queue->count--; queue->count--;
IPS_QUEUE_UNLOCK(queue);
return (item); return (item);
} }
IPS_QUEUE_UNLOCK(queue);
return (NULL); return (NULL);
} }
...@@ -4051,12 +3870,11 @@ ipsintr_done(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -4051,12 +3870,11 @@ ipsintr_done(ips_ha_t *ha, ips_scb_t *scb) {
/* Routine Description: */ /* Routine Description: */
/* */ /* */
/* Do housekeeping on completed commands */ /* Do housekeeping on completed commands */
/* */ /* ASSUMED to be called form within the request lock */
/****************************************************************************/ /****************************************************************************/
static void static void
ips_done(ips_ha_t *ha, ips_scb_t *scb) { ips_done(ips_ha_t *ha, ips_scb_t *scb) {
int ret; int ret;
unsigned long cpu_flags;
METHOD_TRACE("ips_done", 1); METHOD_TRACE("ips_done", 1);
...@@ -4065,9 +3883,7 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -4065,9 +3883,7 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) {
if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd))) { if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd))) {
ips_cleanup_passthru(ha, scb); ips_cleanup_passthru(ha, scb);
IPS_HA_LOCK(cpu_flags);
ha->num_ioctl--; ha->num_ioctl--;
IPS_HA_UNLOCK(cpu_flags);
} else { } else {
/* /*
* Check to see if this command had too much * Check to see if this command had too much
...@@ -4226,9 +4042,7 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -4226,9 +4042,7 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) {
} /* end if passthru */ } /* end if passthru */
if (scb->bus) { if (scb->bus) {
IPS_HA_LOCK(cpu_flags);
ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id); ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id);
IPS_HA_UNLOCK(cpu_flags);
} }
scb->scsi_cmd->scsi_done(scb->scsi_cmd); scb->scsi_cmd->scsi_done(scb->scsi_cmd);
...@@ -4336,7 +4150,7 @@ ips_map_status(ips_ha_t *ha, ips_scb_t *scb, ips_stat_t *sp) { ...@@ -4336,7 +4150,7 @@ ips_map_status(ips_ha_t *ha, ips_scb_t *scb, ips_stat_t *sp) {
(scb->cmd.dcdb.op_code == IPS_CMD_EXTENDED_DCDB_SG)) { (scb->cmd.dcdb.op_code == IPS_CMD_EXTENDED_DCDB_SG)) {
tapeDCDB = (IPS_DCDB_TABLE_TAPE *) &scb->dcdb; tapeDCDB = (IPS_DCDB_TABLE_TAPE *) &scb->dcdb;
memcpy(scb->scsi_cmd->sense_buffer, tapeDCDB->sense_info, memcpy(scb->scsi_cmd->sense_buffer, tapeDCDB->sense_info,
sizeof(tapeDCDB->sense_info)); sizeof(scb->scsi_cmd->sense_buffer));
} else { } else {
memcpy(scb->scsi_cmd->sense_buffer, scb->dcdb.sense_info, memcpy(scb->scsi_cmd->sense_buffer, scb->dcdb.sense_info,
sizeof(scb->scsi_cmd->sense_buffer)); sizeof(scb->scsi_cmd->sense_buffer));
...@@ -4408,6 +4222,7 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -4408,6 +4222,7 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
char *sp; char *sp;
int device_error; int device_error;
IPS_DCDB_TABLE_TAPE *tapeDCDB; IPS_DCDB_TABLE_TAPE *tapeDCDB;
int TimeOut;
METHOD_TRACE("ips_send_cmd", 1); METHOD_TRACE("ips_send_cmd", 1);
...@@ -4478,8 +4293,10 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -4478,8 +4293,10 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
scb->cmd.logical_info.reserved = 0; scb->cmd.logical_info.reserved = 0;
scb->cmd.logical_info.reserved2 = 0; scb->cmd.logical_info.reserved2 = 0;
scb->data_len = sizeof(ha->adapt->logical_drive_info); scb->data_len = sizeof(ha->adapt->logical_drive_info);
scb->data_busaddr = ha->adapt->hw_status_start + sizeof(IPS_ADAPTER) scb->data_busaddr = pci_map_single(ha->pcidev,
- sizeof(IPS_LD_INFO); &ha->adapt->logical_drive_info,
scb->data_len, IPS_DMA_DIR(scb));
scb->flags |= IPS_SCB_MAP_SINGLE;
scb->cmd.logical_info.buffer_addr = scb->data_busaddr; scb->cmd.logical_info.buffer_addr = scb->data_busaddr;
ret = IPS_SUCCESS; ret = IPS_SUCCESS;
} }
...@@ -4586,8 +4403,10 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -4586,8 +4403,10 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
scb->cmd.logical_info.reserved2 = 0; scb->cmd.logical_info.reserved2 = 0;
scb->cmd.logical_info.reserved3 = 0; scb->cmd.logical_info.reserved3 = 0;
scb->data_len = sizeof(ha->adapt->logical_drive_info); scb->data_len = sizeof(ha->adapt->logical_drive_info);
scb->data_busaddr = ha->adapt->hw_status_start + sizeof(IPS_ADAPTER) scb->data_busaddr = pci_map_single(ha->pcidev,
- sizeof(IPS_LD_INFO); &ha->adapt->logical_drive_info,
scb->data_len, IPS_DMA_DIR(scb));
scb->flags |= IPS_SCB_MAP_SINGLE;
scb->cmd.logical_info.buffer_addr = scb->data_busaddr; scb->cmd.logical_info.buffer_addr = scb->data_busaddr;
ret = IPS_SUCCESS; ret = IPS_SUCCESS;
break; break;
...@@ -4642,11 +4461,13 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -4642,11 +4461,13 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
ha->dcdb_active[scb->bus-1] |= (1 << scb->target_id); ha->dcdb_active[scb->bus-1] |= (1 << scb->target_id);
scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.dcdb.dcdb_address = cpu_to_le32(scb->scb_busaddr + scb->cmd.dcdb.dcdb_address = cpu_to_le32(scb->scb_busaddr +
(unsigned long)&scb->dcdb - (unsigned long)&scb->dcdb -
(unsigned long)scb); (unsigned long)scb);
scb->cmd.dcdb.reserved = 0; scb->cmd.dcdb.reserved = 0;
scb->cmd.dcdb.reserved2 = 0; scb->cmd.dcdb.reserved2 = 0;
scb->cmd.dcdb.reserved3 = 0; scb->cmd.dcdb.reserved3 = 0;
TimeOut = scb->scsi_cmd->timeout_per_command;
if (ha->subsys->param[4] & 0x00100000) { /* If NEW Tape DCDB is Supported */ if (ha->subsys->param[4] & 0x00100000) { /* If NEW Tape DCDB is Supported */
if (!scb->sg_len) if (!scb->sg_len)
...@@ -4657,47 +4478,52 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -4657,47 +4478,52 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
tapeDCDB = (IPS_DCDB_TABLE_TAPE *) &scb->dcdb; /* Use Same Data Area as Old DCDB Struct */ tapeDCDB = (IPS_DCDB_TABLE_TAPE *) &scb->dcdb; /* Use Same Data Area as Old DCDB Struct */
tapeDCDB->device_address = ((scb->bus - 1) << 4) | scb->target_id; tapeDCDB->device_address = ((scb->bus - 1) << 4) | scb->target_id;
tapeDCDB->cmd_attribute |= IPS_DISCONNECT_ALLOWED; tapeDCDB->cmd_attribute |= IPS_DISCONNECT_ALLOWED;
tapeDCDB->cmd_attribute &= ~IPS_TRANSFER64K; /* Always Turn OFF 64K Size Flag */
if (scb->timeout) {
if (scb->timeout <= 10) if (TimeOut) {
tapeDCDB->cmd_attribute |= IPS_TIMEOUT10; if (TimeOut < ( 10 * HZ ))
else if (scb->timeout <= 60) tapeDCDB->cmd_attribute |= IPS_TIMEOUT10; /* TimeOut is 10 Seconds */
tapeDCDB->cmd_attribute |= IPS_TIMEOUT60; else if (TimeOut < (60 * HZ))
else tapeDCDB->cmd_attribute |= IPS_TIMEOUT60; /* TimeOut is 60 Seconds */
tapeDCDB->cmd_attribute |= IPS_TIMEOUT20M; else if (TimeOut < (1200 * HZ))
tapeDCDB->cmd_attribute |= IPS_TIMEOUT20M; /* TimeOut is 20 Minutes */
} }
if (!(tapeDCDB->cmd_attribute & IPS_TIMEOUT20M)) tapeDCDB->cdb_length = scb->scsi_cmd->cmd_len;
tapeDCDB->cmd_attribute |= IPS_TIMEOUT20M; tapeDCDB->reserved_for_LUN = 0;
tapeDCDB->sense_length = sizeof(tapeDCDB->sense_info);
tapeDCDB->transfer_length = scb->data_len; tapeDCDB->transfer_length = scb->data_len;
tapeDCDB->buffer_pointer = cpu_to_le32(scb->data_busaddr); tapeDCDB->buffer_pointer = cpu_to_le32(scb->data_busaddr);
tapeDCDB->sg_count = scb->sg_len; tapeDCDB->sg_count = scb->sg_len;
tapeDCDB->cdb_length = scb->scsi_cmd->cmd_len; tapeDCDB->sense_length = sizeof(tapeDCDB->sense_info);
tapeDCDB->scsi_status = 0;
tapeDCDB->reserved = 0;
memcpy(tapeDCDB->scsi_cdb, scb->scsi_cmd->cmnd, scb->scsi_cmd->cmd_len); memcpy(tapeDCDB->scsi_cdb, scb->scsi_cmd->cmnd, scb->scsi_cmd->cmd_len);
} else { } else {
scb->dcdb.device_address = ((scb->bus - 1) << 4) | scb->target_id; scb->dcdb.device_address = ((scb->bus - 1) << 4) | scb->target_id;
scb->dcdb.cmd_attribute |= IPS_DISCONNECT_ALLOWED; scb->dcdb.cmd_attribute |= IPS_DISCONNECT_ALLOWED;
if (scb->timeout) { if (TimeOut) {
if (scb->timeout <= 10) if (TimeOut < (10 * HZ))
scb->dcdb.cmd_attribute |= IPS_TIMEOUT10; scb->dcdb.cmd_attribute |= IPS_TIMEOUT10; /* TimeOut is 10 Seconds */
else if (scb->timeout <= 60) else if (TimeOut < (60 * HZ))
scb->dcdb.cmd_attribute |= IPS_TIMEOUT60; scb->dcdb.cmd_attribute |= IPS_TIMEOUT60; /* TimeOut is 60 Seconds */
else else if (TimeOut < (1200 * HZ))
scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; /* TimeOut is 20 Minutes */
} }
if (!(scb->dcdb.cmd_attribute & IPS_TIMEOUT20M))
scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
scb->dcdb.sense_length = sizeof(scb->dcdb.sense_info);
scb->dcdb.transfer_length = scb->data_len; scb->dcdb.transfer_length = scb->data_len;
if ( scb->dcdb.cmd_attribute & IPS_TRANSFER64K )
scb->dcdb.transfer_length = 0;
scb->dcdb.buffer_pointer = cpu_to_le32(scb->data_busaddr); scb->dcdb.buffer_pointer = cpu_to_le32(scb->data_busaddr);
scb->dcdb.sg_count = scb->sg_len;
scb->dcdb.cdb_length = scb->scsi_cmd->cmd_len; scb->dcdb.cdb_length = scb->scsi_cmd->cmd_len;
scb->dcdb.sense_length = sizeof(scb->dcdb.sense_info);
scb->dcdb.sg_count = scb->sg_len;
scb->dcdb.reserved = 0;
memcpy(scb->dcdb.scsi_cdb, scb->scsi_cmd->cmnd, scb->scsi_cmd->cmd_len); memcpy(scb->dcdb.scsi_cdb, scb->scsi_cmd->cmnd, scb->scsi_cmd->cmd_len);
scb->dcdb.scsi_status = 0;
scb->dcdb.reserved2[0] = 0;
scb->dcdb.reserved2[1] = 0;
scb->dcdb.reserved2[2] = 0;
} }
} }
...@@ -4711,7 +4537,7 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -4711,7 +4537,7 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
/* Routine Description: */ /* Routine Description: */
/* */ /* */
/* Check the status of commands to logical drives */ /* Check the status of commands to logical drives */
/* */ /* Assumed to be called with the HA lock */
/****************************************************************************/ /****************************************************************************/
static void static void
ips_chkstatus(ips_ha_t *ha, IPS_STATUS *pstatus) { ips_chkstatus(ips_ha_t *ha, IPS_STATUS *pstatus) {
...@@ -5240,13 +5066,10 @@ ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -5240,13 +5066,10 @@ ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) {
static ips_scb_t * static ips_scb_t *
ips_getscb(ips_ha_t *ha) { ips_getscb(ips_ha_t *ha) {
ips_scb_t *scb; ips_scb_t *scb;
unsigned long cpu_flags;
METHOD_TRACE("ips_getscb", 1); METHOD_TRACE("ips_getscb", 1);
IPS_SCB_LOCK(cpu_flags);
if ((scb = ha->scb_freelist) == NULL) { if ((scb = ha->scb_freelist) == NULL) {
IPS_SCB_UNLOCK(cpu_flags);
return (NULL); return (NULL);
} }
...@@ -5254,8 +5077,6 @@ ips_getscb(ips_ha_t *ha) { ...@@ -5254,8 +5077,6 @@ ips_getscb(ips_ha_t *ha) {
ha->scb_freelist = scb->q_next; ha->scb_freelist = scb->q_next;
scb->q_next = NULL; scb->q_next = NULL;
IPS_SCB_UNLOCK(cpu_flags);
ips_init_scb(ha, scb); ips_init_scb(ha, scb);
return (scb); return (scb);
...@@ -5274,7 +5095,6 @@ ips_getscb(ips_ha_t *ha) { ...@@ -5274,7 +5095,6 @@ ips_getscb(ips_ha_t *ha) {
/****************************************************************************/ /****************************************************************************/
static void static void
ips_freescb(ips_ha_t *ha, ips_scb_t *scb) { ips_freescb(ips_ha_t *ha, ips_scb_t *scb) {
unsigned long cpu_flags;
METHOD_TRACE("ips_freescb", 1); METHOD_TRACE("ips_freescb", 1);
if(scb->flags & IPS_SCB_MAP_SG) if(scb->flags & IPS_SCB_MAP_SG)
...@@ -5287,10 +5107,8 @@ ips_freescb(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -5287,10 +5107,8 @@ ips_freescb(ips_ha_t *ha, ips_scb_t *scb) {
/* check to make sure this is not our "special" scb */ /* check to make sure this is not our "special" scb */
if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) { if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) {
IPS_SCB_LOCK(cpu_flags);
scb->q_next = ha->scb_freelist; scb->q_next = ha->scb_freelist;
ha->scb_freelist = scb; ha->scb_freelist = scb;
IPS_SCB_UNLOCK(cpu_flags);
} }
} }
...@@ -5702,15 +5520,12 @@ ips_init_morpheus(ips_ha_t *ha) { ...@@ -5702,15 +5520,12 @@ ips_init_morpheus(ips_ha_t *ha) {
static int static int
ips_reset_copperhead(ips_ha_t *ha) { ips_reset_copperhead(ips_ha_t *ha) {
int reset_counter; int reset_counter;
unsigned long cpu_flags;
METHOD_TRACE("ips_reset_copperhead", 1); METHOD_TRACE("ips_reset_copperhead", 1);
DEBUG_VAR(1, "(%s%d) ips_reset_copperhead: io addr: %x, irq: %d", DEBUG_VAR(1, "(%s%d) ips_reset_copperhead: io addr: %x, irq: %d",
ips_name, ha->host_num, ha->io_addr, ha->irq); ips_name, ha->host_num, ha->io_addr, ha->irq);
IPS_HA_LOCK(cpu_flags);
reset_counter = 0; reset_counter = 0;
while (reset_counter < 2) { while (reset_counter < 2) {
...@@ -5729,14 +5544,11 @@ ips_reset_copperhead(ips_ha_t *ha) { ...@@ -5729,14 +5544,11 @@ ips_reset_copperhead(ips_ha_t *ha) {
if ((*ha->func.init)(ha)) if ((*ha->func.init)(ha))
break; break;
else if (reset_counter >= 2) { else if (reset_counter >= 2) {
IPS_HA_UNLOCK(cpu_flags);
return (0); return (0);
} }
} }
IPS_HA_UNLOCK(cpu_flags);
return (1); return (1);
} }
...@@ -5752,15 +5564,12 @@ ips_reset_copperhead(ips_ha_t *ha) { ...@@ -5752,15 +5564,12 @@ ips_reset_copperhead(ips_ha_t *ha) {
static int static int
ips_reset_copperhead_memio(ips_ha_t *ha) { ips_reset_copperhead_memio(ips_ha_t *ha) {
int reset_counter; int reset_counter;
unsigned long cpu_flags;
METHOD_TRACE("ips_reset_copperhead_memio", 1); METHOD_TRACE("ips_reset_copperhead_memio", 1);
DEBUG_VAR(1, "(%s%d) ips_reset_copperhead_memio: mem addr: %x, irq: %d", DEBUG_VAR(1, "(%s%d) ips_reset_copperhead_memio: mem addr: %x, irq: %d",
ips_name, ha->host_num, ha->mem_addr, ha->irq); ips_name, ha->host_num, ha->mem_addr, ha->irq);
IPS_HA_LOCK(cpu_flags);
reset_counter = 0; reset_counter = 0;
while (reset_counter < 2) { while (reset_counter < 2) {
...@@ -5779,14 +5588,11 @@ ips_reset_copperhead_memio(ips_ha_t *ha) { ...@@ -5779,14 +5588,11 @@ ips_reset_copperhead_memio(ips_ha_t *ha) {
if ((*ha->func.init)(ha)) if ((*ha->func.init)(ha))
break; break;
else if (reset_counter >= 2) { else if (reset_counter >= 2) {
IPS_HA_UNLOCK(cpu_flags);
return (0); return (0);
} }
} }
IPS_HA_UNLOCK(cpu_flags);
return (1); return (1);
} }
...@@ -5803,15 +5609,12 @@ static int ...@@ -5803,15 +5609,12 @@ static int
ips_reset_morpheus(ips_ha_t *ha) { ips_reset_morpheus(ips_ha_t *ha) {
int reset_counter; int reset_counter;
uint8_t junk; uint8_t junk;
unsigned long cpu_flags;
METHOD_TRACE("ips_reset_morpheus", 1); METHOD_TRACE("ips_reset_morpheus", 1);
DEBUG_VAR(1, "(%s%d) ips_reset_morpheus: mem addr: %x, irq: %d", DEBUG_VAR(1, "(%s%d) ips_reset_morpheus: mem addr: %x, irq: %d",
ips_name, ha->host_num, ha->mem_addr, ha->irq); ips_name, ha->host_num, ha->mem_addr, ha->irq);
IPS_HA_LOCK(cpu_flags);
reset_counter = 0; reset_counter = 0;
while (reset_counter < 2) { while (reset_counter < 2) {
...@@ -5828,14 +5631,11 @@ ips_reset_morpheus(ips_ha_t *ha) { ...@@ -5828,14 +5631,11 @@ ips_reset_morpheus(ips_ha_t *ha) {
if ((*ha->func.init)(ha)) if ((*ha->func.init)(ha))
break; break;
else if (reset_counter >= 2) { else if (reset_counter >= 2) {
IPS_HA_UNLOCK(cpu_flags);
return (0); return (0);
} }
} }
IPS_HA_UNLOCK(cpu_flags);
return (1); return (1);
} }
...@@ -5980,7 +5780,6 @@ static int ...@@ -5980,7 +5780,6 @@ static int
ips_issue_copperhead(ips_ha_t *ha, ips_scb_t *scb) { ips_issue_copperhead(ips_ha_t *ha, ips_scb_t *scb) {
uint32_t TimeOut; uint32_t TimeOut;
uint32_t val; uint32_t val;
unsigned long cpu_flags;
METHOD_TRACE("ips_issue_copperhead", 1); METHOD_TRACE("ips_issue_copperhead", 1);
...@@ -6000,8 +5799,6 @@ ips_issue_copperhead(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -6000,8 +5799,6 @@ ips_issue_copperhead(ips_ha_t *ha, ips_scb_t *scb) {
scb->cmd.basic_io.command_id); scb->cmd.basic_io.command_id);
} }
IPS_HA_LOCK(cpu_flags);
TimeOut = 0; TimeOut = 0;
while ((val = le32_to_cpu(inl(ha->io_addr + IPS_REG_CCCR))) & IPS_BIT_SEM) { while ((val = le32_to_cpu(inl(ha->io_addr + IPS_REG_CCCR))) & IPS_BIT_SEM) {
...@@ -6016,8 +5813,6 @@ ips_issue_copperhead(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -6016,8 +5813,6 @@ ips_issue_copperhead(ips_ha_t *ha, ips_scb_t *scb) {
printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n", printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n",
ips_name, ha->host_num); ips_name, ha->host_num);
IPS_HA_UNLOCK(cpu_flags);
return (IPS_FAILURE); return (IPS_FAILURE);
} /* end if */ } /* end if */
} /* end while */ } /* end while */
...@@ -6025,8 +5820,6 @@ ips_issue_copperhead(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -6025,8 +5820,6 @@ ips_issue_copperhead(ips_ha_t *ha, ips_scb_t *scb) {
outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_CCSAR); outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_CCSAR);
outw(cpu_to_le32(IPS_BIT_START_CMD), ha->io_addr + IPS_REG_CCCR); outw(cpu_to_le32(IPS_BIT_START_CMD), ha->io_addr + IPS_REG_CCCR);
IPS_HA_UNLOCK(cpu_flags);
return (IPS_SUCCESS); return (IPS_SUCCESS);
} }
...@@ -6043,7 +5836,6 @@ static int ...@@ -6043,7 +5836,6 @@ static int
ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) { ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) {
uint32_t TimeOut; uint32_t TimeOut;
uint32_t val; uint32_t val;
unsigned long cpu_flags;
METHOD_TRACE("ips_issue_copperhead_memio", 1); METHOD_TRACE("ips_issue_copperhead_memio", 1);
...@@ -6063,8 +5855,6 @@ ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -6063,8 +5855,6 @@ ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) {
scb->cmd.basic_io.command_id); scb->cmd.basic_io.command_id);
} }
IPS_HA_LOCK(cpu_flags);
TimeOut = 0; TimeOut = 0;
while ((val = readl(ha->mem_ptr + IPS_REG_CCCR)) & IPS_BIT_SEM) { while ((val = readl(ha->mem_ptr + IPS_REG_CCCR)) & IPS_BIT_SEM) {
...@@ -6079,8 +5869,6 @@ ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -6079,8 +5869,6 @@ ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) {
printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n", printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n",
ips_name, ha->host_num); ips_name, ha->host_num);
IPS_HA_UNLOCK(cpu_flags);
return (IPS_FAILURE); return (IPS_FAILURE);
} /* end if */ } /* end if */
} /* end while */ } /* end while */
...@@ -6088,8 +5876,6 @@ ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -6088,8 +5876,6 @@ ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) {
writel(scb->scb_busaddr, ha->mem_ptr + IPS_REG_CCSAR); writel(scb->scb_busaddr, ha->mem_ptr + IPS_REG_CCSAR);
writel(IPS_BIT_START_CMD, ha->mem_ptr + IPS_REG_CCCR); writel(IPS_BIT_START_CMD, ha->mem_ptr + IPS_REG_CCCR);
IPS_HA_UNLOCK(cpu_flags);
return (IPS_SUCCESS); return (IPS_SUCCESS);
} }
...@@ -6104,7 +5890,6 @@ ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -6104,7 +5890,6 @@ ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) {
/****************************************************************************/ /****************************************************************************/
static int static int
ips_issue_i2o(ips_ha_t *ha, ips_scb_t *scb) { ips_issue_i2o(ips_ha_t *ha, ips_scb_t *scb) {
unsigned long cpu_flags;
METHOD_TRACE("ips_issue_i2o", 1); METHOD_TRACE("ips_issue_i2o", 1);
...@@ -6124,12 +5909,8 @@ ips_issue_i2o(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -6124,12 +5909,8 @@ ips_issue_i2o(ips_ha_t *ha, ips_scb_t *scb) {
scb->cmd.basic_io.command_id); scb->cmd.basic_io.command_id);
} }
IPS_HA_LOCK(cpu_flags);
outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_I2O_INMSGQ); outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_I2O_INMSGQ);
IPS_HA_UNLOCK(cpu_flags);
return (IPS_SUCCESS); return (IPS_SUCCESS);
} }
...@@ -6144,7 +5925,6 @@ ips_issue_i2o(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -6144,7 +5925,6 @@ ips_issue_i2o(ips_ha_t *ha, ips_scb_t *scb) {
/****************************************************************************/ /****************************************************************************/
static int static int
ips_issue_i2o_memio(ips_ha_t *ha, ips_scb_t *scb) { ips_issue_i2o_memio(ips_ha_t *ha, ips_scb_t *scb) {
unsigned long cpu_flags;
METHOD_TRACE("ips_issue_i2o_memio", 1); METHOD_TRACE("ips_issue_i2o_memio", 1);
...@@ -6164,12 +5944,8 @@ ips_issue_i2o_memio(ips_ha_t *ha, ips_scb_t *scb) { ...@@ -6164,12 +5944,8 @@ ips_issue_i2o_memio(ips_ha_t *ha, ips_scb_t *scb) {
scb->cmd.basic_io.command_id); scb->cmd.basic_io.command_id);
} }
IPS_HA_LOCK(cpu_flags);
writel(scb->scb_busaddr, ha->mem_ptr + IPS_REG_I2O_INMSGQ); writel(scb->scb_busaddr, ha->mem_ptr + IPS_REG_I2O_INMSGQ);
IPS_HA_UNLOCK(cpu_flags);
return (IPS_SUCCESS); return (IPS_SUCCESS);
} }
...@@ -6306,12 +6082,7 @@ ips_wait(ips_ha_t *ha, int time, int intr) { ...@@ -6306,12 +6082,7 @@ ips_wait(ips_ha_t *ha, int time, int intr) {
* until after we finish. * until after we finish.
*/ */
while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
udelay(1000);
(*ha->func.intr)(ha); (*ha->func.intr)(ha);
clear_bit(IPS_IN_INTR, &ha->flags);
} }
/* This looks like a very evil loop, but it only does this during start-up */ /* This looks like a very evil loop, but it only does this during start-up */
...@@ -7394,6 +7165,14 @@ static Scsi_Host_Template driver_template = IPS; ...@@ -7394,6 +7165,14 @@ static Scsi_Host_Template driver_template = IPS;
#include "scsi_module.c" #include "scsi_module.c"
#endif #endif
static int ips_abort_init(ips_ha_t *ha, struct Scsi_Host *sh, int index){
ha->active = 0;
ips_free(ha);
scsi_unregister(sh);
ips_ha[index] = 0;
ips_sh[index] = 0;
return -1;
}
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
...@@ -7568,14 +7347,6 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr ) ...@@ -7568,14 +7347,6 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr )
ha = IPS_HA(sh); ha = IPS_HA(sh);
memset(ha, 0, sizeof(ips_ha_t)); memset(ha, 0, sizeof(ips_ha_t));
/* Initialize spin lock */
spin_lock_init(&ha->scb_lock);
spin_lock_init(&ha->copp_lock);
spin_lock_init(&ha->ips_lock);
spin_lock_init(&ha->copp_waitlist.lock);
spin_lock_init(&ha->scb_waitlist.lock);
spin_lock_init(&ha->scb_activelist.lock);
ips_sh[index] = sh; ips_sh[index] = sh;
ips_ha[index] = ha; ips_ha[index] = ha;
ha->active = 1; ha->active = 1;
...@@ -7584,24 +7355,14 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr ) ...@@ -7584,24 +7355,14 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr )
if (!ha->enq) { if (!ha->enq) {
printk(KERN_WARNING "Unable to allocate host inquiry structure\n" ); printk(KERN_WARNING "Unable to allocate host inquiry structure\n" );
ha->active = 0; return ips_abort_init(ha, sh, index);
ips_free(ha);
scsi_unregister(sh);
ips_ha[index] = 0;
ips_sh[index] = 0;
return -1;
} }
ha->adapt = pci_alloc_consistent(ha->pcidev, sizeof(IPS_ADAPTER) + ha->adapt = pci_alloc_consistent(ha->pcidev, sizeof(IPS_ADAPTER) +
sizeof(IPS_IO_CMD), &dma_address); sizeof(IPS_IO_CMD), &dma_address);
if (!ha->adapt) { if (!ha->adapt) {
printk(KERN_WARNING "Unable to allocate host adapt & dummy structures\n"); printk(KERN_WARNING "Unable to allocate host adapt & dummy structures\n");
ha->active = 0; return ips_abort_init(ha, sh, index);
ips_free(ha);
scsi_unregister(sh);
ips_ha[index] = 0;
ips_sh[index] = 0;
return -1;
} }
ha->adapt->hw_status_start = dma_address; ha->adapt->hw_status_start = dma_address;
ha->dummy = (void *)(ha->adapt + 1); ha->dummy = (void *)(ha->adapt + 1);
...@@ -7610,36 +7371,21 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr ) ...@@ -7610,36 +7371,21 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr )
if (!ha->conf) { if (!ha->conf) {
printk(KERN_WARNING "Unable to allocate host conf structure\n" ); printk(KERN_WARNING "Unable to allocate host conf structure\n" );
ha->active = 0; return ips_abort_init(ha, sh, index);
ips_free(ha);
scsi_unregister(sh);
ips_ha[index] = 0;
ips_sh[index] = 0;
return -1;
} }
ha->nvram = kmalloc(sizeof(IPS_NVRAM_P5), GFP_KERNEL); ha->nvram = kmalloc(sizeof(IPS_NVRAM_P5), GFP_KERNEL);
if (!ha->nvram) { if (!ha->nvram) {
printk(KERN_WARNING "Unable to allocate host NVRAM structure\n" ); printk(KERN_WARNING "Unable to allocate host NVRAM structure\n" );
ha->active = 0; return ips_abort_init(ha, sh, index);
ips_free(ha);
scsi_unregister(sh);
ips_ha[index] = 0;
ips_sh[index] = 0;
return -1;
} }
ha->subsys = kmalloc(sizeof(IPS_SUBSYS), GFP_KERNEL); ha->subsys = kmalloc(sizeof(IPS_SUBSYS), GFP_KERNEL);
if (!ha->subsys) { if (!ha->subsys) {
printk(KERN_WARNING "Unable to allocate host subsystem structure\n" ); printk(KERN_WARNING "Unable to allocate host subsystem structure\n" );
ha->active = 0; return ips_abort_init(ha, sh, index);
ips_free(ha);
scsi_unregister(sh);
ips_ha[index] = 0;
ips_sh[index] = 0;
return -1;
} }
for (count = PAGE_SIZE, ha->ioctl_order = 0; for (count = PAGE_SIZE, ha->ioctl_order = 0;
...@@ -7748,24 +7494,14 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr ) ...@@ -7748,24 +7494,14 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr )
* Initialization failed * Initialization failed
*/ */
printk(KERN_WARNING "Unable to initialize controller\n" ); printk(KERN_WARNING "Unable to initialize controller\n" );
ha->active = 0; return ips_abort_init(ha, sh, index);
ips_free(ha);
scsi_unregister(sh);
ips_ha[index] = 0;
ips_sh[index] = 0;
return -1;
} }
} }
/* Install the interrupt handler */ /* Install the interrupt handler */
if (request_irq(irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) { if (request_irq(irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
printk(KERN_WARNING "Unable to install interrupt handler\n" ); printk(KERN_WARNING "Unable to install interrupt handler\n" );
ha->active = 0; return ips_abort_init(ha, sh, index);
ips_free(ha);
scsi_unregister(sh);
ips_ha[index] = 0;
ips_sh[index] = 0;
return -1;
} }
/* /*
...@@ -7774,13 +7510,8 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr ) ...@@ -7774,13 +7510,8 @@ static int ips_init_phase1( struct pci_dev *pci_dev, int *indexPtr )
ha->max_cmds = 1; ha->max_cmds = 1;
if (!ips_allocatescbs(ha)) { if (!ips_allocatescbs(ha)) {
printk(KERN_WARNING "Unable to allocate a CCB\n" ); printk(KERN_WARNING "Unable to allocate a CCB\n" );
ha->active = 0;
free_irq(ha->irq, ha); free_irq(ha->irq, ha);
ips_free(ha); return ips_abort_init(ha, sh, index);
scsi_unregister(sh);
ips_ha[index] = 0;
ips_sh[index] = 0;
return -1;
} }
*indexPtr = index; *indexPtr = index;
...@@ -7816,13 +7547,8 @@ static int ips_init_phase2( int index ) ...@@ -7816,13 +7547,8 @@ static int ips_init_phase2( int index )
if (!ips_hainit(ha)) { if (!ips_hainit(ha)) {
printk(KERN_WARNING "Unable to initialize controller\n" ); printk(KERN_WARNING "Unable to initialize controller\n" );
ha->active = 0;
ips_free(ha);
free_irq(ha->irq, ha); free_irq(ha->irq, ha);
scsi_unregister(sh); return ips_abort_init(ha, sh, index);
ips_ha[index] = NULL;
ips_sh[index] = NULL;
return -1;
} }
/* Free the temporary SCB */ /* Free the temporary SCB */
ips_deallocatescbs(ha, 1); ips_deallocatescbs(ha, 1);
...@@ -7830,13 +7556,8 @@ static int ips_init_phase2( int index ) ...@@ -7830,13 +7556,8 @@ static int ips_init_phase2( int index )
/* allocate CCBs */ /* allocate CCBs */
if (!ips_allocatescbs(ha)) { if (!ips_allocatescbs(ha)) {
printk(KERN_WARNING "Unable to allocate CCBs\n" ); printk(KERN_WARNING "Unable to allocate CCBs\n" );
ha->active = 0;
ips_free(ha);
free_irq(ha->irq, ha); free_irq(ha->irq, ha);
scsi_unregister(sh); return ips_abort_init(ha, sh, index);
ips_ha[index] = NULL;
ips_sh[index] = NULL;
return -1;
} }
/* finish setting values */ /* finish setting values */
......
/*****************************************************************************/ /*****************************************************************************/
/* ips.h -- driver for the IBM ServeRAID controller */ /* ips.h -- driver for the Adaptec / IBM ServeRAID controller */
/* */ /* */
/* Written By: Keith Mitchell, IBM Corporation */ /* Written By: Keith Mitchell, IBM Corporation */
/* Jack Hammer, Adaptec, Inc. */
/* David Jeffery, Adaptec, Inc. */
/* */ /* */
/* Copyright (C) 1999 IBM Corporation */ /* Copyright (C) 1999 IBM Corporation */
/* Copyright (C) 2003 Adaptec, Inc. */
/* */ /* */
/* This program is free software; you can redistribute it and/or modify */ /* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */ /* it under the terms of the GNU General Public License as published by */
...@@ -40,7 +43,7 @@ ...@@ -40,7 +43,7 @@
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */ /* */
/* Bugs/Comments/Suggestions should be mailed to: */ /* Bugs/Comments/Suggestions should be mailed to: */
/* ipslinux@us.ibm.com */ /* ipslinux@adaptec.com */
/* */ /* */
/*****************************************************************************/ /*****************************************************************************/
...@@ -84,32 +87,10 @@ ...@@ -84,32 +87,10 @@
((IPS_IS_TROMBONE(ha) || IPS_IS_CLARINET(ha)) && \ ((IPS_IS_TROMBONE(ha) || IPS_IS_CLARINET(ha)) && \
(ips_force_memio))) ? 1 : 0) (ips_force_memio))) ? 1 : 0)
#ifndef VIRT_TO_BUS
#define VIRT_TO_BUS(x) (uint32_t) virt_to_bus((void *) x)
#endif
#ifndef MDELAY #ifndef MDELAY
#define MDELAY mdelay #define MDELAY mdelay
#endif #endif
#ifndef verify_area_20
#define verify_area_20(t,a,sz) (0) /* success */
#endif
#ifndef DECLARE_MUTEX_LOCKED
#define DECLARE_MUTEX_LOCKED(sem) struct semaphore sem = MUTEX_LOCKED;
#endif
/*
* Lock macros
*/
#define IPS_SCB_LOCK(cpu_flags) spin_lock_irqsave(&ha->scb_lock, cpu_flags)
#define IPS_SCB_UNLOCK(cpu_flags) spin_unlock_irqrestore(&ha->scb_lock, cpu_flags)
#define IPS_QUEUE_LOCK(queue) spin_lock_irqsave(&(queue)->lock, (queue)->cpu_flags)
#define IPS_QUEUE_UNLOCK(queue) spin_unlock_irqrestore(&(queue)->lock, (queue)->cpu_flags)
#define IPS_HA_LOCK(cpu_flags) spin_lock_irqsave(&ha->ips_lock, cpu_flags)
#define IPS_HA_UNLOCK(cpu_flags) spin_unlock_irqrestore(&ha->ips_lock, cpu_flags)
/* /*
* Adapter address map equates * Adapter address map equates
*/ */
...@@ -1063,8 +1044,6 @@ typedef struct ips_scb_queue { ...@@ -1063,8 +1044,6 @@ typedef struct ips_scb_queue {
struct ips_scb *head; struct ips_scb *head;
struct ips_scb *tail; struct ips_scb *tail;
int count; int count;
unsigned long cpu_flags;
spinlock_t lock;
} ips_scb_queue_t; } ips_scb_queue_t;
/* /*
...@@ -1074,13 +1053,10 @@ typedef struct ips_wait_queue { ...@@ -1074,13 +1053,10 @@ typedef struct ips_wait_queue {
Scsi_Cmnd *head; Scsi_Cmnd *head;
Scsi_Cmnd *tail; Scsi_Cmnd *tail;
int count; int count;
unsigned long cpu_flags;
spinlock_t lock;
} ips_wait_queue_t; } ips_wait_queue_t;
typedef struct ips_copp_wait_item { typedef struct ips_copp_wait_item {
Scsi_Cmnd *scsi_cmd; Scsi_Cmnd *scsi_cmd;
struct semaphore *sem;
struct ips_copp_wait_item *next; struct ips_copp_wait_item *next;
} ips_copp_wait_item_t; } ips_copp_wait_item_t;
...@@ -1088,8 +1064,6 @@ typedef struct ips_copp_queue { ...@@ -1088,8 +1064,6 @@ typedef struct ips_copp_queue {
struct ips_copp_wait_item *head; struct ips_copp_wait_item *head;
struct ips_copp_wait_item *tail; struct ips_copp_wait_item *tail;
int count; int count;
unsigned long cpu_flags;
spinlock_t lock;
} ips_copp_queue_t; } ips_copp_queue_t;
/* forward decl for host structure */ /* forward decl for host structure */
...@@ -1138,7 +1112,6 @@ typedef struct ips_ha { ...@@ -1138,7 +1112,6 @@ typedef struct ips_ha {
char *ioctl_data; /* IOCTL data area */ char *ioctl_data; /* IOCTL data area */
uint32_t ioctl_datasize; /* IOCTL data size */ uint32_t ioctl_datasize; /* IOCTL data size */
uint32_t cmd_in_progress; /* Current command in progress*/ uint32_t cmd_in_progress; /* Current command in progress*/
unsigned long flags; /* HA flags */
uint8_t waitflag; /* are we waiting for cmd */ uint8_t waitflag; /* are we waiting for cmd */
uint8_t active; uint8_t active;
int ioctl_reset; /* IOCTL Requested Reset Flag */ int ioctl_reset; /* IOCTL Requested Reset Flag */
...@@ -1158,11 +1131,6 @@ typedef struct ips_ha { ...@@ -1158,11 +1131,6 @@ typedef struct ips_ha {
char *ioremap_ptr; /* ioremapped memory pointer */ char *ioremap_ptr; /* ioremapped memory pointer */
ips_hw_func_t func; /* hw function pointers */ ips_hw_func_t func; /* hw function pointers */
struct pci_dev *pcidev; /* PCI device handle */ struct pci_dev *pcidev; /* PCI device handle */
spinlock_t scb_lock;
spinlock_t copp_lock;
spinlock_t ips_lock;
struct semaphore ioctl_sem; /* Semaphore for new IOCTL's */
struct semaphore flash_ioctl_sem; /* Semaphore for Flashing */
char *flash_data; /* Save Area for flash data */ char *flash_data; /* Save Area for flash data */
u8 flash_order; /* Save Area for flash size order */ u8 flash_order; /* Save Area for flash size order */
u32 flash_datasize; /* Save Area for flash data size */ u32 flash_datasize; /* Save Area for flash data size */
...@@ -1195,7 +1163,6 @@ typedef struct ips_scb { ...@@ -1195,7 +1163,6 @@ typedef struct ips_scb {
Scsi_Cmnd *scsi_cmd; Scsi_Cmnd *scsi_cmd;
struct ips_scb *q_next; struct ips_scb *q_next;
ips_scb_callback callback; ips_scb_callback callback;
struct semaphore *sem;
uint32_t sg_busaddr; uint32_t sg_busaddr;
int sg_count; int sg_count;
} ips_scb_t; } ips_scb_t;
......
...@@ -216,8 +216,8 @@ ...@@ -216,8 +216,8 @@
* *
*/ */
typedef volatile struct mailbox { typedef volatile struct mailbox {
unchar status; unchar status;
unchar scbptr[3]; /* SCSI-style - MSB first (big endian) */ unchar scbptr[3]; /* SCSI-style - MSB first (big endian) */
} Mailbox; } Mailbox;
/* /*
...@@ -225,38 +225,36 @@ typedef volatile struct mailbox { ...@@ -225,38 +225,36 @@ typedef volatile struct mailbox {
* new global per-adapter data should put in here. * new global per-adapter data should put in here.
*/ */
typedef struct adapter { typedef struct adapter {
struct Scsi_Host *sh; /* Pointer to Scsi_Host structure */ struct Scsi_Host *sh; /* Pointer to Scsi_Host structure */
int iobase; /* This adapter's I/O base address */ int iobase; /* This adapter's I/O base address */
int irq; /* This adapter's IRQ level */ int irq; /* This adapter's IRQ level */
int dma; /* This adapter's DMA channel */ int dma; /* This adapter's DMA channel */
int int_counter; /* This adapter's interrupt counter */ int int_counter; /* This adapter's interrupt counter */
int bus_on; /* This adapter's BUS_ON time */ int bus_on; /* This adapter's BUS_ON time */
int bus_off; /* This adapter's BUS_OFF time */ int bus_off; /* This adapter's BUS_OFF time */
struct { /* This adapter's mailboxes */ struct { /* This adapter's mailboxes */
Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes */ Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes */
Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes */ Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes */
} mb; } mb;
int next_ogmb; /* to reduce contention at mailboxes */ int next_ogmb; /* to reduce contention at mailboxes */
unchar control; /* shadows CONTROL port value */ unchar control; /* shadows CONTROL port value */
unchar rev1, rev2; /* filled in by wd7000_revision */ unchar rev1, rev2; /* filled in by wd7000_revision */
} Adapter; } Adapter;
/* /*
* (linear) base address for ROM BIOS * (linear) base address for ROM BIOS
*/ */
static const long wd7000_biosaddr[] = static const long wd7000_biosaddr[] = {
{ 0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000,
0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000, 0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000
0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000
}; };
#define NUM_ADDRS (sizeof(wd7000_biosaddr)/sizeof(long)) #define NUM_ADDRS (sizeof(wd7000_biosaddr)/sizeof(long))
static const unsigned short wd7000_iobase[] = static const unsigned short wd7000_iobase[] = {
{ 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338,
0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, 0x0378,
0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8,
0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8, 0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8
0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8
}; };
#define NUM_IOPORTS (sizeof(wd7000_iobase)/sizeof(unsigned short)) #define NUM_IOPORTS (sizeof(wd7000_iobase)/sizeof(unsigned short))
...@@ -270,36 +268,35 @@ static const short wd7000_dma[] = { 5, 6, 7 }; ...@@ -270,36 +268,35 @@ static const short wd7000_dma[] = { 5, 6, 7 };
* The following is set up by wd7000_detect, and used thereafter for * The following is set up by wd7000_detect, and used thereafter for
* proc and other global ookups * proc and other global ookups
*/ */
#define UNITS 8 #define UNITS 8
static struct Scsi_Host *wd7000_host[UNITS]; static struct Scsi_Host *wd7000_host[UNITS];
#define BUS_ON 64 /* x 125ns = 8000ns (BIOS default) */ #define BUS_ON 64 /* x 125ns = 8000ns (BIOS default) */
#define BUS_OFF 15 /* x 125ns = 1875ns (BIOS default) */ #define BUS_OFF 15 /* x 125ns = 1875ns (BIOS default) */
/* /*
* Standard Adapter Configurations - used by wd7000_detect * Standard Adapter Configurations - used by wd7000_detect
*/ */
typedef struct { typedef struct {
short irq; /* IRQ level */ short irq; /* IRQ level */
short dma; /* DMA channel */ short dma; /* DMA channel */
unsigned iobase; /* I/O base address */ unsigned iobase; /* I/O base address */
short bus_on; /* Time that WD7000 spends on the AT-bus when */ short bus_on; /* Time that WD7000 spends on the AT-bus when */
/* transferring data. BIOS default is 8000ns. */ /* transferring data. BIOS default is 8000ns. */
short bus_off; /* Time that WD7000 spends OFF THE BUS after */ short bus_off; /* Time that WD7000 spends OFF THE BUS after */
/* while it is transferring data. */ /* while it is transferring data. */
/* BIOS default is 1875ns */ /* BIOS default is 1875ns */
} Config; } Config;
/* /*
* Add here your configuration... * Add here your configuration...
*/ */
static Config configs[] = static Config configs[] = {
{ {15, 6, 0x350, BUS_ON, BUS_OFF}, /* defaults for single adapter */
{ 15, 6, 0x350, BUS_ON, BUS_OFF }, /* defaults for single adapter */ {11, 5, 0x320, BUS_ON, BUS_OFF}, /* defaults for second adapter */
{ 11, 5, 0x320, BUS_ON, BUS_OFF }, /* defaults for second adapter */ {7, 6, 0x350, BUS_ON, BUS_OFF}, /* My configuration (Zaga) */
{ 7, 6, 0x350, BUS_ON, BUS_OFF }, /* My configuration (Zaga) */ {-1, -1, 0x0, BUS_ON, BUS_OFF} /* Empty slot */
{ -1, -1, 0x0, BUS_ON, BUS_OFF } /* Empty slot */
}; };
#define NUM_CONFIGS (sizeof(configs)/sizeof(Config)) #define NUM_CONFIGS (sizeof(configs)/sizeof(Config))
...@@ -309,14 +306,13 @@ static Config configs[] = ...@@ -309,14 +306,13 @@ static Config configs[] =
* added for the Future Domain version. * added for the Future Domain version.
*/ */
typedef struct signature { typedef struct signature {
const char *sig; /* String to look for */ const char *sig; /* String to look for */
unsigned long ofs; /* offset from BIOS base address */ unsigned long ofs; /* offset from BIOS base address */
unsigned len; /* length of string */ unsigned len; /* length of string */
} Signature; } Signature;
static const Signature signatures[] = static const Signature signatures[] = {
{ {"SSTBIOS", 0x0000d, 7} /* "SSTBIOS" @ offset 0x0000d */
{"SSTBIOS", 0x0000d, 7} /* "SSTBIOS" @ offset 0x0000d */
}; };
#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature)) #define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature))
...@@ -363,14 +359,14 @@ static const Signature signatures[] = ...@@ -363,14 +359,14 @@ static const Signature signatures[] =
* For INITIALIZATION: * For INITIALIZATION:
*/ */
typedef struct initCmd { typedef struct initCmd {
unchar op; /* command opcode (= 1) */ unchar op; /* command opcode (= 1) */
unchar ID; /* Adapter's SCSI ID */ unchar ID; /* Adapter's SCSI ID */
unchar bus_on; /* Bus on time, x 125ns (see below) */ unchar bus_on; /* Bus on time, x 125ns (see below) */
unchar bus_off; /* Bus off time, "" "" */ unchar bus_off; /* Bus off time, "" "" */
unchar rsvd; /* Reserved */ unchar rsvd; /* Reserved */
unchar mailboxes[3]; /* Address of Mailboxes, MSB first */ unchar mailboxes[3]; /* Address of Mailboxes, MSB first */
unchar ogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */ unchar ogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */
unchar icmbs; /* Number of incoming MBs, "" "" */ unchar icmbs; /* Number of incoming MBs, "" "" */
} InitCmd; } InitCmd;
/* /*
...@@ -430,29 +426,29 @@ typedef struct initCmd { ...@@ -430,29 +426,29 @@ typedef struct initCmd {
* WD7000-specific scatter/gather element structure * WD7000-specific scatter/gather element structure
*/ */
typedef struct sgb { typedef struct sgb {
unchar len[3]; unchar len[3];
unchar ptr[3]; /* Also SCSI-style - MSB first */ unchar ptr[3]; /* Also SCSI-style - MSB first */
} Sgb; } Sgb;
typedef struct scb { /* Command Control Block 5.4.1 */ typedef struct scb { /* Command Control Block 5.4.1 */
unchar op; /* Command Control Block Operation Code */ unchar op; /* Command Control Block Operation Code */
unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */ unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */
/* Outbound data transfer, length is checked */ /* Outbound data transfer, length is checked */
/* Inbound data transfer, length is checked */ /* Inbound data transfer, length is checked */
/* Logical Unit Number */ /* Logical Unit Number */
unchar cdb[12]; /* SCSI Command Block */ unchar cdb[12]; /* SCSI Command Block */
volatile unchar status; /* SCSI Return Status */ volatile unchar status; /* SCSI Return Status */
volatile unchar vue; /* Vendor Unique Error Code */ volatile unchar vue; /* Vendor Unique Error Code */
unchar maxlen[3]; /* Maximum Data Transfer Length */ unchar maxlen[3]; /* Maximum Data Transfer Length */
unchar dataptr[3]; /* SCSI Data Block Pointer */ unchar dataptr[3]; /* SCSI Data Block Pointer */
unchar linkptr[3]; /* Next Command Link Pointer */ unchar linkptr[3]; /* Next Command Link Pointer */
unchar direc; /* Transfer Direction */ unchar direc; /* Transfer Direction */
unchar reserved2[6]; /* SCSI Command Descriptor Block */ unchar reserved2[6]; /* SCSI Command Descriptor Block */
/* end of hardware SCB */ /* end of hardware SCB */
Scsi_Cmnd *SCpnt; /* Scsi_Cmnd using this SCB */ Scsi_Cmnd *SCpnt; /* Scsi_Cmnd using this SCB */
Sgb sgb[WD7000_SG]; /* Scatter/gather list for this SCB */ Sgb sgb[WD7000_SG]; /* Scatter/gather list for this SCB */
Adapter *host; /* host adapter */ Adapter *host; /* host adapter */
struct scb *next; /* for lists of scbs */ struct scb *next; /* for lists of scbs */
} Scb; } Scb;
/* /*
...@@ -484,56 +480,56 @@ typedef struct scb { /* Command Control Block 5.4.1 */ ...@@ -484,56 +480,56 @@ typedef struct scb { /* Command Control Block 5.4.1 */
#define ICB_OP_GET_EPARMS 0x8F /* read execution parameters */ #define ICB_OP_GET_EPARMS 0x8F /* read execution parameters */
typedef struct icbRecvCmd { typedef struct icbRecvCmd {
unchar op; unchar op;
unchar IDlun; /* Initiator SCSI ID/lun */ unchar IDlun; /* Initiator SCSI ID/lun */
unchar len[3]; /* command buffer length */ unchar len[3]; /* command buffer length */
unchar ptr[3]; /* command buffer address */ unchar ptr[3]; /* command buffer address */
unchar rsvd[7]; /* reserved */ unchar rsvd[7]; /* reserved */
volatile unchar vue; /* vendor-unique error code */ volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */ volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */ volatile unchar phase; /* used by interrupt handler */
} IcbRecvCmd; } IcbRecvCmd;
typedef struct icbSendStat { typedef struct icbSendStat {
unchar op; unchar op;
unchar IDlun; /* Target SCSI ID/lun */ unchar IDlun; /* Target SCSI ID/lun */
unchar stat; /* (outgoing) completion status byte 1 */ unchar stat; /* (outgoing) completion status byte 1 */
unchar rsvd[12]; /* reserved */ unchar rsvd[12]; /* reserved */
volatile unchar vue; /* vendor-unique error code */ volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */ volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */ volatile unchar phase; /* used by interrupt handler */
} IcbSendStat; } IcbSendStat;
typedef struct icbRevLvl { typedef struct icbRevLvl {
unchar op; unchar op;
volatile unchar primary; /* primary revision level (returned) */ volatile unchar primary; /* primary revision level (returned) */
volatile unchar secondary; /* secondary revision level (returned) */ volatile unchar secondary; /* secondary revision level (returned) */
unchar rsvd[12]; /* reserved */ unchar rsvd[12]; /* reserved */
volatile unchar vue; /* vendor-unique error code */ volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */ volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */ volatile unchar phase; /* used by interrupt handler */
} IcbRevLvl; } IcbRevLvl;
typedef struct icbUnsMask { /* I'm totally guessing here */ typedef struct icbUnsMask { /* I'm totally guessing here */
unchar op; unchar op;
volatile unchar mask[14]; /* mask bits */ volatile unchar mask[14]; /* mask bits */
#if 0 #if 0
unchar rsvd[12]; /* reserved */ unchar rsvd[12]; /* reserved */
#endif #endif
volatile unchar vue; /* vendor-unique error code */ volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */ volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */ volatile unchar phase; /* used by interrupt handler */
} IcbUnsMask; } IcbUnsMask;
typedef struct icbDiag { typedef struct icbDiag {
unchar op; unchar op;
unchar type; /* diagnostics type code (0-3) */ unchar type; /* diagnostics type code (0-3) */
unchar len[3]; /* buffer length */ unchar len[3]; /* buffer length */
unchar ptr[3]; /* buffer address */ unchar ptr[3]; /* buffer address */
unchar rsvd[7]; /* reserved */ unchar rsvd[7]; /* reserved */
volatile unchar vue; /* vendor-unique error code */ volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */ volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */ volatile unchar phase; /* used by interrupt handler */
} IcbDiag; } IcbDiag;
#define ICB_DIAG_POWERUP 0 /* Power-up diags only */ #define ICB_DIAG_POWERUP 0 /* Power-up diags only */
...@@ -542,34 +538,34 @@ typedef struct icbDiag { ...@@ -542,34 +538,34 @@ typedef struct icbDiag {
#define ICB_DIAG_FULL 3 /* do both 1 & 2 */ #define ICB_DIAG_FULL 3 /* do both 1 & 2 */
typedef struct icbParms { typedef struct icbParms {
unchar op; unchar op;
unchar rsvd1; /* reserved */ unchar rsvd1; /* reserved */
unchar len[3]; /* parms buffer length */ unchar len[3]; /* parms buffer length */
unchar ptr[3]; /* parms buffer address */ unchar ptr[3]; /* parms buffer address */
unchar idx[2]; /* index (MSB-LSB) */ unchar idx[2]; /* index (MSB-LSB) */
unchar rsvd2[5]; /* reserved */ unchar rsvd2[5]; /* reserved */
volatile unchar vue; /* vendor-unique error code */ volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */ volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */ volatile unchar phase; /* used by interrupt handler */
} IcbParms; } IcbParms;
typedef struct icbAny { typedef struct icbAny {
unchar op; unchar op;
unchar data[14]; /* format-specific data */ unchar data[14]; /* format-specific data */
volatile unchar vue; /* vendor-unique error code */ volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */ volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */ volatile unchar phase; /* used by interrupt handler */
} IcbAny; } IcbAny;
typedef union icb { typedef union icb {
unchar op; /* ICB opcode */ unchar op; /* ICB opcode */
IcbRecvCmd recv_cmd; /* format for receive command */ IcbRecvCmd recv_cmd; /* format for receive command */
IcbSendStat send_stat; /* format for send status */ IcbSendStat send_stat; /* format for send status */
IcbRevLvl rev_lvl; /* format for get revision level */ IcbRevLvl rev_lvl; /* format for get revision level */
IcbDiag diag; /* format for execute diagnostics */ IcbDiag diag; /* format for execute diagnostics */
IcbParms eparms; /* format for get/set exec parms */ IcbParms eparms; /* format for get/set exec parms */
IcbAny icb; /* generic format */ IcbAny icb; /* generic format */
unchar data[18]; unchar data[18];
} Icb; } Icb;
#ifdef MODULE #ifdef MODULE
...@@ -586,22 +582,19 @@ MODULE_PARM(wd7000, "s"); ...@@ -586,22 +582,19 @@ MODULE_PARM(wd7000, "s");
static Scb scbs[MAX_SCBS]; static Scb scbs[MAX_SCBS];
static Scb *scbfree; /* free list */ static Scb *scbfree; /* free list */
static int freescbs = MAX_SCBS; /* free list counter */ static int freescbs = MAX_SCBS; /* free list counter */
static spinlock_t scbpool_lock; /* guards the scb free list and count */ static spinlock_t scbpool_lock; /* guards the scb free list and count */
/* /*
* END of data/declarations - code follows. * END of data/declarations - code follows.
*/ */
static void __init setup_error(char *mesg, int *ints) static void __init setup_error(char *mesg, int *ints)
{ {
if (ints[0] == 3) if (ints[0] == 3)
printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x\" -> %s\n", printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x\" -> %s\n", ints[1], ints[2], ints[3], mesg);
ints[1], ints[2], ints[3], mesg); else if (ints[0] == 4)
else if (ints[0] == 4) printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d\" -> %s\n", ints[1], ints[2], ints[3], ints[4], mesg);
printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d\" -> %s\n", else
ints[1], ints[2], ints[3], ints[4], mesg); printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d,%d\" -> %s\n", ints[1], ints[2], ints[3], ints[4], ints[5], mesg);
else
printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d,%d\" -> %s\n",
ints[1], ints[2], ints[3], ints[4], ints[5], mesg);
} }
...@@ -621,23 +614,19 @@ static void __init setup_error(char *mesg, int *ints) ...@@ -621,23 +614,19 @@ static void __init setup_error(char *mesg, int *ints)
*/ */
static int __init wd7000_setup(char *str) static int __init wd7000_setup(char *str)
{ {
static short wd7000_card_num; /* .bss will zero this */ static short wd7000_card_num; /* .bss will zero this */
short i; short i;
int ints[6]; int ints[6];
(void)get_options(str, ARRAY_SIZE(ints), ints); (void) get_options(str, ARRAY_SIZE(ints), ints);
if (wd7000_card_num >= NUM_CONFIGS) { if (wd7000_card_num >= NUM_CONFIGS) {
printk(KERN_ERR printk(KERN_ERR "%s: Too many \"wd7000=\" configurations in " "command line!\n", __FUNCTION__);
"%s: Too many \"wd7000=\" configurations in "
"command line!\n", __FUNCTION__);
return 0; return 0;
} }
if ((ints[0] < 3) || (ints[0] > 5)) { if ((ints[0] < 3) || (ints[0] > 5)) {
printk(KERN_ERR "%s: Error in command line! " printk(KERN_ERR "%s: Error in command line! " "Usage: wd7000=<IRQ>,<DMA>,IO>[,<BUS_ON>" "[,<BUS_OFF>]]\n", __FUNCTION__);
"Usage: wd7000=<IRQ>,<DMA>,IO>[,<BUS_ON>"
"[,<BUS_OFF>]]\n", __FUNCTION__);
} else { } else {
for (i = 0; i < NUM_IRQS; i++) for (i = 0; i < NUM_IRQS; i++)
if (ints[1] == wd7000_irq[i]) if (ints[1] == wd7000_irq[i])
...@@ -671,8 +660,7 @@ static int __init wd7000_setup(char *str) ...@@ -671,8 +660,7 @@ static int __init wd7000_setup(char *str)
if (ints[0] > 3) { if (ints[0] > 3) {
if ((ints[4] < 500) || (ints[4] > 31875)) { if ((ints[4] < 500) || (ints[4] > 31875)) {
setup_error("BUS_ON value is out of range (500" setup_error("BUS_ON value is out of range (500" " to 31875 nanoseconds)!", ints);
" to 31875 nanoseconds)!", ints);
configs[wd7000_card_num].bus_on = BUS_ON; configs[wd7000_card_num].bus_on = BUS_ON;
} else } else
configs[wd7000_card_num].bus_on = ints[4] / 125; configs[wd7000_card_num].bus_on = ints[4] / 125;
...@@ -681,12 +669,10 @@ static int __init wd7000_setup(char *str) ...@@ -681,12 +669,10 @@ static int __init wd7000_setup(char *str)
if (ints[0] > 4) { if (ints[0] > 4) {
if ((ints[5] < 500) || (ints[5] > 31875)) { if ((ints[5] < 500) || (ints[5] > 31875)) {
setup_error("BUS_OFF value is out of range (500" setup_error("BUS_OFF value is out of range (500" " to 31875 nanoseconds)!", ints);
" to 31875 nanoseconds)!", ints);
configs[wd7000_card_num].bus_off = BUS_OFF; configs[wd7000_card_num].bus_off = BUS_OFF;
} else } else
configs[wd7000_card_num].bus_off = ints[5] / configs[wd7000_card_num].bus_off = ints[5] / 125;
125;
} else } else
configs[wd7000_card_num].bus_off = BUS_OFF; configs[wd7000_card_num].bus_off = BUS_OFF;
...@@ -696,32 +682,22 @@ static int __init wd7000_setup(char *str) ...@@ -696,32 +682,22 @@ static int __init wd7000_setup(char *str)
for (; j < wd7000_card_num; j++) for (; j < wd7000_card_num; j++)
if (configs[i].irq == configs[j].irq) { if (configs[i].irq == configs[j].irq) {
setup_error("duplicated IRQ!", setup_error("duplicated IRQ!", ints);
ints);
return 0;
}
if (configs[i].dma == configs[j].dma) {
setup_error("duplicated DMA "
"channel!", ints);
return 0;
}
if (configs[i].iobase ==
configs[j].iobase) {
setup_error("duplicated I/O "
"base address!",
ints);
return 0; return 0;
} }
if (configs[i].dma == configs[j].dma) {
setup_error("duplicated DMA " "channel!", ints);
return 0;
}
if (configs[i].iobase == configs[j].iobase) {
setup_error("duplicated I/O " "base address!", ints);
return 0;
}
} }
} }
dprintk(KERN_DEBUG "wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, " dprintk(KERN_DEBUG "wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, "
"BUS_ON=%dns, BUS_OFF=%dns\n", "BUS_ON=%dns, BUS_OFF=%dns\n", configs[wd7000_card_num].irq, configs[wd7000_card_num].dma, configs[wd7000_card_num].iobase, configs[wd7000_card_num].bus_on * 125, configs[wd7000_card_num].bus_off * 125);
configs[wd7000_card_num].irq,
configs[wd7000_card_num].dma,
configs[wd7000_card_num].iobase,
configs[wd7000_card_num].bus_on * 125,
configs[wd7000_card_num].bus_off * 125);
wd7000_card_num++; wd7000_card_num++;
} }
...@@ -740,29 +716,29 @@ __setup("wd7000=", wd7000_setup); ...@@ -740,29 +716,29 @@ __setup("wd7000=", wd7000_setup);
* (They were simply 4-byte versions of these routines). * (They were simply 4-byte versions of these routines).
*/ */
typedef union { /* let's cheat... */ typedef union { /* let's cheat... */
int i; int i;
unchar u[sizeof (int)]; /* the sizeof(int) makes it more portable */ unchar u[sizeof(int)]; /* the sizeof(int) makes it more portable */
} i_u; } i_u;
static inline void any2scsi (unchar * scsi, int any) static inline void any2scsi(unchar * scsi, int any)
{ {
*scsi++ = ((i_u) any).u[2]; *scsi++ = ((i_u) any).u[2];
*scsi++ = ((i_u) any).u[1]; *scsi++ = ((i_u) any).u[1];
*scsi++ = ((i_u) any).u[0]; *scsi++ = ((i_u) any).u[0];
} }
static inline int scsi2int (unchar * scsi) static inline int scsi2int(unchar * scsi)
{ {
i_u result; i_u result;
result.i = 0; /* clears unused bytes */ result.i = 0; /* clears unused bytes */
result.u[2] = *scsi++; result.u[2] = *scsi++;
result.u[1] = *scsi++; result.u[1] = *scsi++;
result.u[0] = *scsi++; result.u[0] = *scsi++;
return (result.i); return (result.i);
} }
#else #else
/* /*
...@@ -780,63 +756,63 @@ static inline int scsi2int (unchar * scsi) ...@@ -780,63 +756,63 @@ static inline int scsi2int (unchar * scsi)
#endif #endif
static inline void wd7000_enable_intr (Adapter *host) static inline void wd7000_enable_intr(Adapter * host)
{ {
host->control |= INT_EN; host->control |= INT_EN;
outb (host->control, host->iobase + ASC_CONTROL); outb(host->control, host->iobase + ASC_CONTROL);
} }
static inline void wd7000_enable_dma (Adapter *host) static inline void wd7000_enable_dma(Adapter * host)
{ {
unsigned long flags; unsigned long flags;
host->control |= DMA_EN; host->control |= DMA_EN;
outb (host->control, host->iobase + ASC_CONTROL); outb(host->control, host->iobase + ASC_CONTROL);
flags = claim_dma_lock(); flags = claim_dma_lock();
set_dma_mode (host->dma, DMA_MODE_CASCADE); set_dma_mode(host->dma, DMA_MODE_CASCADE);
enable_dma (host->dma); enable_dma(host->dma);
release_dma_lock(flags); release_dma_lock(flags);
} }
#define WAITnexttimeout 200 /* 2 seconds */ #define WAITnexttimeout 200 /* 2 seconds */
static inline short WAIT (unsigned port, unsigned mask, unsigned allof, unsigned noneof) static inline short WAIT(unsigned port, unsigned mask, unsigned allof, unsigned noneof)
{ {
register unsigned WAITbits; register unsigned WAITbits;
register unsigned long WAITtimeout = jiffies + WAITnexttimeout; register unsigned long WAITtimeout = jiffies + WAITnexttimeout;
while (time_before_eq(jiffies, WAITtimeout)) { while (time_before_eq(jiffies, WAITtimeout)) {
WAITbits = inb (port) & mask; WAITbits = inb(port) & mask;
if (((WAITbits & allof) == allof) && ((WAITbits & noneof) == 0)) if (((WAITbits & allof) == allof) && ((WAITbits & noneof) == 0))
return (0); return (0);
} }
return (1); return (1);
} }
static inline int command_out (Adapter * host, unchar * cmd, int len) static inline int command_out(Adapter * host, unchar * cmd, int len)
{ {
if (!WAIT (host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { if (!WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) {
while (len--) { while (len--) {
do { do {
outb (*cmd, host->iobase + ASC_COMMAND); outb(*cmd, host->iobase + ASC_COMMAND);
WAIT (host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0); WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0);
} while (inb (host->iobase + ASC_STAT) & CMD_REJ); } while (inb(host->iobase + ASC_STAT) & CMD_REJ);
cmd++; cmd++;
} }
return (1); return (1);
} }
printk(KERN_WARNING "wd7000 command_out: WAIT failed(%d)\n", len + 1); printk(KERN_WARNING "wd7000 command_out: WAIT failed(%d)\n", len + 1);
return (0); return (0);
} }
...@@ -852,654 +828,645 @@ static inline int command_out (Adapter * host, unchar * cmd, int len) ...@@ -852,654 +828,645 @@ static inline int command_out (Adapter * host, unchar * cmd, int len)
*/ */
static inline Scb *alloc_scbs(struct Scsi_Host *host, int needed) static inline Scb *alloc_scbs(struct Scsi_Host *host, int needed)
{ {
register Scb *scb, *p = NULL; register Scb *scb, *p = NULL;
register unsigned long flags; register unsigned long flags;
register unsigned long timeout = jiffies + WAITnexttimeout; register unsigned long timeout = jiffies + WAITnexttimeout;
register unsigned long now; register unsigned long now;
int i; int i;
if (needed <= 0) if (needed <= 0)
return (NULL); /* sanity check */ return (NULL); /* sanity check */
spin_unlock_irq(host->host_lock); spin_unlock_irq(host->host_lock);
retry: retry:
while (freescbs < needed) { while (freescbs < needed) {
timeout = jiffies + WAITnexttimeout; timeout = jiffies + WAITnexttimeout;
do { do {
/* FIXME: can we actually just yield here ?? */ /* FIXME: can we actually just yield here ?? */
for (now = jiffies; now == jiffies; ) for (now = jiffies; now == jiffies;)
cpu_relax(); /* wait a jiffy */ cpu_relax(); /* wait a jiffy */
} while (freescbs < needed && time_before_eq(jiffies, timeout)); } while (freescbs < needed && time_before_eq(jiffies, timeout));
/* /*
* If we get here with enough free Scbs, we can take them. * If we get here with enough free Scbs, we can take them.
* Otherwise, we timed out and didn't get enough. * Otherwise, we timed out and didn't get enough.
*/ */
if (freescbs < needed) {
printk(KERN_ERR "wd7000: can't get enough free SCBs.\n");
return (NULL);
}
}
/* Take the lock, then check we didnt get beaten, if so try again */
spin_lock_irqsave(&scbpool_lock, flags);
if (freescbs < needed) { if (freescbs < needed) {
printk (KERN_ERR "wd7000: can't get enough free SCBs.\n"); spin_unlock_irqrestore(&scbpool_lock, flags);
return (NULL); goto retry;
} }
}
scb = scbfree;
/* Take the lock, then check we didnt get beaten, if so try again */ freescbs -= needed;
spin_lock_irqsave(&scbpool_lock, flags); for (i = 0; i < needed; i++) {
if(freescbs < needed) p = scbfree;
{ scbfree = p->next;
spin_unlock_irqrestore(&scbpool_lock, flags); }
goto retry; p->next = NULL;
}
spin_unlock_irqrestore(&scbpool_lock, flags);
scb = scbfree;
freescbs -= needed; spin_lock_irq(host->host_lock);
for (i = 0; i < needed; i++) { return (scb);
p = scbfree;
scbfree = p->next;
}
p->next = NULL;
spin_unlock_irqrestore(&scbpool_lock, flags);
spin_lock_irq(host->host_lock);
return (scb);
} }
static inline void free_scb (Scb *scb) static inline void free_scb(Scb * scb)
{ {
register unsigned long flags; register unsigned long flags;
spin_lock_irqsave(&scbpool_lock, flags); spin_lock_irqsave(&scbpool_lock, flags);
memset (scb, 0, sizeof (Scb)); memset(scb, 0, sizeof(Scb));
scb->next = scbfree; scb->next = scbfree;
scbfree = scb; scbfree = scb;
freescbs++; freescbs++;
spin_unlock_irqrestore(&scbpool_lock, flags); spin_unlock_irqrestore(&scbpool_lock, flags);
} }
static inline void init_scbs (void) static inline void init_scbs(void)
{ {
int i; int i;
spin_lock_init(&scbpool_lock); spin_lock_init(&scbpool_lock);
/* This is only ever called before the SCB pool is active */ /* This is only ever called before the SCB pool is active */
scbfree = &(scbs[0]); scbfree = &(scbs[0]);
memset (scbs, 0, sizeof (scbs)); memset(scbs, 0, sizeof(scbs));
for (i = 0; i < MAX_SCBS - 1; i++) { for (i = 0; i < MAX_SCBS - 1; i++) {
scbs[i].next = &(scbs[i + 1]); scbs[i].next = &(scbs[i + 1]);
scbs[i].SCpnt = NULL; scbs[i].SCpnt = NULL;
} }
scbs[MAX_SCBS - 1].next = NULL; scbs[MAX_SCBS - 1].next = NULL;
scbs[MAX_SCBS - 1].SCpnt = NULL; scbs[MAX_SCBS - 1].SCpnt = NULL;
} }
static int mail_out (Adapter *host, Scb *scbptr) static int mail_out(Adapter * host, Scb * scbptr)
/* /*
* Note: this can also be used for ICBs; just cast to the parm type. * Note: this can also be used for ICBs; just cast to the parm type.
*/ */
{ {
register int i, ogmb; register int i, ogmb;
register unsigned long flags; register unsigned long flags;
unchar start_ogmb; unchar start_ogmb;
Mailbox *ogmbs = host->mb.ogmb; Mailbox *ogmbs = host->mb.ogmb;
int *next_ogmb = &(host->next_ogmb); int *next_ogmb = &(host->next_ogmb);
dprintk("wd7000_mail_out: 0x%06lx", (long) scbptr); dprintk("wd7000_mail_out: 0x%06lx", (long) scbptr);
/* We first look for a free outgoing mailbox */ /* We first look for a free outgoing mailbox */
spin_lock_irqsave(host->sh->host_lock, flags); spin_lock_irqsave(host->sh->host_lock, flags);
ogmb = *next_ogmb; ogmb = *next_ogmb;
for (i = 0; i < OGMB_CNT; i++) { for (i = 0; i < OGMB_CNT; i++) {
if (ogmbs[ogmb].status == 0) { if (ogmbs[ogmb].status == 0) {
dprintk(" using OGMB 0x%x", ogmb); dprintk(" using OGMB 0x%x", ogmb);
ogmbs[ogmb].status = 1; ogmbs[ogmb].status = 1;
any2scsi ((unchar *) ogmbs[ogmb].scbptr, (int) scbptr); any2scsi((unchar *) ogmbs[ogmb].scbptr, (int) scbptr);
*next_ogmb = (ogmb + 1) % OGMB_CNT; *next_ogmb = (ogmb + 1) % OGMB_CNT;
break; break;
} else
ogmb = (ogmb + 1) % OGMB_CNT;
} }
else spin_unlock_irqrestore(host->sh->host_lock, flags);
ogmb = (ogmb + 1) % OGMB_CNT;
}
spin_unlock_irqrestore(host->sh->host_lock, flags);
dprintk(", scb is 0x%06lx", (long) scbptr);
if (i >= OGMB_CNT) { dprintk(", scb is 0x%06lx", (long) scbptr);
/*
* Alternatively, we might issue the "interrupt on free OGMB",
* and sleep, but it must be ensured that it isn't the init
* task running. Instead, this version assumes that the caller
* will be persistent, and try again. Since it's the adapter
* that marks OGMB's free, waiting even with interrupts off
* should work, since they are freed very quickly in most cases.
*/
dprintk(", no free OGMBs.\n");
return (0);
}
wd7000_enable_intr (host); if (i >= OGMB_CNT) {
/*
* Alternatively, we might issue the "interrupt on free OGMB",
* and sleep, but it must be ensured that it isn't the init
* task running. Instead, this version assumes that the caller
* will be persistent, and try again. Since it's the adapter
* that marks OGMB's free, waiting even with interrupts off
* should work, since they are freed very quickly in most cases.
*/
dprintk(", no free OGMBs.\n");
return (0);
}
start_ogmb = START_OGMB | ogmb; wd7000_enable_intr(host);
command_out (host, &start_ogmb, 1);
dprintk(", awaiting interrupt.\n"); start_ogmb = START_OGMB | ogmb;
command_out(host, &start_ogmb, 1);
return (1); dprintk(", awaiting interrupt.\n");
return (1);
} }
static int make_code (unsigned hosterr, unsigned scsierr) static int make_code(unsigned hosterr, unsigned scsierr)
{ {
#ifdef WD7000_DEBUG #ifdef WD7000_DEBUG
int in_error = hosterr; int in_error = hosterr;
#endif #endif
switch ((hosterr >> 8) & 0xff) { switch ((hosterr >> 8) & 0xff) {
case 0: /* Reserved */ case 0: /* Reserved */
hosterr = DID_ERROR; hosterr = DID_ERROR;
break; break;
case 1: /* Command Complete, no errors */ case 1: /* Command Complete, no errors */
hosterr = DID_OK; hosterr = DID_OK;
break; break;
case 2: /* Command complete, error logged in scb status (scsierr) */ case 2: /* Command complete, error logged in scb status (scsierr) */
hosterr = DID_OK; hosterr = DID_OK;
break; break;
case 4: /* Command failed to complete - timeout */ case 4: /* Command failed to complete - timeout */
hosterr = DID_TIME_OUT; hosterr = DID_TIME_OUT;
break; break;
case 5: /* Command terminated; Bus reset by external device */ case 5: /* Command terminated; Bus reset by external device */
hosterr = DID_RESET; hosterr = DID_RESET;
break; break;
case 6: /* Unexpected Command Received w/ host as target */ case 6: /* Unexpected Command Received w/ host as target */
hosterr = DID_BAD_TARGET; hosterr = DID_BAD_TARGET;
break; break;
case 80: /* Unexpected Reselection */ case 80: /* Unexpected Reselection */
case 81: /* Unexpected Selection */ case 81: /* Unexpected Selection */
hosterr = DID_BAD_INTR; hosterr = DID_BAD_INTR;
break; break;
case 82: /* Abort Command Message */ case 82: /* Abort Command Message */
hosterr = DID_ABORT; hosterr = DID_ABORT;
break; break;
case 83: /* SCSI Bus Software Reset */ case 83: /* SCSI Bus Software Reset */
case 84: /* SCSI Bus Hardware Reset */ case 84: /* SCSI Bus Hardware Reset */
hosterr = DID_RESET; hosterr = DID_RESET;
break; break;
default: /* Reserved */ default: /* Reserved */
hosterr = DID_ERROR; hosterr = DID_ERROR;
} }
#ifdef WD7000_DEBUG #ifdef WD7000_DEBUG
if (scsierr || hosterr) if (scsierr || hosterr)
dprintk("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n", dprintk("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n", scsierr, in_error, hosterr);
scsierr, in_error, hosterr);
#endif #endif
return (scsierr | (hosterr << 16)); return (scsierr | (hosterr << 16));
} }
static void wd7000_scsi_done (Scsi_Cmnd *SCpnt) static void wd7000_scsi_done(Scsi_Cmnd * SCpnt)
{ {
dprintk("wd7000_scsi_done: 0x%06lx\n", (long)SCpnt); dprintk("wd7000_scsi_done: 0x%06lx\n", (long) SCpnt);
SCpnt->SCp.phase = 0; SCpnt->SCp.phase = 0;
} }
#define wd7000_intr_ack(host) outb (0, host->iobase + ASC_INTR_ACK) #define wd7000_intr_ack(host) outb (0, host->iobase + ASC_INTR_ACK)
static void wd7000_intr_handle (int irq, void *dev_id, struct pt_regs *regs) static void wd7000_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
{ {
register int flag, icmb, errstatus, icmb_status; register int flag, icmb, errstatus, icmb_status;
register int host_error, scsi_error; register int host_error, scsi_error;
register Scb *scb; /* for SCSI commands */ register Scb *scb; /* for SCSI commands */
register IcbAny *icb; /* for host commands */ register IcbAny *icb; /* for host commands */
register Scsi_Cmnd *SCpnt; register Scsi_Cmnd *SCpnt;
Adapter *host = (Adapter *)dev_id; Adapter *host = (Adapter *) dev_id;
Mailbox *icmbs = host->mb.icmb; Mailbox *icmbs = host->mb.icmb;
host->int_counter++; host->int_counter++;
dprintk("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host); dprintk("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host);
flag = inb (host->iobase + ASC_INTR_STAT); flag = inb(host->iobase + ASC_INTR_STAT);
dprintk("wd7000_intr_handle: intr stat = 0x%02x\n", flag); dprintk("wd7000_intr_handle: intr stat = 0x%02x\n", flag);
if (!(inb (host->iobase + ASC_STAT) & INT_IM)) { if (!(inb(host->iobase + ASC_STAT) & INT_IM)) {
/* NB: these are _very_ possible if IRQ 15 is being used, since /* NB: these are _very_ possible if IRQ 15 is being used, since
* it's the "garbage collector" on the 2nd 8259 PIC. Specifically, * it's the "garbage collector" on the 2nd 8259 PIC. Specifically,
* any interrupt signal into the 8259 which can't be identified * any interrupt signal into the 8259 which can't be identified
* comes out as 7 from the 8259, which is 15 to the host. Thus, it * comes out as 7 from the 8259, which is 15 to the host. Thus, it
* is a good thing the WD7000 has an interrupt status port, so we * is a good thing the WD7000 has an interrupt status port, so we
* can sort these out. Otherwise, electrical noise and other such * can sort these out. Otherwise, electrical noise and other such
* problems would be indistinguishable from valid interrupts... * problems would be indistinguishable from valid interrupts...
*/ */
dprintk("wd7000_intr_handle: phantom interrupt...\n"); dprintk("wd7000_intr_handle: phantom interrupt...\n");
wd7000_intr_ack (host); wd7000_intr_ack(host);
return;
}
if (flag & MB_INTR) {
/* The interrupt is for a mailbox */
if (!(flag & IMB_INTR)) {
dprintk("wd7000_intr_handle: free outgoing mailbox\n");
/*
* If sleep_on() and the "interrupt on free OGMB" command are
* used in mail_out(), wake_up() should correspondingly be called
* here. For now, we don't need to do anything special.
*/
wd7000_intr_ack (host);
return;
}
else {
/* The interrupt is for an incoming mailbox */
icmb = flag & MB_MASK;
icmb_status = icmbs[icmb].status;
if (icmb_status & 0x80) { /* unsolicited - result in ICMB */
dprintk("wd7000_intr_handle: unsolicited interrupt 0x%02x\n",
icmb_status);
wd7000_intr_ack (host);
return; return;
} }
/* Aaaargh! (Zaga) */
scb = isa_bus_to_virt(scsi2int ((unchar *) icmbs[icmb].scbptr)); if (flag & MB_INTR) {
icmbs[icmb].status = 0; /* The interrupt is for a mailbox */
if (!(scb->op & ICB_OP_MASK)) { /* an SCB is done */ if (!(flag & IMB_INTR)) {
SCpnt = scb->SCpnt; dprintk("wd7000_intr_handle: free outgoing mailbox\n");
if (--(SCpnt->SCp.phase) <= 0) { /* all scbs are done */ /*
host_error = scb->vue | (icmb_status << 8); * If sleep_on() and the "interrupt on free OGMB" command are
scsi_error = scb->status; * used in mail_out(), wake_up() should correspondingly be called
errstatus = make_code (host_error, scsi_error); * here. For now, we don't need to do anything special.
SCpnt->result = errstatus; */
wd7000_intr_ack(host);
free_scb (scb); return;
} else {
SCpnt->scsi_done (SCpnt); /* The interrupt is for an incoming mailbox */
} icmb = flag & MB_MASK;
} icmb_status = icmbs[icmb].status;
else { /* an ICB is done */ if (icmb_status & 0x80) { /* unsolicited - result in ICMB */
icb = (IcbAny *) scb; dprintk("wd7000_intr_handle: unsolicited interrupt 0x%02x\n", icmb_status);
icb->status = icmb_status; wd7000_intr_ack(host);
icb->phase = 0; return;
} }
} /* incoming mailbox */ /* Aaaargh! (Zaga) */
} scb = isa_bus_to_virt(scsi2int((unchar *) icmbs[icmb].scbptr));
icmbs[icmb].status = 0;
wd7000_intr_ack (host); if (!(scb->op & ICB_OP_MASK)) { /* an SCB is done */
SCpnt = scb->SCpnt;
dprintk("wd7000_intr_handle: return from interrupt handler\n"); if (--(SCpnt->SCp.phase) <= 0) { /* all scbs are done */
host_error = scb->vue | (icmb_status << 8);
scsi_error = scb->status;
errstatus = make_code(host_error, scsi_error);
SCpnt->result = errstatus;
free_scb(scb);
SCpnt->scsi_done(SCpnt);
}
} else { /* an ICB is done */
icb = (IcbAny *) scb;
icb->status = icmb_status;
icb->phase = 0;
}
} /* incoming mailbox */
}
wd7000_intr_ack(host);
dprintk("wd7000_intr_handle: return from interrupt handler\n");
} }
static void do_wd7000_intr_handle (int irq, void *dev_id, struct pt_regs *regs) static void do_wd7000_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned long flags; unsigned long flags;
struct Scsi_Host *host = dev_id; struct Scsi_Host *host = dev_id;
spin_lock_irqsave(host->host_lock, flags); spin_lock_irqsave(host->host_lock, flags);
wd7000_intr_handle(irq, dev_id, regs); wd7000_intr_handle(irq, dev_id, regs);
spin_unlock_irqrestore(host->host_lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
} }
static int wd7000_queuecommand (Scsi_Cmnd *SCpnt, void (*done) (Scsi_Cmnd *)) static int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
{ {
register Scb *scb; register Scb *scb;
register Sgb *sgb; register Sgb *sgb;
register unchar *cdb = (unchar *) SCpnt->cmnd; register unchar *cdb = (unchar *) SCpnt->cmnd;
register unchar idlun; register unchar idlun;
register short cdblen; register short cdblen;
Adapter *host = (Adapter *) SCpnt->host->hostdata; Adapter *host = (Adapter *) SCpnt->host->hostdata;
cdblen = SCpnt->cmd_len; cdblen = SCpnt->cmd_len;
idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7); idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7);
SCpnt->scsi_done = done; SCpnt->scsi_done = done;
SCpnt->SCp.phase = 1; SCpnt->SCp.phase = 1;
scb = alloc_scbs(SCpnt->host, 1); scb = alloc_scbs(SCpnt->host, 1);
scb->idlun = idlun; scb->idlun = idlun;
memcpy (scb->cdb, cdb, cdblen); memcpy(scb->cdb, cdb, cdblen);
scb->direc = 0x40; /* Disable direction check */ scb->direc = 0x40; /* Disable direction check */
scb->SCpnt = SCpnt; /* so we can find stuff later */ scb->SCpnt = SCpnt; /* so we can find stuff later */
SCpnt->host_scribble = (unchar *) scb; SCpnt->host_scribble = (unchar *) scb;
scb->host = host; scb->host = host;
if (SCpnt->use_sg) { if (SCpnt->use_sg) {
struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer; struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
unsigned i; unsigned i;
if (SCpnt->host->sg_tablesize == SG_NONE) { if (SCpnt->host->sg_tablesize == SG_NONE) {
panic ("wd7000_queuecommand: scatter/gather not supported.\n"); panic("wd7000_queuecommand: scatter/gather not supported.\n");
} }
dprintk ("Using scatter/gather with %d elements.\n", SCpnt->use_sg); dprintk("Using scatter/gather with %d elements.\n", SCpnt->use_sg);
sgb = scb->sgb; sgb = scb->sgb;
scb->op = 1; scb->op = 1;
any2scsi (scb->dataptr, (int) sgb); any2scsi(scb->dataptr, (int) sgb);
any2scsi (scb->maxlen, SCpnt->use_sg * sizeof (Sgb)); any2scsi(scb->maxlen, SCpnt->use_sg * sizeof(Sgb));
for (i = 0; i < SCpnt->use_sg; i++) { for (i = 0; i < SCpnt->use_sg; i++) {
any2scsi (sgb[i].ptr, any2scsi(sgb[i].ptr, isa_page_to_bus(sg[i].page) + sg[i].offset);
isa_page_to_bus(sg[i].page) + sg[i].offset); any2scsi(sgb[i].len, sg[i].length);
any2scsi (sgb[i].len, sg[i].length); }
} else {
scb->op = 0;
any2scsi(scb->dataptr, isa_virt_to_bus(SCpnt->request_buffer));
any2scsi(scb->maxlen, SCpnt->request_bufflen);
} }
}
else { /* FIXME: drop lock and yield here ? */
scb->op = 0;
any2scsi (scb->dataptr, isa_virt_to_bus(SCpnt->request_buffer)); while (!mail_out(host, scb))
any2scsi (scb->maxlen, SCpnt->request_bufflen); cpu_relax(); /* keep trying */
}
return 0;
/* FIXME: drop lock and yield here ? */
while (!mail_out (host, scb))
cpu_relax(); /* keep trying */
return 0;
} }
static int wd7000_command (Scsi_Cmnd *SCpnt) static int wd7000_command(Scsi_Cmnd * SCpnt)
{ {
wd7000_queuecommand (SCpnt, wd7000_scsi_done); wd7000_queuecommand(SCpnt, wd7000_scsi_done);
while (SCpnt->SCp.phase > 0) while (SCpnt->SCp.phase > 0) {
{ cpu_relax();
cpu_relax(); barrier(); /* phase counts scbs down to 0 */
barrier(); /* phase counts scbs down to 0 */ }
}
return (SCpnt->result); return (SCpnt->result);
} }
static int wd7000_diagnostics (Adapter *host, int code) static int wd7000_diagnostics(Adapter * host, int code)
{ {
static IcbDiag icb = {ICB_OP_DIAGNOSTICS}; static IcbDiag icb = { ICB_OP_DIAGNOSTICS };
static unchar buf[256]; static unchar buf[256];
unsigned long timeout; unsigned long timeout;
icb.type = code; icb.type = code;
any2scsi (icb.len, sizeof (buf)); any2scsi(icb.len, sizeof(buf));
any2scsi (icb.ptr, (int) &buf); any2scsi(icb.ptr, (int) &buf);
icb.phase = 1; icb.phase = 1;
/* /*
* This routine is only called at init, so there should be OGMBs * This routine is only called at init, so there should be OGMBs
* available. I'm assuming so here. If this is going to * available. I'm assuming so here. If this is going to
* fail, I can just let the timeout catch the failure. * fail, I can just let the timeout catch the failure.
*/ */
mail_out (host, (struct scb *) &icb); mail_out(host, (struct scb *) &icb);
timeout = jiffies + WAITnexttimeout; /* wait up to 2 seconds */ timeout = jiffies + WAITnexttimeout; /* wait up to 2 seconds */
while (icb.phase && time_before(jiffies, timeout)) while (icb.phase && time_before(jiffies, timeout)) {
{ cpu_relax(); /* wait for completion */
cpu_relax(); /* wait for completion */ barrier();
barrier(); }
}
if (icb.phase) {
if (icb.phase) { printk("wd7000_diagnostics: timed out.\n");
printk ("wd7000_diagnostics: timed out.\n"); return (0);
return (0); }
} if (make_code(icb.vue | (icb.status << 8), 0)) {
if (make_code (icb.vue | (icb.status << 8), 0)) { printk("wd7000_diagnostics: failed (0x%02x,0x%02x)\n", icb.vue, icb.status);
printk ("wd7000_diagnostics: failed (0x%02x,0x%02x)\n", return (0);
icb.vue, icb.status); }
return (0);
}
return (1); return (1);
} }
static int wd7000_adapter_reset(Adapter *host) static int wd7000_adapter_reset(Adapter * host)
{ {
InitCmd init_cmd = InitCmd init_cmd = {
{ INITIALIZATION,
INITIALIZATION, 7,
7, host->bus_on,
host->bus_on, host->bus_off,
host->bus_off, 0,
0, {0, 0, 0},
{ 0, 0, 0 }, OGMB_CNT,
OGMB_CNT, ICMB_CNT
ICMB_CNT };
}; int diag;
int diag; /*
/* * Reset the adapter - only. The SCSI bus was initialized at power-up,
* Reset the adapter - only. The SCSI bus was initialized at power-up, * and we need to do this just so we control the mailboxes, etc.
* and we need to do this just so we control the mailboxes, etc. */
*/ outb(ASC_RES, host->iobase + ASC_CONTROL);
outb (ASC_RES, host->iobase + ASC_CONTROL); udelay(40); /* reset pulse: this is 40us, only need 25us */
udelay(40); /* reset pulse: this is 40us, only need 25us */ outb(0, host->iobase + ASC_CONTROL);
outb (0, host->iobase + ASC_CONTROL); host->control = 0; /* this must always shadow ASC_CONTROL */
host->control = 0; /* this must always shadow ASC_CONTROL */
if (WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) {
if (WAIT (host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { printk("wd7000_init: WAIT timed out.\n");
printk ("wd7000_init: WAIT timed out.\n"); return -1; /* -1 = not ok */
return -1; /* -1 = not ok */ }
}
if ((diag = inb(host->iobase + ASC_INTR_STAT)) != 1) {
if ((diag = inb (host->iobase + ASC_INTR_STAT)) != 1) { printk("wd7000_init: ");
printk ("wd7000_init: ");
switch (diag) {
switch (diag) { case 2:
case 2: printk ("RAM failure.\n"); printk("RAM failure.\n");
break; break;
case 3: printk ("FIFO R/W failed\n"); case 3:
break; printk("FIFO R/W failed\n");
case 4: printk ("SBIC register R/W failed\n"); break;
break; case 4:
case 5: printk ("Initialization D-FF failed.\n"); printk("SBIC register R/W failed\n");
break; break;
case 6: printk ("Host IRQ D-FF failed.\n"); case 5:
break; printk("Initialization D-FF failed.\n");
case 7: printk ("ROM checksum error.\n"); break;
break; case 6:
default: printk ("diagnostic code 0x%02Xh received.\n", diag); printk("Host IRQ D-FF failed.\n");
break;
case 7:
printk("ROM checksum error.\n");
break;
default:
printk("diagnostic code 0x%02Xh received.\n", diag);
}
return -1;
}
/* Clear mailboxes */
memset(&(host->mb), 0, sizeof(host->mb));
/* Execute init command */
any2scsi((unchar *) & (init_cmd.mailboxes), (int) &(host->mb));
if (!command_out(host, (unchar *) & init_cmd, sizeof(init_cmd))) {
printk(KERN_ERR "wd7000_adapter_reset: adapter initialization failed.\n");
return -1;
}
if (WAIT(host->iobase + ASC_STAT, ASC_STATMASK, ASC_INIT, 0)) {
printk("wd7000_adapter_reset: WAIT timed out.\n");
return -1;
} }
return -1; return 0;
}
/* Clear mailboxes */
memset (&(host->mb), 0, sizeof (host->mb));
/* Execute init command */
any2scsi ((unchar *) & (init_cmd.mailboxes), (int) &(host->mb));
if (!command_out (host, (unchar *) &init_cmd, sizeof (init_cmd))) {
printk (KERN_ERR "wd7000_adapter_reset: adapter initialization failed.\n");
return -1;
}
if (WAIT (host->iobase + ASC_STAT, ASC_STATMASK, ASC_INIT, 0)) {
printk ("wd7000_adapter_reset: WAIT timed out.\n");
return -1;
}
return 0;
} }
static int wd7000_init (Adapter *host) static int wd7000_init(Adapter * host)
{ {
if(wd7000_adapter_reset(host) == -1) if (wd7000_adapter_reset(host) == -1)
return 0; return 0;
if (request_irq (host->irq, do_wd7000_intr_handle, SA_INTERRUPT, "wd7000", host)) {
printk ("wd7000_init: can't get IRQ %d.\n", host->irq);
return (0);
}
if (request_dma (host->dma, "wd7000")) {
printk ("wd7000_init: can't get DMA channel %d.\n", host->dma);
free_irq (host->irq, host);
return (0);
}
wd7000_enable_dma (host);
wd7000_enable_intr (host);
if (!wd7000_diagnostics (host, ICB_DIAG_FULL)) { if (request_irq(host->irq, do_wd7000_intr_handle, SA_INTERRUPT, "wd7000", host)) {
free_dma (host->dma); printk("wd7000_init: can't get IRQ %d.\n", host->irq);
free_irq (host->irq, NULL); return (0);
return (0); }
} if (request_dma(host->dma, "wd7000")) {
printk("wd7000_init: can't get DMA channel %d.\n", host->dma);
free_irq(host->irq, host);
return (0);
}
wd7000_enable_dma(host);
wd7000_enable_intr(host);
return (1); if (!wd7000_diagnostics(host, ICB_DIAG_FULL)) {
free_dma(host->dma);
free_irq(host->irq, NULL);
return (0);
}
return (1);
} }
static void wd7000_revision (Adapter *host) static void wd7000_revision(Adapter * host)
{ {
static IcbRevLvl icb = static IcbRevLvl icb = { ICB_OP_GET_REVISION };
{ICB_OP_GET_REVISION};
icb.phase = 1;
icb.phase = 1; /*
/* * Like diagnostics, this is only done at init time, in fact, from
* Like diagnostics, this is only done at init time, in fact, from * wd7000_detect, so there should be OGMBs available. If it fails,
* wd7000_detect, so there should be OGMBs available. If it fails, * the only damage will be that the revision will show up as 0.0,
* the only damage will be that the revision will show up as 0.0, * which in turn means that scatter/gather will be disabled.
* which in turn means that scatter/gather will be disabled. */
*/ mail_out(host, (struct scb *) &icb);
mail_out (host, (struct scb *) &icb); while (icb.phase) {
while (icb.phase) cpu_relax(); /* wait for completion */
{ barrier();
cpu_relax(); /* wait for completion */ }
barrier(); host->rev1 = icb.primary;
} host->rev2 = icb.secondary;
host->rev1 = icb.primary;
host->rev2 = icb.secondary;
} }
#undef SPRINTF #undef SPRINTF
#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); } #define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
static int wd7000_set_info (char *buffer, int length, struct Scsi_Host *host) static int wd7000_set_info(char *buffer, int length, struct Scsi_Host *host)
{ {
dprintk("Buffer = <%.*s>, length = %d\n", length, buffer, length); dprintk("Buffer = <%.*s>, length = %d\n", length, buffer, length);
/* /*
* Currently this is a no-op * Currently this is a no-op
*/ */
dprintk("Sorry, this function is currently out of order...\n"); dprintk("Sorry, this function is currently out of order...\n");
return (length); return (length);
} }
static int wd7000_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout) static int wd7000_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout)
{ {
struct Scsi_Host *host = NULL; struct Scsi_Host *host = NULL;
Scsi_Device *scd; Scsi_Device *scd;
Adapter *adapter; Adapter *adapter;
unsigned long flags; unsigned long flags;
char *pos = buffer; char *pos = buffer;
short i; short i;
#ifdef WD7000_DEBUG #ifdef WD7000_DEBUG
Mailbox *ogmbs, *icmbs; Mailbox *ogmbs, *icmbs;
short count; short count;
#endif #endif
/* /*
* Find the specified host board. * Find the specified host board.
*/ */
for (i = 0; i < UNITS; i++) for (i = 0; i < UNITS; i++)
if (wd7000_host[i] && (wd7000_host[i]->host_no == hostno)) { if (wd7000_host[i] && (wd7000_host[i]->host_no == hostno)) {
host = wd7000_host[i]; host = wd7000_host[i];
break; break;
} }
/* /*
* Host not found! * Host not found!
*/ */
if (! host) if (!host)
return (-ESRCH); return (-ESRCH);
/* /*
* Has data been written to the file ? * Has data been written to the file ?
*/ */
if (inout) if (inout)
return (wd7000_set_info (buffer, length, host)); return (wd7000_set_info(buffer, length, host));
adapter = (Adapter *) host->hostdata; adapter = (Adapter *) host->hostdata;
spin_lock_irqsave(host->host_lock, flags); spin_lock_irqsave(host->host_lock, flags);
SPRINTF ("Host scsi%d: Western Digital WD-7000 (rev %d.%d)\n", hostno, adapter->rev1, adapter->rev2); SPRINTF("Host scsi%d: Western Digital WD-7000 (rev %d.%d)\n", hostno, adapter->rev1, adapter->rev2);
SPRINTF (" IO base: 0x%x\n", adapter->iobase); SPRINTF(" IO base: 0x%x\n", adapter->iobase);
SPRINTF (" IRQ: %d\n", adapter->irq); SPRINTF(" IRQ: %d\n", adapter->irq);
SPRINTF (" DMA channel: %d\n", adapter->dma); SPRINTF(" DMA channel: %d\n", adapter->dma);
SPRINTF (" Interrupts: %d\n", adapter->int_counter); SPRINTF(" Interrupts: %d\n", adapter->int_counter);
SPRINTF (" BUS_ON time: %d nanoseconds\n", adapter->bus_on * 125); SPRINTF(" BUS_ON time: %d nanoseconds\n", adapter->bus_on * 125);
SPRINTF (" BUS_OFF time: %d nanoseconds\n", adapter->bus_off * 125); SPRINTF(" BUS_OFF time: %d nanoseconds\n", adapter->bus_off * 125);
#ifdef WD7000_DEBUG #ifdef WD7000_DEBUG
ogmbs = adapter->mb.ogmb; ogmbs = adapter->mb.ogmb;
icmbs = adapter->mb.icmb; icmbs = adapter->mb.icmb;
SPRINTF ("\nControl port value: 0x%x\n", adapter->control); SPRINTF("\nControl port value: 0x%x\n", adapter->control);
SPRINTF ("Incoming mailbox:\n"); SPRINTF("Incoming mailbox:\n");
SPRINTF (" size: %d\n", ICMB_CNT); SPRINTF(" size: %d\n", ICMB_CNT);
SPRINTF (" queued messages: "); SPRINTF(" queued messages: ");
for (i = count = 0; i < ICMB_CNT; i++) for (i = count = 0; i < ICMB_CNT; i++)
if (icmbs[i].status) { if (icmbs[i].status) {
count++; count++;
SPRINTF ("0x%x ", i); SPRINTF("0x%x ", i);
} }
SPRINTF (count ? "\n" : "none\n"); SPRINTF(count ? "\n" : "none\n");
SPRINTF ("Outgoing mailbox:\n"); SPRINTF("Outgoing mailbox:\n");
SPRINTF (" size: %d\n", OGMB_CNT); SPRINTF(" size: %d\n", OGMB_CNT);
SPRINTF (" next message: 0x%x\n", adapter->next_ogmb); SPRINTF(" next message: 0x%x\n", adapter->next_ogmb);
SPRINTF (" queued messages: "); SPRINTF(" queued messages: ");
for (i = count = 0; i < OGMB_CNT; i++) for (i = count = 0; i < OGMB_CNT; i++)
if (ogmbs[i].status) { if (ogmbs[i].status) {
count++; count++;
SPRINTF ("0x%x ", i); SPRINTF("0x%x ", i);
} }
SPRINTF (count ? "\n" : "none\n"); SPRINTF(count ? "\n" : "none\n");
#endif #endif
/* /*
* Display driver information for each device attached to the board. * Display driver information for each device attached to the board.
*/ */
scd = host->host_queue; scd = host->host_queue;
SPRINTF ("\nAttached devices: %s\n", scd ? "" : "none");
for ( ; scd; scd = scd->next)
if (scd->host->host_no == hostno) {
SPRINTF (" [Channel: %02d, Id: %02d, Lun: %02d] ",
scd->channel, scd->id, scd->lun);
SPRINTF ("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ?
scsi_device_types[(short) scd->type] : "Unknown device");
for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++)
SPRINTF ("%c", scd->vendor[i]);
SPRINTF (" ");
for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++)
SPRINTF ("%c", scd->model[i]);
SPRINTF ("\n");
}
SPRINTF ("\n"); SPRINTF("\nAttached devices: %s\n", scd ? "" : "none");
spin_unlock_irqrestore(host->host_lock, flags); for (; scd; scd = scd->next)
if (scd->host->host_no == hostno) {
SPRINTF(" [Channel: %02d, Id: %02d, Lun: %02d] ", scd->channel, scd->id, scd->lun);
SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(short) scd->type] : "Unknown device");
/* for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++)
* Calculate start of next buffer, and return value. SPRINTF("%c", scd->vendor[i]);
*/ SPRINTF(" ");
*start = buffer + offset;
if ((pos - buffer) < offset) for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++)
return (0); SPRINTF("%c", scd->model[i]);
else if ((pos - buffer - offset) < length) SPRINTF("\n");
return (pos - buffer - offset); }
else
return (length); SPRINTF("\n");
spin_unlock_irqrestore(host->host_lock, flags);
/*
* Calculate start of next buffer, and return value.
*/
*start = buffer + offset;
if ((pos - buffer) < offset)
return (0);
else if ((pos - buffer - offset) < length)
return (pos - buffer - offset);
else
return (length);
} }
...@@ -1514,191 +1481,181 @@ static int wd7000_proc_info (char *buffer, char **start, off_t offset, int lengt ...@@ -1514,191 +1481,181 @@ static int wd7000_proc_info (char *buffer, char **start, off_t offset, int lengt
* *
*/ */
static int wd7000_detect (Scsi_Host_Template *tpnt) static int wd7000_detect(Scsi_Host_Template * tpnt)
{ {
short present = 0, biosaddr_ptr, sig_ptr, i, pass; short present = 0, biosaddr_ptr, sig_ptr, i, pass;
short biosptr[NUM_CONFIGS]; short biosptr[NUM_CONFIGS];
unsigned iobase; unsigned iobase;
Adapter *host = NULL; Adapter *host = NULL;
struct Scsi_Host *sh; struct Scsi_Host *sh;
int unit = 0; int unit = 0;
dprintk("wd7000_detect: started\n"); dprintk("wd7000_detect: started\n");
#ifdef MODULE #ifdef MODULE
if (wd7000) if (wd7000)
wd7000_setup(wd7000); wd7000_setup(wd7000);
#endif #endif
for (i = 0; i < UNITS; wd7000_host[i++] = NULL) ; for (i = 0; i < UNITS; wd7000_host[i++] = NULL);
for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1) ; for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1);
tpnt->proc_name = "wd7000";
tpnt->proc_info = &wd7000_proc_info;
/* tpnt->proc_name = "wd7000";
* Set up SCB free list, which is shared by all adapters tpnt->proc_info = &wd7000_proc_info;
*/
init_scbs ();
for (pass = 0; pass < NUM_CONFIGS; pass++) {
/* /*
* First, search for BIOS SIGNATURE... * Set up SCB free list, which is shared by all adapters
*/ */
for (biosaddr_ptr = 0; biosaddr_ptr < NUM_ADDRS; biosaddr_ptr++) init_scbs();
for (sig_ptr = 0; sig_ptr < NUM_SIGNATURES; sig_ptr++) {
for (i = 0; i < pass; i++)
if (biosptr[i] == biosaddr_ptr)
break;
if (i == pass) {
void *biosaddr = ioremap (wd7000_biosaddr[biosaddr_ptr] +
signatures[sig_ptr].ofs,
signatures[sig_ptr].len);
short bios_match=0;
if(biosaddr)
bios_match = memcmp ((char *) biosaddr, signatures[sig_ptr].sig,
signatures[sig_ptr].len);
iounmap (biosaddr);
if (! bios_match)
goto bios_matched;
}
}
bios_matched:
/*
* BIOS SIGNATURE has been found.
*/
#ifdef WD7000_DEBUG
dprintk("wd7000_detect: pass %d\n", pass + 1);
if (biosaddr_ptr == NUM_ADDRS) for (pass = 0; pass < NUM_CONFIGS; pass++) {
dprintk("WD-7000 SST BIOS not detected...\n"); /*
else * First, search for BIOS SIGNATURE...
dprintk("WD-7000 SST BIOS detected at 0x%lx: checking...\n", */
wd7000_biosaddr[biosaddr_ptr]); for (biosaddr_ptr = 0; biosaddr_ptr < NUM_ADDRS; biosaddr_ptr++)
#endif for (sig_ptr = 0; sig_ptr < NUM_SIGNATURES; sig_ptr++) {
for (i = 0; i < pass; i++)
if (configs[pass].irq < 0) if (biosptr[i] == biosaddr_ptr)
continue; break;
if (unit == UNITS)
continue;
iobase = configs[pass].iobase;
dprintk("wd7000_detect: check IO 0x%x region...\n", iobase); if (i == pass) {
void *biosaddr = ioremap(wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs,
signatures[sig_ptr].len);
short bios_match = 0;
if (request_region (iobase, 4, "wd7000")) { if (biosaddr)
bios_match = memcmp((char *) biosaddr, signatures[sig_ptr].sig, signatures[sig_ptr].len);
dprintk("wd7000_detect: ASC reset (IO 0x%x) ...", iobase); iounmap(biosaddr);
/*
* ASC reset...
*/
outb (ASC_RES, iobase + ASC_CONTROL);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/100);
outb (0, iobase + ASC_CONTROL);
if (WAIT (iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { if (!bios_match)
dprintk("failed!\n"); goto bios_matched;
goto err_release; }
} else }
dprintk("ok!\n");
if (inb (iobase + ASC_INTR_STAT) == 1) { bios_matched:
/* /*
* We register here, to get a pointer to the extra space, * BIOS SIGNATURE has been found.
* which we'll use as the Adapter structure (host) for
* this adapter. It is located just after the registered
* Scsi_Host structure (sh), and is located by the empty
* array hostdata.
*/ */
sh = scsi_register (tpnt, sizeof (Adapter)); #ifdef WD7000_DEBUG
if(sh==NULL) dprintk("wd7000_detect: pass %d\n", pass + 1);
goto err_release;
host = (Adapter *) sh->hostdata;
dprintk("wd7000_detect: adapter allocated at 0x%x\n",
(int)host);
memset (host, 0, sizeof (Adapter));
host->irq = configs[pass].irq; if (biosaddr_ptr == NUM_ADDRS)
host->dma = configs[pass].dma; dprintk("WD-7000 SST BIOS not detected...\n");
host->iobase = iobase; else
host->int_counter = 0; dprintk("WD-7000 SST BIOS detected at 0x%lx: checking...\n", wd7000_biosaddr[biosaddr_ptr]);
host->bus_on = configs[pass].bus_on; #endif
host->bus_off = configs[pass].bus_off;
host->sh = wd7000_host[unit] = sh;
unit++;
dprintk("wd7000_detect: Trying init WD-7000 card at IO " if (configs[pass].irq < 0)
"0x%x, IRQ %d, DMA %d...\n", continue;
host->iobase, host->irq, host->dma);
if (!wd7000_init (host)) /* Initialization failed */ if (unit == UNITS)
goto err_unregister; continue;
/* iobase = configs[pass].iobase;
* OK from here - we'll use this adapter/configuration.
*/
wd7000_revision (host); /* important for scatter/gather */
/* dprintk("wd7000_detect: check IO 0x%x region...\n", iobase);
* For boards before rev 6.0, scatter/gather isn't supported.
*/
if (host->rev1 < 6)
sh->sg_tablesize = SG_NONE;
present++; /* count it */ if (request_region(iobase, 4, "wd7000")) {
if (biosaddr_ptr != NUM_ADDRS) dprintk("wd7000_detect: ASC reset (IO 0x%x) ...", iobase);
biosptr[pass] = biosaddr_ptr; /*
* ASC reset...
*/
outb(ASC_RES, iobase + ASC_CONTROL);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ / 100);
outb(0, iobase + ASC_CONTROL);
printk (KERN_INFO "Western Digital WD-7000 (rev %d.%d) ", if (WAIT(iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) {
host->rev1, host->rev2); dprintk("failed!\n");
printk ("using IO 0x%x, IRQ %d, DMA %d.\n", goto err_release;
host->iobase, host->irq, host->dma); } else
printk (" BUS_ON time: %dns, BUS_OFF time: %dns\n", dprintk("ok!\n");
host->bus_on * 125, host->bus_off * 125);
} if (inb(iobase + ASC_INTR_STAT) == 1) {
} else /*
dprintk("wd7000_detect: IO 0x%x region already allocated!\n", * We register here, to get a pointer to the extra space,
iobase); * which we'll use as the Adapter structure (host) for
* this adapter. It is located just after the registered
* Scsi_Host structure (sh), and is located by the empty
* array hostdata.
*/
sh = scsi_register(tpnt, sizeof(Adapter));
if (sh == NULL)
goto err_release;
host = (Adapter *) sh->hostdata;
dprintk("wd7000_detect: adapter allocated at 0x%x\n", (int) host);
memset(host, 0, sizeof(Adapter));
host->irq = configs[pass].irq;
host->dma = configs[pass].dma;
host->iobase = iobase;
host->int_counter = 0;
host->bus_on = configs[pass].bus_on;
host->bus_off = configs[pass].bus_off;
host->sh = wd7000_host[unit] = sh;
unit++;
dprintk("wd7000_detect: Trying init WD-7000 card at IO " "0x%x, IRQ %d, DMA %d...\n", host->iobase, host->irq, host->dma);
if (!wd7000_init(host)) /* Initialization failed */
goto err_unregister;
/*
* OK from here - we'll use this adapter/configuration.
*/
wd7000_revision(host); /* important for scatter/gather */
/*
* For boards before rev 6.0, scatter/gather isn't supported.
*/
if (host->rev1 < 6)
sh->sg_tablesize = SG_NONE;
present++; /* count it */
if (biosaddr_ptr != NUM_ADDRS)
biosptr[pass] = biosaddr_ptr;
printk(KERN_INFO "Western Digital WD-7000 (rev %d.%d) ", host->rev1, host->rev2);
printk("using IO 0x%x, IRQ %d, DMA %d.\n", host->iobase, host->irq, host->dma);
printk(" BUS_ON time: %dns, BUS_OFF time: %dns\n", host->bus_on * 125, host->bus_off * 125);
}
} else
dprintk("wd7000_detect: IO 0x%x region already allocated!\n", iobase);
continue; continue;
err_unregister: err_unregister:
scsi_unregister (sh); scsi_unregister(sh);
err_release: err_release:
release_region(iobase, 4); release_region(iobase, 4);
} }
if (!present) if (!present)
printk ("Failed initialization of WD-7000 SCSI card!\n"); printk("Failed initialization of WD-7000 SCSI card!\n");
return (present); return (present);
} }
/* /*
* I have absolutely NO idea how to do an abort with the WD7000... * I have absolutely NO idea how to do an abort with the WD7000...
*/ */
static int wd7000_abort (Scsi_Cmnd *SCpnt) static int wd7000_abort(Scsi_Cmnd * SCpnt)
{ {
Adapter *host = (Adapter *) SCpnt->host->hostdata; Adapter *host = (Adapter *) SCpnt->host->hostdata;
if (inb (host->iobase + ASC_STAT) & INT_IM) { if (inb(host->iobase + ASC_STAT) & INT_IM) {
printk ("wd7000_abort: lost interrupt\n"); printk("wd7000_abort: lost interrupt\n");
wd7000_intr_handle (host->irq, NULL, NULL); wd7000_intr_handle(host->irq, NULL, NULL);
return FAILED;
}
return FAILED; return FAILED;
}
return FAILED;
} }
...@@ -1706,28 +1663,28 @@ static int wd7000_abort (Scsi_Cmnd *SCpnt) ...@@ -1706,28 +1663,28 @@ static int wd7000_abort (Scsi_Cmnd *SCpnt)
* I also have no idea how to do a reset... * I also have no idea how to do a reset...
*/ */
static int wd7000_bus_reset (Scsi_Cmnd *SCpnt) static int wd7000_bus_reset(Scsi_Cmnd * SCpnt)
{ {
return FAILED; return FAILED;
} }
static int wd7000_device_reset (Scsi_Cmnd *SCpnt) static int wd7000_device_reset(Scsi_Cmnd * SCpnt)
{ {
return FAILED; return FAILED;
} }
/* /*
* Last resort. Reinitialize the board. * Last resort. Reinitialize the board.
*/ */
static int wd7000_host_reset (Scsi_Cmnd *SCpnt) static int wd7000_host_reset(Scsi_Cmnd * SCpnt)
{ {
Adapter *host = (Adapter *) SCpnt->host->hostdata; Adapter *host = (Adapter *) SCpnt->host->hostdata;
if(wd7000_adapter_reset(host)<0) if (wd7000_adapter_reset(host) < 0)
return FAILED; return FAILED;
wd7000_enable_intr (host); wd7000_enable_intr(host);
return SUCCESS; return SUCCESS;
} }
...@@ -1735,52 +1692,46 @@ static int wd7000_host_reset (Scsi_Cmnd *SCpnt) ...@@ -1735,52 +1692,46 @@ static int wd7000_host_reset (Scsi_Cmnd *SCpnt)
* This was borrowed directly from aha1542.c. (Zaga) * This was borrowed directly from aha1542.c. (Zaga)
*/ */
static int wd7000_biosparam (Disk *disk, struct block_device *bdev, int *ip) static int wd7000_biosparam(Disk * disk, struct block_device *bdev, int *ip)
{ {
dprintk("wd7000_biosparam: dev=%s, size=%d, ", bdevname(bdev), dprintk("wd7000_biosparam: dev=%s, size=%d, ", bdevname(bdev), disk->capacity);
disk->capacity);
/*
* try default translation
*/
ip[0] = 64;
ip[1] = 32;
ip[2] = disk->capacity >> 11;
/*
* for disks >1GB do some guessing
*/
if (ip[2] >= 1024) {
int info[3];
/* /*
* try to figure out the geometry from the partition table * try default translation
*/ */
if ((scsicam_bios_param (disk, bdev, info) < 0) || ip[0] = 64;
!(((info[0] == 64) && (info[1] == 32)) || ip[1] = 32;
((info[0] == 255) && (info[1] == 63)))) { ip[2] = disk->capacity >> 11;
printk ("wd7000_biosparam: unable to verify geometry for disk with >1GB.\n"
" using extended translation.\n"); /*
* for disks >1GB do some guessing
ip[0] = 255; */
ip[1] = 63; if (ip[2] >= 1024) {
ip[2] = (unsigned long)disk->capacity / (255 * 63); int info[3];
}
else { /*
ip[0] = info[0]; * try to figure out the geometry from the partition table
ip[1] = info[1]; */
ip[2] = info[2]; if ((scsicam_bios_param(disk, bdev, info) < 0) || !(((info[0] == 64) && (info[1] == 32)) || ((info[0] == 255) && (info[1] == 63)))) {
printk("wd7000_biosparam: unable to verify geometry for disk with >1GB.\n" " using extended translation.\n");
if (info[0] == 255)
printk(KERN_INFO "%s: current partition table is " ip[0] = 255;
"using extended translation.\n", __FUNCTION__); ip[1] = 63;
ip[2] = (unsigned long) disk->capacity / (255 * 63);
} else {
ip[0] = info[0];
ip[1] = info[1];
ip[2] = info[2];
if (info[0] == 255)
printk(KERN_INFO "%s: current partition table is " "using extended translation.\n", __FUNCTION__);
}
} }
}
dprintk("bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]); dprintk("bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]);
dprintk("WARNING: check, if the bios geometry is correct.\n"); dprintk("WARNING: check, if the bios geometry is correct.\n");
return (0); return (0);
} }
MODULE_AUTHOR("Thomas Wuensche, John Boyd, Miroslav Zagorac"); MODULE_AUTHOR("Thomas Wuensche, John Boyd, Miroslav Zagorac");
......
...@@ -13,16 +13,16 @@ ...@@ -13,16 +13,16 @@
#include <linux/types.h> #include <linux/types.h>
static int wd7000_set_info (char *buffer, int length, struct Scsi_Host *host); static int wd7000_set_info(char *buffer, int length, struct Scsi_Host *host);
static int wd7000_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout); static int wd7000_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout);
static int wd7000_detect (Scsi_Host_Template *); static int wd7000_detect(Scsi_Host_Template *);
static int wd7000_command (Scsi_Cmnd *); static int wd7000_command(Scsi_Cmnd *);
static int wd7000_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int wd7000_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int wd7000_abort (Scsi_Cmnd *); static int wd7000_abort(Scsi_Cmnd *);
static int wd7000_bus_reset (Scsi_Cmnd *); static int wd7000_bus_reset(Scsi_Cmnd *);
static int wd7000_host_reset (Scsi_Cmnd *); static int wd7000_host_reset(Scsi_Cmnd *);
static int wd7000_device_reset (Scsi_Cmnd *); static int wd7000_device_reset(Scsi_Cmnd *);
static int wd7000_biosparam (Disk *, struct block_device *, int *); static int wd7000_biosparam(Disk *, struct block_device *, int *);
#ifndef NULL #ifndef NULL
#define NULL 0L #define NULL 0L
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
#define PAL_wrperfmon 57 #define PAL_wrperfmon 57
#define PAL_rdusp 58 #define PAL_rdusp 58
#define PAL_whami 60 #define PAL_whami 60
#define PAL_rtsys 61 #define PAL_retsys 61
#define PAL_rti 63 #define PAL_rti 63
#endif /* __ALPHA_PAL_H */ #endif /* __ALPHA_PAL_H */
...@@ -331,19 +331,19 @@ ...@@ -331,19 +331,19 @@
#define __NR_removexattr 391 #define __NR_removexattr 391
#define __NR_lremovexattr 392 #define __NR_lremovexattr 392
#define __NR_fremovexattr 393 #define __NR_fremovexattr 393
#define __NR_futex 394 #define __NR_futex 394
#define __NR_sched_setaffinity 395 #define __NR_sched_setaffinity 395
#define __NR_sched_getaffinity 396 #define __NR_sched_getaffinity 396
#define __NR_tuxcall 397 #define __NR_tuxcall 397
#define __NR_io_setup 398 #define __NR_io_setup 398
#define __NR_io_destroy 399 #define __NR_io_destroy 399
#define __NR_io_getevents 400 #define __NR_io_getevents 400
#define __NR_io_submit 401 #define __NR_io_submit 401
#define __NR_io_cancel 402 #define __NR_io_cancel 402
#define __NR_alloc_hugepages 403 #define __NR_alloc_hugepages 403
#define __NR_free_hugepages 404 #define __NR_free_hugepages 404
#define __NR_exit_group 405 #define __NR_exit_group 405
#define NR_SYSCALLS 406
#if defined(__GNUC__) #if defined(__GNUC__)
...@@ -598,7 +598,7 @@ static inline pid_t waitpid(int pid, int * wait_stat, int flags) ...@@ -598,7 +598,7 @@ static inline pid_t waitpid(int pid, int * wait_stat, int flags)
return sys_wait4(pid, wait_stat, flags, NULL); return sys_wait4(pid, wait_stat, flags, NULL);
} }
#endif #endif /* __KERNEL_SYSCALLS__ */
/* /*
* "Conditional" syscalls * "Conditional" syscalls
......
...@@ -91,7 +91,7 @@ typedef struct siginfo { ...@@ -91,7 +91,7 @@ typedef struct siginfo {
#define __SI_FAULT (3 << 16) #define __SI_FAULT (3 << 16)
#define __SI_CHLD (4 << 16) #define __SI_CHLD (4 << 16)
#define __SI_RT (5 << 16) #define __SI_RT (5 << 16)
#define __SI_CODE(T,N) ((T) << 16 | ((N) & 0xffff)) #define __SI_CODE(T,N) ((T) | ((N) & 0xffff))
#else #else
#define __SI_KILL 0 #define __SI_KILL 0
#define __SI_TIMER 0 #define __SI_TIMER 0
......
...@@ -794,6 +794,7 @@ typedef struct ide_drive_s { ...@@ -794,6 +794,7 @@ typedef struct ide_drive_s {
int lun; /* logical unit */ int lun; /* logical unit */
int crc_count; /* crc counter to reduce drive speed */ int crc_count; /* crc counter to reduce drive speed */
struct list_head list; struct list_head list;
struct device gendev;
struct gendisk *disk; struct gendisk *disk;
} ide_drive_t; } ide_drive_t;
...@@ -1199,6 +1200,7 @@ typedef struct ide_driver_s { ...@@ -1199,6 +1200,7 @@ typedef struct ide_driver_s {
int (*attach)(ide_drive_t *); int (*attach)(ide_drive_t *);
void (*ata_prebuilder)(ide_drive_t *); void (*ata_prebuilder)(ide_drive_t *);
void (*atapi_prebuilder)(ide_drive_t *); void (*atapi_prebuilder)(ide_drive_t *);
struct device_driver gen_driver;
struct list_head drives; struct list_head drives;
struct list_head drivers; struct list_head drivers;
} ide_driver_t; } ide_driver_t;
......
...@@ -798,10 +798,18 @@ asmlinkage unsigned long sys_alarm(unsigned int seconds) ...@@ -798,10 +798,18 @@ asmlinkage unsigned long sys_alarm(unsigned int seconds)
* The Alpha uses getxpid, getxuid, and getxgid instead. Maybe this * The Alpha uses getxpid, getxuid, and getxgid instead. Maybe this
* should be moved into arch/i386 instead? * should be moved into arch/i386 instead?
*/ */
/**
* sys_getpid - return the thread group id of the current process
*
* Note, despite the name, this returns the tgid not the pid. The tgid and
* the pid are identical unless CLONE_THREAD was specified on clone() in
* which case the tgid is the same in all threads of the same group.
*
* This is SMP safe as current->tgid does not change.
*/
asmlinkage long sys_getpid(void) asmlinkage long sys_getpid(void)
{ {
/* This is SMP safe - current->pid doesn't change */
return current->tgid; return current->tgid;
} }
......
...@@ -24,8 +24,9 @@ void __br_write_lock (enum brlock_indices idx) ...@@ -24,8 +24,9 @@ void __br_write_lock (enum brlock_indices idx)
{ {
int i; int i;
preempt_disable();
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
write_lock(&__brlock_array[i][idx]); _raw_write_lock(&__brlock_array[i][idx]);
} }
void __br_write_unlock (enum brlock_indices idx) void __br_write_unlock (enum brlock_indices idx)
...@@ -33,7 +34,8 @@ void __br_write_unlock (enum brlock_indices idx) ...@@ -33,7 +34,8 @@ void __br_write_unlock (enum brlock_indices idx)
int i; int i;
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
write_unlock(&__brlock_array[i][idx]); _raw_write_unlock(&__brlock_array[i][idx]);
preempt_enable();
} }
#else /* ! __BRLOCK_USE_ATOMICS */ #else /* ! __BRLOCK_USE_ATOMICS */
...@@ -48,11 +50,12 @@ void __br_write_lock (enum brlock_indices idx) ...@@ -48,11 +50,12 @@ void __br_write_lock (enum brlock_indices idx)
{ {
int i; int i;
preempt_disable();
again: again:
spin_lock(&__br_write_locks[idx].lock); _raw_spin_lock(&__br_write_locks[idx].lock);
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
if (__brlock_array[i][idx] != 0) { if (__brlock_array[i][idx] != 0) {
spin_unlock(&__br_write_locks[idx].lock); _raw_spin_unlock(&__br_write_locks[idx].lock);
barrier(); barrier();
cpu_relax(); cpu_relax();
goto again; goto again;
......
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