@@ -104,14 +104,15 @@ static void sr_release(struct cdrom_device_info *);
104
104
static void get_sectorsize (struct scsi_cd * );
105
105
static void get_capabilities (struct scsi_cd * );
106
106
107
- static int sr_media_change (struct cdrom_device_info * , int );
107
+ static unsigned int sr_check_events (struct cdrom_device_info * cdi ,
108
+ unsigned int clearing , int slot );
108
109
static int sr_packet (struct cdrom_device_info * , struct packet_command * );
109
110
110
111
static struct cdrom_device_ops sr_dops = {
111
112
.open = sr_open ,
112
113
.release = sr_release ,
113
114
.drive_status = sr_drive_status ,
114
- .media_changed = sr_media_change ,
115
+ .check_events = sr_check_events ,
115
116
.tray_move = sr_tray_move ,
116
117
.lock_door = sr_lock_door ,
117
118
.select_speed = sr_select_speed ,
@@ -165,90 +166,96 @@ static void scsi_cd_put(struct scsi_cd *cd)
165
166
mutex_unlock (& sr_ref_mutex );
166
167
}
167
168
168
- /* identical to scsi_test_unit_ready except that it doesn't
169
- * eat the NOT_READY returns for removable media */
170
- int sr_test_unit_ready (struct scsi_device * sdev , struct scsi_sense_hdr * sshdr )
169
+ static unsigned int sr_get_events (struct scsi_device * sdev )
171
170
{
172
- int retries = MAX_RETRIES ;
173
- int the_result ;
174
- u8 cmd [] = {TEST_UNIT_READY , 0 , 0 , 0 , 0 , 0 };
171
+ u8 buf [8 ];
172
+ u8 cmd [] = { GET_EVENT_STATUS_NOTIFICATION ,
173
+ 1 , /* polled */
174
+ 0 , 0 , /* reserved */
175
+ 1 << 4 , /* notification class: media */
176
+ 0 , 0 , /* reserved */
177
+ 0 , sizeof (buf ), /* allocation length */
178
+ 0 , /* control */
179
+ };
180
+ struct event_header * eh = (void * )buf ;
181
+ struct media_event_desc * med = (void * )(buf + 4 );
182
+ struct scsi_sense_hdr sshdr ;
183
+ int result ;
175
184
176
- /* issue TEST_UNIT_READY until the initial startup UNIT_ATTENTION
177
- * conditions are gone, or a timeout happens
178
- */
179
- do {
180
- the_result = scsi_execute_req ( sdev , cmd , DMA_NONE , NULL ,
181
- 0 , sshdr , SR_TIMEOUT ,
182
- retries -- , NULL ) ;
183
- if ( scsi_sense_valid ( sshdr ) &&
184
- sshdr -> sense_key == UNIT_ATTENTION )
185
- sdev -> changed = 1 ;
186
-
187
- } while ( retries > 0 &&
188
- (! scsi_status_is_good ( the_result ) ||
189
- ( scsi_sense_valid ( sshdr ) &&
190
- sshdr -> sense_key == UNIT_ATTENTION ))) ;
191
- return the_result ;
185
+ result = scsi_execute_req ( sdev , cmd , DMA_FROM_DEVICE , buf , sizeof ( buf ),
186
+ & sshdr , SR_TIMEOUT , MAX_RETRIES , NULL );
187
+ if ( scsi_sense_valid ( & sshdr ) && sshdr . sense_key == UNIT_ATTENTION )
188
+ return DISK_EVENT_MEDIA_CHANGE ;
189
+
190
+ if ( result || be16_to_cpu ( eh -> data_len ) < sizeof ( * med ))
191
+ return 0 ;
192
+
193
+ if ( eh -> nea || eh -> notification_class != 0x4 )
194
+ return 0 ;
195
+
196
+ if ( med -> media_event_code == 1 )
197
+ return DISK_EVENT_EJECT_REQUEST ;
198
+ else if ( med -> media_event_code == 2 )
199
+ return DISK_EVENT_MEDIA_CHANGE ;
200
+ return 0 ;
192
201
}
193
202
194
203
/*
195
- * This function checks to see if the media has been changed in the
196
- * CDROM drive. It is possible that we have already sensed a change,
197
- * or the drive may have sensed one and not yet reported it. We must
198
- * be ready for either case. This function always reports the current
199
- * value of the changed bit. If flag is 0, then the changed bit is reset.
200
- * This function could be done as an ioctl, but we would need to have
201
- * an inode for that to work, and we do not always have one.
204
+ * This function checks to see if the media has been changed or eject
205
+ * button has been pressed. It is possible that we have already
206
+ * sensed a change, or the drive may have sensed one and not yet
207
+ * reported it. The past events are accumulated in sdev->changed and
208
+ * returned together with the current state.
202
209
*/
203
-
204
- static int sr_media_change ( struct cdrom_device_info * cdi , int slot )
210
+ static unsigned int sr_check_events ( struct cdrom_device_info * cdi ,
211
+ unsigned int clearing , int slot )
205
212
{
206
213
struct scsi_cd * cd = cdi -> handle ;
207
- int retval ;
208
- struct scsi_sense_hdr * sshdr ;
214
+ bool last_present ;
215
+ struct scsi_sense_hdr sshdr ;
216
+ unsigned int events ;
217
+ int ret ;
209
218
210
- if (CDSL_CURRENT != slot ) {
211
- /* no changer support */
212
- return - EINVAL ;
213
- }
219
+ /* no changer support */
220
+ if (CDSL_CURRENT != slot )
221
+ return 0 ;
214
222
215
- sshdr = kzalloc (sizeof (* sshdr ), GFP_KERNEL );
216
- retval = sr_test_unit_ready (cd -> device , sshdr );
217
- if (retval || (scsi_sense_valid (sshdr ) &&
218
- /* 0x3a is medium not present */
219
- sshdr -> asc == 0x3a )) {
220
- /* Media not present or unable to test, unit probably not
221
- * ready. This usually means there is no disc in the drive.
222
- * Mark as changed, and we will figure it out later once
223
- * the drive is available again.
224
- */
225
- cd -> device -> changed = 1 ;
226
- /* This will force a flush, if called from check_disk_change */
227
- retval = 1 ;
228
- goto out ;
229
- };
223
+ events = sr_get_events (cd -> device );
224
+ /*
225
+ * GET_EVENT_STATUS_NOTIFICATION is enough unless MEDIA_CHANGE
226
+ * is being cleared. Note that there are devices which hang
227
+ * if asked to execute TUR repeatedly.
228
+ */
229
+ if (!(clearing & DISK_EVENT_MEDIA_CHANGE ))
230
+ goto skip_tur ;
231
+
232
+ /* let's see whether the media is there with TUR */
233
+ last_present = cd -> media_present ;
234
+ ret = scsi_test_unit_ready (cd -> device , SR_TIMEOUT , MAX_RETRIES , & sshdr );
235
+
236
+ /*
237
+ * Media is considered to be present if TUR succeeds or fails with
238
+ * sense data indicating something other than media-not-present
239
+ * (ASC 0x3a).
240
+ */
241
+ cd -> media_present = scsi_status_is_good (ret ) ||
242
+ (scsi_sense_valid (& sshdr ) && sshdr .asc != 0x3a );
230
243
231
- retval = cd -> device -> changed ;
232
- cd -> device -> changed = 0 ;
233
- /* If the disk changed, the capacity will now be different,
234
- * so we force a re-read of this information */
235
- if (retval ) {
236
- /* check multisession offset etc */
237
- sr_cd_check (cdi );
238
- get_sectorsize (cd );
244
+ if (last_present != cd -> media_present )
245
+ events |= DISK_EVENT_MEDIA_CHANGE ;
246
+ skip_tur :
247
+ if (cd -> device -> changed ) {
248
+ events |= DISK_EVENT_MEDIA_CHANGE ;
249
+ cd -> device -> changed = 0 ;
239
250
}
240
251
241
- out :
242
- /* Notify userspace, that media has changed. */
243
- if (retval != cd -> previous_state )
252
+ /* for backward compatibility */
253
+ if (events & DISK_EVENT_MEDIA_CHANGE )
244
254
sdev_evt_send_simple (cd -> device , SDEV_EVT_MEDIA_CHANGE ,
245
255
GFP_KERNEL );
246
- cd -> previous_state = retval ;
247
- kfree (sshdr );
248
-
249
- return retval ;
256
+ return events ;
250
257
}
251
-
258
+
252
259
/*
253
260
* sr_done is the interrupt routine for the device driver.
254
261
*
@@ -533,10 +540,25 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
533
540
return ret ;
534
541
}
535
542
536
- static int sr_block_media_changed (struct gendisk * disk )
543
+ static unsigned int sr_block_check_events (struct gendisk * disk ,
544
+ unsigned int clearing )
537
545
{
538
546
struct scsi_cd * cd = scsi_cd (disk );
539
- return cdrom_media_changed (& cd -> cdi );
547
+ return cdrom_check_events (& cd -> cdi , clearing );
548
+ }
549
+
550
+ static int sr_block_revalidate_disk (struct gendisk * disk )
551
+ {
552
+ struct scsi_cd * cd = scsi_cd (disk );
553
+ struct scsi_sense_hdr sshdr ;
554
+
555
+ /* if the unit is not ready, nothing more to do */
556
+ if (scsi_test_unit_ready (cd -> device , SR_TIMEOUT , MAX_RETRIES , & sshdr ))
557
+ return 0 ;
558
+
559
+ sr_cd_check (& cd -> cdi );
560
+ get_sectorsize (cd );
561
+ return 0 ;
540
562
}
541
563
542
564
static const struct block_device_operations sr_bdops =
@@ -545,7 +567,8 @@ static const struct block_device_operations sr_bdops =
545
567
.open = sr_block_open ,
546
568
.release = sr_block_release ,
547
569
.ioctl = sr_block_ioctl ,
548
- .media_changed = sr_block_media_changed ,
570
+ .check_events = sr_block_check_events ,
571
+ .revalidate_disk = sr_block_revalidate_disk ,
549
572
/*
550
573
* No compat_ioctl for now because sr_block_ioctl never
551
574
* seems to pass arbitary ioctls down to host drivers.
@@ -618,6 +641,7 @@ static int sr_probe(struct device *dev)
618
641
sprintf (disk -> disk_name , "sr%d" , minor );
619
642
disk -> fops = & sr_bdops ;
620
643
disk -> flags = GENHD_FL_CD ;
644
+ disk -> events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST ;
621
645
622
646
blk_queue_rq_timeout (sdev -> request_queue , SR_TIMEOUT );
623
647
@@ -627,7 +651,7 @@ static int sr_probe(struct device *dev)
627
651
cd -> disk = disk ;
628
652
cd -> capacity = 0x1fffff ;
629
653
cd -> device -> changed = 1 ; /* force recheck CD type */
630
- cd -> previous_state = 1 ;
654
+ cd -> media_present = 1 ;
631
655
cd -> use = 1 ;
632
656
cd -> readcd_known = 0 ;
633
657
cd -> readcd_cdda = 0 ;
@@ -780,7 +804,7 @@ static void get_capabilities(struct scsi_cd *cd)
780
804
}
781
805
782
806
/* eat unit attentions */
783
- sr_test_unit_ready (cd -> device , & sshdr );
807
+ scsi_test_unit_ready (cd -> device , SR_TIMEOUT , MAX_RETRIES , & sshdr );
784
808
785
809
/* ask for mode page 0x2a */
786
810
rc = scsi_mode_sense (cd -> device , 0 , 0x2a , buffer , 128 ,
0 commit comments