]> git.hungrycats.org Git - linux/commitdiff
[PATCH] scsi stuff
authorAndries E. Brouwer <andries.brouwer@cwi.nl>
Sat, 15 Jun 2002 07:23:19 +0000 (00:23 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sat, 15 Jun 2002 07:23:19 +0000 (00:23 -0700)
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.

drivers/block/genhd.c
drivers/scsi/NCR53C9x.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/sr.h
fs/partitions/check.c
include/scsi/scsi.h

index a44f35f604e05b04b772d23a172766b0449f94ae..e84d202b09111a70a111eb9dd29a04a4e582494d 100644 (file)
@@ -177,9 +177,10 @@ static int show_partition(struct seq_file *part, void *v)
        if (sgp == gendisk_head)
                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++) {
-               if (sgp->part[n].nr_sects == 0)
+               int minormask = (1<<sgp->minor_shift) - 1;
+               if ((n & minormask) && sgp->part[n].nr_sects == 0)
                        continue;
                seq_printf(part, "%4d  %4d %10d %s\n",
                        sgp->major, n, sgp->sizes[n],
index 1c86fb3a9e27190a4730007021340a9e70cbc177..2020b44979e1f76a1713209b7840d8977f235c8b 100644 (file)
@@ -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
         * is way to expensive performance wise.
         * 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.
         */
        if(!esp->fas_premature_intr_workaround && (fifocnt == 1) &&
index d68a625f2ff605c7ae4bcec66ea6723d0e252feb..ec5daff09efc9092e630a16a5404468fe766efbf 100644 (file)
@@ -1095,6 +1095,8 @@ int scsi_decide_disposition(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
         * that would indicate what we need to do.
@@ -1102,20 +1104,25 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
        if (host_byte(SCpnt->result) == DID_RESET) {
                if (SCpnt->flags & IS_RESETTING) {
                        /*
-                        * OK, this is normal.  We don't know whether in fact the
-                        * command in question really needs to be rerun or not - 
-                        * if this was the original data command then the answer is yes,
-                        * otherwise we just flag it as success.
+                        * OK, this is normal.  We don't know whether in fact
+                        * the command in question really needs to be rerun
+                        * or not - if this was the original data command then
+                        * the answer is yes, otherwise we just flag it as
+                        * success.
                         */
                        SCpnt->flags &= ~IS_RESETTING;
-                       return NEEDS_RETRY;
+                       goto maybe_retry;
                }
                /*
-                * Rats.  We are already in the error handler, so we now get to try
-                * and figure out what to do next.  If the sense is valid, we have
-                * a pretty good idea of what to do.  If not, we mark it as failed.
+                * Rats.  We are already in the error handler, so we now
+                * get to try and figure out what to do next.  If the sense
+                * 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) {
                return FAILED;
@@ -1127,14 +1134,18 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
                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)) {
        case GOOD:
        case COMMAND_TERMINATED:
                return SUCCESS;
        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 INTERMEDIATE_GOOD:
        case INTERMEDIATE_C_GOOD:
@@ -1149,6 +1160,14 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
                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;
+       }
 }
 
 /*
index b99553c5e51be82118c1bc915d5b59330d8df2a6..40ba88d6f0e094e28b281868879dd6a429e79de9 100644 (file)
@@ -127,7 +127,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
                                /* gag this error, VFS will log it anyway /axboe */
                                /* printk(KERN_INFO "Disc change detected.\n"); */
                                break;
-                       };
+                       }
                default:        /* Fall through for non-removable media */
                        printk("SCSI error: host %d id %d lun %d return code = %x\n",
                               dev->host->host_no,
@@ -139,7 +139,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
                               sense_error(SRpnt->sr_sense_buffer[0]),
                               SRpnt->sr_sense_buffer[2] & 0xf);
 
-               };
+               }
 
        result = SRpnt->sr_result;
 
@@ -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
  * generic SCSI commands on a device.
  *
@@ -516,22 +516,3 @@ int kernel_scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
        set_fs(oldfs);
        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:
- */
index 46748748854c4517c97da310288ba8556c02ff2a..b039b866448b04850f1869d9fc36470acdab4e09 100644 (file)
@@ -96,7 +96,7 @@ static int *sd_max_sectors;
 static int check_scsidisk_media_change(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 void sd_finish(void);
@@ -152,22 +152,24 @@ sd_find_target(void *hp, int scsi_id)
        Scsi_Device *sdp;
        struct Scsi_Host *shp = hp;
        int dsk_nr;
+       kdev_t retval = NODEV;
        unsigned long iflags;
 
        SCSI_LOG_HLQUEUE(3, printk("sd_find_target: host_nr=%d, "
                            "scsi_id=%d\n", shp->host_no, scsi_id));
        read_lock_irqsave(&sd_dsk_arr_lock, iflags);
        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;
                sdp = sdkp->device;
                if (sdp && (sdp->host == shp) && (sdp->id == scsi_id)) {
-                       read_unlock_irqrestore(&sd_dsk_arr_lock, iflags);
-                       return MKDEV_SD(dsk_nr);
+                       retval = MKDEV_SD(dsk_nr);
+                       break;
                }
        }
        read_unlock_irqrestore(&sd_dsk_arr_lock, iflags);
-       return NODEV;
+       return retval;
 }
 #endif
 
@@ -222,8 +224,8 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
        
                        /* default to most commonly used values */
        
-                       diskinfo[0] = 0x40;
-                       diskinfo[1] = 0x20;
+                       diskinfo[0] = 0x40;     /* 1 << 6 */
+                       diskinfo[1] = 0x20;     /* 1 << 5 */
                        diskinfo[2] = sdkp->capacity >> 11;
        
                        /* override with calculated, extended default, 
@@ -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 ((!sdkp->ready) && !(filp->f_flags & O_NDELAY)) {
+               if ((!sdkp->media_present) && !(filp->f_flags & O_NDELAY)) {
                        retval = -ENOMEDIUM;
                        goto error_out;
                }
@@ -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.
         */
        if (sdp->online == FALSE) {
-               sdkp->ready = 0;
-               sdp->changed = 1;
+               sd_set_media_not_present(sdkp);
                return 1;       /* This will force a flush, if called from
                                 * check_disk_change */
        }
@@ -809,18 +810,17 @@ static int check_scsidisk_media_change(kdev_t full_dev)
                                 * it out later once the drive is available
                                 * again.  */
 
-               sdkp->ready = 0;
-               sdp->changed = 1;
+               sd_set_media_not_present(sdkp);
                return 1;       /* This will force a flush, if called from
                                 * check_disk_change */
        }
        /*
-        * for removable scsi disk ( FLOPTICAL ) we have to recognise the
-        * presence of disk in the drive. This is kept in the Scsi_Disk
+        * For removable scsi disk we have to recognise the presence
+        * of a disk in the drive. This is kept in the Scsi_Disk
         * struct and tested at open !  Daniel Roche ( dan@lectra.fr )
         */
 
-       sdkp->ready = 1;        /* FLOPTICAL */
+       sdkp->media_present = 1;
 
        retval = sdp->changed;
        if (!flag)
@@ -828,63 +828,38 @@ static int check_scsidisk_media_change(kdev_t full_dev)
        return retval;
 }
 
-/**
- *     sd_init_onedisk - called the first time a new disk is seen,
- *     performs read_capacity, disk spin up (as required), etc.
- *     @sdkp: pointer to associated Scsi_Disk object
- *     @dsk_nr: disk number within this driver (e.g. 0->/dev/sda,
- *     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 void
+sd_set_media_not_present(Scsi_Disk *sdkp) {
+       sdkp->media_present = 0;
+       sdkp->capacity = 0;
+       sdkp->device->changed = 1;
+}
 
-       /*
-        * 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
+sd_media_not_present(Scsi_Disk *sdkp, Scsi_Request *SRpnt) {
+       int the_result = SRpnt->sr_result;
 
-       /*
-        * We need to retry the READ_CAPACITY because a UNIT_ATTENTION is
-        * considered a fatal error, and many devices report such an error
-        * just after a scsi bus reset.
-        */
-
-       SRpnt = scsi_allocate_request(sdp);
-       if (!SRpnt) {
-               printk(KERN_WARNING "(sd_init_onedisk:) Request allocation "
-                      "failure.\n");
-               return dsk_nr;
+       if (the_result != 0
+           && (driver_byte(the_result) & DRIVER_SENSE) != 0
+           && (SRpnt->sr_sense_buffer[2] == NOT_READY ||
+               SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION)
+           && 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) {
-               printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation "
-                      "failure.\n");
-               scsi_release_request(SRpnt);
-               return dsk_nr;
-       }
+/*
+ * spinup disk - called only in sd_init_onedisk()
+ */
+static void
+sd_spinup_disk(Scsi_Disk *sdkp, char *diskname,
+              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;
 
@@ -896,15 +871,16 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
                while (retries < 3) {
                        cmd[0] = TEST_UNIT_READY;
                        cmd[1] = (sdp->scsi_level <= SCSI_2) ?
-                                ((sdp->lun << 5) & 0xe0) : 0;
+                               ((sdp->lun << 5) & 0xe0) : 0;
                        memset((void *) &cmd[2], 0, 8);
+
                        SRpnt->sr_cmd_len = 0;
                        SRpnt->sr_sense_buffer[0] = 0;
                        SRpnt->sr_sense_buffer[2] = 0;
                        SRpnt->sr_data_direction = SCSI_DATA_NONE;
 
                        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;
                        retries++;
@@ -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
                 * this crap.
                 */
-               if( the_result != 0
-                   && ((driver_byte(the_result) & DRIVER_SENSE) != 0)
-                   && 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;
-               }
+               if (sd_media_not_present(sdkp, SRpnt))
+                       return;
 
                /* Look for non-removable devices that return NOT_READY.
                 * Issue command to spin up drive for these cases. */
@@ -936,10 +904,10 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
                        unsigned long time1;
                        if (!spintime) {
                                printk(KERN_NOTICE "%s: Spinning up disk...",
-                                      nbuff);
+                                      diskname);
                                cmd[0] = START_STOP;
                                cmd[1] = (sdp->scsi_level <= SCSI_2) ?
-                                        ((sdp->lun << 5) & 0xe0) : 0;
+                                       ((sdp->lun << 5) & 0xe0) : 0;
                                cmd[1] |= 1;    /* Return immediately */
                                memset((void *) &cmd[2], 0, 8);
                                cmd[4] = 1;     /* Start spin cycle */
@@ -964,65 +932,63 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
                }
        } while (the_result && spintime &&
                 time_after(spintime_value + 100 * HZ, jiffies));
+
        if (spintime) {
                if (the_result)
                        printk("not responding...\n");
                else
                        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;
        do {
                cmd[0] = READ_CAPACITY;
                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 *) buffer, 0, 8);
+
                SRpnt->sr_cmd_len = 0;
                SRpnt->sr_sense_buffer[0] = 0;
                SRpnt->sr_sense_buffer[2] = 0;
-
                SRpnt->sr_data_direction = SCSI_DATA_READ;
+
                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;
                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) {
                printk(KERN_NOTICE "%s : READ CAPACITY failed.\n"
                       "%s : status=%x, message=%02x, host=%d, driver=%02x \n",
-                      nbuff, nbuff,
+                      diskname, diskname,
                       status_byte(the_result),
                       msg_byte(the_result),
                       host_byte(the_result),
-                      driver_byte(the_result)
-                   );
+                      driver_byte(the_result));
+
                if (driver_byte(the_result) & DRIVER_SENSE)
                        print_req_sense("sd", SRpnt);
                else
-                       printk("%s : sense not available. \n", nbuff);
-
-               printk(KERN_NOTICE "%s : block size assumed to be 512 "
-                      "bytes, disk size 1GB.  \n", nbuff);
-               sdkp->capacity = 0x1fffff;
-               sector_size = 512;
+                       printk("%s : sense not available. \n", diskname);
 
                /* Set dirty bit for removable devices if not ready -
                 * sometimes drives will not report this properly. */
@@ -1030,130 +996,193 @@ static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr)
                    SRpnt->sr_sense_buffer[2] == NOT_READY)
                        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) |
-                                     (buffer[1] << 16) |
-                                     (buffer[2] << 8) |
-                                     buffer[3]);
+       /* Rescale capacity to 512-byte units */
+       if (sector_size == 4096)
+               sdkp->capacity <<= 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;
-                       printk(KERN_NOTICE "%s : sector size 0 reported, "
-                              "assuming 512.\n", nbuff);
-               }
-               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", nbuff, 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;
-               }
-               {
-                       /*
-                        * 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)
-                        */
-                       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",
-                              nbuff, sdkp->capacity,
-                              hard_sector, (sz/2 - sz/1250 + 974)/1950);
-               }
+       /*
+        * For removable scsi disks we have to recognise the
+        * Write Protect Flag. This flag is kept in the Scsi_Disk
+        * struct and tested at open !
+        * Daniel Roche ( dan@lectra.fr )
+        *
+        * Changed to get all pages (0x3f) rather than page 1 to
+        * 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);
+       cmd[0] = MODE_SENSE;
+       cmd[1] = (sdp->scsi_level <= SCSI_2) ?
+               ((sdp->lun << 5) & 0xe0) : 0;
+       cmd[2] = 0x3f;  /* Get all pages */
+       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;
+       SRpnt->sr_data_direction = SCSI_DATA_READ;
+
+       scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
+                     512, SD_TIMEOUT, MAX_RETRIES);
 
-               /* Rescale capacity to 512-byte units */
-               if (sector_size == 4096)
-                       sdkp->capacity <<= 3;
-               if (sector_size == 2048)
-                       sdkp->capacity <<= 2;
-               if (sector_size == 1024)
-                       sdkp->capacity <<= 1;
-               if (sector_size == 256)
-                       sdkp->capacity >>= 1;
+       the_result = SRpnt->sr_result;
+
+       if (the_result) {
+               printk("%s: test WP failed, assume Write Enabled\n",
+                      diskname);
+               /* alternatively, try page 0 */
+       } else {
+               sdkp->write_prot = ((buffer[2] & 0x80) != 0);
+               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;
-       if (sdp->removable && sdkp->ready) {
-               /* FLOPTICAL */
+       sd_dskname(dsk_nr, diskname);
 
-               /*
-                * For removable scsi disk ( FLOPTICAL ) we have to recognise
-                * the Write Protect Flag. This flag is kept in the Scsi_Disk
-                * struct and tested at open !
-                * Daniel Roche ( dan@lectra.fr )
-                *
-                * Changed to get all pages (0x3f) rather than page 1 to
-                * 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
-                */
+       /*
+        * 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;
 
-               memset((void *) &cmd[0], 0, 8);
-               cmd[0] = MODE_SENSE;
-               cmd[1] = (sdp->scsi_level <= SCSI_2) ?
-                        ((sdp->lun << 5) & 0xe0) : 0;
-               cmd[2] = 0x3f;  /* Get all pages */
-               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;
+       SRpnt = scsi_allocate_request(sdp);
+       if (!SRpnt) {
+               printk(KERN_WARNING "(sd_init_onedisk:) Request allocation "
+                      "failure.\n");
+               return;
+       }
 
-               /* same code as READCAPA !! */
-               SRpnt->sr_data_direction = SCSI_DATA_READ;
-               scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
-                           512, SD_TIMEOUT, MAX_RETRIES);
+       buffer = kmalloc(512, GFP_DMA);
+       if (!buffer) {
+               printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation "
+                      "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) {
-                       printk("%s: test WP failed, assume Write Enabled\n",
-                              nbuff);
-                       /* alternatively, try page 0 */
-               } else {
-                       sdkp->write_prot = ((buffer[2] & 0x80) != 0);
-                       printk(KERN_NOTICE "%s: Write Protect is %s\n", nbuff,
-                              sdkp->write_prot ? "on" : "off");
-               }
+       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->remap = 1;
-       SRpnt->sr_device->sector_size = sector_size;
-       /* Wake up a process waiting for device */
+
+ leave:
        scsi_release_request(SRpnt);
-       SRpnt = NULL;
 
        kfree(buffer);
-       return dsk_nr;
 }
 
 /*
@@ -1276,18 +1305,15 @@ cleanup_gendisks:
                vfree(sd_gendisks[k].flags);
        }
 cleanup_mem:
-       if (sd_gendisks) vfree(sd_gendisks);
+       vfree(sd_gendisks);
        sd_gendisks = NULL;
-       if (sd) vfree(sd);
+       vfree(sd);
        sd = NULL;
-       if (sd_sizes) vfree(sd_sizes);
+       vfree(sd_sizes);
        sd_sizes = NULL;
        if (sd_dsk_arr) {
-                for (k = 0; k < sd_template.dev_max; ++k) {
-                       sdkp = sd_dsk_arr[k];
-                       if (sdkp)
-                               vfree(sdkp);
-               }
+                for (k = 0; k < sd_template.dev_max; ++k)
+                       vfree(sd_dsk_arr[k]);
                vfree(sd_dsk_arr);
                sd_dsk_arr = NULL;
        }
@@ -1322,12 +1348,12 @@ static void sd_finish()
                sdkp = sd_get_sdisk(k);
                if (sdkp && (0 == sdkp->capacity) && sdkp->device) {
                        sd_init_onedisk(sdkp, k);
-                       if (!sdkp->has_part_table) {
+                       if (!sdkp->has_been_registered) {
                                sd_sizes[k << 4] = sdkp->capacity;
                                register_disk(&SD_GENDISK(k), MKDEV_SD(k),
                                                1<<4, &sd_fops,
                                                sdkp->capacity);
-                               sdkp->has_part_table = 1;
+                               sdkp->has_been_registered = 1;
                        }
                }
        }
@@ -1373,7 +1399,7 @@ static int sd_attach(Scsi_Device * sdp)
         unsigned int devnum;
        Scsi_Disk *sdkp;
        int dsk_nr;
-       char nbuff[6];
+       char diskname[6];
        unsigned long iflags;
 
        if ((NULL == sdp) ||
@@ -1394,8 +1420,8 @@ static int sd_attach(Scsi_Device * sdp)
        for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) {
                sdkp = sd_dsk_arr[dsk_nr];
                if (!sdkp->device) {
+                       memset(sdkp, 0, sizeof(Scsi_Disk));
                        sdkp->device = sdp;
-                       sdkp->has_part_table = 0;
                        break;
                }
        }
@@ -1413,10 +1439,10 @@ static int sd_attach(Scsi_Device * sdp)
         SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de;
         if (sdp->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, "
               "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;
 }
 
@@ -1437,8 +1463,8 @@ int revalidate_scsidisk(kdev_t dev, int maxusage)
        Scsi_Disk * sdkp;
        Scsi_Device * sdp;
 
-        SCSI_LOG_HLQUEUE(3, printk("revalidate_scsidisk: dsk_nr=%d\n", 
-                            DEVICE_NR(dev)));
+       SCSI_LOG_HLQUEUE(3, printk("revalidate_scsidisk: dsk_nr=%d\n", 
+                                  DEVICE_NR(dev)));
        sdkp = sd_get_sdisk(dsk_nr);
        if ((NULL == sdkp) || (NULL == (sdp = sdkp->device)))
                return -ENODEV;
@@ -1458,6 +1484,7 @@ int revalidate_scsidisk(kdev_t dev, int maxusage)
        sd_init_onedisk(sdkp, dsk_nr);
 
        grok_partitions(dev, sdkp->capacity);
+
 leave:
        sdp->busy = 0;
        return res;
@@ -1495,7 +1522,7 @@ static void sd_detach(Scsi_Device * sdp)
        for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) {
                sdkp = sd_dsk_arr[dsk_nr];
                if (sdkp->device == sdp) {
-                       sdkp->has_part_table = 0;
+                       sdkp->has_been_registered = 0;
                        sdkp->device = NULL;
                        sdkp->capacity = 0;
                        /* sdkp->detaching = 1; */
index 7e12f2696e057ad5553e2e3e80b8995c81d4bfdc..e3eb4be41a26e6fb339ebc659a02d08ee104bded 100644 (file)
@@ -11,9 +11,6 @@
  */
 #ifndef _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
 #include "scsi.h"
 extern struct hd_struct *sd;
 
 typedef struct scsi_disk {
-       unsigned capacity;      /* size in blocks */
+       unsigned capacity;              /* size in 512-byte sectors */
        Scsi_Device *device;
-       unsigned char ready;    /* flag ready for FLOPTICAL */
-       unsigned char write_prot;       /* flag write_protect for rmvable dev */
-       unsigned char sector_bit_size;  /* sector_size = 2 to the  bit size power */
-       unsigned char sector_bit_shift;         /* power of 2 sectors per FS block */
-       unsigned has_part_table:1;      /* has partition table */
+       unsigned char media_present;
+       unsigned char write_prot;
+       unsigned has_been_registered:1;
 } Scsi_Disk;
 
 extern int revalidate_scsidisk(kdev_t dev, int maxusage);
@@ -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))
 
 #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:
- */
index 6bd473ee7795c62fab2a4f4c0d075f7b14a74e87..e4ac7cb2265d21ca9c8289ed3f64e2313303e97d 100644 (file)
@@ -24,8 +24,6 @@ typedef struct {
        Scsi_Device *device;
        unsigned int vendor;    /* vendor code, see sr_vendor.c         */
        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 use:1;         /* is this device still supportable     */
        unsigned xa_flag:1;     /* CD has XA sectors ? */
index fdc7c3c9e6e871c1b37d061264936127a599473f..87d202b99b2c6f2fedfe47eb0f724f10ae95b2d3 100644 (file)
@@ -412,8 +412,8 @@ void grok_partitions(kdev_t dev, long size)
 
        g->part[first_minor].nr_sects = size;
 
-       /* No such device or no minors to use for partitions */
-       if (!size || minors == 1)
+       /* No minors to use for partitions */
+       if (minors == 1)
                return;
 
        if (g->sizes) {
@@ -422,6 +422,11 @@ void grok_partitions(kdev_t dev, long size)
                        g->sizes[i] = 0;
        }
        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);
 
        /*
index a85c7804d2c0820b086554509152f9cb74e7d017..9a9709b4af8e4cccbe7b09c527849b67c6862860 100644 (file)
@@ -223,23 +223,4 @@ typedef struct scsi_lun {
 /* Used to get the PCI location of a device */
 #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