Blame view
drivers/scsi/sr.c
25.3 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/* * sr.c Copyright (C) 1992 David Giller * Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale * * adapted from: * sd.c Copyright (C) 1992 Drew Eckhardt * Linux scsi disk driver by * Drew Eckhardt <drew@colorado.edu> * * Modified by Eric Youngdale ericy@andante.org to * add scatter-gather, multiple outstanding request, and other * enhancements. * * Modified by Eric Youngdale eric@andante.org to support loadable * low-level scsi drivers. * * Modified by Thomas Quinot thomas@melchior.cuivre.fdn.fr to * provide auto-eject. * * Modified by Gerd Knorr <kraxel@cs.tu-berlin.de> to support the * generic cdrom interface * * Modified by Jens Axboe <axboe@suse.de> - Uniform sr_packet() * interface, capabilities probe additions, ioctl cleanups, etc. * * Modified by Richard Gooch <rgooch@atnf.csiro.au> to support devfs * * Modified by Jens Axboe <axboe@suse.de> - support DVD-RAM * transparently and lose the GHOST hack * * Modified by Arnaldo Carvalho de Melo <acme@conectiva.com.br> * check resource allocation in sr_init and some cleanups */ #include <linux/module.h> #include <linux/fs.h> #include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
38 39 40 41 42 43 44 45 |
#include <linux/mm.h> #include <linux/bio.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/cdrom.h> #include <linux/interrupt.h> #include <linux/init.h> #include <linux/blkdev.h> |
0b9506723 [SCSI] turn most ... |
46 |
#include <linux/mutex.h> |
5a0e3ad6a include cleanup: ... |
47 |
#include <linux/slab.h> |
6c7f1e2f1 [SCSI] sr: suppor... |
48 |
#include <linux/pm_runtime.h> |
1da177e4c Linux-2.6.12-rc2 |
49 50 51 52 53 54 |
#include <asm/uaccess.h> #include <scsi/scsi.h> #include <scsi/scsi_dbg.h> #include <scsi/scsi_device.h> #include <scsi/scsi_driver.h> |
820732b50 [SCSI] convert sr... |
55 |
#include <scsi/scsi_cmnd.h> |
1da177e4c Linux-2.6.12-rc2 |
56 57 58 |
#include <scsi/scsi_eh.h> #include <scsi/scsi_host.h> #include <scsi/scsi_ioctl.h> /* For the door lock/unlock commands */ |
1da177e4c Linux-2.6.12-rc2 |
59 60 61 |
#include "scsi_logging.h" #include "sr.h" |
f018fa552 [SCSI] MODULE_ALI... |
62 63 64 |
MODULE_DESCRIPTION("SCSI cdrom (sr) driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR); |
d7b8bcb0a [SCSI] modalias f... |
65 66 |
MODULE_ALIAS_SCSI_DEVICE(TYPE_ROM); MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM); |
f018fa552 [SCSI] MODULE_ALI... |
67 |
|
1da177e4c Linux-2.6.12-rc2 |
68 |
#define SR_DISKS 256 |
1da177e4c Linux-2.6.12-rc2 |
69 70 71 |
#define SR_CAPABILITIES \ (CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|CDC_SELECT_SPEED| \ CDC_SELECT_DISC|CDC_MULTI_SESSION|CDC_MCN|CDC_MEDIA_CHANGED| \ |
6a2900b67 [PATCH] kill cdro... |
72 |
CDC_PLAY_AUDIO|CDC_RESET|CDC_DRIVE_STATUS| \ |
1da177e4c Linux-2.6.12-rc2 |
73 74 |
CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \ CDC_MRW|CDC_MRW_W|CDC_RAM) |
2a48fc0ab block: autoconver... |
75 |
static DEFINE_MUTEX(sr_mutex); |
1da177e4c Linux-2.6.12-rc2 |
76 77 |
static int sr_probe(struct device *); static int sr_remove(struct device *); |
a1b73fc19 scsi: reintroduce... |
78 |
static int sr_init_command(struct scsi_cmnd *SCpnt); |
7b3d9545f Revert "scsi: rev... |
79 |
static int sr_done(struct scsi_cmnd *); |
6c7f1e2f1 [SCSI] sr: suppor... |
80 81 82 83 84 |
static int sr_runtime_suspend(struct device *dev); static struct dev_pm_ops sr_pm_ops = { .runtime_suspend = sr_runtime_suspend, }; |
1da177e4c Linux-2.6.12-rc2 |
85 86 |
static struct scsi_driver sr_template = { |
1da177e4c Linux-2.6.12-rc2 |
87 88 |
.gendrv = { .name = "sr", |
3af6b3526 scsi: remove scsi... |
89 |
.owner = THIS_MODULE, |
1da177e4c Linux-2.6.12-rc2 |
90 91 |
.probe = sr_probe, .remove = sr_remove, |
6c7f1e2f1 [SCSI] sr: suppor... |
92 |
.pm = &sr_pm_ops, |
1da177e4c Linux-2.6.12-rc2 |
93 |
}, |
a1b73fc19 scsi: reintroduce... |
94 |
.init_command = sr_init_command, |
7b3d9545f Revert "scsi: rev... |
95 |
.done = sr_done, |
1da177e4c Linux-2.6.12-rc2 |
96 97 98 99 100 101 102 103 |
}; static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG]; static DEFINE_SPINLOCK(sr_index_lock); /* This semaphore is used to mediate the 0->1 reference get in the * face of object destruction (i.e. we can't allow a get on an * object after last put) */ |
0b9506723 [SCSI] turn most ... |
104 |
static DEFINE_MUTEX(sr_ref_mutex); |
1da177e4c Linux-2.6.12-rc2 |
105 106 107 108 109 110 |
static int sr_open(struct cdrom_device_info *, int); static void sr_release(struct cdrom_device_info *); static void get_sectorsize(struct scsi_cd *); static void get_capabilities(struct scsi_cd *); |
93aae17af sr: implement sr_... |
111 112 |
static unsigned int sr_check_events(struct cdrom_device_info *cdi, unsigned int clearing, int slot); |
1da177e4c Linux-2.6.12-rc2 |
113 114 115 116 117 118 |
static int sr_packet(struct cdrom_device_info *, struct packet_command *); static struct cdrom_device_ops sr_dops = { .open = sr_open, .release = sr_release, .drive_status = sr_drive_status, |
93aae17af sr: implement sr_... |
119 |
.check_events = sr_check_events, |
1da177e4c Linux-2.6.12-rc2 |
120 121 122 123 124 125 126 |
.tray_move = sr_tray_move, .lock_door = sr_lock_door, .select_speed = sr_select_speed, .get_last_session = sr_get_last_session, .get_mcn = sr_get_mcn, .reset = sr_reset, .audio_ioctl = sr_audio_ioctl, |
1da177e4c Linux-2.6.12-rc2 |
127 128 129 130 131 132 133 134 135 136 |
.capability = SR_CAPABILITIES, .generic_packet = sr_packet, }; static void sr_kref_release(struct kref *kref); static inline struct scsi_cd *scsi_cd(struct gendisk *disk) { return container_of(disk->private_data, struct scsi_cd, driver); } |
6c7f1e2f1 [SCSI] sr: suppor... |
137 138 139 140 141 142 143 144 145 |
static int sr_runtime_suspend(struct device *dev) { struct scsi_cd *cd = dev_get_drvdata(dev); if (cd->media_present) return -EBUSY; else return 0; } |
1da177e4c Linux-2.6.12-rc2 |
146 147 148 149 150 151 152 |
/* * The get and put routines for the struct scsi_cd. Note this entity * has a scsi_device pointer and owns a reference to this. */ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) { struct scsi_cd *cd = NULL; |
0b9506723 [SCSI] turn most ... |
153 |
mutex_lock(&sr_ref_mutex); |
1da177e4c Linux-2.6.12-rc2 |
154 155 156 157 |
if (disk->private_data == NULL) goto out; cd = scsi_cd(disk); kref_get(&cd->kref); |
6627b38fd [SCSI] sr: use bl... |
158 159 160 161 |
if (scsi_device_get(cd->device)) { kref_put(&cd->kref, sr_kref_release); cd = NULL; } |
1da177e4c Linux-2.6.12-rc2 |
162 |
out: |
0b9506723 [SCSI] turn most ... |
163 |
mutex_unlock(&sr_ref_mutex); |
1da177e4c Linux-2.6.12-rc2 |
164 165 |
return cd; } |
858119e15 [PATCH] Unlinline... |
166 |
static void scsi_cd_put(struct scsi_cd *cd) |
1da177e4c Linux-2.6.12-rc2 |
167 168 |
{ struct scsi_device *sdev = cd->device; |
0b9506723 [SCSI] turn most ... |
169 |
mutex_lock(&sr_ref_mutex); |
1da177e4c Linux-2.6.12-rc2 |
170 171 |
kref_put(&cd->kref, sr_kref_release); scsi_device_put(sdev); |
0b9506723 [SCSI] turn most ... |
172 |
mutex_unlock(&sr_ref_mutex); |
1da177e4c Linux-2.6.12-rc2 |
173 |
} |
93aae17af sr: implement sr_... |
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
static unsigned int sr_get_events(struct scsi_device *sdev) { u8 buf[8]; u8 cmd[] = { GET_EVENT_STATUS_NOTIFICATION, 1, /* polled */ 0, 0, /* reserved */ 1 << 4, /* notification class: media */ 0, 0, /* reserved */ 0, sizeof(buf), /* allocation length */ 0, /* control */ }; struct event_header *eh = (void *)buf; struct media_event_desc *med = (void *)(buf + 4); struct scsi_sense_hdr sshdr; int result; result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, sizeof(buf), &sshdr, SR_TIMEOUT, MAX_RETRIES, NULL); if (scsi_sense_valid(&sshdr) && sshdr.sense_key == UNIT_ATTENTION) return DISK_EVENT_MEDIA_CHANGE; if (result || be16_to_cpu(eh->data_len) < sizeof(*med)) return 0; if (eh->nea || eh->notification_class != 0x4) return 0; if (med->media_event_code == 1) return DISK_EVENT_EJECT_REQUEST; else if (med->media_event_code == 2) return DISK_EVENT_MEDIA_CHANGE; return 0; } |
1da177e4c Linux-2.6.12-rc2 |
207 |
/* |
93aae17af sr: implement sr_... |
208 209 210 211 212 |
* This function checks to see if the media has been changed or eject * button has been pressed. It is possible that we have already * sensed a change, or the drive may have sensed one and not yet * reported it. The past events are accumulated in sdev->changed and * returned together with the current state. |
1da177e4c Linux-2.6.12-rc2 |
213 |
*/ |
93aae17af sr: implement sr_... |
214 215 |
static unsigned int sr_check_events(struct cdrom_device_info *cdi, unsigned int clearing, int slot) |
1da177e4c Linux-2.6.12-rc2 |
216 217 |
{ struct scsi_cd *cd = cdi->handle; |
93aae17af sr: implement sr_... |
218 219 220 221 |
bool last_present; struct scsi_sense_hdr sshdr; unsigned int events; int ret; |
1da177e4c Linux-2.6.12-rc2 |
222 |
|
93aae17af sr: implement sr_... |
223 224 225 226 227 |
/* no changer support */ if (CDSL_CURRENT != slot) return 0; events = sr_get_events(cd->device); |
79b9677d8 [SCSI] sr: check_... |
228 229 230 231 232 233 234 235 236 237 238 239 |
cd->get_event_changed |= events & DISK_EVENT_MEDIA_CHANGE; /* * If earlier GET_EVENT_STATUS_NOTIFICATION and TUR did not agree * for several times in a row. We rely on TUR only for this likely * broken device, to prevent generating incorrect media changed * events for every open(). */ if (cd->ignore_get_event) { events &= ~DISK_EVENT_MEDIA_CHANGE; goto do_tur; } |
93aae17af sr: implement sr_... |
240 241 242 243 244 |
/* * GET_EVENT_STATUS_NOTIFICATION is enough unless MEDIA_CHANGE * is being cleared. Note that there are devices which hang * if asked to execute TUR repeatedly. */ |
79b9677d8 [SCSI] sr: check_... |
245 246 247 248 249 |
if (cd->device->changed) { events |= DISK_EVENT_MEDIA_CHANGE; cd->device->changed = 0; cd->tur_changed = true; } |
93aae17af sr: implement sr_... |
250 |
|
79b9677d8 [SCSI] sr: check_... |
251 252 253 |
if (!(clearing & DISK_EVENT_MEDIA_CHANGE)) return events; do_tur: |
93aae17af sr: implement sr_... |
254 255 256 |
/* let's see whether the media is there with TUR */ last_present = cd->media_present; ret = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); |
1da177e4c Linux-2.6.12-rc2 |
257 |
|
638428ece scsi: fix TUR err... |
258 259 260 261 262 |
/* * Media is considered to be present if TUR succeeds or fails with * sense data indicating something other than media-not-present * (ASC 0x3a). */ |
93aae17af sr: implement sr_... |
263 264 |
cd->media_present = scsi_status_is_good(ret) || (scsi_sense_valid(&sshdr) && sshdr.asc != 0x3a); |
1da177e4c Linux-2.6.12-rc2 |
265 |
|
93aae17af sr: implement sr_... |
266 |
if (last_present != cd->media_present) |
79b9677d8 [SCSI] sr: check_... |
267 |
cd->device->changed = 1; |
93aae17af sr: implement sr_... |
268 269 270 |
if (cd->device->changed) { events |= DISK_EVENT_MEDIA_CHANGE; cd->device->changed = 0; |
79b9677d8 [SCSI] sr: check_... |
271 272 273 274 275 276 277 278 279 280 |
cd->tur_changed = true; } if (cd->ignore_get_event) return events; /* check whether GET_EVENT is reporting spurious MEDIA_CHANGE */ if (!cd->tur_changed) { if (cd->get_event_changed) { if (cd->tur_mismatch++ > 8) { |
96eefad2d scsi: Implement s... |
281 282 283 |
sr_printk(KERN_WARNING, cd, "GET_EVENT and TUR disagree continuously, suppress GET_EVENT events "); |
79b9677d8 [SCSI] sr: check_... |
284 285 286 287 288 |
cd->ignore_get_event = true; } } else { cd->tur_mismatch = 0; } |
1da177e4c Linux-2.6.12-rc2 |
289 |
} |
79b9677d8 [SCSI] sr: check_... |
290 291 |
cd->tur_changed = false; cd->get_event_changed = false; |
285e9670d [SCSI] sr,sd: sen... |
292 |
|
93aae17af sr: implement sr_... |
293 |
return events; |
1da177e4c Linux-2.6.12-rc2 |
294 |
} |
93aae17af sr: implement sr_... |
295 |
|
1da177e4c Linux-2.6.12-rc2 |
296 |
/* |
7b3d9545f Revert "scsi: rev... |
297 |
* sr_done is the interrupt routine for the device driver. |
1da177e4c Linux-2.6.12-rc2 |
298 |
* |
7b3d9545f Revert "scsi: rev... |
299 |
* It will be notified on the end of a SCSI read / write, and will take one |
1da177e4c Linux-2.6.12-rc2 |
300 301 |
* of several actions based on success or failure. */ |
7b3d9545f Revert "scsi: rev... |
302 |
static int sr_done(struct scsi_cmnd *SCpnt) |
1da177e4c Linux-2.6.12-rc2 |
303 304 |
{ int result = SCpnt->result; |
30b0c37b2 [SCSI] implement ... |
305 |
int this_count = scsi_bufflen(SCpnt); |
1da177e4c Linux-2.6.12-rc2 |
306 307 308 309 310 311 |
int good_bytes = (result == 0 ? this_count : 0); int block_sectors = 0; long error_sector; struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk); #ifdef DEBUG |
96eefad2d scsi: Implement s... |
312 313 |
scmd_printk(KERN_INFO, SCpnt, "done: %x ", result); |
1da177e4c Linux-2.6.12-rc2 |
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
#endif /* * Handle MEDIUM ERRORs or VOLUME OVERFLOWs that indicate partial * success. Since this is a relatively rare error condition, no * care is taken to avoid unnecessary additional work such as * memcpy's that could be avoided. */ if (driver_byte(result) != 0 && /* An error occurred */ (SCpnt->sense_buffer[0] & 0x7f) == 0x70) { /* Sense current */ switch (SCpnt->sense_buffer[2]) { case MEDIUM_ERROR: case VOLUME_OVERFLOW: case ILLEGAL_REQUEST: if (!(SCpnt->sense_buffer[0] & 0x90)) break; |
1da177e4c Linux-2.6.12-rc2 |
330 331 332 333 334 335 336 337 338 339 340 341 |
error_sector = (SCpnt->sense_buffer[3] << 24) | (SCpnt->sense_buffer[4] << 16) | (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6]; if (SCpnt->request->bio != NULL) block_sectors = bio_sectors(SCpnt->request->bio); if (block_sectors < 4) block_sectors = 4; if (cd->device->sector_size == 2048) error_sector <<= 2; error_sector &= ~(block_sectors - 1); |
83096ebf1 block: convert to... |
342 343 |
good_bytes = (error_sector - blk_rq_pos(SCpnt->request)) << 9; |
1da177e4c Linux-2.6.12-rc2 |
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
if (good_bytes < 0 || good_bytes >= this_count) good_bytes = 0; /* * The SCSI specification allows for the value * returned by READ CAPACITY to be up to 75 2K * sectors past the last readable block. * Therefore, if we hit a medium error within the * last 75 2K sectors, we decrease the saved size * value. */ if (error_sector < get_capacity(cd->disk) && cd->capacity - error_sector < 4 * 75) set_capacity(cd->disk, error_sector); break; case RECOVERED_ERROR: |
1da177e4c Linux-2.6.12-rc2 |
360 361 362 363 364 365 366 |
good_bytes = this_count; break; default: break; } } |
7b3d9545f Revert "scsi: rev... |
367 |
return good_bytes; |
1da177e4c Linux-2.6.12-rc2 |
368 |
} |
a1b73fc19 scsi: reintroduce... |
369 |
static int sr_init_command(struct scsi_cmnd *SCpnt) |
1da177e4c Linux-2.6.12-rc2 |
370 |
{ |
242f9dcb8 block: unify requ... |
371 |
int block = 0, this_count, s_size; |
7f9a6bc4e [SCSI] move ULD a... |
372 |
struct scsi_cd *cd; |
a1b73fc19 scsi: reintroduce... |
373 |
struct request *rq = SCpnt->request; |
7f9a6bc4e [SCSI] move ULD a... |
374 |
int ret; |
3c356bde1 scsi: stop passin... |
375 |
ret = scsi_init_io(SCpnt); |
7f9a6bc4e [SCSI] move ULD a... |
376 377 378 379 380 381 382 383 |
if (ret != BLKPREP_OK) goto out; SCpnt = rq->special; cd = scsi_cd(rq->rq_disk); /* from here on until we're complete, any goto out * is used for a killable error condition */ ret = BLKPREP_KILL; |
1da177e4c Linux-2.6.12-rc2 |
384 |
|
96eefad2d scsi: Implement s... |
385 386 387 |
SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt, "Doing sr request, block = %d ", block)); |
1da177e4c Linux-2.6.12-rc2 |
388 389 |
if (!cd->device || !scsi_device_online(cd->device)) { |
96eefad2d scsi: Implement s... |
390 391 392 393 394 395 |
SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "Finishing %u sectors ", blk_rq_sectors(rq))); SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "Retry with 0x%p ", SCpnt)); |
7f9a6bc4e [SCSI] move ULD a... |
396 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
397 398 399 400 401 402 403 |
} if (cd->device->changed) { /* * quietly refuse to do anything to a changed disc until the * changed bit has been reset */ |
7f9a6bc4e [SCSI] move ULD a... |
404 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
405 406 407 |
} /* |
1da177e4c Linux-2.6.12-rc2 |
408 409 410 411 412 413 414 415 |
* we do lazy blocksize switching (when reading XA sectors, * see CDROMREADMODE2 ioctl) */ s_size = cd->device->sector_size; if (s_size > 2048) { if (!in_interrupt()) sr_set_blocklength(cd, 2048); else |
96eefad2d scsi: Implement s... |
416 417 418 |
scmd_printk(KERN_INFO, SCpnt, "can't switch blocksize: in interrupt "); |
1da177e4c Linux-2.6.12-rc2 |
419 420 421 |
} if (s_size != 512 && s_size != 1024 && s_size != 2048) { |
3bf743e7c [SCSI] use {sdev,... |
422 423 |
scmd_printk(KERN_ERR, SCpnt, "bad sector size %d ", s_size); |
7f9a6bc4e [SCSI] move ULD a... |
424 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
425 |
} |
7f9a6bc4e [SCSI] move ULD a... |
426 |
if (rq_data_dir(rq) == WRITE) { |
fd2eb9034 scsi: move the wr... |
427 |
if (!cd->writeable) |
7f9a6bc4e [SCSI] move ULD a... |
428 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
429 |
SCpnt->cmnd[0] = WRITE_10; |
96eefad2d scsi: Implement s... |
430 |
cd->cdi.media_written = 1; |
7f9a6bc4e [SCSI] move ULD a... |
431 |
} else if (rq_data_dir(rq) == READ) { |
1da177e4c Linux-2.6.12-rc2 |
432 |
SCpnt->cmnd[0] = READ_10; |
1da177e4c Linux-2.6.12-rc2 |
433 |
} else { |
7f9a6bc4e [SCSI] move ULD a... |
434 435 |
blk_dump_rq_flags(rq, "Unknown sr command"); goto out; |
1da177e4c Linux-2.6.12-rc2 |
436 437 438 |
} { |
30b0c37b2 [SCSI] implement ... |
439 440 |
struct scatterlist *sg; int i, size = 0, sg_count = scsi_sg_count(SCpnt); |
1da177e4c Linux-2.6.12-rc2 |
441 |
|
30b0c37b2 [SCSI] implement ... |
442 443 444 445 |
scsi_for_each_sg(SCpnt, sg, sg_count, i) size += sg->length; if (size != scsi_bufflen(SCpnt)) { |
3bf743e7c [SCSI] use {sdev,... |
446 447 448 |
scmd_printk(KERN_ERR, SCpnt, "mismatch count %d, bytes %d ", |
30b0c37b2 [SCSI] implement ... |
449 450 451 |
size, scsi_bufflen(SCpnt)); if (scsi_bufflen(SCpnt) > size) SCpnt->sdb.length = size; |
1da177e4c Linux-2.6.12-rc2 |
452 453 454 455 456 457 |
} } /* * request doesn't start on hw block boundary, add scatter pads */ |
83096ebf1 block: convert to... |
458 |
if (((unsigned int)blk_rq_pos(rq) % (s_size >> 9)) || |
30b0c37b2 [SCSI] implement ... |
459 |
(scsi_bufflen(SCpnt) % s_size)) { |
3bf743e7c [SCSI] use {sdev,... |
460 461 |
scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer "); |
7f9a6bc4e [SCSI] move ULD a... |
462 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
463 |
} |
30b0c37b2 [SCSI] implement ... |
464 |
this_count = (scsi_bufflen(SCpnt) >> 9) / (s_size >> 9); |
1da177e4c Linux-2.6.12-rc2 |
465 |
|
96eefad2d scsi: Implement s... |
466 467 468 469 |
SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "%s %d/%u 512 byte blocks. ", (rq_data_dir(rq) == WRITE) ? |
1da177e4c Linux-2.6.12-rc2 |
470 |
"writing" : "reading", |
96eefad2d scsi: Implement s... |
471 |
this_count, blk_rq_sectors(rq))); |
1da177e4c Linux-2.6.12-rc2 |
472 473 |
SCpnt->cmnd[1] = 0; |
83096ebf1 block: convert to... |
474 |
block = (unsigned int)blk_rq_pos(rq) / (s_size >> 9); |
1da177e4c Linux-2.6.12-rc2 |
475 476 477 |
if (this_count > 0xffff) { this_count = 0xffff; |
30b0c37b2 [SCSI] implement ... |
478 |
SCpnt->sdb.length = this_count * s_size; |
1da177e4c Linux-2.6.12-rc2 |
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 |
} SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; SCpnt->cmnd[5] = (unsigned char) block & 0xff; SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0; SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; /* * We shouldn't disconnect in the middle of a sector, so with a dumb * host adapter, it's safe to assume that we can at least transfer * this many bytes between each connect / disconnect. */ SCpnt->transfersize = cd->device->sector_size; SCpnt->underflow = this_count << 9; |
1da177e4c Linux-2.6.12-rc2 |
496 |
SCpnt->allowed = MAX_RETRIES; |
1da177e4c Linux-2.6.12-rc2 |
497 498 |
/* |
1da177e4c Linux-2.6.12-rc2 |
499 500 501 |
* This indicates that the command is ready from our end to be * queued. */ |
7f9a6bc4e [SCSI] move ULD a... |
502 503 |
ret = BLKPREP_OK; out: |
a1b73fc19 scsi: reintroduce... |
504 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
505 |
} |
40cc51be6 [PATCH] switch sr |
506 |
static int sr_block_open(struct block_device *bdev, fmode_t mode) |
1da177e4c Linux-2.6.12-rc2 |
507 |
{ |
6e9624b8c block: push down ... |
508 |
struct scsi_cd *cd; |
40cc51be6 [PATCH] switch sr |
509 |
int ret = -ENXIO; |
1da177e4c Linux-2.6.12-rc2 |
510 |
|
2a48fc0ab block: autoconver... |
511 |
mutex_lock(&sr_mutex); |
6e9624b8c block: push down ... |
512 |
cd = scsi_cd_get(bdev->bd_disk); |
40cc51be6 [PATCH] switch sr |
513 514 515 516 517 |
if (cd) { ret = cdrom_open(&cd->cdi, bdev, mode); if (ret) scsi_cd_put(cd); } |
2a48fc0ab block: autoconver... |
518 |
mutex_unlock(&sr_mutex); |
1da177e4c Linux-2.6.12-rc2 |
519 520 |
return ret; } |
db2a144be block_device_oper... |
521 |
static void sr_block_release(struct gendisk *disk, fmode_t mode) |
1da177e4c Linux-2.6.12-rc2 |
522 |
{ |
40cc51be6 [PATCH] switch sr |
523 |
struct scsi_cd *cd = scsi_cd(disk); |
2a48fc0ab block: autoconver... |
524 |
mutex_lock(&sr_mutex); |
40cc51be6 [PATCH] switch sr |
525 |
cdrom_release(&cd->cdi, mode); |
1da177e4c Linux-2.6.12-rc2 |
526 |
scsi_cd_put(cd); |
2a48fc0ab block: autoconver... |
527 |
mutex_unlock(&sr_mutex); |
1da177e4c Linux-2.6.12-rc2 |
528 |
} |
40cc51be6 [PATCH] switch sr |
529 |
static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, |
1da177e4c Linux-2.6.12-rc2 |
530 531 |
unsigned long arg) { |
40cc51be6 [PATCH] switch sr |
532 |
struct scsi_cd *cd = scsi_cd(bdev->bd_disk); |
1da177e4c Linux-2.6.12-rc2 |
533 |
struct scsi_device *sdev = cd->device; |
6a2900b67 [PATCH] kill cdro... |
534 535 |
void __user *argp = (void __user *)arg; int ret; |
1da177e4c Linux-2.6.12-rc2 |
536 |
|
2a48fc0ab block: autoconver... |
537 |
mutex_lock(&sr_mutex); |
8a6cfeb6d block: push down ... |
538 |
|
906d15fbd scsi: split scsi_... |
539 540 541 542 |
ret = scsi_ioctl_block_when_processing_errors(sdev, cmd, (mode & FMODE_NDELAY) != 0); if (ret) goto out; |
6a2900b67 [PATCH] kill cdro... |
543 544 545 546 547 548 549 |
/* * Send SCSI addressing ioctls directly to mid level, send other * ioctls to cdrom/block level. */ switch (cmd) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: |
8a6cfeb6d block: push down ... |
550 551 |
ret = scsi_ioctl(sdev, cmd, argp); goto out; |
1da177e4c Linux-2.6.12-rc2 |
552 |
} |
6a2900b67 [PATCH] kill cdro... |
553 |
|
40cc51be6 [PATCH] switch sr |
554 |
ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); |
6397256b0 [SCSI] sr: fix er... |
555 |
if (ret != -ENOSYS) |
8a6cfeb6d block: push down ... |
556 |
goto out; |
6a2900b67 [PATCH] kill cdro... |
557 |
|
8a6cfeb6d block: push down ... |
558 559 560 |
ret = scsi_ioctl(sdev, cmd, argp); out: |
2a48fc0ab block: autoconver... |
561 |
mutex_unlock(&sr_mutex); |
8a6cfeb6d block: push down ... |
562 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
563 |
} |
93aae17af sr: implement sr_... |
564 565 |
static unsigned int sr_block_check_events(struct gendisk *disk, unsigned int clearing) |
1da177e4c Linux-2.6.12-rc2 |
566 567 |
{ struct scsi_cd *cd = scsi_cd(disk); |
6c7f1e2f1 [SCSI] sr: suppor... |
568 |
|
6627b38fd [SCSI] sr: use bl... |
569 570 |
if (atomic_read(&cd->device->disk_events_disable_depth)) return 0; |
6c7f1e2f1 [SCSI] sr: suppor... |
571 |
|
6627b38fd [SCSI] sr: use bl... |
572 |
return cdrom_check_events(&cd->cdi, clearing); |
93aae17af sr: implement sr_... |
573 574 575 576 577 578 579 580 581 |
} static int sr_block_revalidate_disk(struct gendisk *disk) { struct scsi_cd *cd = scsi_cd(disk); struct scsi_sense_hdr sshdr; /* if the unit is not ready, nothing more to do */ if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr)) |
6c7f1e2f1 [SCSI] sr: suppor... |
582 |
goto out; |
93aae17af sr: implement sr_... |
583 584 585 |
sr_cd_check(&cd->cdi); get_sectorsize(cd); |
6c7f1e2f1 [SCSI] sr: suppor... |
586 |
out: |
93aae17af sr: implement sr_... |
587 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
588 |
} |
83d5cde47 const: make block... |
589 |
static const struct block_device_operations sr_bdops = |
1da177e4c Linux-2.6.12-rc2 |
590 591 |
{ .owner = THIS_MODULE, |
40cc51be6 [PATCH] switch sr |
592 593 |
.open = sr_block_open, .release = sr_block_release, |
8a6cfeb6d block: push down ... |
594 |
.ioctl = sr_block_ioctl, |
93aae17af sr: implement sr_... |
595 596 |
.check_events = sr_block_check_events, .revalidate_disk = sr_block_revalidate_disk, |
1da177e4c Linux-2.6.12-rc2 |
597 598 |
/* * No compat_ioctl for now because sr_block_ioctl never |
25985edce Fix common misspe... |
599 |
* seems to pass arbitrary ioctls down to host drivers. |
1da177e4c Linux-2.6.12-rc2 |
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 |
*/ }; static int sr_open(struct cdrom_device_info *cdi, int purpose) { struct scsi_cd *cd = cdi->handle; struct scsi_device *sdev = cd->device; int retval; /* * If the device is in error recovery, wait until it is done. * If the device is offline, then disallow any access to it. */ retval = -ENXIO; if (!scsi_block_when_processing_errors(sdev)) goto error_out; |
1da177e4c Linux-2.6.12-rc2 |
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 |
return 0; error_out: return retval; } static void sr_release(struct cdrom_device_info *cdi) { struct scsi_cd *cd = cdi->handle; if (cd->device->sector_size > 2048) sr_set_blocklength(cd, 2048); } static int sr_probe(struct device *dev) { struct scsi_device *sdev = to_scsi_device(dev); struct gendisk *disk; struct scsi_cd *cd; int minor, error; |
6fe8c1dbe scsi: balance out... |
637 |
scsi_autopm_get_device(sdev); |
1da177e4c Linux-2.6.12-rc2 |
638 639 640 641 642 |
error = -ENODEV; if (sdev->type != TYPE_ROM && sdev->type != TYPE_WORM) goto fail; error = -ENOMEM; |
24669f75a [SCSI] SCSI core ... |
643 |
cd = kzalloc(sizeof(*cd), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
644 645 |
if (!cd) goto fail; |
1da177e4c Linux-2.6.12-rc2 |
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 |
kref_init(&cd->kref); disk = alloc_disk(1); if (!disk) goto fail_free; spin_lock(&sr_index_lock); minor = find_first_zero_bit(sr_index_bits, SR_DISKS); if (minor == SR_DISKS) { spin_unlock(&sr_index_lock); error = -EBUSY; goto fail_put; } __set_bit(minor, sr_index_bits); spin_unlock(&sr_index_lock); disk->major = SCSI_CDROM_MAJOR; disk->first_minor = minor; sprintf(disk->disk_name, "sr%d", minor); disk->fops = &sr_bdops; |
d4dc210f6 block: don't bloc... |
667 |
disk->flags = GENHD_FL_CD | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; |
93aae17af sr: implement sr_... |
668 |
disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST; |
1da177e4c Linux-2.6.12-rc2 |
669 |
|
242f9dcb8 block: unify requ... |
670 |
blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT); |
1da177e4c Linux-2.6.12-rc2 |
671 672 673 674 675 |
cd->device = sdev; cd->disk = disk; cd->driver = &sr_template; cd->disk = disk; cd->capacity = 0x1fffff; |
1da177e4c Linux-2.6.12-rc2 |
676 |
cd->device->changed = 1; /* force recheck CD type */ |
93aae17af sr: implement sr_... |
677 |
cd->media_present = 1; |
1da177e4c Linux-2.6.12-rc2 |
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 |
cd->use = 1; cd->readcd_known = 0; cd->readcd_cdda = 0; cd->cdi.ops = &sr_dops; cd->cdi.handle = cd; cd->cdi.mask = 0; cd->cdi.capacity = 1; sprintf(cd->cdi.name, "sr%d", minor); sdev->sector_size = 2048; /* A guess, just in case */ /* FIXME: need to handle a get_capabilities failure properly ?? */ get_capabilities(cd); sr_vendor_init(cd); |
1da177e4c Linux-2.6.12-rc2 |
693 694 695 696 697 698 699 700 |
disk->driverfs_dev = &sdev->sdev_gendev; set_capacity(disk, cd->capacity); disk->private_data = &cd->driver; disk->queue = sdev->request_queue; cd->cdi.disk = disk; if (register_cdrom(&cd->cdi)) goto fail_put; |
6627b38fd [SCSI] sr: use bl... |
701 702 703 704 705 |
/* * Initialize block layer runtime PM stuffs before the * periodic event checking request gets started in add_disk. */ blk_pm_runtime_init(sdev->request_queue, dev); |
1da177e4c Linux-2.6.12-rc2 |
706 707 708 |
dev_set_drvdata(dev, cd); disk->flags |= GENHD_FL_REMOVABLE; add_disk(disk); |
9ccfc756a [SCSI] move the m... |
709 710 711 |
sdev_printk(KERN_DEBUG, sdev, "Attached scsi CD-ROM %s ", cd->cdi.name); |
6c7f1e2f1 [SCSI] sr: suppor... |
712 |
scsi_autopm_put_device(cd->device); |
1da177e4c Linux-2.6.12-rc2 |
713 714 715 716 717 718 719 |
return 0; fail_put: put_disk(disk); fail_free: kfree(cd); fail: |
6fe8c1dbe scsi: balance out... |
720 |
scsi_autopm_put_device(sdev); |
1da177e4c Linux-2.6.12-rc2 |
721 722 723 724 725 726 727 |
return error; } static void get_sectorsize(struct scsi_cd *cd) { unsigned char cmd[10]; |
62858dacc scsi: sr avoids u... |
728 |
unsigned char buffer[8]; |
1da177e4c Linux-2.6.12-rc2 |
729 730 |
int the_result, retries = 3; int sector_size; |
165125e1e [BLOCK] Get rid o... |
731 |
struct request_queue *queue; |
1da177e4c Linux-2.6.12-rc2 |
732 |
|
1da177e4c Linux-2.6.12-rc2 |
733 734 735 |
do { cmd[0] = READ_CAPACITY; memset((void *) &cmd[1], 0, 9); |
62858dacc scsi: sr avoids u... |
736 |
memset(buffer, 0, sizeof(buffer)); |
1da177e4c Linux-2.6.12-rc2 |
737 738 |
/* Do the command and wait.. */ |
820732b50 [SCSI] convert sr... |
739 |
the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE, |
62858dacc scsi: sr avoids u... |
740 |
buffer, sizeof(buffer), NULL, |
f4f4e47e4 [SCSI] add residu... |
741 |
SR_TIMEOUT, MAX_RETRIES, NULL); |
1da177e4c Linux-2.6.12-rc2 |
742 |
|
1da177e4c Linux-2.6.12-rc2 |
743 744 745 |
retries--; } while (the_result && retries); |
1da177e4c Linux-2.6.12-rc2 |
746 747 748 |
if (the_result) { cd->capacity = 0x1fffff; sector_size = 2048; /* A guess, just in case */ |
1da177e4c Linux-2.6.12-rc2 |
749 |
} else { |
5915136d4 [SCSI] sr: consid... |
750 751 752 753 754 755 756 757 758 759 760 761 762 |
long last_written; cd->capacity = 1 + ((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); /* * READ_CAPACITY doesn't return the correct size on * certain UDF media. If last_written is larger, use * it instead. * * http://bugzilla.kernel.org/show_bug.cgi?id=9668 */ if (!cdrom_get_last_written(&cd->cdi, &last_written)) cd->capacity = max_t(long, cd->capacity, last_written); |
1da177e4c Linux-2.6.12-rc2 |
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 |
sector_size = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; switch (sector_size) { /* * HP 4020i CD-Recorder reports 2340 byte sectors * Philips CD-Writers report 2352 byte sectors * * Use 2k sectors for them.. */ case 0: case 2340: case 2352: sector_size = 2048; /* fall through */ case 2048: cd->capacity *= 4; /* fall through */ case 512: break; default: |
96eefad2d scsi: Implement s... |
783 784 |
sr_printk(KERN_INFO, cd, "unsupported sector size %d.", sector_size); |
1da177e4c Linux-2.6.12-rc2 |
785 |
cd->capacity = 0; |
1da177e4c Linux-2.6.12-rc2 |
786 787 788 789 790 791 792 793 |
} cd->device->sector_size = sector_size; /* * Add this so that we have the ability to correctly gauge * what the device is capable of. */ |
1da177e4c Linux-2.6.12-rc2 |
794 795 796 797 |
set_capacity(cd->disk, cd->capacity); } queue = cd->device->request_queue; |
e1defc4ff block: Do away wi... |
798 |
blk_queue_logical_block_size(queue, sector_size); |
1da177e4c Linux-2.6.12-rc2 |
799 |
|
62858dacc scsi: sr avoids u... |
800 |
return; |
1da177e4c Linux-2.6.12-rc2 |
801 802 803 804 805 806 |
} static void get_capabilities(struct scsi_cd *cd) { unsigned char *buffer; struct scsi_mode_data data; |
820732b50 [SCSI] convert sr... |
807 |
struct scsi_sense_hdr sshdr; |
38582a62e [SCSI] sr: fix te... |
808 |
int rc, n; |
1da177e4c Linux-2.6.12-rc2 |
809 |
|
0ad78200b [SCSI] Mark some ... |
810 |
static const char *loadmech[] = |
1da177e4c Linux-2.6.12-rc2 |
811 812 813 814 815 816 817 818 819 820 |
{ "caddy", "tray", "pop-up", "", "changer", "cartridge changer", "", "" }; |
1da177e4c Linux-2.6.12-rc2 |
821 822 823 824 |
/* allocate transfer buffer */ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) { |
96eefad2d scsi: Implement s... |
825 826 |
sr_printk(KERN_ERR, cd, "out of memory. "); |
1da177e4c Linux-2.6.12-rc2 |
827 828 |
return; } |
38582a62e [SCSI] sr: fix te... |
829 |
/* eat unit attentions */ |
9f8a2c23c scsi: replace sr_... |
830 |
scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); |
1da177e4c Linux-2.6.12-rc2 |
831 832 833 |
/* ask for mode page 0x2a */ rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128, |
1cf72699c [SCSI] convert th... |
834 |
SR_TIMEOUT, 3, &data, NULL); |
1da177e4c Linux-2.6.12-rc2 |
835 836 837 838 839 |
if (!scsi_status_is_good(rc)) { /* failed, drive doesn't have capabilities mode page */ cd->cdi.speed = 1; cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | |
bcc1e382b [SCSI] Mask capab... |
840 841 842 |
CDC_DVD | CDC_DVD_RAM | CDC_SELECT_DISC | CDC_SELECT_SPEED | CDC_MRW | CDC_MRW_W | CDC_RAM); |
1da177e4c Linux-2.6.12-rc2 |
843 |
kfree(buffer); |
96eefad2d scsi: Implement s... |
844 |
sr_printk(KERN_INFO, cd, "scsi-1 drive"); |
1da177e4c Linux-2.6.12-rc2 |
845 846 847 848 849 850 851 852 |
return; } n = data.header_length + data.block_descriptor_length; cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176; cd->readcd_known = 1; cd->readcd_cdda = buffer[n + 5] & 0x01; /* print some capability bits */ |
96eefad2d scsi: Implement s... |
853 854 855 856 857 858 859 860 861 862 863 |
sr_printk(KERN_INFO, cd, "scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s ", ((buffer[n + 14] << 8) + buffer[n + 15]) / 176, cd->cdi.speed, buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */ buffer[n + 3] & 0x20 ? "dvd-ram " : "", buffer[n + 2] & 0x02 ? "cd/rw " : "", /* can read rewriteable */ buffer[n + 4] & 0x20 ? "xa/form2 " : "", /* can read xa/from2 */ buffer[n + 5] & 0x01 ? "cdda " : "", /* can read audio data */ loadmech[buffer[n + 6] >> 5]); |
1da177e4c Linux-2.6.12-rc2 |
864 865 866 867 868 869 |
if ((buffer[n + 6] >> 5) == 0) /* caddy drives can't close tray... */ cd->cdi.mask |= CDC_CLOSE_TRAY; if ((buffer[n + 2] & 0x8) == 0) /* not a DVD drive */ cd->cdi.mask |= CDC_DVD; |
96eefad2d scsi: Implement s... |
870 |
if ((buffer[n + 3] & 0x20) == 0) |
1da177e4c Linux-2.6.12-rc2 |
871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 |
/* can't write DVD-RAM media */ cd->cdi.mask |= CDC_DVD_RAM; if ((buffer[n + 3] & 0x10) == 0) /* can't write DVD-R media */ cd->cdi.mask |= CDC_DVD_R; if ((buffer[n + 3] & 0x2) == 0) /* can't write CD-RW media */ cd->cdi.mask |= CDC_CD_RW; if ((buffer[n + 3] & 0x1) == 0) /* can't write CD-R media */ cd->cdi.mask |= CDC_CD_R; if ((buffer[n + 6] & 0x8) == 0) /* can't eject */ cd->cdi.mask |= CDC_OPEN_TRAY; if ((buffer[n + 6] >> 5) == mechtype_individual_changer || (buffer[n + 6] >> 5) == mechtype_cartridge_changer) cd->cdi.capacity = cdrom_number_of_slots(&cd->cdi); if (cd->cdi.capacity <= 1) /* not a changer */ cd->cdi.mask |= CDC_SELECT_DISC; /*else I don't think it can close its tray cd->cdi.mask |= CDC_CLOSE_TRAY; */ /* * if DVD-RAM, MRW-W or CD-RW, we are randomly writable */ if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) != (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) { |
fd2eb9034 scsi: move the wr... |
901 |
cd->writeable = 1; |
1da177e4c Linux-2.6.12-rc2 |
902 |
} |
1da177e4c Linux-2.6.12-rc2 |
903 904 905 906 907 |
kfree(buffer); } /* * sr_packet() is the entry point for the generic commands generated |
96eefad2d scsi: Implement s... |
908 |
* by the Uniform CD-ROM layer. |
1da177e4c Linux-2.6.12-rc2 |
909 910 911 912 |
*/ static int sr_packet(struct cdrom_device_info *cdi, struct packet_command *cgc) { |
8e04d8056 scsi/sr: add no_r... |
913 914 915 916 917 |
struct scsi_cd *cd = cdi->handle; struct scsi_device *sdev = cd->device; if (cgc->cmd[0] == GPCMD_READ_DISC_INFO && sdev->no_read_disc_info) return -EDRIVE_CANT_DO_THIS; |
1da177e4c Linux-2.6.12-rc2 |
918 919 |
if (cgc->timeout <= 0) cgc->timeout = IOCTL_TIMEOUT; |
8e04d8056 scsi/sr: add no_r... |
920 |
sr_do_ioctl(cd, cgc); |
1da177e4c Linux-2.6.12-rc2 |
921 922 923 924 925 926 927 928 |
return cgc->stat; } /** * sr_kref_release - Called to free the scsi_cd structure * @kref: pointer to embedded kref * |
0b9506723 [SCSI] turn most ... |
929 |
* sr_ref_mutex must be held entering this routine. Because it is |
1da177e4c Linux-2.6.12-rc2 |
930 931 932 933 934 935 936 937 938 939 |
* called on last put, you should always use the scsi_cd_get() * scsi_cd_put() helpers which manipulate the semaphore directly * and never do a direct kref_put(). **/ static void sr_kref_release(struct kref *kref) { struct scsi_cd *cd = container_of(kref, struct scsi_cd, kref); struct gendisk *disk = cd->disk; spin_lock(&sr_index_lock); |
f331c0296 block: don't depe... |
940 |
clear_bit(MINOR(disk_devt(disk)), sr_index_bits); |
1da177e4c Linux-2.6.12-rc2 |
941 942 943 944 945 946 947 948 949 950 951 952 953 954 |
spin_unlock(&sr_index_lock); unregister_cdrom(&cd->cdi); disk->private_data = NULL; put_disk(disk); kfree(cd); } static int sr_remove(struct device *dev) { struct scsi_cd *cd = dev_get_drvdata(dev); |
6c7f1e2f1 [SCSI] sr: suppor... |
955 |
scsi_autopm_get_device(cd->device); |
1da177e4c Linux-2.6.12-rc2 |
956 |
del_gendisk(cd->disk); |
0b9506723 [SCSI] turn most ... |
957 |
mutex_lock(&sr_ref_mutex); |
1da177e4c Linux-2.6.12-rc2 |
958 |
kref_put(&cd->kref, sr_kref_release); |
0b9506723 [SCSI] turn most ... |
959 |
mutex_unlock(&sr_ref_mutex); |
1da177e4c Linux-2.6.12-rc2 |
960 961 962 963 964 965 966 967 968 969 970 |
return 0; } static int __init init_sr(void) { int rc; rc = register_blkdev(SCSI_CDROM_MAJOR, "sr"); if (rc) return rc; |
da3962fe6 [SCSI] sr: fix er... |
971 972 973 974 975 |
rc = scsi_register_driver(&sr_template.gendrv); if (rc) unregister_blkdev(SCSI_CDROM_MAJOR, "sr"); return rc; |
1da177e4c Linux-2.6.12-rc2 |
976 977 978 979 980 981 982 983 984 985 986 |
} static void __exit exit_sr(void) { scsi_unregister_driver(&sr_template.gendrv); unregister_blkdev(SCSI_CDROM_MAJOR, "sr"); } module_init(init_sr); module_exit(exit_sr); MODULE_LICENSE("GPL"); |