Commit a19bafa6 authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Linus Torvalds

[PATCH] scsi stuff

The patch below cleans up some SCSI stuff.

The main purpose is to avoid trying to read the partition table
of a removable disk when the drive has told us that no media
are present. (Right now we try to read a 4K block and fail and
retry and fail, and give an I/O error on the first sector,
then try to read the second sector and fail and retry ...)

Unused fields  sector_bit_size  and  sector_bit_shift  in
struct scsi_disk were removed. The field  has_part_table
(that has nothing to do with partition tables) was
renamed to  has_been_registered . The field  ready  was
renamed to  media_present .
The overly long  sd_init_onedisk()  was split up.

When we notice that no media are present anymore, the
partitions are removed from /proc/partitions, but the
drive remains, with size 0.

A future patch will remove the field  capacity  - there are
all too many places where capacities are stored - but the
present patch is large enough already.

There is also a quite independent patch in scsi_error.c
(yesterday someone had an infinite loop retrying to read
bad media) - this patch honours the SCpnt->retries.
In case you applied this already, just ignore the scsi_error.c part.

Also some "Overrides for Emacs" were removed.
parent 2b4b6c20
...@@ -177,9 +177,10 @@ static int show_partition(struct seq_file *part, void *v) ...@@ -177,9 +177,10 @@ static int show_partition(struct seq_file *part, void *v)
if (sgp == gendisk_head) if (sgp == gendisk_head)
seq_puts(part, "major minor #blocks name\n\n"); seq_puts(part, "major minor #blocks name\n\n");
/* show all non-0 size partitions of this disk */ /* show the full disk and all non-0 size partitions of it */
for (n = 0; n < (sgp->nr_real << sgp->minor_shift); n++) { for (n = 0; n < (sgp->nr_real << sgp->minor_shift); n++) {
if (sgp->part[n].nr_sects == 0) int minormask = (1<<sgp->minor_shift) - 1;
if ((n & minormask) && sgp->part[n].nr_sects == 0)
continue; continue;
seq_printf(part, "%4d %4d %10d %s\n", seq_printf(part, "%4d %4d %10d %s\n",
sgp->major, n, sgp->sizes[n], sgp->major, n, sgp->sizes[n],
......
...@@ -2048,7 +2048,7 @@ static int esp_do_data_finale(struct NCR_ESP *esp, ...@@ -2048,7 +2048,7 @@ static int esp_do_data_finale(struct NCR_ESP *esp,
* and not only for the entire host adapter as it is now, the workaround * and not only for the entire host adapter as it is now, the workaround
* is way to expensive performance wise. * is way to expensive performance wise.
* Instead, it turns out that when this happens the target has disconnected * Instead, it turns out that when this happens the target has disconnected
* allready but it doesn't show in the interrupt register. Compensate for * already but it doesn't show in the interrupt register. Compensate for
* that here to try and avoid a SCSI bus reset. * that here to try and avoid a SCSI bus reset.
*/ */
if(!esp->fas_premature_intr_workaround && (fifocnt == 1) && if(!esp->fas_premature_intr_workaround && (fifocnt == 1) &&
......
...@@ -1095,6 +1095,8 @@ int scsi_decide_disposition(Scsi_Cmnd * SCpnt) ...@@ -1095,6 +1095,8 @@ int scsi_decide_disposition(Scsi_Cmnd * SCpnt)
*/ */
STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt) STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
{ {
int rtn;
/* /*
* First check the host byte, to see if there is anything in there * First check the host byte, to see if there is anything in there
* that would indicate what we need to do. * that would indicate what we need to do.
...@@ -1102,20 +1104,25 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt) ...@@ -1102,20 +1104,25 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
if (host_byte(SCpnt->result) == DID_RESET) { if (host_byte(SCpnt->result) == DID_RESET) {
if (SCpnt->flags & IS_RESETTING) { if (SCpnt->flags & IS_RESETTING) {
/* /*
* OK, this is normal. We don't know whether in fact the * OK, this is normal. We don't know whether in fact
* command in question really needs to be rerun or not - * the command in question really needs to be rerun
* if this was the original data command then the answer is yes, * or not - if this was the original data command then
* otherwise we just flag it as success. * the answer is yes, otherwise we just flag it as
* success.
*/ */
SCpnt->flags &= ~IS_RESETTING; SCpnt->flags &= ~IS_RESETTING;
return NEEDS_RETRY; goto maybe_retry;
} }
/* /*
* Rats. We are already in the error handler, so we now get to try * Rats. We are already in the error handler, so we now
* and figure out what to do next. If the sense is valid, we have * get to try and figure out what to do next. If the sense
* a pretty good idea of what to do. If not, we mark it as failed. * is valid, we have a pretty good idea of what to do.
* If not, we mark it as failed.
*/ */
return scsi_check_sense(SCpnt); rtn = scsi_check_sense(SCpnt);
if (rtn == NEEDS_RETRY)
goto maybe_retry;
return rtn;
} }
if (host_byte(SCpnt->result) != DID_OK) { if (host_byte(SCpnt->result) != DID_OK) {
return FAILED; return FAILED;
...@@ -1127,14 +1134,18 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt) ...@@ -1127,14 +1134,18 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
return FAILED; return FAILED;
} }
/* /*
* Now, check the status byte to see if this indicates anything special. * Now, check the status byte to see if this indicates
* anything special.
*/ */
switch (status_byte(SCpnt->result)) { switch (status_byte(SCpnt->result)) {
case GOOD: case GOOD:
case COMMAND_TERMINATED: case COMMAND_TERMINATED:
return SUCCESS; return SUCCESS;
case CHECK_CONDITION: case CHECK_CONDITION:
return scsi_check_sense(SCpnt); rtn = scsi_check_sense(SCpnt);
if (rtn == NEEDS_RETRY)
goto maybe_retry;
return rtn;
case CONDITION_GOOD: case CONDITION_GOOD:
case INTERMEDIATE_GOOD: case INTERMEDIATE_GOOD:
case INTERMEDIATE_C_GOOD: case INTERMEDIATE_C_GOOD:
...@@ -1149,6 +1160,14 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt) ...@@ -1149,6 +1160,14 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
return FAILED; return FAILED;
} }
return FAILED; return FAILED;
maybe_retry:
if ((++SCpnt->retries) < SCpnt->allowed) {
return NEEDS_RETRY;
} else {
/* No more retries - report this one back to upper level */
return SUCCESS;
}
} }
/* /*
......
...@@ -127,7 +127,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd, ...@@ -127,7 +127,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
/* gag this error, VFS will log it anyway /axboe */ /* gag this error, VFS will log it anyway /axboe */
/* printk(KERN_INFO "Disc change detected.\n"); */ /* printk(KERN_INFO "Disc change detected.\n"); */
break; break;
}; }
default: /* Fall through for non-removable media */ default: /* Fall through for non-removable media */
printk("SCSI error: host %d id %d lun %d return code = %x\n", printk("SCSI error: host %d id %d lun %d return code = %x\n",
dev->host->host_no, dev->host->host_no,
...@@ -139,7 +139,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd, ...@@ -139,7 +139,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
sense_error(SRpnt->sr_sense_buffer[0]), sense_error(SRpnt->sr_sense_buffer[0]),
SRpnt->sr_sense_buffer[2] & 0xf); SRpnt->sr_sense_buffer[2] & 0xf);
}; }
result = SRpnt->sr_result; result = SRpnt->sr_result;
...@@ -152,7 +152,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd, ...@@ -152,7 +152,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
} }
/* /*
* This interface is depreciated - users should use the scsi generic (sg) * This interface is deprecated - users should use the scsi generic (sg)
* interface instead, as this is a more flexible approach to performing * interface instead, as this is a more flexible approach to performing
* generic SCSI commands on a device. * generic SCSI commands on a device.
* *
...@@ -516,22 +516,3 @@ int kernel_scsi_ioctl(Scsi_Device * dev, int cmd, void *arg) ...@@ -516,22 +516,3 @@ int kernel_scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
set_fs(oldfs); set_fs(oldfs);
return tmp; return tmp;
} }
/*
* Overrides for Emacs so that we almost follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 4
* c-brace-imaginary-offset: 0
* c-brace-offset: -4
* c-argdecl-indent: 4
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
...@@ -96,7 +96,7 @@ static int *sd_max_sectors; ...@@ -96,7 +96,7 @@ static int *sd_max_sectors;
static int check_scsidisk_media_change(kdev_t); static int check_scsidisk_media_change(kdev_t);
static int fop_revalidate_scsidisk(kdev_t); static int fop_revalidate_scsidisk(kdev_t);
static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr); static void sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr);
static int sd_init(void); static int sd_init(void);
static void sd_finish(void); static void sd_finish(void);
...@@ -152,22 +152,24 @@ sd_find_target(void *hp, int scsi_id) ...@@ -152,22 +152,24 @@ sd_find_target(void *hp, int scsi_id)
Scsi_Device *sdp; Scsi_Device *sdp;
struct Scsi_Host *shp = hp; struct Scsi_Host *shp = hp;
int dsk_nr; int dsk_nr;
kdev_t retval = NODEV;
unsigned long iflags; unsigned long iflags;
SCSI_LOG_HLQUEUE(3, printk("sd_find_target: host_nr=%d, " SCSI_LOG_HLQUEUE(3, printk("sd_find_target: host_nr=%d, "
"scsi_id=%d\n", shp->host_no, scsi_id)); "scsi_id=%d\n", shp->host_no, scsi_id));
read_lock_irqsave(&sd_dsk_arr_lock, iflags); read_lock_irqsave(&sd_dsk_arr_lock, iflags);
for (dsk_nr = 0; dsk_nr < sd_template.dev_max; ++dsk_nr) { for (dsk_nr = 0; dsk_nr < sd_template.dev_max; ++dsk_nr) {
if (NULL == (sdkp = sd_dsk_arr[dsk_nr])) sdkp = sd_dsk_arr[dsk_nr];
if (sdkp == NULL)
continue; continue;
sdp = sdkp->device; sdp = sdkp->device;
if (sdp && (sdp->host == shp) && (sdp->id == scsi_id)) { if (sdp && (sdp->host == shp) && (sdp->id == scsi_id)) {
read_unlock_irqrestore(&sd_dsk_arr_lock, iflags); retval = MKDEV_SD(dsk_nr);
return MKDEV_SD(dsk_nr); break;
} }
} }
read_unlock_irqrestore(&sd_dsk_arr_lock, iflags); read_unlock_irqrestore(&sd_dsk_arr_lock, iflags);
return NODEV; return retval;
} }
#endif #endif
...@@ -222,8 +224,8 @@ static int sd_ioctl(struct inode * inode, struct file * filp, ...@@ -222,8 +224,8 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
/* default to most commonly used values */ /* default to most commonly used values */
diskinfo[0] = 0x40; diskinfo[0] = 0x40; /* 1 << 6 */
diskinfo[1] = 0x20; diskinfo[1] = 0x20; /* 1 << 5 */
diskinfo[2] = sdkp->capacity >> 11; diskinfo[2] = sdkp->capacity >> 11;
/* override with calculated, extended default, /* override with calculated, extended default,
...@@ -531,7 +533,7 @@ static int sd_open(struct inode *inode, struct file *filp) ...@@ -531,7 +533,7 @@ static int sd_open(struct inode *inode, struct file *filp)
/* /*
* If the drive is empty, just let the open fail. * If the drive is empty, just let the open fail.
*/ */
if ((!sdkp->ready) && !(filp->f_flags & O_NDELAY)) { if ((!sdkp->media_present) && !(filp->f_flags & O_NDELAY)) {
retval = -ENOMEDIUM; retval = -ENOMEDIUM;
goto error_out; goto error_out;
} }
...@@ -787,8 +789,7 @@ static int check_scsidisk_media_change(kdev_t full_dev) ...@@ -787,8 +789,7 @@ static int check_scsidisk_media_change(kdev_t full_dev)
* that we would ever take a device offline in the first place. * that we would ever take a device offline in the first place.
*/ */
if (sdp->online == FALSE) { if (sdp->online == FALSE) {
sdkp->ready = 0; sd_set_media_not_present(sdkp);
sdp->changed = 1;
return 1; /* This will force a flush, if called from return 1; /* This will force a flush, if called from
* check_disk_change */ * check_disk_change */
} }
...@@ -809,18 +810,17 @@ static int check_scsidisk_media_change(kdev_t full_dev) ...@@ -809,18 +810,17 @@ static int check_scsidisk_media_change(kdev_t full_dev)
* it out later once the drive is available * it out later once the drive is available
* again. */ * again. */
sdkp->ready = 0; sd_set_media_not_present(sdkp);
sdp->changed = 1;
return 1; /* This will force a flush, if called from return 1; /* This will force a flush, if called from
* check_disk_change */ * check_disk_change */
} }
/* /*
* for removable scsi disk ( FLOPTICAL ) we have to recognise the * For removable scsi disk we have to recognise the presence
* presence of disk in the drive. This is kept in the Scsi_Disk * of a disk in the drive. This is kept in the Scsi_Disk
* struct and tested at open ! Daniel Roche ( dan@lectra.fr ) * struct and tested at open ! Daniel Roche ( dan@lectra.fr )
*/ */
sdkp->ready = 1; /* FLOPTICAL */ sdkp->media_present = 1;
retval = sdp->changed; retval = sdp->changed;
if (!flag) if (!flag)
...@@ -828,63 +828,38 @@ static int check_scsidisk_media_change(kdev_t full_dev) ...@@ -828,63 +828,38 @@ static int check_scsidisk_media_change(kdev_t full_dev)
return retval; return retval;
} }
/** static void
* sd_init_onedisk - called the first time a new disk is seen, sd_set_media_not_present(Scsi_Disk *sdkp) {
* performs read_capacity, disk spin up (as required), etc. sdkp->media_present = 0;
* @sdkp: pointer to associated Scsi_Disk object sdkp->capacity = 0;
* @dsk_nr: disk number within this driver (e.g. 0->/dev/sda, sdkp->device->changed = 1;
* 1->/dev/sdb, etc) }
*
* Returns dsk_nr (pointless)
*
* Note: this function is local to this driver.
**/
static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
{
unsigned char cmd[10];
char nbuff[6];
unsigned char *buffer;
unsigned long spintime_value = 0;
int the_result, retries, spintime;
int sector_size;
Scsi_Device *sdp;
Scsi_Request *SRpnt;
SCSI_LOG_HLQUEUE(3, printk("sd_init_onedisk: dsk_nr=%d\n",
dsk_nr));
/*
* Get the name of the disk, in case we need to log it somewhere.
*/
sd_dskname(dsk_nr, nbuff);
/* static int
* If the device is offline, don't try and read capacity or any sd_media_not_present(Scsi_Disk *sdkp, Scsi_Request *SRpnt) {
* of the other niceties. int the_result = SRpnt->sr_result;
*/
sdp = sdkp->device;
if (sdp->online == FALSE)
return dsk_nr;
/* if (the_result != 0
* We need to retry the READ_CAPACITY because a UNIT_ATTENTION is && (driver_byte(the_result) & DRIVER_SENSE) != 0
* considered a fatal error, and many devices report such an error && (SRpnt->sr_sense_buffer[2] == NOT_READY ||
* just after a scsi bus reset. SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION)
*/ && SRpnt->sr_sense_buffer[12] == 0x3A /* medium not present */) {
sd_set_media_not_present(sdkp);
SRpnt = scsi_allocate_request(sdp); return 1;
if (!SRpnt) {
printk(KERN_WARNING "(sd_init_onedisk:) Request allocation "
"failure.\n");
return dsk_nr;
} }
return 0;
}
buffer = kmalloc(512, GFP_DMA); /*
if (!buffer) { * spinup disk - called only in sd_init_onedisk()
printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation " */
"failure.\n"); static void
scsi_release_request(SRpnt); sd_spinup_disk(Scsi_Disk *sdkp, char *diskname,
return dsk_nr; Scsi_Request *SRpnt, unsigned char *buffer) {
} unsigned char cmd[10];
Scsi_Device *sdp = sdkp->device;
unsigned long spintime_value = 0;
int the_result, retries, spintime;
spintime = 0; spintime = 0;
...@@ -896,15 +871,16 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -896,15 +871,16 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
while (retries < 3) { while (retries < 3) {
cmd[0] = TEST_UNIT_READY; cmd[0] = TEST_UNIT_READY;
cmd[1] = (sdp->scsi_level <= SCSI_2) ? cmd[1] = (sdp->scsi_level <= SCSI_2) ?
((sdp->lun << 5) & 0xe0) : 0; ((sdp->lun << 5) & 0xe0) : 0;
memset((void *) &cmd[2], 0, 8); memset((void *) &cmd[2], 0, 8);
SRpnt->sr_cmd_len = 0; SRpnt->sr_cmd_len = 0;
SRpnt->sr_sense_buffer[0] = 0; SRpnt->sr_sense_buffer[0] = 0;
SRpnt->sr_sense_buffer[2] = 0; SRpnt->sr_sense_buffer[2] = 0;
SRpnt->sr_data_direction = SCSI_DATA_NONE; SRpnt->sr_data_direction = SCSI_DATA_NONE;
scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer, scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer,
0/*512*/, SD_TIMEOUT, MAX_RETRIES); 0/*512*/, SD_TIMEOUT, MAX_RETRIES);
the_result = SRpnt->sr_result; the_result = SRpnt->sr_result;
retries++; retries++;
...@@ -918,16 +894,8 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -918,16 +894,8 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
* any media in it, don't bother with any of the rest of * any media in it, don't bother with any of the rest of
* this crap. * this crap.
*/ */
if( the_result != 0 if (sd_media_not_present(sdkp, SRpnt))
&& ((driver_byte(the_result) & DRIVER_SENSE) != 0) return;
&& SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION
&& SRpnt->sr_sense_buffer[12] == 0x3A ) {
sdkp->capacity = 0x1fffff;
sector_size = 512;
sdp->changed = 1;
sdkp->ready = 0;
break;
}
/* Look for non-removable devices that return NOT_READY. /* Look for non-removable devices that return NOT_READY.
* Issue command to spin up drive for these cases. */ * Issue command to spin up drive for these cases. */
...@@ -936,10 +904,10 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -936,10 +904,10 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
unsigned long time1; unsigned long time1;
if (!spintime) { if (!spintime) {
printk(KERN_NOTICE "%s: Spinning up disk...", printk(KERN_NOTICE "%s: Spinning up disk...",
nbuff); diskname);
cmd[0] = START_STOP; cmd[0] = START_STOP;
cmd[1] = (sdp->scsi_level <= SCSI_2) ? cmd[1] = (sdp->scsi_level <= SCSI_2) ?
((sdp->lun << 5) & 0xe0) : 0; ((sdp->lun << 5) & 0xe0) : 0;
cmd[1] |= 1; /* Return immediately */ cmd[1] |= 1; /* Return immediately */
memset((void *) &cmd[2], 0, 8); memset((void *) &cmd[2], 0, 8);
cmd[4] = 1; /* Start spin cycle */ cmd[4] = 1; /* Start spin cycle */
...@@ -964,65 +932,63 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -964,65 +932,63 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
} }
} while (the_result && spintime && } while (the_result && spintime &&
time_after(spintime_value + 100 * HZ, jiffies)); time_after(spintime_value + 100 * HZ, jiffies));
if (spintime) { if (spintime) {
if (the_result) if (the_result)
printk("not responding...\n"); printk("not responding...\n");
else else
printk("ready\n"); printk("ready\n");
} }
}
/*
* read disk capacity - called only in sd_init_onedisk()
*/
static void
sd_read_capacity(Scsi_Disk *sdkp, char *diskname,
Scsi_Request *SRpnt, unsigned char *buffer) {
unsigned char cmd[10];
Scsi_Device *sdp = sdkp->device;
int the_result, retries;
int sector_size;
retries = 3; retries = 3;
do { do {
cmd[0] = READ_CAPACITY; cmd[0] = READ_CAPACITY;
cmd[1] = (sdp->scsi_level <= SCSI_2) ? cmd[1] = (sdp->scsi_level <= SCSI_2) ?
((sdp->lun << 5) & 0xe0) : 0; ((sdp->lun << 5) & 0xe0) : 0;
memset((void *) &cmd[2], 0, 8); memset((void *) &cmd[2], 0, 8);
memset((void *) buffer, 0, 8); memset((void *) buffer, 0, 8);
SRpnt->sr_cmd_len = 0; SRpnt->sr_cmd_len = 0;
SRpnt->sr_sense_buffer[0] = 0; SRpnt->sr_sense_buffer[0] = 0;
SRpnt->sr_sense_buffer[2] = 0; SRpnt->sr_sense_buffer[2] = 0;
SRpnt->sr_data_direction = SCSI_DATA_READ; SRpnt->sr_data_direction = SCSI_DATA_READ;
scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
8, SD_TIMEOUT, MAX_RETRIES); 8, SD_TIMEOUT, MAX_RETRIES);
if (sd_media_not_present(sdkp, SRpnt))
return;
the_result = SRpnt->sr_result; the_result = SRpnt->sr_result;
retries--; retries--;
} while (the_result && retries); } while (the_result && retries);
/*
* The SCSI standard says:
* "READ CAPACITY is necessary for self configuring software"
* While not mandatory, support of READ CAPACITY is strongly
* encouraged.
* We used to die if we couldn't successfully do a READ CAPACITY.
* But, now we go on about our way. The side effects of this are
*
* 1. We can't know block size with certainty. I have said
* "512 bytes is it" as this is most common.
*
* 2. Recovery from when someone attempts to read past the
* end of the raw device will be slower.
*/
if (the_result) { if (the_result) {
printk(KERN_NOTICE "%s : READ CAPACITY failed.\n" printk(KERN_NOTICE "%s : READ CAPACITY failed.\n"
"%s : status=%x, message=%02x, host=%d, driver=%02x \n", "%s : status=%x, message=%02x, host=%d, driver=%02x \n",
nbuff, nbuff, diskname, diskname,
status_byte(the_result), status_byte(the_result),
msg_byte(the_result), msg_byte(the_result),
host_byte(the_result), host_byte(the_result),
driver_byte(the_result) driver_byte(the_result));
);
if (driver_byte(the_result) & DRIVER_SENSE) if (driver_byte(the_result) & DRIVER_SENSE)
print_req_sense("sd", SRpnt); print_req_sense("sd", SRpnt);
else else
printk("%s : sense not available. \n", nbuff); printk("%s : sense not available. \n", diskname);
printk(KERN_NOTICE "%s : block size assumed to be 512 "
"bytes, disk size 1GB. \n", nbuff);
sdkp->capacity = 0x1fffff;
sector_size = 512;
/* Set dirty bit for removable devices if not ready - /* Set dirty bit for removable devices if not ready -
* sometimes drives will not report this properly. */ * sometimes drives will not report this properly. */
...@@ -1030,130 +996,193 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -1030,130 +996,193 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
SRpnt->sr_sense_buffer[2] == NOT_READY) SRpnt->sr_sense_buffer[2] == NOT_READY)
sdp->changed = 1; sdp->changed = 1;
} else { /* Either no media are present but the drive didnt tell us,
or they are present but the read capacity command fails */
/* sdkp->media_present = 0; -- not always correct */
sdkp->capacity = 0x200000; /* 1 GB - random */
return;
}
sdkp->capacity = 1 + ((buffer[0] << 24) |
(buffer[1] << 16) |
(buffer[2] << 8) |
buffer[3]);
sector_size = (buffer[4] << 24) |
(buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
if (sector_size == 0) {
sector_size = 512;
printk(KERN_NOTICE "%s : sector size 0 reported, "
"assuming 512.\n", diskname);
}
if (sector_size != 512 &&
sector_size != 1024 &&
sector_size != 2048 &&
sector_size != 4096 &&
sector_size != 256) {
printk(KERN_NOTICE "%s : unsupported sector size "
"%d.\n", diskname, sector_size);
/*
* The user might want to re-format the drive with
* a supported sectorsize. Once this happens, it
* would be relatively trivial to set the thing up.
* For this reason, we leave the thing in the table.
*/
sdkp->capacity = 0;
}
{
/* /*
* FLOPTICAL, if read_capa is ok, drive is assumed to be ready * The msdos fs needs to know the hardware sector size
* So I have created this table. See ll_rw_blk.c
* Jacques Gelinas (Jacques@solucorp.qc.ca)
*/ */
sdkp->ready = 1; int hard_sector = sector_size;
int sz = sdkp->capacity * (hard_sector/256);
request_queue_t *queue = &sdp->request_queue;
blk_queue_hardsect_size(queue, hard_sector);
printk(KERN_NOTICE "SCSI device %s: "
"%d %d-byte hdwr sectors (%d MB)\n",
diskname, sdkp->capacity,
hard_sector, (sz/2 - sz/1250 + 974)/1950);
}
sdkp->capacity = 1 + ((buffer[0] << 24) | /* Rescale capacity to 512-byte units */
(buffer[1] << 16) | if (sector_size == 4096)
(buffer[2] << 8) | sdkp->capacity <<= 3;
buffer[3]); if (sector_size == 2048)
sdkp->capacity <<= 2;
if (sector_size == 1024)
sdkp->capacity <<= 1;
if (sector_size == 256)
sdkp->capacity >>= 1;
sdkp->device->sector_size = sector_size;
}
sector_size = (buffer[4] << 24) | /*
(buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; * read write protect setting, if possible - called only in sd_init_onedisk()
*/
static void
sd_read_write_protect_flag(Scsi_Disk *sdkp, char *diskname,
Scsi_Request *SRpnt, unsigned char *buffer) {
Scsi_Device *sdp = sdkp->device;
unsigned char cmd[8];
int the_result;
if (sector_size == 0) { /*
sector_size = 512; * For removable scsi disks we have to recognise the
printk(KERN_NOTICE "%s : sector size 0 reported, " * Write Protect Flag. This flag is kept in the Scsi_Disk
"assuming 512.\n", nbuff); * struct and tested at open !
} * Daniel Roche ( dan@lectra.fr )
if (sector_size != 512 && *
sector_size != 1024 && * Changed to get all pages (0x3f) rather than page 1 to
sector_size != 2048 && * get around devices which do not have a page 1. Since
sector_size != 4096 && * we're only interested in the header anyway, this should
sector_size != 256) { * be fine.
printk(KERN_NOTICE "%s : unsupported sector size " * -- Matthew Dharm (mdharm-scsi@one-eyed-alien.net)
"%d.\n", nbuff, sector_size); *
/* * As it turns out, some devices return an error for
* The user might want to re-format the drive with * every MODE_SENSE request except one for page 0.
* a supported sectorsize. Once this happens, it * So, we should also try that. --aeb
* would be relatively trivial to set the thing up. */
* For this reason, we leave the thing in the table.
*/ memset((void *) &cmd[0], 0, 8);
sdkp->capacity = 0; cmd[0] = MODE_SENSE;
} cmd[1] = (sdp->scsi_level <= SCSI_2) ?
{ ((sdp->lun << 5) & 0xe0) : 0;
/* cmd[2] = 0x3f; /* Get all pages */
* The msdos fs needs to know the hardware sector size cmd[4] = 255; /* Ask for 255 bytes, even tho we want just the first 8 */
* So I have created this table. See ll_rw_blk.c SRpnt->sr_cmd_len = 0;
* Jacques Gelinas (Jacques@solucorp.qc.ca) SRpnt->sr_sense_buffer[0] = 0;
*/ SRpnt->sr_sense_buffer[2] = 0;
int hard_sector = sector_size; SRpnt->sr_data_direction = SCSI_DATA_READ;
int sz = sdkp->capacity * (hard_sector/256);
request_queue_t *queue = &sdp->request_queue; scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
512, SD_TIMEOUT, MAX_RETRIES);
blk_queue_hardsect_size(queue, hard_sector);
printk(KERN_NOTICE "SCSI device %s: "
"%d %d-byte hdwr sectors (%d MB)\n",
nbuff, sdkp->capacity,
hard_sector, (sz/2 - sz/1250 + 974)/1950);
}
/* Rescale capacity to 512-byte units */ the_result = SRpnt->sr_result;
if (sector_size == 4096)
sdkp->capacity <<= 3; if (the_result) {
if (sector_size == 2048) printk("%s: test WP failed, assume Write Enabled\n",
sdkp->capacity <<= 2; diskname);
if (sector_size == 1024) /* alternatively, try page 0 */
sdkp->capacity <<= 1; } else {
if (sector_size == 256) sdkp->write_prot = ((buffer[2] & 0x80) != 0);
sdkp->capacity >>= 1; printk(KERN_NOTICE "%s: Write Protect is %s\n", diskname,
sdkp->write_prot ? "on" : "off");
} }
}
/**
* sd_init_onedisk - called the first time a new disk is seen,
* performs disk spin up, read_capacity, etc.
* @sdkp: pointer to associated Scsi_Disk object
* @dsk_nr: disk number within this driver (e.g. 0->/dev/sda,
* 1->/dev/sdb, etc)
*
* Note: this function is local to this driver.
**/
static void
sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) {
char diskname[40];
unsigned char *buffer;
Scsi_Device *sdp;
Scsi_Request *SRpnt;
SCSI_LOG_HLQUEUE(3, printk("sd_init_onedisk: dsk_nr=%d\n", dsk_nr));
/* /*
* Unless otherwise specified, this is not write protected. * Get the name of the disk, in case we need to log it somewhere.
*/ */
sdkp->write_prot = 0; sd_dskname(dsk_nr, diskname);
if (sdp->removable && sdkp->ready) {
/* FLOPTICAL */
/* /*
* For removable scsi disk ( FLOPTICAL ) we have to recognise * If the device is offline, don't try and read capacity or any
* the Write Protect Flag. This flag is kept in the Scsi_Disk * of the other niceties.
* struct and tested at open ! */
* Daniel Roche ( dan@lectra.fr ) sdp = sdkp->device;
* if (sdp->online == FALSE)
* Changed to get all pages (0x3f) rather than page 1 to return;
* get around devices which do not have a page 1. Since
* we're only interested in the header anyway, this should
* be fine.
* -- Matthew Dharm (mdharm-scsi@one-eyed-alien.net)
*
* As it turns out, some devices return an error for
* every MODE_SENSE request except one for page 0.
* So, we should also try that. --aeb
*/
memset((void *) &cmd[0], 0, 8); SRpnt = scsi_allocate_request(sdp);
cmd[0] = MODE_SENSE; if (!SRpnt) {
cmd[1] = (sdp->scsi_level <= SCSI_2) ? printk(KERN_WARNING "(sd_init_onedisk:) Request allocation "
((sdp->lun << 5) & 0xe0) : 0; "failure.\n");
cmd[2] = 0x3f; /* Get all pages */ return;
cmd[4] = 255; /* Ask for 255 bytes, even tho we want just the first 8 */ }
SRpnt->sr_cmd_len = 0;
SRpnt->sr_sense_buffer[0] = 0;
SRpnt->sr_sense_buffer[2] = 0;
/* same code as READCAPA !! */ buffer = kmalloc(512, GFP_DMA);
SRpnt->sr_data_direction = SCSI_DATA_READ; if (!buffer) {
scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation "
512, SD_TIMEOUT, MAX_RETRIES); "failure.\n");
goto leave;
}
the_result = SRpnt->sr_result; /* defaults, until the device tells us otherwise */
sdkp->capacity = 0;
sdkp->device->sector_size = 512;
sdkp->media_present = 1;
sdkp->write_prot = 0;
if (the_result) { sd_spinup_disk(sdkp, diskname, SRpnt, buffer);
printk("%s: test WP failed, assume Write Enabled\n",
nbuff); if (sdkp->media_present)
/* alternatively, try page 0 */ sd_read_capacity(sdkp, diskname, SRpnt, buffer);
} else {
sdkp->write_prot = ((buffer[2] & 0x80) != 0); if (sdp->removable && sdkp->media_present)
printk(KERN_NOTICE "%s: Write Protect is %s\n", nbuff, sd_read_write_protect_flag(sdkp, diskname, SRpnt, buffer);
sdkp->write_prot ? "on" : "off");
}
} /* check for write protect */
SRpnt->sr_device->ten = 1; SRpnt->sr_device->ten = 1;
SRpnt->sr_device->remap = 1; SRpnt->sr_device->remap = 1;
SRpnt->sr_device->sector_size = sector_size;
/* Wake up a process waiting for device */ leave:
scsi_release_request(SRpnt); scsi_release_request(SRpnt);
SRpnt = NULL;
kfree(buffer); kfree(buffer);
return dsk_nr;
} }
/* /*
...@@ -1276,18 +1305,15 @@ static int sd_init() ...@@ -1276,18 +1305,15 @@ static int sd_init()
vfree(sd_gendisks[k].flags); vfree(sd_gendisks[k].flags);
} }
cleanup_mem: cleanup_mem:
if (sd_gendisks) vfree(sd_gendisks); vfree(sd_gendisks);
sd_gendisks = NULL; sd_gendisks = NULL;
if (sd) vfree(sd); vfree(sd);
sd = NULL; sd = NULL;
if (sd_sizes) vfree(sd_sizes); vfree(sd_sizes);
sd_sizes = NULL; sd_sizes = NULL;
if (sd_dsk_arr) { if (sd_dsk_arr) {
for (k = 0; k < sd_template.dev_max; ++k) { for (k = 0; k < sd_template.dev_max; ++k)
sdkp = sd_dsk_arr[k]; vfree(sd_dsk_arr[k]);
if (sdkp)
vfree(sdkp);
}
vfree(sd_dsk_arr); vfree(sd_dsk_arr);
sd_dsk_arr = NULL; sd_dsk_arr = NULL;
} }
...@@ -1322,12 +1348,12 @@ static void sd_finish() ...@@ -1322,12 +1348,12 @@ static void sd_finish()
sdkp = sd_get_sdisk(k); sdkp = sd_get_sdisk(k);
if (sdkp && (0 == sdkp->capacity) && sdkp->device) { if (sdkp && (0 == sdkp->capacity) && sdkp->device) {
sd_init_onedisk(sdkp, k); sd_init_onedisk(sdkp, k);
if (!sdkp->has_part_table) { if (!sdkp->has_been_registered) {
sd_sizes[k << 4] = sdkp->capacity; sd_sizes[k << 4] = sdkp->capacity;
register_disk(&SD_GENDISK(k), MKDEV_SD(k), register_disk(&SD_GENDISK(k), MKDEV_SD(k),
1<<4, &sd_fops, 1<<4, &sd_fops,
sdkp->capacity); sdkp->capacity);
sdkp->has_part_table = 1; sdkp->has_been_registered = 1;
} }
} }
} }
...@@ -1373,7 +1399,7 @@ static int sd_attach(Scsi_Device * sdp) ...@@ -1373,7 +1399,7 @@ static int sd_attach(Scsi_Device * sdp)
unsigned int devnum; unsigned int devnum;
Scsi_Disk *sdkp; Scsi_Disk *sdkp;
int dsk_nr; int dsk_nr;
char nbuff[6]; char diskname[6];
unsigned long iflags; unsigned long iflags;
if ((NULL == sdp) || if ((NULL == sdp) ||
...@@ -1394,8 +1420,8 @@ static int sd_attach(Scsi_Device * sdp) ...@@ -1394,8 +1420,8 @@ static int sd_attach(Scsi_Device * sdp)
for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) { for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) {
sdkp = sd_dsk_arr[dsk_nr]; sdkp = sd_dsk_arr[dsk_nr];
if (!sdkp->device) { if (!sdkp->device) {
memset(sdkp, 0, sizeof(Scsi_Disk));
sdkp->device = sdp; sdkp->device = sdp;
sdkp->has_part_table = 0;
break; break;
} }
} }
...@@ -1413,10 +1439,10 @@ static int sd_attach(Scsi_Device * sdp) ...@@ -1413,10 +1439,10 @@ static int sd_attach(Scsi_Device * sdp)
SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de; SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de;
if (sdp->removable) if (sdp->removable)
SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE; SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE;
sd_dskname(dsk_nr, nbuff); sd_dskname(dsk_nr, diskname);
printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, " printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, "
"id %d, lun %d\n", sdp->removable ? "removable " : "", "id %d, lun %d\n", sdp->removable ? "removable " : "",
nbuff, sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); diskname, sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
return 0; return 0;
} }
...@@ -1437,8 +1463,8 @@ int revalidate_scsidisk(kdev_t dev, int maxusage) ...@@ -1437,8 +1463,8 @@ int revalidate_scsidisk(kdev_t dev, int maxusage)
Scsi_Disk * sdkp; Scsi_Disk * sdkp;
Scsi_Device * sdp; Scsi_Device * sdp;
SCSI_LOG_HLQUEUE(3, printk("revalidate_scsidisk: dsk_nr=%d\n", SCSI_LOG_HLQUEUE(3, printk("revalidate_scsidisk: dsk_nr=%d\n",
DEVICE_NR(dev))); DEVICE_NR(dev)));
sdkp = sd_get_sdisk(dsk_nr); sdkp = sd_get_sdisk(dsk_nr);
if ((NULL == sdkp) || (NULL == (sdp = sdkp->device))) if ((NULL == sdkp) || (NULL == (sdp = sdkp->device)))
return -ENODEV; return -ENODEV;
...@@ -1458,6 +1484,7 @@ int revalidate_scsidisk(kdev_t dev, int maxusage) ...@@ -1458,6 +1484,7 @@ int revalidate_scsidisk(kdev_t dev, int maxusage)
sd_init_onedisk(sdkp, dsk_nr); sd_init_onedisk(sdkp, dsk_nr);
grok_partitions(dev, sdkp->capacity); grok_partitions(dev, sdkp->capacity);
leave: leave:
sdp->busy = 0; sdp->busy = 0;
return res; return res;
...@@ -1495,7 +1522,7 @@ static void sd_detach(Scsi_Device * sdp) ...@@ -1495,7 +1522,7 @@ static void sd_detach(Scsi_Device * sdp)
for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) { for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) {
sdkp = sd_dsk_arr[dsk_nr]; sdkp = sd_dsk_arr[dsk_nr];
if (sdkp->device == sdp) { if (sdkp->device == sdp) {
sdkp->has_part_table = 0; sdkp->has_been_registered = 0;
sdkp->device = NULL; sdkp->device = NULL;
sdkp->capacity = 0; sdkp->capacity = 0;
/* sdkp->detaching = 1; */ /* sdkp->detaching = 1; */
......
...@@ -11,9 +11,6 @@ ...@@ -11,9 +11,6 @@
*/ */
#ifndef _SD_H #ifndef _SD_H
#define _SD_H #define _SD_H
/*
$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/sd.h,v 1.1 1992/07/24 06:27:38 root Exp root $
*/
#ifndef _SCSI_H #ifndef _SCSI_H
#include "scsi.h" #include "scsi.h"
...@@ -26,13 +23,11 @@ ...@@ -26,13 +23,11 @@
extern struct hd_struct *sd; extern struct hd_struct *sd;
typedef struct scsi_disk { typedef struct scsi_disk {
unsigned capacity; /* size in blocks */ unsigned capacity; /* size in 512-byte sectors */
Scsi_Device *device; Scsi_Device *device;
unsigned char ready; /* flag ready for FLOPTICAL */ unsigned char media_present;
unsigned char write_prot; /* flag write_protect for rmvable dev */ unsigned char write_prot;
unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */ unsigned has_been_registered:1;
unsigned char sector_bit_shift; /* power of 2 sectors per FS block */
unsigned has_part_table:1; /* has partition table */
} Scsi_Disk; } Scsi_Disk;
extern int revalidate_scsidisk(kdev_t dev, int maxusage); extern int revalidate_scsidisk(kdev_t dev, int maxusage);
...@@ -48,22 +43,3 @@ extern kdev_t sd_find_target(void *host, int tgt); ...@@ -48,22 +43,3 @@ extern kdev_t sd_find_target(void *host, int tgt);
#define SD_PARTITION(i) (((major(i) & SD_MAJOR_MASK) << 8) | (minor(i) & 255)) #define SD_PARTITION(i) (((major(i) & SD_MAJOR_MASK) << 8) | (minor(i) & 255))
#endif #endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 4
* c-brace-imaginary-offset: 0
* c-brace-offset: -4
* c-argdecl-indent: 4
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
...@@ -24,8 +24,6 @@ typedef struct { ...@@ -24,8 +24,6 @@ typedef struct {
Scsi_Device *device; Scsi_Device *device;
unsigned int vendor; /* vendor code, see sr_vendor.c */ unsigned int vendor; /* vendor code, see sr_vendor.c */
unsigned long ms_offset; /* for reading multisession-CD's */ unsigned long ms_offset; /* for reading multisession-CD's */
unsigned char sector_bit_size; /* sector size = 2^sector_bit_size */
unsigned char sector_bit_shift; /* sectors/FS block = 2^sector_bit_shift */
unsigned needs_sector_size:1; /* needs to get sector size */ unsigned needs_sector_size:1; /* needs to get sector size */
unsigned use:1; /* is this device still supportable */ unsigned use:1; /* is this device still supportable */
unsigned xa_flag:1; /* CD has XA sectors ? */ unsigned xa_flag:1; /* CD has XA sectors ? */
......
...@@ -412,8 +412,8 @@ void grok_partitions(kdev_t dev, long size) ...@@ -412,8 +412,8 @@ void grok_partitions(kdev_t dev, long size)
g->part[first_minor].nr_sects = size; g->part[first_minor].nr_sects = size;
/* No such device or no minors to use for partitions */ /* No minors to use for partitions */
if (!size || minors == 1) if (minors == 1)
return; return;
if (g->sizes) { if (g->sizes) {
...@@ -422,6 +422,11 @@ void grok_partitions(kdev_t dev, long size) ...@@ -422,6 +422,11 @@ void grok_partitions(kdev_t dev, long size)
g->sizes[i] = 0; g->sizes[i] = 0;
} }
blk_size[g->major] = g->sizes; blk_size[g->major] = g->sizes;
/* No such device (e.g., media were just removed) */
if (!size)
return;
check_partition(g, mk_kdev(g->major, first_minor), 1 + first_minor); check_partition(g, mk_kdev(g->major, first_minor), 1 + first_minor);
/* /*
......
...@@ -223,23 +223,4 @@ typedef struct scsi_lun { ...@@ -223,23 +223,4 @@ typedef struct scsi_lun {
/* Used to get the PCI location of a device */ /* Used to get the PCI location of a device */
#define SCSI_IOCTL_GET_PCI 0x5387 #define SCSI_IOCTL_GET_PCI 0x5387
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 4
* c-brace-imaginary-offset: 0
* c-brace-offset: -4
* c-argdecl-indent: 4
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
#endif #endif
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