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);
/*
* If the device is offline, don't try and read capacity or any
* of the other niceties.
*/
sdp = sdkp->device;
if (sdp->online == FALSE)
return dsk_nr;
/* static int
* We need to retry the READ_CAPACITY because a UNIT_ATTENTION is sd_media_not_present(Scsi_Disk *sdkp, Scsi_Request *SRpnt) {
* considered a fatal error, and many devices report such an error int the_result = SRpnt->sr_result;
* just after a scsi bus reset.
*/
SRpnt = scsi_allocate_request(sdp); if (the_result != 0
if (!SRpnt) { && (driver_byte(the_result) & DRIVER_SENSE) != 0
printk(KERN_WARNING "(sd_init_onedisk:) Request allocation " && (SRpnt->sr_sense_buffer[2] == NOT_READY ||
"failure.\n"); SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION)
return dsk_nr; && SRpnt->sr_sense_buffer[12] == 0x3A /* medium not present */) {
sd_set_media_not_present(sdkp);
return 1;
} }
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;
...@@ -898,6 +873,7 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -898,6 +873,7 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
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;
...@@ -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,7 +904,7 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -936,7 +904,7 @@ 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;
...@@ -964,12 +932,26 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -964,12 +932,26 @@ 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;
...@@ -977,52 +959,36 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -977,52 +959,36 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
((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,11 +996,13 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -1030,11 +996,13 @@ 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 */
* FLOPTICAL, if read_capa is ok, drive is assumed to be ready /* sdkp->media_present = 0; -- not always correct */
*/ sdkp->capacity = 0x200000; /* 1 GB - random */
sdkp->ready = 1;
return;
}
sdkp->capacity = 1 + ((buffer[0] << 24) | sdkp->capacity = 1 + ((buffer[0] << 24) |
(buffer[1] << 16) | (buffer[1] << 16) |
...@@ -1047,15 +1015,16 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -1047,15 +1015,16 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
if (sector_size == 0) { if (sector_size == 0) {
sector_size = 512; sector_size = 512;
printk(KERN_NOTICE "%s : sector size 0 reported, " printk(KERN_NOTICE "%s : sector size 0 reported, "
"assuming 512.\n", nbuff); "assuming 512.\n", diskname);
} }
if (sector_size != 512 && if (sector_size != 512 &&
sector_size != 1024 && sector_size != 1024 &&
sector_size != 2048 && sector_size != 2048 &&
sector_size != 4096 && sector_size != 4096 &&
sector_size != 256) { sector_size != 256) {
printk(KERN_NOTICE "%s : unsupported sector size " printk(KERN_NOTICE "%s : unsupported sector size "
"%d.\n", nbuff, sector_size); "%d.\n", diskname, sector_size);
/* /*
* The user might want to re-format the drive with * The user might want to re-format the drive with
* a supported sectorsize. Once this happens, it * a supported sectorsize. Once this happens, it
...@@ -1077,7 +1046,7 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -1077,7 +1046,7 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
blk_queue_hardsect_size(queue, hard_sector); blk_queue_hardsect_size(queue, hard_sector);
printk(KERN_NOTICE "SCSI device %s: " printk(KERN_NOTICE "SCSI device %s: "
"%d %d-byte hdwr sectors (%d MB)\n", "%d %d-byte hdwr sectors (%d MB)\n",
nbuff, sdkp->capacity, diskname, sdkp->capacity,
hard_sector, (sz/2 - sz/1250 + 974)/1950); hard_sector, (sz/2 - sz/1250 + 974)/1950);
} }
...@@ -1090,19 +1059,23 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -1090,19 +1059,23 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
sdkp->capacity <<= 1; sdkp->capacity <<= 1;
if (sector_size == 256) if (sector_size == 256)
sdkp->capacity >>= 1; sdkp->capacity >>= 1;
}
sdkp->device->sector_size = sector_size;
}
/* /*
* Unless otherwise specified, this is not write protected. * read write protect setting, if possible - called only in sd_init_onedisk()
*/ */
sdkp->write_prot = 0; static void
if (sdp->removable && sdkp->ready) { sd_read_write_protect_flag(Scsi_Disk *sdkp, char *diskname,
/* FLOPTICAL */ Scsi_Request *SRpnt, unsigned char *buffer) {
Scsi_Device *sdp = sdkp->device;
unsigned char cmd[8];
int the_result;
/* /*
* For removable scsi disk ( FLOPTICAL ) we have to recognise * For removable scsi disks we have to recognise the
* the Write Protect Flag. This flag is kept in the Scsi_Disk * Write Protect Flag. This flag is kept in the Scsi_Disk
* struct and tested at open ! * struct and tested at open !
* Daniel Roche ( dan@lectra.fr ) * Daniel Roche ( dan@lectra.fr )
* *
...@@ -1126,9 +1099,8 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -1126,9 +1099,8 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
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;
/* same code as READCAPA !! */
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,
512, SD_TIMEOUT, MAX_RETRIES); 512, SD_TIMEOUT, MAX_RETRIES);
...@@ -1136,24 +1108,81 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) ...@@ -1136,24 +1108,81 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
if (the_result) { if (the_result) {
printk("%s: test WP failed, assume Write Enabled\n", printk("%s: test WP failed, assume Write Enabled\n",
nbuff); diskname);
/* alternatively, try page 0 */ /* alternatively, try page 0 */
} else { } else {
sdkp->write_prot = ((buffer[2] & 0x80) != 0); sdkp->write_prot = ((buffer[2] & 0x80) != 0);
printk(KERN_NOTICE "%s: Write Protect is %s\n", nbuff, printk(KERN_NOTICE "%s: Write Protect is %s\n", diskname,
sdkp->write_prot ? "on" : "off"); 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));
/*
* Get the name of the disk, in case we need to log it somewhere.
*/
sd_dskname(dsk_nr, diskname);
/*
* If the device is offline, don't try and read capacity or any
* of the other niceties.
*/
sdp = sdkp->device;
if (sdp->online == FALSE)
return;
SRpnt = scsi_allocate_request(sdp);
if (!SRpnt) {
printk(KERN_WARNING "(sd_init_onedisk:) Request allocation "
"failure.\n");
return;
}
buffer = kmalloc(512, GFP_DMA);
if (!buffer) {
printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation "
"failure.\n");
goto leave;
}
/* defaults, until the device tells us otherwise */
sdkp->capacity = 0;
sdkp->device->sector_size = 512;
sdkp->media_present = 1;
sdkp->write_prot = 0;
sd_spinup_disk(sdkp, diskname, SRpnt, buffer);
if (sdkp->media_present)
sd_read_capacity(sdkp, diskname, SRpnt, buffer);
if (sdp->removable && sdkp->media_present)
sd_read_write_protect_flag(sdkp, diskname, SRpnt, buffer);
} /* 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;
} }
...@@ -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