patch-1.3.28 linux/drivers/scsi/scsi.c
Next file: linux/drivers/scsi/scsi.h
Previous file: linux/drivers/scsi/qlogic.h
Back to the patch index
Back to the overall index
- Lines: 591
- Date:
Mon Sep 18 09:01:57 1995
- Orig file:
v1.3.27/linux/drivers/scsi/scsi.c
- Orig date:
Wed Sep 13 12:45:31 1995
diff -u --recursive --new-file v1.3.27/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
@@ -43,18 +43,21 @@
#include <asm/dma.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
+#include<linux/stat.h>
#include "../block/blk.h"
#include "scsi.h"
#include "hosts.h"
#include "constants.h"
+
#undef USE_STATIC_SCSI_MEMORY
/*
static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.c,v 1.5 1993/09/24 12:45:18 drew Exp drew $";
*/
+
/* Command groups 3 and 4 are reserved and should never be used. */
const unsigned char scsi_command_size[8] = { 6, 10, 10, 12, 12, 12, 10, 10 };
@@ -111,6 +114,14 @@
extern int dispatch_scsi_info(int ino, char *buffer, char **start,
off_t offset, int length, int inout);
+struct proc_dir_entry proc_scsi_scsi = {
+ PROC_SCSI_SCSI, 4, "scsi",
+ S_IFREG | S_IRUGO | S_IWUSR, 2, 0, 0, 0,
+ NULL,
+ NULL, NULL,
+ NULL, NULL, NULL
+};
+
/*
* As the scsi do command functions are intelligent, and may need to
@@ -333,7 +344,7 @@
#ifdef DEBUG
printk ("scan_scsis_done(%p, %06x)\n", SCpnt->host, SCpnt->result);
#endif
- SCpnt->request.dev = 0xfffe;
+ SCpnt->request.rq_status = RQ_SCSI_DONE;
if (SCpnt->request.sem != NULL)
up(SCpnt->request.sem);
@@ -359,7 +370,7 @@
* lun address of all sequential devices to the tape driver, all random
* devices to the disk driver.
*/
-
+static
void scan_scsis (struct Scsi_Host * shpnt, unchar hardcoded,
unchar hchannel, unchar hid, unchar hlun)
{
@@ -431,6 +442,7 @@
*/
SDpnt->borken = 1;
SDpnt->was_reset = 0;
+ SDpnt->expecting_cc_ua = 0;
scsi_cmd[0] = TEST_UNIT_READY;
scsi_cmd[1] = lun << 5;
@@ -445,8 +457,7 @@
/* Used for mutex if loading devices after boot */
SCpnt->request.sem = NULL;
-
- SCpnt->request.dev = 0xffff; /* Mark not busy */
+ SCpnt->request.rq_status = RQ_SCSI_BUSY;
scsi_do_cmd (SCpnt, (void *) scsi_cmd,
(void *) scsi_result,
@@ -458,16 +469,17 @@
*/
if (current->pid == 0)
- while (SCpnt->request.dev != 0xfffe)
+ while (SCpnt->request.rq_status != RQ_SCSI_DONE)
barrier();
- else if (SCpnt->request.dev != 0xfffe) {
+ else if (SCpnt->request.rq_status != RQ_SCSI_DONE) {
struct semaphore sem = MUTEX_LOCKED;
SCpnt->request.sem = &sem;
down(&sem);
/* Hmm.. Have to ask about this one */
- while (SCpnt->request.dev != 0xfffe) schedule();
+ while (SCpnt->request.rq_status != RQ_SCSI_DONE)
+ schedule();
}
#if defined(DEBUG) || defined(DEBUG_INIT)
@@ -503,7 +515,7 @@
scsi_cmd[4] = 255;
scsi_cmd[5] = 0;
- SCpnt->request.dev = 0xffff; /* Mark not busy */
+ SCpnt->request.rq_status = RQ_SCSI_BUSY;
SCpnt->cmd_len = 0;
scsi_do_cmd (SCpnt, (void *) scsi_cmd,
@@ -511,16 +523,17 @@
256, scan_scsis_done, SCSI_TIMEOUT, 3);
if (current->pid == 0)
- while (SCpnt->request.dev != 0xfffe)
+ while (SCpnt->request.rq_status != RQ_SCSI_DONE)
barrier();
- else if (SCpnt->request.dev != 0xfffe) {
+ else if (SCpnt->request.rq_status != RQ_SCSI_DONE) {
struct semaphore sem = MUTEX_LOCKED;
SCpnt->request.sem = &sem;
down(&sem);
/* Hmm.. Have to ask about this one */
- while (SCpnt->request.dev != 0xfffe) schedule();
+ while (SCpnt->request.rq_status != RQ_SCSI_DONE)
+ schedule();
}
the_result = SCpnt->result;
@@ -674,7 +687,7 @@
scsi_cmd[4] = 0x2a;
scsi_cmd[5] = 0;
- SCpnt->request.dev = 0xffff; /* Mark not busy */
+ SCpnt->request.rq_status = RQ_SCSI_BUSY;
SCpnt->cmd_len = 0;
scsi_do_cmd (SCpnt, (void *) scsi_cmd,
@@ -682,15 +695,15 @@
scan_scsis_done, SCSI_TIMEOUT, 3);
if (current->pid == 0)
- while (SCpnt->request.dev != 0xfffe);
- else if (SCpnt->request.dev != 0xfffe) {
+ while (SCpnt->request.rq_status != RQ_SCSI_DONE);
+ else if (SCpnt->request.rq_status != RQ_SCSI_DONE) {
struct semaphore sem = MUTEX_LOCKED;
SCpnt->request.sem = &sem;
down(&sem);
/* Hmm.. Have to ask about this one */
- while (SCpnt->request.dev != 0xfffe)
+ while (SCpnt->request.rq_status != RQ_SCSI_DONE)
schedule();
}
}
@@ -709,8 +722,8 @@
/*
* If we want to only allow I/O to one of the luns
- * attached to this device at a time, then we set this
- * flag.
+ * attached to this device at a time, then we set
+ * this flag.
*/
if(bflags & BLIST_SINGLELUN)
{
@@ -718,14 +731,15 @@
}
/*
- * If this device is known to support multiple units, override
- * the other settings, and scan all of them.
+ * If this device is known to support multiple
+ * units, override the other settings, and scan
+ * all of them.
*/
if(bflags & BLIST_FORCELUN)
{
/*
- * We probably want to make this a variable, but this
- * will do for now.
+ * We probably want to make this a variable,
+ * but this will do for now.
*/
max_dev_lun = 8;
}
@@ -743,8 +757,8 @@
} /* if result == DID_OK ends */
/*
- * This might screw us up with multi-lun devices, but the user can
- * scan for them too.
+ * This might screw us up with multi-lun devices, but the
+ * user can scan for them too.
*/
if(hardcoded == 1)
goto leave;
@@ -756,7 +770,6 @@
leave:
shpnt->host_queue = NULL; /* No longer needed here */
-
/* Last device block does not exist. Free memory. */
if(SDpnt != NULL)
scsi_init_free((char *) SDpnt, sizeof(Scsi_Device));
@@ -839,15 +852,15 @@
if (!device)
panic ("No device passed to request_queueable().\n");
- if (req && req->dev <= 0)
- panic("Invalid device in request_queueable");
+ if (req && req->rq_status == RQ_INACTIVE)
+ panic("Inactive in request_queueable");
SCpnt = device->host->host_queue;
/*
* Look for a free command block. If we have been instructed not to queue
- * multiple commands to multi-lun devices, then check to see what else is going on
- * for this device first.
+ * multiple commands to multi-lun devices, then check to see what else is
+ * going for this device first.
*/
SCpnt = device->host->host_queue;
@@ -855,7 +868,7 @@
while(SCpnt){
if(SCpnt->target == device->id &&
SCpnt->lun == device->lun) {
- if(SCpnt->request.dev < 0) break;
+ if(SCpnt->request.rq_status == RQ_INACTIVE) break;
}
SCpnt = SCpnt->next;
}
@@ -864,16 +877,16 @@
if(SCpnt->target == device->id) {
if (SCpnt->lun == device->lun) {
if(found == NULL
- && SCpnt->request.dev < 0)
+ && SCpnt->request.rq_status == RQ_INACTIVE)
{
found=SCpnt;
}
}
- if(SCpnt->request.dev >= 0) {
+ if(SCpnt->request.rq_status != RQ_INACTIVE) {
/*
* I think that we should really limit things to one
- * outstanding command per device - this is what tends to trip
- * up buggy firmware.
+ * outstanding command per device - this is what tends
+ * to trip up buggy firmware.
*/
return NULL;
}
@@ -916,11 +929,11 @@
req->buffer = bh->b_data;
SCpnt->request.sem = NULL; /* Wait until whole thing done */
} else {
- req->dev = -1;
+ req->rq_status = RQ_INACTIVE;
wake_up(&wait_for_request);
}
} else {
- SCpnt->request.dev = 0xffff; /* Busy, but no request */
+ SCpnt->request.rq_status = RQ_SCSI_BUSY; /* Busy, but no request */
SCpnt->request.sem = NULL; /* And no one is waiting for the device
* either */
}
@@ -954,7 +967,7 @@
Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device,
int wait)
{
- int dev = -1;
+ kdev_t dev;
struct request * req = NULL;
int tablesize;
unsigned int flags;
@@ -970,7 +983,11 @@
if (reqp) req = *reqp;
/* See if this request has already been queued by an interrupt routine */
- if (req && (dev = req->dev) <= 0) return NULL;
+ if (req) {
+ if(req->rq_status == RQ_INACTIVE) return NULL;
+ dev = req->rq_dev;
+ } else
+ dev = 0; /* unused */
host = device->host;
@@ -983,7 +1000,7 @@
if(SCpnt->target == device->id &&
SCpnt->lun == device->lun) {
SCwait = SCpnt;
- if(SCpnt->request.dev < 0) break;
+ if(SCpnt->request.rq_status == RQ_INACTIVE) break;
}
SCpnt = SCpnt->next;
}
@@ -993,16 +1010,16 @@
if (SCpnt->lun == device->lun) {
SCwait = SCpnt;
if(found == NULL
- && SCpnt->request.dev < 0)
+ && SCpnt->request.rq_status == RQ_INACTIVE)
{
found=SCpnt;
}
}
- if(SCpnt->request.dev >= 0) {
+ if(SCpnt->request.rq_status != RQ_INACTIVE) {
/*
* I think that we should really limit things to one
- * outstanding command per device - this is what tends to trip
- * up buggy firmware.
+ * outstanding command per device - this is what tends
+ * to trip up buggy firmware.
*/
found = NULL;
break;
@@ -1017,11 +1034,11 @@
cli();
/* See if this request has already been queued by an interrupt routine
*/
- if (req && ((req->dev < 0) || (req->dev != dev))) {
+ if (req && (req->rq_status == RQ_INACTIVE || req->rq_dev != dev)) {
restore_flags(flags);
return NULL;
}
- if (!SCpnt || SCpnt->request.dev >= 0) /* Might have changed */
+ if (!SCpnt || SCpnt->request.rq_status != RQ_INACTIVE) /* Might have changed */
{
restore_flags(flags);
if(!wait) return NULL;
@@ -1031,7 +1048,7 @@
panic("No device found in allocate_device\n");
}
SCSI_SLEEP(&device->device_wait,
- (SCwait->request.dev > 0));
+ (SCwait->request.rq_status != RQ_INACTIVE));
} else {
if (req) {
memcpy(&SCpnt->request, req, sizeof(struct request));
@@ -1063,12 +1080,12 @@
}
else
{
- req->dev = -1;
+ req->rq_status = RQ_INACTIVE;
*reqp = req->next;
wake_up(&wait_for_request);
}
} else {
- SCpnt->request.dev = 0xffff; /* Busy */
+ SCpnt->request.rq_status = RQ_SCSI_BUSY;
SCpnt->request.sem = NULL; /* And no one is waiting for this
* to complete */
}
@@ -1371,6 +1388,17 @@
return SUGGEST_RETRY;
case NOT_READY:
case UNIT_ATTENTION:
+ /*
+ * If we are expecting a CC/UA because of a bus reset that we
+ * performed, treat this just as a retry. Otherwise this is
+ * information that we should pass up to the upper-level driver
+ * so that we can deal with it there.
+ */
+ if( SCpnt->device->expecting_cc_ua )
+ {
+ SCpnt->device->expecting_cc_ua = 0;
+ return SUGGEST_RETRY;
+ }
return SUGGEST_ABORT;
/* these three are not supported */
@@ -1721,8 +1749,8 @@
host_active = NULL;
/* For block devices "wake_up" is done in end_scsi_request */
- if (MAJOR(SCpnt->request.dev) != SCSI_DISK_MAJOR &&
- MAJOR(SCpnt->request.dev) != SCSI_CDROM_MAJOR) {
+ if (MAJOR(SCpnt->request.rq_dev) != SCSI_DISK_MAJOR &&
+ MAJOR(SCpnt->request.rq_dev) != SCSI_CDROM_MAJOR) {
struct Scsi_Host * next;
for (next = host->block; next != host; next = next->block)
@@ -1775,7 +1803,7 @@
* Protect against races here. If the command is done, or we are
* on a different command forget it.
*/
- if (SCpnt->request.dev == -1 || pid != SCpnt->pid) {
+ if (SCpnt->request.rq_status == RQ_INACTIVE || pid != SCpnt->pid) {
restore_flags(flags);
return 0;
}
@@ -1812,7 +1840,7 @@
SCpnt->pid, SCpnt->host->host_no, (int) SCpnt->channel,
(int) SCpnt->target, (int) SCpnt->lun);
print_command (SCpnt->cmnd);
- if (SCpnt->request.dev == -1 || pid != SCpnt->pid)
+ if (SCpnt->request.rq_status == RQ_INACTIVE || pid != SCpnt->pid)
return 0;
SCpnt->abort_reason = why;
switch(host->hostt->abort(SCpnt)) {
@@ -1898,7 +1926,7 @@
*/
SCpnt1 = host->host_queue;
while(SCpnt1) {
- if( SCpnt->request.dev > 0
+ if( SCpnt->request.rq_status != RQ_INACTIVE
&& (SCpnt->flags & WAS_RESET) == 0 )
break;
SCpnt1 = SCpnt1->next;
@@ -1934,7 +1962,7 @@
restore_flags(flags);
SCpnt1 = host->host_queue;
while(SCpnt1) {
- if (SCpnt1->request.dev > 0) {
+ if (SCpnt1->request.rq_status != RQ_INACTIVE) {
#if 0
if (!(SCpnt1->flags & IS_RESETTING) &&
!(SCpnt1->internal_timeout & IN_ABORT))
@@ -1973,6 +2001,7 @@
SCpnt1 = host->host_queue;
while(SCpnt1) {
SCpnt1->device->was_reset = 1;
+ SCpnt1->device->expecting_cc_ua = 1;
SCpnt1 = SCpnt1->next;
}
}
@@ -2007,7 +2036,7 @@
{
SCpnt1 = host->host_queue;
while(SCpnt1) {
- if( SCpnt->request.dev > 0
+ if( SCpnt->request.rq_status != RQ_INACTIVE
&& SCpnt1 != SCpnt)
scsi_request_sense (SCpnt);
SCpnt1 = SCpnt1->next;
@@ -2317,7 +2346,7 @@
SCpnt->target = SDpnt->id;
SCpnt->lun = SDpnt->lun;
SCpnt->channel = SDpnt->channel;
- SCpnt->request.dev = -1; /* Mark not busy */
+ SCpnt->request.rq_status = RQ_INACTIVE;
SCpnt->use_sg = 0;
SCpnt->old_use_sg = 0;
SCpnt->old_cmd_len = 0;
@@ -2365,6 +2394,12 @@
timer_table[SCSI_TIMER].fn = scsi_main_timeout;
timer_table[SCSI_TIMER].expires = 0;
+
+ /* Register the core /proc/scsi entry */
+#if CONFIG_PROC_FS
+ proc_scsi_register(0, &proc_scsi_scsi);
+#endif
+
/* initialize all hosts */
scsi_init();
@@ -2525,7 +2560,8 @@
pos = begin + len;
while (HBA_ptr) {
#if 0
- size += sprintf(buffer+len,"scsi%2d: %s\n", (int) HBA_ptr->host_no, HBA_ptr->hostt->procname);
+ size += sprintf(buffer+len,"scsi%2d: %s\n", (int) HBA_ptr->host_no,
+ HBA_ptr->hostt->procname);
len += size;
pos = begin + len;
#endif
@@ -2550,9 +2586,9 @@
stop_output:
*start=buffer+(offset-begin); /* Start of wanted data */
- len-=(offset-begin); /* Start slop */
+ len-=(offset-begin); /* Start slop */
if(len>length)
- len = length; /* Ending slop */
+ len = length; /* Ending slop */
return (len);
}
@@ -2626,7 +2662,7 @@
/* Add the new driver to /proc/scsi */
#if CONFIG_PROC_FS
- build_proc_dir_entries();
+ build_proc_dir_entries(tpnt);
#endif
for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next)
@@ -2794,14 +2830,15 @@
{
save_flags(flags);
cli();
- if(SCpnt->request.dev != -1) {
+ if(SCpnt->request.rq_status != RQ_INACTIVE) {
restore_flags(flags);
for(SCpnt = shpnt->host_queue; SCpnt; SCpnt = SCpnt->next)
- if(SCpnt->request.dev == 0xffe0) SCpnt->request.dev = -1;
+ if(SCpnt->request.rq_status == RQ_SCSI_DISCONNECTING)
+ SCpnt->request.rq_status = RQ_INACTIVE;
printk("Device busy???\n");
return;
}
- SCpnt->request.dev = 0xffe0; /* Mark as busy */
+ SCpnt->request.rq_status = RQ_SCSI_DISCONNECTING; /* Mark as busy */
restore_flags(flags);
}
}
@@ -2856,6 +2893,11 @@
if(shpnt->hostt == tpnt) {
if(shpnt->loaded_as_module) {
pcount = next_scsi_host;
+ /* Remove the /proc/scsi directory entry */
+#if CONFIG_PROC_FS
+ proc_scsi_unregister(tpnt->proc_dir,
+ shpnt->host_no + PROC_SCSI_FILE);
+#endif
if(tpnt->release)
(*tpnt->release)(shpnt);
else {
@@ -2905,7 +2947,7 @@
/* Rebuild the /proc/scsi directory entries */
#if CONFIG_PROC_FS
- build_proc_dir_entries();
+ proc_scsi_unregister(tpnt->proc_dir, tpnt->proc_dir->low_ino);
#endif
MOD_DEC_USE_COUNT;
}
@@ -3075,12 +3117,12 @@
for(SCpnt=shpnt->host_queue; SCpnt; SCpnt = SCpnt->next)
{
/* (0) 0:0:0:0 (802 123434 8 8 0) (3 3 2) (%d %d %d) %d %x */
- printk("(%d) %d:%d:%d:%d (%4.4x %ld %ld %ld %ld) (%d %d %x) (%d %d %d) %x %x %x\n",
+ printk("(%d) %d:%d:%d:%d (%s %ld %ld %ld %ld) (%d %d %x) (%d %d %d) %x %x %x\n",
i++, SCpnt->host->host_no,
SCpnt->channel,
SCpnt->target,
SCpnt->lun,
- SCpnt->request.dev,
+ kdevname(SCpnt->request.rq_dev),
SCpnt->request.sector,
SCpnt->request.nr_sectors,
SCpnt->request.current_nr_sectors,
@@ -3105,8 +3147,8 @@
printk("%d: ", i);
req = blk_dev[i].current_request;
while(req) {
- printk("(%x %d %ld %ld %ld) ",
- req->dev,
+ printk("(%s %d %ld %ld %ld) ",
+ kdevname(req->rq_dev),
req->cmd,
req->sector,
req->nr_sectors,
@@ -3125,18 +3167,10 @@
extern struct symbol_table scsi_symbol_table;
-int init_module(void) {
-
-#if CONFIG_PROC_FS
- /*
- * This will initialize the directory so that we do not have
- * random crap in there.
- */
- build_proc_dir_entries();
-#endif
+int init_module(void) {
/*
- * This makes the real /proc/scsi visible.
+ * This makes /proc/scsi visible.
*/
dispatch_scsi_info_ptr = dispatch_scsi_info;
@@ -3181,8 +3215,10 @@
*/
for(i=0; i < dma_sectors >> 3; i++)
scsi_init_free(dma_malloc_pages[i], PAGE_SIZE);
- scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
- scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
+ if (dma_malloc_pages)
+ scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
+ if (dma_malloc_freelist)
+ scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
timer_table[SCSI_TIMER].fn = NULL;
timer_table[SCSI_TIMER].expires = 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this