Commit 491447e1 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] next NCR5380 updates

Fix more locking, do a major rethink on the bh handling (now workqueue)
parent 00a442fa
...@@ -92,12 +92,10 @@ if [ "$CONFIG_MCA" = "y" ]; then ...@@ -92,12 +92,10 @@ if [ "$CONFIG_MCA" = "y" ]; then
dep_tristate 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS $CONFIG_SCSI dep_tristate 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS $CONFIG_SCSI
fi fi
dep_tristate 'Intel/ICP (former GDT SCSI Disk Array) RAID Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI dep_tristate 'Intel/ICP (former GDT SCSI Disk Array) RAID Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI
dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI dep_tristate 'Generic NCR5380/53c400 SCSI PIO support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
dep_tristate 'Generic NCR5380/53c400 SCSI MMIO support' CONFIG_SCSI_GENERIC_NCR5380_MMIO $CONFIG_SCSI
if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then
bool ' Enable NCR53c400 extensions' CONFIG_SCSI_GENERIC_NCR53C400 bool ' Enable NCR53c400 extensions' CONFIG_SCSI_GENERIC_NCR53C400
choice 'NCR5380/53c400 mapping method (use Port for T130B)' \
"Port CONFIG_SCSI_G_NCR5380_PORT \
Memory CONFIG_SCSI_G_NCR5380_MEM" Port
fi fi
if [ "$CONFIG_MCA" = "y" ]; then if [ "$CONFIG_MCA" = "y" ]; then
dep_tristate 'IBMMCA SCSI support' CONFIG_SCSI_IBMMCA $CONFIG_SCSI dep_tristate 'IBMMCA SCSI support' CONFIG_SCSI_IBMMCA $CONFIG_SCSI
......
...@@ -65,6 +65,7 @@ obj-$(CONFIG_SCSI_FD_MCS) += fd_mcs.o ...@@ -65,6 +65,7 @@ obj-$(CONFIG_SCSI_FD_MCS) += fd_mcs.o
obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o
obj-$(CONFIG_SCSI_IN2000) += in2000.o obj-$(CONFIG_SCSI_IN2000) += in2000.o
obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o
obj-$(CONFIG_SCSI_GENERIC_NCR5380_MMIO) += g_NCR5380_mmio.o
obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o
obj-$(CONFIG_SCSI_NCR_D700) += NCR_D700.o 53c700.o obj-$(CONFIG_SCSI_NCR_D700) += NCR_D700.o 53c700.o
obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o
......
#ifndef NDEBUG
#define NDEBUG (NDEBUG_RESTART_SELECT | NDEBUG_ABORT)
#endif
/* /*
* NCR 5380 generic driver routines. These should make it *trivial* * NCR 5380 generic driver routines. These should make it *trivial*
* to implement 5380 SCSI drivers under Linux with a non-trantor * to implement 5380 SCSI drivers under Linux with a non-trantor
...@@ -316,8 +313,8 @@ ...@@ -316,8 +313,8 @@
static int do_abort(struct Scsi_Host *host); static int do_abort(struct Scsi_Host *host);
static void do_reset(struct Scsi_Host *host); static void do_reset(struct Scsi_Host *host);
static struct Scsi_Host *first_instance = NULL; static struct NCR5380_hostdata *first_host = NULL;
static Scsi_Host_Template *the_template = NULL; static struct NCR5380_hostdata *last_host = NULL;
static struct timer_list usleep_timer; static struct timer_list usleep_timer;
/* /*
...@@ -348,7 +345,18 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd) ...@@ -348,7 +345,18 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
} }
} }
#include <linux/delay.h> static struct {
unsigned char value;
const char *name;
} phases[] = {
{PHASE_DATAOUT, "DATAOUT"},
{PHASE_DATAIN, "DATAIN"},
{PHASE_CMDOUT, "CMDOUT"},
{PHASE_STATIN, "STATIN"},
{PHASE_MSGOUT, "MSGOUT"},
{PHASE_MSGIN, "MSGIN"},
{PHASE_UNKNOWN, "UNKNOWN"}
};
#ifdef NDEBUG #ifdef NDEBUG
static struct { static struct {
...@@ -430,18 +438,6 @@ static void NCR5380_print(struct Scsi_Host *instance) ...@@ -430,18 +438,6 @@ static void NCR5380_print(struct Scsi_Host *instance)
printk("\n"); printk("\n");
} }
static struct {
unsigned char value;
const char *name;
} phases[] = {
{PHASE_DATAOUT, "DATAOUT"},
{PHASE_DATAIN, "DATAIN"},
{PHASE_CMDOUT, "CMDOUT"},
{PHASE_STATIN, "STATIN"},
{PHASE_MSGOUT, "MSGOUT"},
{PHASE_MSGIN, "MSGIN"},
{PHASE_UNKNOWN, "UNKNOWN"}
};
/* /*
* NCR5380_print_phase - show SCSI phase * NCR5380_print_phase - show SCSI phase
...@@ -469,44 +465,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) ...@@ -469,44 +465,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
} }
#endif #endif
/*
* We need to have our coroutine active given these constraints :
* 1. The mutex flag, main_running, can only be set when the main
* routine can actually process data, otherwise SCSI commands
* will never get issued.
*
* 2. NCR5380_main() shouldn't be called before it has exited, because
* other drivers have had kernel stack overflows in similar
* situations.
*
* 3. We don't want to inline NCR5380_main() because of space concerns,
* even though it is only called in two places.
*
* So, the solution is to set the mutex in an inline wrapper for the
* main coroutine, and have the main coroutine exit with interrupts
* disabled after the final search through the queues so that no race
* conditions are possible.
*/
static unsigned long main_running = 0;
/*
* Function : run_main(void)
*
* Purpose : insure that the coroutine is running and will process our
* request. main_running is checked/set here (in an inline function)
* rather than in NCR5380_main itself to reduce the chances of stack
* overflow.
* FIXME: NCR5380_main should probably be run with schedule_task or be a
* thread.
*/
static __inline__ void run_main(void)
{
if (!test_and_set_bit(0, &main_running))
NCR5380_main();
}
/* /*
* These need tweaking, and would probably work best as per-device * These need tweaking, and would probably work best as per-device
* flags initialized differently for disk, tape, cd, etc devices. * flags initialized differently for disk, tape, cd, etc devices.
...@@ -621,13 +579,17 @@ static int NCR5380_set_timer(struct Scsi_Host *instance) ...@@ -621,13 +579,17 @@ static int NCR5380_set_timer(struct Scsi_Host *instance)
static void NCR5380_timer_fn(unsigned long unused) static void NCR5380_timer_fn(unsigned long unused)
{ {
struct Scsi_Host *instance; struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&timer_lock, flags); spin_lock_irqsave(&timer_lock, flags);
for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);) { for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);)
instance = ((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer; {
((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer = NULL; hostdata = (struct NCR5380_hostdata *) expires_first->hostdata;
((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires = 0; schedule_work(&hostdata->coroutine);
instance = hostdata->next_timer;
hostdata->next_timer = NULL;
hostdata->time_expires = 0;
expires_first = instance; expires_first = instance;
} }
...@@ -636,10 +598,7 @@ static void NCR5380_timer_fn(unsigned long unused) ...@@ -636,10 +598,7 @@ static void NCR5380_timer_fn(unsigned long unused)
usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires; usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires;
add_timer(&usleep_timer); add_timer(&usleep_timer);
} }
spin_unlock_irqrestore(&timer_lock, flags); spin_unlock_irqrestore(&timer_lock, flags);
run_main();
} }
/** /**
...@@ -778,6 +737,22 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance) ...@@ -778,6 +737,22 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
} }
} }
/**
* NCR5380_coroutine_running - coroutine status
* @instance: controller to check
*
* Return true if the co-routine for this controller is running
* or scheduled to run
*
* FIXME: this test function belongs in the workqueue code!
*/
static int NCR5380_coroutine_running(struct Scsi_Host *instance)
{
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata;
return test_bit(0, &hostdata->coroutine.pending);
}
/** /**
* NCR5380_print_status - dump controller info * NCR5380_print_status - dump controller info
* @instance: controller to dump * @instance: controller to dump
...@@ -794,7 +769,7 @@ static void NCR5380_print_status(struct Scsi_Host *instance) ...@@ -794,7 +769,7 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
char *start; char *start;
int len; int len;
printk("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't"); printk("NCR5380 : coroutine is%s running.\n", NCR5380_coroutine_running(instance)? "" : "n't");
NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint(NDEBUG_ANY, instance);
NCR5380_dprint_phase(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance);
...@@ -837,7 +812,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int ...@@ -837,7 +812,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int
struct NCR5380_hostdata *hostdata; struct NCR5380_hostdata *hostdata;
Scsi_Cmnd *ptr; Scsi_Cmnd *ptr;
for (instance = first_instance; instance && instance->host_no != hostno; instance = instance->next); instance = scsi_host_hn_get(hostno);
if (!instance) if (!instance)
return (-ESRCH); return (-ESRCH);
hostdata = (struct NCR5380_hostdata *) instance->hostdata; hostdata = (struct NCR5380_hostdata *) instance->hostdata;
...@@ -881,7 +856,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int ...@@ -881,7 +856,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int
SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi); SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi);
#endif #endif
spin_lock_irq(instance->host_lock); spin_lock_irq(instance->host_lock);
SPRINTF("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't"); SPRINTF("NCR5380 : coroutine is%s running.\n", NCR5380_coroutine_running(instance) ? "" : "n't");
if (!hostdata->connected) if (!hostdata->connected)
SPRINTF("scsi%d: no currently connected command\n", instance->host_no); SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
else else
...@@ -904,8 +879,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int ...@@ -904,8 +879,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int
return length; return length;
} }
static static char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length)
char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length)
{ {
SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->host->host_no, cmd->target, cmd->lun); SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->host->host_no, cmd->target, cmd->lun);
SPRINTF(" command = "); SPRINTF(" command = ");
...@@ -913,8 +887,7 @@ char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length) ...@@ -913,8 +887,7 @@ char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length)
return (pos); return (pos);
} }
static static char *lprint_command(unsigned char *command, char *pos, char *buffer, int length)
char *lprint_command(unsigned char *command, char *pos, char *buffer, int length)
{ {
int i, s; int i, s;
pos = lprint_opcode(command[0], pos, buffer, length); pos = lprint_opcode(command[0], pos, buffer, length);
...@@ -924,8 +897,7 @@ char *lprint_command(unsigned char *command, char *pos, char *buffer, int length ...@@ -924,8 +897,7 @@ char *lprint_command(unsigned char *command, char *pos, char *buffer, int length
return (pos); return (pos);
} }
static static char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
{ {
SPRINTF("%2d (0x%02x)", opcode, opcode); SPRINTF("%2d (0x%02x)", opcode, opcode);
return (pos); return (pos);
...@@ -943,10 +915,12 @@ char *lprint_opcode(int opcode, char *pos, char *buffer, int length) ...@@ -943,10 +915,12 @@ char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
* Notes : I assume that the host, hostno, and id bits have been * Notes : I assume that the host, hostno, and id bits have been
* set correctly. I don't care about the irq and other fields. * set correctly. I don't care about the irq and other fields.
* *
* Returns 0 for success
*
* Locks: interrupts must be enabled when we are called * Locks: interrupts must be enabled when we are called
*/ */
static void __init NCR5380_init(struct Scsi_Host *instance, int flags) static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
{ {
NCR5380_local_declare(); NCR5380_local_declare();
int i, pass; int i, pass;
...@@ -982,6 +956,9 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -982,6 +956,9 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
hostdata->connected = NULL; hostdata->connected = NULL;
hostdata->issue_queue = NULL; hostdata->issue_queue = NULL;
hostdata->disconnected_queue = NULL; hostdata->disconnected_queue = NULL;
INIT_WORK(&hostdata->coroutine, NCR5380_main, hostdata);
#ifdef NCR5380_STATS #ifdef NCR5380_STATS
for (i = 0; i < 8; ++i) { for (i = 0; i < 8; ++i) {
hostdata->time_read[i] = 0; hostdata->time_read[i] = 0;
...@@ -1000,10 +977,16 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1000,10 +977,16 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
else else
hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags; hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags;
if (!the_template) { hostdata->next = NULL;
the_template = instance->hostt;
first_instance = instance; if (!first_host)
} first_host = hostdata;
else
last_host->next = hostdata;
last_host = hostdata;
hostdata->host = instance;
hostdata->time_expires = 0; hostdata->time_expires = 0;
hostdata->next_timer = NULL; hostdata->next_timer = NULL;
...@@ -1041,22 +1024,28 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1041,22 +1024,28 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
case 1: case 1:
case 3: case 3:
case 5: case 5:
printk("scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no); printk(KERN_INFO "scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no);
timeout = jiffies + 5 * HZ; timeout = jiffies + 5 * HZ;
while (time_before(jiffies, timeout) && (NCR5380_read(STATUS_REG) & SR_BSY)); while (time_before(jiffies, timeout) && (NCR5380_read(STATUS_REG) & SR_BSY))
{
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
break; break;
case 2: case 2:
printk("scsi%d: bus busy, attempting abort\n", instance->host_no); printk(KERN_WARNING "scsi%d: bus busy, attempting abort\n", instance->host_no);
do_abort(instance); do_abort(instance);
break; break;
case 4: case 4:
printk("scsi%d: bus busy, attempting reset\n", instance->host_no); printk(KERN_WARNING "scsi%d: bus busy, attempting reset\n", instance->host_no);
do_reset(instance); do_reset(instance);
break; break;
case 6: case 6:
printk("scsi%d: bus locked solid or invalid override\n", instance->host_no); printk(KERN_ERR "scsi%d: bus locked solid or invalid override\n", instance->host_no);
return -ENXIO;
} }
} }
return 0;
} }
/** /**
...@@ -1072,15 +1061,11 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags) ...@@ -1072,15 +1061,11 @@ static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
* retake this lock. Called functions take dma lock. * retake this lock. Called functions take dma lock.
*/ */
/* Only make static if a wrapper function is used */ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
#ifndef NCR5380_queue_command {
static
#endif
int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
struct Scsi_Host *instance = cmd->host; struct Scsi_Host *instance = cmd->host;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
Scsi_Cmnd *tmp; Scsi_Cmnd *tmp;
unsigned long flags;
#if (NDEBUG & NDEBUG_NO_WRITE) #if (NDEBUG & NDEBUG_NO_WRITE)
switch (cmd->cmnd[0]) { switch (cmd->cmnd[0]) {
...@@ -1093,7 +1078,6 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { ...@@ -1093,7 +1078,6 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
} }
#endif /* (NDEBUG & NDEBUG_NO_WRITE) */ #endif /* (NDEBUG & NDEBUG_NO_WRITE) */
spin_lock_irqsave(instance->host_lock, flags);
#ifdef NCR5380_STATS #ifdef NCR5380_STATS
switch (cmd->cmnd[0]) { switch (cmd->cmnd[0]) {
case WRITE: case WRITE:
...@@ -1141,9 +1125,8 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { ...@@ -1141,9 +1125,8 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
dprintk(NDEBUG_QUEUES, ("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail")); dprintk(NDEBUG_QUEUES, ("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"));
/* Run the coroutine if it isn't already running. */ /* Run the coroutine if it isn't already running. */
spin_unlock_irqrestore(instance->host_lock, flags); /* Kick off command processing */
schedule_work(&hostdata->coroutine);
run_main();
return 0; return 0;
} }
...@@ -1155,21 +1138,22 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { ...@@ -1155,21 +1138,22 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
* NCR5380_queue_command() and NCR5380_intr() will try to start it * NCR5380_queue_command() and NCR5380_intr() will try to start it
* in case it is not running. * in case it is not running.
* *
* Locks; The caller must hold the io_request_lock. The lock will still be * Locks: called as its own thread with no locks held. Takes the
* held on return but may be dropped while running. Called functions take * host lock and called routines may take the isa dma lock.
* the DMA lock.
*/ */
static void NCR5380_main(void) { static void NCR5380_main(void *p)
{
struct NCR5380_hostdata *hostdata = p;
Scsi_Cmnd *tmp, *prev; Scsi_Cmnd *tmp, *prev;
struct Scsi_Host *instance; struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata;
int done; int done;
unsigned long flags;
/* /*
* We run (with interrupts disabled) until we're sure that none of * We run (with interrupts disabled) until we're sure that none of
* the host adapters have anything that can be done, at which point * the host adapters have anything that can be done, at which point
* we set main_running to 0 and exit. * we can exit
* *
* Interrupts are enabled before doing various other internal * Interrupts are enabled before doing various other internal
* instructions, after we've decided that we need to run through * instructions, after we've decided that we need to run through
...@@ -1178,113 +1162,112 @@ static void NCR5380_main(void) { ...@@ -1178,113 +1162,112 @@ static void NCR5380_main(void) {
* this should prevent any race conditions. * this should prevent any race conditions.
*/ */
instance = hostdata->host;
spin_lock_irqsave(instance->host_lock, flags);
do { do {
/* Lock held here */ /* Lock held here */
done = 1; done = 1;
for (instance = first_instance; instance && instance->hostt == the_template; instance = instance->next) { if (!hostdata->connected && !hostdata->selecting) {
hostdata = (struct NCR5380_hostdata *) instance->hostdata; dprintk(NDEBUG_MAIN, ("scsi%d : not connected\n", instance->host_no));
/* Lock held here */ /*
if (!hostdata->connected && !hostdata->selecting) { * Search through the issue_queue for a command destined
dprintk(NDEBUG_MAIN, ("scsi%d : not connected\n", instance->host_no)); * for a target that's not busy.
/* */
* Search through the issue_queue for a command destined for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
* for a target that's not busy. {
*/ if (prev != tmp)
for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) dprintk(NDEBUG_LISTS, ("MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun));
{ /* When we find one, remove it from the issue queue. */
if (prev != tmp) if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) {
dprintk(NDEBUG_LISTS, ("MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun)); if (prev) {
/* When we find one, remove it from the issue queue. */ REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble);
if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) { prev->host_scribble = tmp->host_scribble;
if (prev) { } else {
REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble); REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble);
prev->host_scribble = tmp->host_scribble; hostdata->issue_queue = (Scsi_Cmnd *) tmp->host_scribble;
} else { }
REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble); tmp->host_scribble = NULL;
hostdata->issue_queue = (Scsi_Cmnd *) tmp->host_scribble;
}
tmp->host_scribble = NULL;
/*
* Attempt to establish an I_T_L nexus here.
* On success, instance->hostdata->connected is set.
* On failure, we must add the command back to the
* issue queue so we can keep trying.
*/
dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->target, tmp->lun));
/* /*
* A successful selection is defined as one that * Attempt to establish an I_T_L nexus here.
* leaves us with the command connected and * On success, instance->hostdata->connected is set.
* in hostdata->connected, OR has terminated the * On failure, we must add the command back to the
* command. * issue queue so we can keep trying.
* */
* With successful commands, we fall through dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->target, tmp->lun));
* and see if we can do an information transfer,
* with failures we will restart. /*
*/ * A successful selection is defined as one that
hostdata->selecting = 0; * leaves us with the command connected and
/* RvC: have to preset this to indicate a new command is being performed */ * in hostdata->connected, OR has terminated the
* command.
if (!NCR5380_select(instance, tmp, *
/* * With successful commands, we fall through
* REQUEST SENSE commands are issued without tagged * and see if we can do an information transfer,
* queueing, even on SCSI-II devices because the * with failures we will restart.
* contingent allegiance condition exists for the */
* entire unit. hostdata->selecting = 0;
*/ /* RvC: have to preset this to indicate a new command is being performed */
(tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
break; if (!NCR5380_select(instance, tmp,
} else { /*
LIST(tmp, hostdata->issue_queue); * REQUEST SENSE commands are issued without tagged
tmp->host_scribble = (unsigned char *) hostdata->issue_queue; * queueing, even on SCSI-II devices because the
hostdata->issue_queue = tmp; * contingent allegiance condition exists for the
done = 0; * entire unit.
dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no)); */
} (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
/* lock held here still */ break;
} /* if target/lun is not busy */ } else {
} /* for */ LIST(tmp, hostdata->issue_queue);
/* exited locked */ tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
} /* if (!hostdata->connected) */ hostdata->issue_queue = tmp;
if (hostdata->selecting) { done = 0;
tmp = (Scsi_Cmnd *) hostdata->selecting; dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no));
/* Selection will drop and retake the lock */ }
if (!NCR5380_select(instance, tmp, (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) { /* lock held here still */
/* Ok ?? */ } /* if target/lun is not busy */
} else { } /* for */
/* RvC: device failed, so we wait a long time /* exited locked */
this is needed for Mustek scanners, that } /* if (!hostdata->connected) */
do not respond to commands immediately if (hostdata->selecting) {
after a scan */ tmp = (Scsi_Cmnd *) hostdata->selecting;
printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->target); /* Selection will drop and retake the lock */
//spin_lock_irq(&io_request_lock); if (!NCR5380_select(instance, tmp, (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
LIST(tmp, hostdata->issue_queue); /* Ok ?? */
tmp->host_scribble = (unsigned char *) hostdata->issue_queue; } else {
hostdata->issue_queue = tmp; /* RvC: device failed, so we wait a long time
//spin_unlock_irq(&io_request_lock); this is needed for Mustek scanners, that
do not respond to commands immediately
hostdata->time_expires = jiffies + USLEEP_WAITLONG; after a scan */
NCR5380_set_timer(instance); printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->target);
} //spin_lock_irq(&io_request_lock);
} /* if hostdata->selecting */ LIST(tmp, hostdata->issue_queue);
if (hostdata->connected tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
hostdata->issue_queue = tmp;
//spin_unlock_irq(&io_request_lock);
hostdata->time_expires = jiffies + USLEEP_WAITLONG;
NCR5380_set_timer(instance);
}
} /* if hostdata->selecting */
if (hostdata->connected
#ifdef REAL_DMA #ifdef REAL_DMA
&& !hostdata->dmalen && !hostdata->dmalen
#endif #endif
&& (!hostdata->time_expires || time_before_eq(hostdata->time_expires, jiffies)) && (!hostdata->time_expires || time_before_eq(hostdata->time_expires, jiffies))
) { ) {
dprintk(NDEBUG_MAIN, ("scsi%d : main() : performing information transfer\n", instance->host_no)); dprintk(NDEBUG_MAIN, ("scsi%d : main() : performing information transfer\n", instance->host_no));
NCR5380_information_transfer(instance); NCR5380_information_transfer(instance);
dprintk(NDEBUG_MAIN, ("scsi%d : main() : done set false\n", instance->host_no)); dprintk(NDEBUG_MAIN, ("scsi%d : main() : done set false\n", instance->host_no));
done = 0; done = 0;
} else } else
break; break;
} /* for instance */
} while (!done); } while (!done);
/* Exit lock held */
clear_bit(0, &main_running); spin_unlock_irqrestore(instance->host_lock, flags);
} }
#ifndef DONT_USE_INTR #ifndef DONT_USE_INTR
...@@ -1308,6 +1291,7 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1308,6 +1291,7 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
struct Scsi_Host *instance; struct Scsi_Host *instance;
int done; int done;
unsigned char basr; unsigned char basr;
struct NCR5380_hostdata *hostdata;
dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq)); dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));
...@@ -1315,8 +1299,9 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1315,8 +1299,9 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
done = 1; done = 1;
/* The instance list is constant while the driver is /* The instance list is constant while the driver is
loaded */ loaded */
for (instance = first_instance; instance && (instance->hostt == the_template); instance = instance->next) for (hostdata = first_host; hostdata != NULL; hostdata = hostdata->next)
{ {
instance = hostdata->host;
if (instance->irq == irq) { if (instance->irq == irq) {
spin_lock_irq(instance->host_lock); spin_lock_irq(instance->host_lock);
/* Look for pending interrupts */ /* Look for pending interrupts */
...@@ -1385,8 +1370,8 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1385,8 +1370,8 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
} }
} /* if BASR_IRQ */ } /* if BASR_IRQ */
spin_unlock_irq(instance->host_lock); spin_unlock_irq(instance->host_lock);
if (!done) if(!done)
run_main(); schedule_work(&hostdata->coroutine);
} /* if (instance->irq == irq) */ } /* if (instance->irq == irq) */
} }
} while (!done); } while (!done);
......
...@@ -248,6 +248,8 @@ ...@@ -248,6 +248,8 @@
#ifndef ASM #ifndef ASM
struct NCR5380_hostdata { struct NCR5380_hostdata {
NCR5380_implementation_fields; /* implementation specific */ NCR5380_implementation_fields; /* implementation specific */
struct Scsi_Host *host; /* Host backpointer */
struct NCR5380_hostdata *next; /* Next in our hot chain */
unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */ unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */
unsigned char targets_present; /* targets we have connected unsigned char targets_present; /* targets we have connected
to, so we can call a select to, so we can call a select
...@@ -269,6 +271,7 @@ struct NCR5380_hostdata { ...@@ -269,6 +271,7 @@ struct NCR5380_hostdata {
struct Scsi_Host *next_timer; struct Scsi_Host *next_timer;
int select_time; /* timer in select for target response */ int select_time; /* timer in select for target response */
volatile Scsi_Cmnd *selecting; volatile Scsi_Cmnd *selecting;
struct work_struct coroutine; /* our co-routine */
#ifdef NCR5380_STATS #ifdef NCR5380_STATS
unsigned timebase; /* Base for time calcs */ unsigned timebase; /* Base for time calcs */
long time_read[8]; /* time to do reads */ long time_read[8]; /* time to do reads */
...@@ -281,7 +284,6 @@ struct NCR5380_hostdata { ...@@ -281,7 +284,6 @@ struct NCR5380_hostdata {
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
static struct Scsi_Host *first_instance; /* linked list of 5380's */
#define dprintk(a,b) do {} while(0) #define dprintk(a,b) do {} while(0)
#define NCR5380_dprint(a,b) do {} while(0) #define NCR5380_dprint(a,b) do {} while(0)
...@@ -290,36 +292,22 @@ static struct Scsi_Host *first_instance; /* linked list of 5380's */ ...@@ -290,36 +292,22 @@ static struct Scsi_Host *first_instance; /* linked list of 5380's */
#if defined(AUTOPROBE_IRQ) #if defined(AUTOPROBE_IRQ)
static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible); static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
#endif #endif
static void NCR5380_init(struct Scsi_Host *instance, int flags); static int NCR5380_init(struct Scsi_Host *instance, int flags);
static void NCR5380_information_transfer(struct Scsi_Host *instance); static void NCR5380_information_transfer(struct Scsi_Host *instance);
#ifndef DONT_USE_INTR #ifndef DONT_USE_INTR
static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs); static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
#endif #endif
static void NCR5380_main(void); static void NCR5380_main(void *ptr);
static void NCR5380_print_options(struct Scsi_Host *instance); static void NCR5380_print_options(struct Scsi_Host *instance);
#ifdef NDEBUG
static void NCR5380_print_phase(struct Scsi_Host *instance); static void NCR5380_print_phase(struct Scsi_Host *instance);
static void NCR5380_print(struct Scsi_Host *instance); static void NCR5380_print(struct Scsi_Host *instance);
#ifndef NCR5380_abort
static
#endif #endif
int NCR5380_abort(Scsi_Cmnd * cmd); static int NCR5380_abort(Scsi_Cmnd * cmd);
#ifndef NCR5380_bus_reset static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
static static int NCR5380_host_reset(Scsi_Cmnd * cmd);
#endif static int NCR5380_device_reset(Scsi_Cmnd * cmd);
int NCR5380_bus_reset(Scsi_Cmnd * cmd); static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
#ifndef NCR5380_host_reset
static
#endif
int NCR5380_host_reset(Scsi_Cmnd * cmd);
#ifndef NCR5380_device_reset
static
#endif
int NCR5380_device_reset(Scsi_Cmnd * cmd);
#ifndef NCR5380_queue_command
static
#endif
int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
static void NCR5380_reselect(struct Scsi_Host *instance); static void NCR5380_reselect(struct Scsi_Host *instance);
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/delay.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
...@@ -52,7 +53,7 @@ ...@@ -52,7 +53,7 @@
#include "NCR5380.c" #include "NCR5380.c"
int __init dmx3191d_detect(Scsi_Host_Template *tmpl) { static int __init dmx3191d_detect(Scsi_Host_Template *tmpl) {
int boards = 0; int boards = 0;
struct Scsi_Host *instance = NULL; struct Scsi_Host *instance = NULL;
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
...@@ -90,7 +91,7 @@ int __init dmx3191d_detect(Scsi_Host_Template *tmpl) { ...@@ -90,7 +91,7 @@ int __init dmx3191d_detect(Scsi_Host_Template *tmpl) {
instance->irq = pdev->irq; instance->irq = pdev->irq;
NCR5380_init(instance, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E); NCR5380_init(instance, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
if (request_irq(pdev->irq, dmx3191d_do_intr, SA_SHIRQ, if (request_irq(pdev->irq, dmx3191d_intr, SA_SHIRQ,
DMX3191D_DRIVER_NAME, instance)) { DMX3191D_DRIVER_NAME, instance)) {
printk(KERN_WARNING "dmx3191: IRQ %d not available - switching to polled mode.\n", pdev->irq); printk(KERN_WARNING "dmx3191: IRQ %d not available - switching to polled mode.\n", pdev->irq);
/* Steam powered scsi controllers run without an IRQ /* Steam powered scsi controllers run without an IRQ
...@@ -103,13 +104,13 @@ int __init dmx3191d_detect(Scsi_Host_Template *tmpl) { ...@@ -103,13 +104,13 @@ int __init dmx3191d_detect(Scsi_Host_Template *tmpl) {
return boards; return boards;
} }
const char * dmx3191d_info(struct Scsi_Host *host) { static const char * dmx3191d_info(struct Scsi_Host *host) {
static const char *info ="Domex DMX3191D"; static const char *info ="Domex DMX3191D";
return info; return info;
} }
int dmx3191d_release_resources(struct Scsi_Host *instance) static int dmx3191d_release_resources(struct Scsi_Host *instance)
{ {
release_region(instance->io_port, DMX3191D_REGION); release_region(instance->io_port, DMX3191D_REGION);
if(instance->irq!=IRQ_NONE) if(instance->irq!=IRQ_NONE)
......
...@@ -20,16 +20,15 @@ ...@@ -20,16 +20,15 @@
#define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001 #define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001
#endif #endif
#ifndef ASM static int dmx3191d_abort(Scsi_Cmnd *);
int dmx3191d_abort(Scsi_Cmnd *); static int dmx3191d_detect(Scsi_Host_Template *);
int dmx3191d_detect(Scsi_Host_Template *); static const char* dmx3191d_info(struct Scsi_Host *);
const char* dmx3191d_info(struct Scsi_Host *); static int dmx3191d_proc_info(char *, char **, off_t, int, int, int);
int dmx3191d_proc_info(char *, char **, off_t, int, int, int); static int dmx3191d_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int dmx3191d_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int dmx3191d_release_resources(struct Scsi_Host *);
int dmx3191d_release_resources(struct Scsi_Host *); static int dmx3191d_bus_reset(Scsi_Cmnd *);
int dmx3191d_bus_reset(Scsi_Cmnd *); static int dmx3191d_host_reset(Scsi_Cmnd *);
int dmx3191d_host_reset(Scsi_Cmnd *); static int dmx3191d_device_reset(Scsi_Cmnd *);
int dmx3191d_device_reset(Scsi_Cmnd *);
#define DMX3191D { \ #define DMX3191D { \
...@@ -64,9 +63,9 @@ int dmx3191d_device_reset(Scsi_Cmnd *); ...@@ -64,9 +63,9 @@ int dmx3191d_device_reset(Scsi_Cmnd *);
#define NCR5380_intr dmx3191d_intr #define NCR5380_intr dmx3191d_intr
#define NCR5380_proc_info dmx3191d_proc_info #define NCR5380_proc_info dmx3191d_proc_info
#define NCR5380_queue_command dmx3191d_queue_command #define NCR5380_queue_command dmx3191d_queue_command
#define NCR5380_reset dmx3191d_reset #define NCR5380_host_reset dmx3191d_host_reset
#define NCR5380_bus_reset dmx3191d_bus_reset
#endif /* ASM */ #define NCR5380_device_reset dmx3191d_device_reset
#endif /* __DMX3191D_H */ #endif /* __DMX3191D_H */
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#define AUTOSENSE #define AUTOSENSE
#define PSEUDO_DMA #define PSEUDO_DMA
#define DONT_USE_INTR #define DONT_USE_INTR
#define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */ #define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */
#define xNDEBUG (NDEBUG_INTR+NDEBUG_RESELECTION+\ #define xNDEBUG (NDEBUG_INTR+NDEBUG_RESELECTION+\
NDEBUG_SELECTION+NDEBUG_ARBITRATION) NDEBUG_SELECTION+NDEBUG_ARBITRATION)
#define DMA_WORKS_RIGHT #define DMA_WORKS_RIGHT
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/delay.h>
#include <asm/io.h> #include <asm/io.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
...@@ -101,65 +102,77 @@ ...@@ -101,65 +102,77 @@
*/ */
/* /*
*/ */
/* Offset from DTC_5380_OFFSET */ /* Offset from DTC_5380_OFFSET */
#define DTC_CONTROL_REG 0x100 /* rw */ #define DTC_CONTROL_REG 0x100 /* rw */
#define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */ #define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */
#define CSR_DIR_READ 0x40 /* rw direction, 1 = read 0 = write */ #define CSR_DIR_READ 0x40 /* rw direction, 1 = read 0 = write */
#define CSR_RESET 0x80 /* wo Resets 53c400 */ #define CSR_RESET 0x80 /* wo Resets 53c400 */
#define CSR_5380_REG 0x80 /* ro 5380 registers can be accessed */ #define CSR_5380_REG 0x80 /* ro 5380 registers can be accessed */
#define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */ #define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */
#define CSR_SCSI_BUFF_INTR 0x20 /* rw Enable int on transfer ready */ #define CSR_SCSI_BUFF_INTR 0x20 /* rw Enable int on transfer ready */
#define CSR_5380_INTR 0x10 /* rw Enable 5380 interrupts */ #define CSR_5380_INTR 0x10 /* rw Enable 5380 interrupts */
#define CSR_SHARED_INTR 0x08 /* rw Interrupt sharing */ #define CSR_SHARED_INTR 0x08 /* rw Interrupt sharing */
#define CSR_HOST_BUF_NOT_RDY 0x04 /* ro Host buffer not ready */ #define CSR_HOST_BUF_NOT_RDY 0x04 /* ro Host buffer not ready */
#define CSR_SCSI_BUF_RDY 0x02 /* ro SCSI buffer ready */ #define CSR_SCSI_BUF_RDY 0x02 /* ro SCSI buffer ready */
#define CSR_GATED_5380_IRQ 0x01 /* ro Last block xferred */ #define CSR_GATED_5380_IRQ 0x01 /* ro Last block xferred */
#define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR) #define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR)
#define DTC_BLK_CNT 0x101 /* rw #define DTC_BLK_CNT 0x101 /* rw
* # of 128-byte blocks to transfer */ * # of 128-byte blocks to transfer */
#define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */ #define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */
#define DTC_SWITCH_REG 0x3982 /* ro - DIP switches */ #define DTC_SWITCH_REG 0x3982 /* ro - DIP switches */
#define DTC_RESUME_XFER 0x3982 /* wo - resume data xfer #define DTC_RESUME_XFER 0x3982 /* wo - resume data xfer
* after disconnect/reconnect*/ * after disconnect/reconnect*/
#define DTC_5380_OFFSET 0x3880 /* 8 registers here, see NCR5380.h */ #define DTC_5380_OFFSET 0x3880 /* 8 registers here, see NCR5380.h */
/*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */ /*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */
#define DTC_DATA_BUF 0x3900 /* rw 128 bytes long */ #define DTC_DATA_BUF 0x3900 /* rw 128 bytes long */
static struct override { static struct override {
unsigned int address; unsigned int address;
int irq; int irq;
} overrides } overrides
#ifdef OVERRIDE #ifdef OVERRIDE
[] __initdata = OVERRIDE; [] __initdata = OVERRIDE;
#else #else
[4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, {0, IRQ_AUTO}, {0, IRQ_AUTO}}; [4] __initdata = { {
0, IRQ_AUTO}, {
0, IRQ_AUTO}, {
0, IRQ_AUTO}, {
0, IRQ_AUTO}};
#endif #endif
#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
static struct base { static struct base {
unsigned long address; unsigned long address;
int noauto; int noauto;
} bases[] __initdata = {{0xcc000, 0}, {0xc8000, 0}, {0xdc000, 0}, {0xd8000, 0}}; } bases[] __initdata = {
{ 0xcc000, 0 },
{ 0xc8000, 0 },
{ 0xdc000, 0 },
{ 0xd8000, 0 }
};
#define NO_BASES (sizeof (bases) / sizeof (struct base)) #define NO_BASES (sizeof (bases) / sizeof (struct base))
static const struct signature { static const struct signature {
const char *string; const char *string;
int offset; int offset;
} signatures[] = { {"DATA TECHNOLOGY CORPORATION BIOS", 0x25}, }; } signatures[] = {
{"DATA TECHNOLOGY CORPORATION BIOS", 0x25},
};
#define NO_SIGNATURES (sizeof (signatures) / sizeof (struct signature)) #define NO_SIGNATURES (sizeof (signatures) / sizeof (struct signature))
#ifndef MODULE
/* /*
* Function : dtc_setup(char *str, int *ints) * Function : dtc_setup(char *str, int *ints)
* *
...@@ -170,23 +183,24 @@ static const struct signature { ...@@ -170,23 +183,24 @@ static const struct signature {
* *
*/ */
void __init dtc_setup(char *str, int *ints){ static void __init dtc_setup(char *str, int *ints)
static int commandline_current = 0; {
int i; static int commandline_current = 0;
if (ints[0] != 2) int i;
printk("dtc_setup: usage dtc=address,irq\n"); if (ints[0] != 2)
else printk("dtc_setup: usage dtc=address,irq\n");
if (commandline_current < NO_OVERRIDES) { else if (commandline_current < NO_OVERRIDES) {
overrides[commandline_current].address = ints[1]; overrides[commandline_current].address = ints[1];
overrides[commandline_current].irq = ints[2]; overrides[commandline_current].irq = ints[2];
for (i = 0; i < NO_BASES; ++i) for (i = 0; i < NO_BASES; ++i)
if (bases[i].address == ints[1]) { if (bases[i].address == ints[1]) {
bases[i].noauto = 1; bases[i].noauto = 1;
break; break;
} }
++commandline_current; ++commandline_current;
} }
} }
#endif
/* /*
* Function : int dtc_detect(Scsi_Host_Template * tpnt) * Function : int dtc_detect(Scsi_Host_Template * tpnt)
...@@ -201,97 +215,92 @@ void __init dtc_setup(char *str, int *ints){ ...@@ -201,97 +215,92 @@ void __init dtc_setup(char *str, int *ints){
* *
*/ */
int __init dtc_detect(Scsi_Host_Template * tpnt){ static int __init dtc_detect(Scsi_Host_Template * tpnt)
static int current_override = 0, current_base = 0; {
struct Scsi_Host *instance; static int current_override = 0, current_base = 0;
unsigned int base; struct Scsi_Host *instance;
int sig, count; unsigned int base;
int sig, count;
tpnt->proc_name = "dtc3x80"; tpnt->proc_name = "dtc3x80";
tpnt->proc_info = &dtc_proc_info; tpnt->proc_info = &dtc_proc_info;
for (count = 0; current_override < NO_OVERRIDES; ++current_override) { for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
base = 0; base = 0;
if (overrides[current_override].address) if (overrides[current_override].address)
base = overrides[current_override].address; base = overrides[current_override].address;
else else
for (; !base && (current_base < NO_BASES); ++current_base) { for (; !base && (current_base < NO_BASES); ++current_base) {
#if (DTCDEBUG & DTCDEBUG_INIT) #if (DTCDEBUG & DTCDEBUG_INIT)
printk("scsi-dtc : probing address %08x\n", bases[current_base].address); printk("scsi-dtc : probing address %08x\n", bases[current_base].address);
#endif #endif
for (sig = 0; sig < NO_SIGNATURES; ++sig) for (sig = 0; sig < NO_SIGNATURES; ++sig)
if (!bases[current_base].noauto && if (!bases[current_base].noauto && isa_check_signature(bases[current_base].address + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) {
isa_check_signature(bases[current_base].address + base = bases[current_base].address;
signatures[sig].offset,
signatures[sig].string, strlen(signatures[sig].string))) {
base = bases[current_base].address;
#if (DTCDEBUG & DTCDEBUG_INIT) #if (DTCDEBUG & DTCDEBUG_INIT)
printk("scsi-dtc : detected board.\n"); printk("scsi-dtc : detected board.\n");
#endif #endif
break; break;
} }
} }
#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
printk("scsi-dtc : base = %08x\n", base); printk("scsi-dtc : base = %08x\n", base);
#endif #endif
if (!base) if (!base)
break; break;
instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
if(instance == NULL) if (instance == NULL)
break; break;
instance->base = base;
NCR5380_init(instance, 0); instance->base = base;
NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */ NCR5380_init(instance, 0);
if (overrides[current_override].irq != IRQ_AUTO)
instance->irq = overrides[current_override].irq; NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */
else if (overrides[current_override].irq != IRQ_AUTO)
instance->irq = NCR5380_probe_irq(instance, DTC_IRQS); instance->irq = overrides[current_override].irq;
else
instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
#ifndef DONT_USE_INTR #ifndef DONT_USE_INTR
/* With interrupts enabled, it will sometimes hang when doing heavy /* With interrupts enabled, it will sometimes hang when doing heavy
* reads. So better not enable them until I finger it out. */ * reads. So better not enable them until I finger it out. */
if (instance->irq != IRQ_NONE) if (instance->irq != IRQ_NONE)
if (request_irq(instance->irq, do_dtc_intr, SA_INTERRUPT, "dtc", instance)) { if (request_irq(instance->irq, dtc_intr, SA_INTERRUPT, "dtc", instance)) {
printk("scsi%d : IRQ%d not free, interrupts disabled\n", printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
instance->host_no, instance->irq); instance->irq = IRQ_NONE;
instance->irq = IRQ_NONE; }
}
if (instance->irq == IRQ_NONE) {
if (instance->irq == IRQ_NONE) { printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); }
}
#else #else
if (instance->irq != IRQ_NONE) if (instance->irq != IRQ_NONE)
printk("scsi%d : interrupts not used. Might as well not jumper it.\n", printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no);
instance->host_no); instance->irq = IRQ_NONE;
instance->irq = IRQ_NONE;
#endif #endif
#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
printk("scsi%d : irq = %d\n", instance->host_no, instance->irq); printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
#endif #endif
printk("scsi%d : at 0x%05X", instance->host_no, (int)instance->base); printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base);
if (instance->irq == IRQ_NONE) if (instance->irq == IRQ_NONE)
printk (" interrupts disabled"); printk(" interrupts disabled");
else else
printk (" irq %d", instance->irq); printk(" irq %d", instance->irq);
printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE); NCR5380_print_options(instance);
NCR5380_print_options(instance); printk("\n");
printk("\n");
++current_override;
++current_override; ++count;
++count; }
} return count;
return count;
} }
/* /*
...@@ -314,14 +323,14 @@ int __init dtc_detect(Scsi_Host_Template * tpnt){ ...@@ -314,14 +323,14 @@ int __init dtc_detect(Scsi_Host_Template * tpnt){
* and matching the H_C_S coordinates to what DOS uses. * and matching the H_C_S coordinates to what DOS uses.
*/ */
int dtc_biosparam(Disk * disk, struct block_device *dev, int * ip) static int dtc_biosparam(Disk * disk, struct block_device *dev, int *ip)
{ {
int size = disk->capacity; int size = disk->capacity;
ip[0] = 64; ip[0] = 64;
ip[1] = 32; ip[1] = 32;
ip[2] = size >> 11; ip[2] = size >> 11;
return 0; return 0;
} }
...@@ -341,43 +350,43 @@ int dtc_biosparam(Disk * disk, struct block_device *dev, int * ip) ...@@ -341,43 +350,43 @@ int dtc_biosparam(Disk * disk, struct block_device *dev, int * ip)
static int dtc_maxi = 0; static int dtc_maxi = 0;
static int dtc_wmaxi = 0; static int dtc_wmaxi = 0;
static inline int NCR5380_pread (struct Scsi_Host *instance, static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
unsigned char *dst, int len) {
{ unsigned char *d = dst;
unsigned char *d = dst; int i; /* For counting time spent in the poll-loop */
int i; /* For counting time spent in the poll-loop */ NCR5380_local_declare();
NCR5380_local_declare(); NCR5380_setup(instance);
NCR5380_setup(instance);
i = 0;
i = 0; NCR5380_read(RESET_PARITY_INTERRUPT_REG);
NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); if (instance->irq == IRQ_NONE)
if (instance->irq == IRQ_NONE) NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ); else
else NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE); NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */
NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */ rtrc(1);
rtrc(1); while (len > 0) {
while (len > 0) { rtrc(2);
rtrc(2); while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) ++i;
++i; rtrc(3);
rtrc(3); isa_memcpy_fromio(d, base + DTC_DATA_BUF, 128);
isa_memcpy_fromio(d, base + DTC_DATA_BUF, 128); d += 128;
d += 128; len -= 128;
len -= 128; rtrc(7);
rtrc(7); /*** with int's on, it sometimes hangs after here. /*** with int's on, it sometimes hangs after here.
* Looks like something makes HBNR go away. */ * Looks like something makes HBNR go away. */
} }
rtrc(4); rtrc(4);
while ( !(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
++i; ++i;
NCR5380_write(MODE_REG, 0); /* Clear the operating mode */ NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
rtrc(0); rtrc(0);
NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_read(RESET_PARITY_INTERRUPT_REG);
if (i > dtc_maxi) if (i > dtc_maxi)
dtc_maxi = i; dtc_maxi = i;
return(0); return (0);
} }
/**************************************************************** /****************************************************************
...@@ -393,44 +402,44 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, ...@@ -393,44 +402,44 @@ static inline int NCR5380_pread (struct Scsi_Host *instance,
* timeout. * timeout.
*/ */
static inline int NCR5380_pwrite (struct Scsi_Host *instance, static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
unsigned char *src, int len) { {
int i; int i;
NCR5380_local_declare(); NCR5380_local_declare();
NCR5380_setup(instance); NCR5380_setup(instance);
NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_read(RESET_PARITY_INTERRUPT_REG);
NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
/* set direction (write) */ /* set direction (write) */
if (instance->irq == IRQ_NONE) if (instance->irq == IRQ_NONE)
NCR5380_write(DTC_CONTROL_REG, 0); NCR5380_write(DTC_CONTROL_REG, 0);
else else
NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */ NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */
for (i = 0; len > 0; ++i) { for (i = 0; len > 0; ++i) {
rtrc(5); rtrc(5);
/* Poll until the host buffer can accept data. */ /* Poll until the host buffer can accept data. */
while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
++i; ++i;
rtrc(3); rtrc(3);
isa_memcpy_toio(base + DTC_DATA_BUF, src, 128); isa_memcpy_toio(base + DTC_DATA_BUF, src, 128);
src += 128; src += 128;
len -= 128; len -= 128;
} }
rtrc(4); rtrc(4);
while ( !(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
++i; ++i;
rtrc(6); rtrc(6);
/* Wait until the last byte has been sent to the disk */ /* Wait until the last byte has been sent to the disk */
while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)) while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
++i; ++i;
rtrc(7); rtrc(7);
/* Check for parity error here. fixme. */ /* Check for parity error here. fixme. */
NCR5380_write(MODE_REG, 0); /* Clear the operating mode */ NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
rtrc(0); rtrc(0);
if (i > dtc_wmaxi) if (i > dtc_wmaxi)
dtc_wmaxi = i; dtc_wmaxi = i;
return (0); return (0);
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -28,19 +28,16 @@ ...@@ -28,19 +28,16 @@
#ifndef DTC3280_H #ifndef DTC3280_H
#define DTC3280_H #define DTC3280_H
#ifndef ASM static int dtc_abort(Scsi_Cmnd *);
int dtc_abort(Scsi_Cmnd *); static int dtc_biosparam(Disk *, struct block_device *, int*);
int dtc_biosparam(Disk *, struct block_device *, int*); static int dtc_detect(Scsi_Host_Template *);
int dtc_detect(Scsi_Host_Template *); static int dtc_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int dtc_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int dtc_bus_reset(Scsi_Cmnd *);
int dtc_reset(Scsi_Cmnd *, unsigned int reset_flags); static int dtc_device_reset(Scsi_Cmnd *);
int dtc_proc_info (char *buffer, char **start, off_t offset, static int dtc_host_reset(Scsi_Cmnd *);
static int dtc_proc_info (char *buffer, char **start, off_t offset,
int length, int hostno, int inout); int length, int hostno, int inout);
#ifndef NULL
#define NULL 0
#endif
#ifndef CMD_PER_LUN #ifndef CMD_PER_LUN
#define CMD_PER_LUN 2 #define CMD_PER_LUN 2
#endif #endif
...@@ -55,24 +52,26 @@ int dtc_proc_info (char *buffer, char **start, off_t offset, ...@@ -55,24 +52,26 @@ int dtc_proc_info (char *buffer, char **start, off_t offset,
* macros when this is being used solely for the host stub. * macros when this is being used solely for the host stub.
*/ */
#define DTC3x80 { \ #define DTC3x80 { \
name: "DTC 3180/3280 ", \ name: "DTC 3180/3280 ", \
detect: dtc_detect, \ detect: dtc_detect, \
queuecommand: dtc_queue_command, \ queuecommand: dtc_queue_command, \
abort: dtc_abort, \ eh_abort_handler: dtc_abort, \
reset: dtc_reset, \ eh_bus_reset_handler: dtc_bus_reset, \
bios_param: dtc_biosparam, \ eh_device_reset_handler: dtc_device_reset, \
can_queue: CAN_QUEUE, \ eh_host_reset_handler: dtc_host_reset, \
this_id: 7, \ bios_param: dtc_biosparam, \
sg_tablesize: SG_ALL, \ can_queue: CAN_QUEUE, \
cmd_per_lun: CMD_PER_LUN , \ this_id: 7, \
sg_tablesize: SG_ALL, \
cmd_per_lun: CMD_PER_LUN , \
use_clustering: DISABLE_CLUSTERING} use_clustering: DISABLE_CLUSTERING}
#define NCR5380_implementation_fields \ #define NCR5380_implementation_fields \
volatile unsigned int base unsigned int base
#define NCR5380_local_declare() \ #define NCR5380_local_declare() \
volatile unsigned int base unsigned int base
#define NCR5380_setup(instance) \ #define NCR5380_setup(instance) \
base = (unsigned int)(instance)->base base = (unsigned int)(instance)->base
...@@ -105,12 +104,13 @@ int dtc_proc_info (char *buffer, char **start, off_t offset, ...@@ -105,12 +104,13 @@ int dtc_proc_info (char *buffer, char **start, off_t offset,
isa_writeb(value, DTC_address(reg));} while(0) isa_writeb(value, DTC_address(reg));} while(0)
#endif #endif
#define NCR5380_intr dtc_intr #define NCR5380_intr dtc_intr
#define do_NCR5380_intr do_dtc_intr #define NCR5380_queue_command dtc_queue_command
#define NCR5380_queue_command dtc_queue_command #define NCR5380_abort dtc_abort
#define NCR5380_abort dtc_abort #define NCR5380_bus_reset dtc_bus_reset
#define NCR5380_reset dtc_reset #define NCR5380_device_reset dtc_device_reset
#define NCR5380_proc_info dtc_proc_info #define NCR5380_host_reset dtc_host_reset
#define NCR5380_proc_info dtc_proc_info
/* 15 12 11 10 /* 15 12 11 10
1001 1100 0000 0000 */ 1001 1100 0000 0000 */
...@@ -118,5 +118,4 @@ int dtc_proc_info (char *buffer, char **start, off_t offset, ...@@ -118,5 +118,4 @@ int dtc_proc_info (char *buffer, char **start, off_t offset,
#define DTC_IRQS 0x9c00 #define DTC_IRQS 0x9c00
#endif /* ndef ASM */
#endif /* DTC3280_H */ #endif /* DTC3280_H */
...@@ -100,12 +100,6 @@ ...@@ -100,12 +100,6 @@
#define NCR5380_STATS #define NCR5380_STATS
#undef NCR5380_STAT_LIMIT #undef NCR5380_STAT_LIMIT
#endif #endif
#if defined(CONFIG_SCSI_G_NCR5380_PORT) && defined(CONFIG_SCSI_G_NCR5380_MEM)
#error You can not configure the Generic NCR 5380 SCSI Driver for memory mapped I/O and port mapped I/O at the same time (yet)
#endif
#if !defined(CONFIG_SCSI_G_NCR5380_PORT) && !defined(CONFIG_SCSI_G_NCR5380_MEM)
#error You must configure the Generic NCR 5380 SCSI Driver for one of memory mapped I/O and port mapped I/O.
#endif
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -121,6 +115,7 @@ ...@@ -121,6 +115,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/isapnp.h> #include <linux/isapnp.h>
#include <linux/delay.h>
#define NCR_NOT_SET 0 #define NCR_NOT_SET 0
static int ncr_irq = NCR_NOT_SET; static int ncr_irq = NCR_NOT_SET;
...@@ -143,8 +138,11 @@ static struct override { ...@@ -143,8 +138,11 @@ static struct override {
[1] __initdata = { { 0,},}; [1] __initdata = { { 0,},};
#endif #endif
#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
#ifndef MODULE
/** /**
* internal_setup - handle lilo command string override * internal_setup - handle lilo command string override
* @board: BOARD_* identifier for the board * @board: BOARD_* identifier for the board
...@@ -199,6 +197,7 @@ static void __init internal_setup(int board, char *str, int *ints) ...@@ -199,6 +197,7 @@ static void __init internal_setup(int board, char *str, int *ints)
} }
} }
/** /**
* do_NCR53C80_setup - set up entry point * do_NCR53C80_setup - set up entry point
* @str: unused * @str: unused
...@@ -270,6 +269,8 @@ static int __init do_DTC3181E_setup(char *str) ...@@ -270,6 +269,8 @@ static int __init do_DTC3181E_setup(char *str)
return 1; return 1;
} }
#endif
/** /**
* generic_NCR5380_detect - look for NCR5380 controllers * generic_NCR5380_detect - look for NCR5380 controllers
* @tpnt: the scsi template * @tpnt: the scsi template
...@@ -367,7 +368,7 @@ int __init generic_NCR5380_detect(Scsi_Host_Template * tpnt) ...@@ -367,7 +368,7 @@ int __init generic_NCR5380_detect(Scsi_Host_Template * tpnt)
break; break;
} }
#ifdef CONFIG_SCSI_G_NCR5380_PORT #ifndef CONFIG_SCSI_G_NCR5380_MEM
if (ports) { if (ports) {
/* wakeup sequence for the NCR53C400A and DTC3181E */ /* wakeup sequence for the NCR53C400A and DTC3181E */
...@@ -412,7 +413,7 @@ int __init generic_NCR5380_detect(Scsi_Host_Template * tpnt) ...@@ -412,7 +413,7 @@ int __init generic_NCR5380_detect(Scsi_Host_Template * tpnt)
#endif #endif
instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
if (instance == NULL) { if (instance == NULL) {
#ifdef CONFIG_SCSI_G_NCR5380_PORT #ifndef CONFIG_SCSI_G_NCR5380_MEM
release_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size); release_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size);
#else #else
release_mem_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size); release_mem_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size);
...@@ -430,7 +431,7 @@ int __init generic_NCR5380_detect(Scsi_Host_Template * tpnt) ...@@ -430,7 +431,7 @@ int __init generic_NCR5380_detect(Scsi_Host_Template * tpnt)
instance->irq = NCR5380_probe_irq(instance, 0xffff); instance->irq = NCR5380_probe_irq(instance, 0xffff);
if (instance->irq != IRQ_NONE) if (instance->irq != IRQ_NONE)
if (request_irq(instance->irq, do_generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", NULL)) { if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", NULL)) {
printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
instance->irq = IRQ_NONE; instance->irq = IRQ_NONE;
} }
...@@ -482,7 +483,7 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance) ...@@ -482,7 +483,7 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance)
NCR5380_local_declare(); NCR5380_local_declare();
NCR5380_setup(instance); NCR5380_setup(instance);
#ifdef CONFIG_SCSI_G_NCR5380_PORT #ifndef CONFIG_SCSI_G_NCR5380_MEM
release_region(instance->NCR5380_instance_name, NCR5380_region_size); release_region(instance->NCR5380_instance_name, NCR5380_region_size);
#else #else
release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size); release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size);
...@@ -555,7 +556,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, ...@@ -555,7 +556,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
} }
while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY); while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY);
#ifdef CONFIG_SCSI_G_NCR5380_PORT #ifndef CONFIG_SCSI_G_NCR5380_MEM
{ {
int i; int i;
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
...@@ -575,7 +576,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, ...@@ -575,7 +576,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
// FIXME - no timeout // FIXME - no timeout
} }
#ifdef CONFIG_SCSI_G_NCR5380_PORT #ifndef CONFIG_SCSI_G_NCR5380_MEM
{ {
int i; int i;
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
...@@ -641,7 +642,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, ...@@ -641,7 +642,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
} }
while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - timeout ; // FIXME - timeout
#ifdef CONFIG_SCSI_G_NCR5380_PORT #ifndef CONFIG_SCSI_G_NCR5380_MEM
{ {
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
NCR5380_write(C400_HOST_BUFFER, src[start + i]); NCR5380_write(C400_HOST_BUFFER, src[start + i]);
...@@ -657,7 +658,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, ...@@ -657,7 +658,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - no timeout ; // FIXME - no timeout
#ifdef CONFIG_SCSI_G_NCR5380_PORT #ifndef CONFIG_SCSI_G_NCR5380_MEM
{ {
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
NCR5380_write(C400_HOST_BUFFER, src[start + i]); NCR5380_write(C400_HOST_BUFFER, src[start + i]);
...@@ -781,9 +782,8 @@ int generic_NCR5380_proc_info(char *buffer, char **start, off_t offset, int leng ...@@ -781,9 +782,8 @@ int generic_NCR5380_proc_info(char *buffer, char **start, off_t offset, int leng
#endif #endif
/* For now this is constant so we may walk it */ /* For now this is constant so we may walk it */
for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr = scsi_ptr->next) scsi_ptr = scsi_host_hn_get(hostno);
if (scsi_ptr->host_no == hostno)
break;
NCR5380_setup(scsi_ptr); NCR5380_setup(scsi_ptr);
hostdata = (struct NCR5380_hostdata *) scsi_ptr->hostdata; hostdata = (struct NCR5380_hostdata *) scsi_ptr->hostdata;
......
...@@ -44,25 +44,19 @@ ...@@ -44,25 +44,19 @@
#endif #endif
#ifndef ASM #ifndef ASM
int generic_NCR5380_abort(Scsi_Cmnd *); static int generic_NCR5380_abort(Scsi_Cmnd *);
int generic_NCR5380_detect(Scsi_Host_Template *); static int generic_NCR5380_detect(Scsi_Host_Template *);
int generic_NCR5380_release_resources(struct Scsi_Host *); static int generic_NCR5380_release_resources(struct Scsi_Host *);
int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int generic_NCR5380_bus_reset(Scsi_Cmnd *); static int generic_NCR5380_bus_reset(Scsi_Cmnd *);
int generic_NCR5380_host_reset(Scsi_Cmnd *); static int generic_NCR5380_host_reset(Scsi_Cmnd *);
int generic_NCR5380_device_reset(Scsi_Cmnd *); static int generic_NCR5380_device_reset(Scsi_Cmnd *);
int notyet_generic_proc_info (char *buffer ,char **start, off_t offset, static int notyet_generic_proc_info (char *buffer ,char **start, off_t offset,
int length, int hostno, int inout); int length, int hostno, int inout);
const char* generic_NCR5380_info(struct Scsi_Host *); static const char* generic_NCR5380_info(struct Scsi_Host *);
#ifdef BIOSPARAM static int generic_NCR5380_biosparam(Disk *, struct block_device *, int *);
int generic_NCR5380_biosparam(Disk *, struct block_device *, int *);
#endif
int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout);
#ifndef NULL static int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout);
#define NULL 0
#endif
#ifndef CMD_PER_LUN #ifndef CMD_PER_LUN
#define CMD_PER_LUN 2 #define CMD_PER_LUN 2
...@@ -95,18 +89,13 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng ...@@ -95,18 +89,13 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
#define __STRVAL(x) #x #define __STRVAL(x) #x
#define STRVAL(x) __STRVAL(x) #define STRVAL(x) __STRVAL(x)
#ifdef CONFIG_SCSI_G_NCR5380_PORT #ifndef CONFIG_SCSI_G_NCR5380_MEM
#define NCR5380_map_config port #define NCR5380_map_config port
#define NCR5380_map_type int #define NCR5380_map_type int
#define NCR5380_map_name port #define NCR5380_map_name port
#define NCR5380_instance_name io_port #define NCR5380_instance_name io_port
#define NCR53C400_register_offset 0 #define NCR53C400_register_offset 0
#define NCR53C400_address_adjust 8 #define NCR53C400_address_adjust 8
#ifdef NCR53C400 #ifdef NCR53C400
...@@ -122,27 +111,17 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng ...@@ -122,27 +111,17 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
/* therefore CONFIG_SCSI_G_NCR5380_MEM */ /* therefore CONFIG_SCSI_G_NCR5380_MEM */
#define NCR5380_map_config memory #define NCR5380_map_config memory
#define NCR5380_map_type unsigned long #define NCR5380_map_type unsigned long
#define NCR5380_map_name base #define NCR5380_map_name base
#define NCR5380_instance_name base #define NCR5380_instance_name base
#define NCR53C400_register_offset 0x108 #define NCR53C400_register_offset 0x108
#define NCR53C400_address_adjust 0 #define NCR53C400_address_adjust 0
#define NCR53C400_mem_base 0x3880 #define NCR53C400_mem_base 0x3880
#define NCR53C400_host_buffer 0x3900 #define NCR53C400_host_buffer 0x3900
#define NCR5380_region_size 0x3a00 #define NCR5380_region_size 0x3a00
#define NCR5380_read(reg) isa_readb(NCR5380_map_name + NCR53C400_mem_base + (reg)) #define NCR5380_read(reg) isa_readb(NCR5380_map_name + NCR53C400_mem_base + (reg))
#define NCR5380_write(reg, value) isa_writeb(NCR5380_map_name + NCR53C400_mem_base + (reg), value) #define NCR5380_write(reg, value) isa_writeb(NCR5380_map_name + NCR53C400_mem_base + (reg), value)
#endif #endif
#define NCR5380_implementation_fields \ #define NCR5380_implementation_fields \
...@@ -155,7 +134,6 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng ...@@ -155,7 +134,6 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name) NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name)
#define NCR5380_intr generic_NCR5380_intr #define NCR5380_intr generic_NCR5380_intr
#define do_NCR5380_intr do_generic_NCR5380_intr
#define NCR5380_queue_command generic_NCR5380_queue_command #define NCR5380_queue_command generic_NCR5380_queue_command
#define NCR5380_abort generic_NCR5380_abort #define NCR5380_abort generic_NCR5380_abort
#define NCR5380_bus_reset generic_NCR5380_bus_reset #define NCR5380_bus_reset generic_NCR5380_bus_reset
......
/*
* There is probably a nicer way to do this but this one makes
* pretty obvious what is happening. We rebuild the same file with
* different options for mmio versus pio.
*/
#define SCSI_G_NCR5380_MEM
#include "g_NCR5380.c"
...@@ -118,6 +118,7 @@ ...@@ -118,6 +118,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <asm/io.h> #include <asm/io.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/delay.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
#include "pas16.h" #include "pas16.h"
...@@ -450,7 +451,7 @@ int __init pas16_detect(Scsi_Host_Template * tpnt) ...@@ -450,7 +451,7 @@ int __init pas16_detect(Scsi_Host_Template * tpnt)
instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS); instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS);
if (instance->irq != IRQ_NONE) if (instance->irq != IRQ_NONE)
if (request_irq(instance->irq, do_pas16_intr, SA_INTERRUPT, "pas16", instance)) { if (request_irq(instance->irq, pas16_intr, SA_INTERRUPT, "pas16", instance)) {
printk("scsi%d : IRQ%d not free, interrupts disabled\n", printk("scsi%d : IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq); instance->host_no, instance->irq);
instance->irq = IRQ_NONE; instance->irq = IRQ_NONE;
......
...@@ -114,14 +114,14 @@ ...@@ -114,14 +114,14 @@
#ifndef ASM #ifndef ASM
int pas16_abort(Scsi_Cmnd *); static int pas16_abort(Scsi_Cmnd *);
int pas16_biosparam(Disk *, struct block_device *, int*); static int pas16_biosparam(Disk *, struct block_device *, int*);
int pas16_detect(Scsi_Host_Template *); static int pas16_detect(Scsi_Host_Template *);
int pas16_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int pas16_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int pas16_bus_reset(Scsi_Cmnd *); static int pas16_bus_reset(Scsi_Cmnd *);
int pas16_host_reset(Scsi_Cmnd *); static int pas16_host_reset(Scsi_Cmnd *);
int pas16_device_reset(Scsi_Cmnd *); static int pas16_device_reset(Scsi_Cmnd *);
int pas16_proc_info (char *buffer ,char **start, off_t offset, static int pas16_proc_info (char *buffer ,char **start, off_t offset,
int length, int hostno, int inout); int length, int hostno, int inout);
#ifndef NULL #ifndef NULL
......
...@@ -120,6 +120,7 @@ ...@@ -120,6 +120,7 @@
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h>
static struct override { static struct override {
unsigned long address; unsigned long address;
...@@ -247,7 +248,7 @@ int __init t128_detect(Scsi_Host_Template * tpnt){ ...@@ -247,7 +248,7 @@ int __init t128_detect(Scsi_Host_Template * tpnt){
instance->irq = NCR5380_probe_irq(instance, T128_IRQS); instance->irq = NCR5380_probe_irq(instance, T128_IRQS);
if (instance->irq != IRQ_NONE) if (instance->irq != IRQ_NONE)
if (request_irq(instance->irq, do_t128_intr, SA_INTERRUPT, "t128", instance)) { if (request_irq(instance->irq, t128_intr, SA_INTERRUPT, "t128", instance)) {
printk("scsi%d : IRQ%d not free, interrupts disabled\n", printk("scsi%d : IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq); instance->host_no, instance->irq);
instance->irq = IRQ_NONE; instance->irq = IRQ_NONE;
......
...@@ -91,14 +91,14 @@ ...@@ -91,14 +91,14 @@
#define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */ #define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */
#ifndef ASM #ifndef ASM
int t128_abort(Scsi_Cmnd *); static int t128_abort(Scsi_Cmnd *);
int t128_biosparam(Disk *, struct block_device *, int*); static int t128_biosparam(Disk *, struct block_device *, int*);
int t128_detect(Scsi_Host_Template *); static int t128_detect(Scsi_Host_Template *);
int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int t128_host_reset(Scsi_Cmnd *); static int t128_host_reset(Scsi_Cmnd *);
int t128_bus_reset(Scsi_Cmnd *); static int t128_bus_reset(Scsi_Cmnd *);
int t128_device_reset(Scsi_Cmnd *); static int t128_device_reset(Scsi_Cmnd *);
int t128_proc_info (char *buffer, char **start, off_t offset, static int t128_proc_info (char *buffer, char **start, off_t offset,
int length, int hostno, int inout); int length, int hostno, int inout);
#ifndef NULL #ifndef NULL
...@@ -166,7 +166,7 @@ int t128_proc_info (char *buffer, char **start, off_t offset, ...@@ -166,7 +166,7 @@ int t128_proc_info (char *buffer, char **start, off_t offset,
#define do_NCR5380_intr do_t128_intr #define do_NCR5380_intr do_t128_intr
#define NCR5380_queue_command t128_queue_command #define NCR5380_queue_command t128_queue_command
#define NCR5380_abort t128_abort #define NCR5380_abort t128_abort
#define NCR5380_host_reset t128_hostreset #define NCR5380_host_reset t128_host_reset
#define NCR5380_device_reset t128_device_reset #define NCR5380_device_reset t128_device_reset
#define NCR5380_bus_reset t128_bus_reset #define NCR5380_bus_reset t128_bus_reset
#define NCR5380_proc_info t128_proc_info #define NCR5380_proc_info t128_proc_info
......
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