patch-1.3.35 linux/drivers/scsi/sd.c
Next file: linux/drivers/scsi/sd.h
Previous file: linux/drivers/scsi/scsi_ioctl.c
Back to the patch index
Back to the overall index
- Lines: 239
- Date:
Mon Oct 16 10:33:51 1995
- Orig file:
v1.3.34/linux/drivers/scsi/sd.c
- Orig date:
Wed Oct 4 14:14:32 1995
diff -u --recursive --new-file v1.3.34/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
@@ -112,6 +112,22 @@
if(rscsi_disks[target].device->removable) {
check_disk_change(inode->i_rdev);
+ /*
+ * If the drive is empty, just let the open fail.
+ */
+ if ( !rscsi_disks[target].ready ) {
+ return -ENXIO;
+ }
+
+ /*
+ * Similarily, if the device has the write protect tab set,
+ * have the open fail if the user expects to be able to write
+ * to the thing.
+ */
+ if ( (rscsi_disks[target].write_prot) && (filp->f_mode & 2) ) {
+ return -EROFS;
+ }
+
if(!rscsi_disks[target].device->access_count)
sd_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
};
@@ -904,11 +920,20 @@
* and we will figure it out later once the drive is
* available again. */
+ rscsi_disks[target].ready = 0;
rscsi_disks[target].device->changed = 1;
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
+ * struct and tested at open ! Daniel Roche ( dan@lectra.fr )
+ */
+
+ rscsi_disks[target].ready = 1; /* FLOPTICAL */
+
retval = rscsi_disks[target].device->changed;
if(!flag) rscsi_disks[target].device->changed = 0;
return retval;
@@ -945,7 +970,7 @@
spintime = 0;
/* Spin up drives, as required. Only do this at boot time */
- if (current->pid == 0){
+ if (!MODULE_FLAG){
do{
retries = 0;
while(retries < 3)
@@ -953,18 +978,22 @@
cmd[0] = TEST_UNIT_READY;
cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
memset ((void *) &cmd[2], 0, 8);
- SCpnt->request.rq_status = RQ_SCSI_BUSY; /* Mark as really busy again */
SCpnt->cmd_len = 0;
SCpnt->sense_buffer[0] = 0;
SCpnt->sense_buffer[2] = 0;
-
- scsi_do_cmd (SCpnt,
- (void *) cmd, (void *) buffer,
- 512, sd_init_done, SD_TIMEOUT,
- MAX_RETRIES);
-
- while(SCpnt->request.rq_status != RQ_SCSI_DONE) barrier();
-
+
+ {
+ struct semaphore sem = MUTEX_LOCKED;
+ /* Mark as really busy again */
+ SCpnt->request.rq_status = RQ_SCSI_BUSY;
+ SCpnt->request.sem = &sem;
+ scsi_do_cmd (SCpnt,
+ (void *) cmd, (void *) buffer,
+ 512, sd_init_done, SD_TIMEOUT,
+ MAX_RETRIES);
+ down(&sem);
+ }
+
the_result = SCpnt->result;
retries++;
if( the_result == 0
@@ -984,22 +1013,24 @@
cmd[1] |= 1; /* Return immediately */
memset ((void *) &cmd[2], 0, 8);
cmd[4] = 1; /* Start spin cycle */
- /* Mark as really busy again */
- SCpnt->request.rq_status = RQ_SCSI_BUSY;
SCpnt->cmd_len = 0;
SCpnt->sense_buffer[0] = 0;
SCpnt->sense_buffer[2] = 0;
- scsi_do_cmd (SCpnt,
- (void *) cmd, (void *) buffer,
- 512, sd_init_done, SD_TIMEOUT,
- MAX_RETRIES);
-
- while(SCpnt->request.rq_status != RQ_SCSI_DONE)
- barrier();
+ {
+ struct semaphore sem = MUTEX_LOCKED;
+ /* Mark as really busy again */
+ SCpnt->request.rq_status = RQ_SCSI_BUSY;
+ SCpnt->request.sem = &sem;
+ scsi_do_cmd (SCpnt,
+ (void *) cmd, (void *) buffer,
+ 512, sd_init_done, SD_TIMEOUT,
+ MAX_RETRIES);
+ down(&sem);
+ }
spintime = jiffies;
- };
+ }
time1 = jiffies;
while(jiffies < time1 + HZ); /* Wait 1 second for next try */
@@ -1012,7 +1043,7 @@
else
printk( "ready\n" );
}
- }; /* current->pid == 0 */
+ }; /* !MODULE_FLAG */
retries = 3;
@@ -1021,28 +1052,20 @@
cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
memset ((void *) &cmd[2], 0, 8);
memset ((void *) buffer, 0, 8);
- SCpnt->request.rq_status = RQ_SCSI_BUSY; /* Mark as really busy again */
SCpnt->cmd_len = 0;
SCpnt->sense_buffer[0] = 0;
SCpnt->sense_buffer[2] = 0;
-
- scsi_do_cmd (SCpnt,
- (void *) cmd, (void *) buffer,
- 8, sd_init_done, SD_TIMEOUT,
- MAX_RETRIES);
-
- if (current->pid == 0) {
- while(SCpnt->request.rq_status != RQ_SCSI_DONE)
- barrier();
- } else {
- if (SCpnt->request.rq_status != RQ_SCSI_DONE){
- struct semaphore sem = MUTEX_LOCKED;
- SCpnt->request.sem = &sem;
- down(&sem);
- /* Hmm.. Have to ask about this one.. */
- while (SCpnt->request.rq_status != RQ_SCSI_DONE)
- schedule();
- }
+
+ {
+ struct semaphore sem = MUTEX_LOCKED;
+ /* Mark as really busy again */
+ SCpnt->request.rq_status = RQ_SCSI_BUSY;
+ SCpnt->request.sem = &sem;
+ scsi_do_cmd (SCpnt,
+ (void *) cmd, (void *) buffer,
+ 8, sd_init_done, SD_TIMEOUT,
+ MAX_RETRIES);
+ down(&sem); /* sleep until it is ready */
}
the_result = SCpnt->result;
@@ -1100,6 +1123,11 @@
}
else
{
+ /*
+ * FLOPTICAL , if read_capa is ok , drive is assumed to be ready
+ */
+ rscsi_disks[i].ready = 1;
+
rscsi_disks[i].capacity = (buffer[0] << 24) |
(buffer[1] << 16) |
(buffer[2] << 8) |
@@ -1144,6 +1172,57 @@
rscsi_disks[i].capacity >>= 1; /* Change into 512 byte sectors */
}
+
+ /*
+ * Unless otherwise specified, this is not write protected.
+ */
+ rscsi_disks[i].write_prot = 0;
+ if ( rscsi_disks[i].device->removable && rscsi_disks[i].ready ) {
+ /* FLOPTICAL */
+
+ /*
+ * 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 )
+ */
+
+ memset ((void *) &cmd[0], 0, 8);
+ cmd[0] = MODE_SENSE;
+ cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
+ cmd[2] = 1; /* page code 1 ?? */
+ cmd[4] = 12;
+ SCpnt->cmd_len = 0;
+ SCpnt->sense_buffer[0] = 0;
+ SCpnt->sense_buffer[2] = 0;
+
+ /* same code as READCAPA !! */
+ {
+ struct semaphore sem = MUTEX_LOCKED;
+ SCpnt->request.rq_status = RQ_SCSI_BUSY; /* Mark as really busy again */
+ SCpnt->request.sem = &sem;
+ scsi_do_cmd (SCpnt,
+ (void *) cmd, (void *) buffer,
+ 512, sd_init_done, SD_TIMEOUT,
+ MAX_RETRIES);
+ down(&sem);
+ }
+
+ the_result = SCpnt->result;
+ SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
+ wake_up(&SCpnt->device->device_wait);
+
+ if ( the_result ) {
+ printk ("sd%c: test WP failed, assume Write Protected\n",i+'a');
+ rscsi_disks[i].write_prot = 1;
+ } else {
+ rscsi_disks[i].write_prot = ((buffer[2] & 0x80) != 0);
+ printk ("sd%c: Write Protect is %s\n",i+'a',
+ rscsi_disks[i].write_prot ? "on" : "off");
+ }
+
+ } /* check for write protect */
+
rscsi_disks[i].ten = 1;
rscsi_disks[i].remap = 1;
scsi_free(buffer, 512);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this