patch-1.3.47 linux/drivers/scsi/scsi.c
Next file: linux/drivers/scsi/scsi.h
Previous file: linux/drivers/scsi/constants.c
Back to the patch index
Back to the overall index
- Lines: 301
- Date:
Tue Dec 12 07:16:37 1995
- Orig file:
v1.3.46/linux/drivers/scsi/scsi.c
- Orig date:
Mon Dec 11 15:42:03 1995
diff -u --recursive --new-file v1.3.46/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
@@ -65,6 +65,7 @@
static int scan_scsis_single (int channel,int dev,int lun,int * max_scsi_dev ,
Scsi_Device ** SDpnt, Scsi_Cmnd * SCpnt,
struct Scsi_Host *shpnt, char * scsi_result);
+void scsi_build_commandblocks(Scsi_Device * SDpnt);
static unsigned char * dma_malloc_freelist = NULL;
@@ -272,18 +273,6 @@
return 0;
}
-/*
- * As the actual SCSI command runs in the background, we must set up a
- * flag that tells scan_scsis() when the result it has is valid.
- * scan_scsis can set the_result to -1, and watch for it to become the
- * actual return code for that call. the scan_scsis_done function() is
- * our user specified completion function that is passed on to the
- * scsi_do_cmd() function.
- */
-
-volatile int in_scan_scsis = 0;
-static int the_result;
-
void scsi_make_blocked_list(void) {
int block_count = 0, index;
unsigned int flags;
@@ -385,9 +374,10 @@
int max_dev_lun;
Scsi_Cmnd *SCpnt;
- in_scan_scsis++;
SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), GFP_ATOMIC | GFP_DMA);
SDpnt = (Scsi_Device *) scsi_init_malloc (sizeof (Scsi_Device), GFP_ATOMIC);
+ memset (SCpnt, 0, sizeof (Scsi_Cmnd));
+
/* Make sure we have something that is valid for DMA purposes */
scsi_result = ((!dma_malloc_freelist || !shpnt->unchecked_isa_dma)
@@ -398,9 +388,17 @@
goto leave;
}
- shpnt->host_queue = SCpnt; /* We need this so that commands can time out */
+ /* We must chain ourself in the host_queue, so commands can time out */
+ if(shpnt->host_queue)
+ shpnt->host_queue->prev = SCpnt;
+ SCpnt->next = shpnt->host_queue;
+ SCpnt->prev = NULL;
+ shpnt->host_queue = SCpnt;
+
if (hardcoded == 1) {
+ Scsi_Device *oldSDpnt=SDpnt;
+ struct Scsi_Device_Template * sdtpnt;
channel = hchannel;
if(channel > shpnt->max_channel) goto leave;
dev = hid;
@@ -409,11 +407,31 @@
if(lun >= shpnt->max_lun) goto leave;
scan_scsis_single (channel, dev, lun, &max_dev_lun,
&SDpnt, SCpnt, shpnt, scsi_result);
+ if(SDpnt!=oldSDpnt) {
+
+ /* it could happen the blockdevice hasn't yet been inited */
+ for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
+ if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)();
+
+ oldSDpnt->scsi_request_fn = NULL;
+ for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
+ if(sdtpnt->attach) {
+ (*sdtpnt->attach)(oldSDpnt);
+ if(oldSDpnt->attached) scsi_build_commandblocks(oldSDpnt);}
+ resize_dma_pool();
+
+ for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
+ if(sdtpnt->finish && sdtpnt->nr_dev)
+ {(*sdtpnt->finish)();}
+ }
+ }
+
}
else {
for (channel = 0; channel <= shpnt->max_channel; channel++) {
for (dev = 0; dev < shpnt->max_id; ++dev) {
if (shpnt->this_id != dev) {
+
/*
* We need the for so our continue, etc. work fine. We put this in
* a variable so that we can override it during the scan if we
@@ -421,20 +439,32 @@
*/
max_dev_lun = (max_scsi_luns < shpnt->max_lun ?
max_scsi_luns : shpnt->max_lun);
-
for (lun = 0; lun < max_dev_lun; ++lun) {
-
if (!scan_scsis_single (channel, dev, lun, &max_dev_lun,
&SDpnt, SCpnt, shpnt, scsi_result))
- break; /* break means don't probe for luns!=0 */
+ break; /* break means don't probe further for luns!=0 */
} /* for lun ends */
} /* if this_id != id ends */
} /* for dev ends */
} /* for channel ends */
+ } /* if/else hardcoded */
-leave:
- shpnt->host_queue = NULL; /* No longer needed here */
+ leave:
+ {/* Unchain SCpnt from host_queue */
+ Scsi_Cmnd *prev,*next,*hqptr;
+ for(hqptr=shpnt->host_queue; hqptr!=SCpnt; hqptr=hqptr->next) ;
+ if(hqptr) {
+ prev=hqptr->prev;
+ next=hqptr->next;
+ if(prev)
+ prev->next=next;
+ else
+ shpnt->host_queue=next;
+ if(next) next->prev=prev;
+ }
+ }
+
/* Last device block does not exist. Free memory. */
if (SDpnt != NULL)
scsi_init_free ((char *) SDpnt, sizeof (Scsi_Device));
@@ -446,14 +476,12 @@
if (scsi_result != &scsi_result0[0] && scsi_result != NULL)
scsi_free (scsi_result, 512);
- in_scan_scsis--;
- }
}
/*
* The worker for scan_scsis.
* Returning 0 means Please don't ask further for lun!=0, 1 means OK go on.
- * Global variables used : scsi_devices(linked list), the_result
+ * Global variables used : scsi_devices(linked list)
*/
int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun,
Scsi_Device **SDpnt2, Scsi_Cmnd * SCpnt, struct Scsi_Host * shpnt,
@@ -490,7 +518,6 @@
scsi_cmd[1] = lun << 5;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = 0;
- memset (SCpnt, 0, sizeof (Scsi_Cmnd));
SCpnt->host = SDpnt->host;
SCpnt->device = SDpnt;
SCpnt->target = SDpnt->id;
@@ -507,8 +534,10 @@
}
#if defined(DEBUG) || defined(DEBUG_INIT)
- printk ("scsi: scan_scsis_single id %d lun %d. Return code %d\n",
+ printk ("scsi: scan_scsis_single id %d lun %d. Return code 0x%08x\n",
dev, lun, SCpnt->result);
+ print_driverbyte(SCpnt->result); print_hostbyte(SCpnt->result);
+ printk("\n");
#endif
if (SCpnt->result) {
@@ -546,13 +575,12 @@
down (&sem);
}
- the_result = SCpnt->result;
#if defined(DEBUG) || defined(DEBUG_INIT)
printk ("scsi: INQUIRY %s with code 0x%x\n",
- the_result ? "failed" : "successful", the->result);
+ SCpnt->result ? "failed" : "successful", SCpnt->result);
#endif
- if (the_result)
+ if (SCpnt->result)
return 0; /* assume no peripheral if any sort of error */
/*
@@ -696,7 +724,7 @@
SDpnt = (Scsi_Device *) scsi_init_malloc (sizeof (Scsi_Device), GFP_ATOMIC);
*SDpnt2=SDpnt;
if (!SDpnt)
- printk ("scsi: scan_scsis_single: No memory\n");
+ printk ("scsi: scan_scsis_single: Cannot malloc\n");
/*
@@ -750,7 +778,7 @@
switch (SCpnt->internal_timeout & (IN_ABORT | IN_RESET))
{
case NORMAL_TIMEOUT:
- if (!in_scan_scsis) {
+ {
#ifdef DEBUG_TIMEOUT
scsi_dump_status();
#endif
@@ -1460,7 +1488,7 @@
printk ("Internal error %s %d \n", __FILE__,
__LINE__);
}
- }
+ } /* end WAS_SENSE */
else
{
#ifdef DEBUG
@@ -1734,8 +1762,7 @@
SCpnt->internal_timeout |= IN_ABORT;
oldto = update_timeout(SCpnt, ABORT_TIMEOUT);
- if ((SCpnt->flags & IS_RESETTING) &&
- SCpnt->device->soft_reset) {
+ if ((SCpnt->flags & IS_RESETTING) && SCpnt->device->soft_reset) {
/* OK, this command must have died when we did the
* reset. The device itself must have lied.
*/
@@ -1797,6 +1824,8 @@
/* We should have already aborted this one. No
* need to adjust timeout
*/
+ SCpnt->internal_timeout &= ~IN_ABORT;
+ return 0;
case SCSI_ABORT_NOT_RUNNING:
SCpnt->internal_timeout &= ~IN_ABORT;
update_timeout(SCpnt, 0);
@@ -1837,10 +1866,8 @@
Scsi_Cmnd * SCpnt1;
struct Scsi_Host * host = SCpnt->host;
-#ifdef DEBUG
- printk("Danger Will Robinson! - SCSI bus for host %d is being reset.\n",
+ printk("SCSI bus is being reset for host %d.\n",
host->host_no);
-#endif
/*
* First of all, we need to make a recommendation to the low-level
@@ -1862,10 +1889,8 @@
SCpnt1 = host->host_queue;
while(SCpnt1) {
if( SCpnt1->request.rq_status != RQ_INACTIVE
- && (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0 )
- {
- break;
- }
+ && (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0 )
+ break;
SCpnt1 = SCpnt1->next;
}
if( SCpnt1 == NULL ) {
@@ -2154,7 +2179,7 @@
unsigned long flags;
#ifdef DEBUG
- printk("Sfree %p %d\n",obj, len);
+ printk("scsi_free %p %d\n",obj, len);
#endif
offset = -1;
@@ -2167,20 +2192,20 @@
break;
}
- if (page == (dma_sectors >> 3)) panic("Bad offset");
+ if (page == (dma_sectors >> 3)) panic("scsi_free:Bad offset");
sector = offset >> 9;
- if(sector >= dma_sectors) panic ("Bad page");
+ if(sector >= dma_sectors) panic ("scsi_free:Bad page");
sector = (offset >> 9) & (sizeof(*dma_malloc_freelist) * 8 - 1);
nbits = len >> 9;
mask = (1 << nbits) - 1;
- if ((mask << sector) > 0xffff) panic ("Bad memory alignment");
+ if ((mask << sector) > 0xffff) panic ("scsi_free:Bad memory alignment");
save_flags(flags);
cli();
if((dma_malloc_freelist[page] & (mask << sector)) != (mask<<sector))
- panic("Trying to free unused memory");
+ panic("scsi_free:Trying to free unused memory");
dma_free_sectors += nbits;
dma_malloc_freelist[page] &= ~(mask << sector);
@@ -2438,8 +2463,13 @@
/*
* Usage: echo "scsi singledevice 0 1 2 3" >/proc/scsi/scsi
* with "0 1 2 3" replaced by your "Host Channel Id Lun".
- * Consider this feature ALPHA, as you can easily hang your
- * scsi system (depending on your low level driver).
+ * Consider this feature BETA.
+ * CAUTION: This is not for hotplugging your peripherals. As
+ * SCSI was not designed for this you could damage your
+ * hardware !
+ * However perhaps it is legal to switch on an
+ * already connected device. It is perhaps not
+ * guaranteed this device doesn't corrupt an ongoing data transfer.
*/
if(!buffer || length < 25 || strncmp("scsi", buffer, 4))
return(-EINVAL);
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