diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/scsi/sr.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/scsi/sr.c')
-rw-r--r-- | drivers/scsi/sr.c | 965 |
1 files changed, 965 insertions, 0 deletions
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c new file mode 100644 index 000000000000..2f259f249522 --- /dev/null +++ b/drivers/scsi/sr.c | |||
@@ -0,0 +1,965 @@ | |||
1 | /* | ||
2 | * sr.c Copyright (C) 1992 David Giller | ||
3 | * Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale | ||
4 | * | ||
5 | * adapted from: | ||
6 | * sd.c Copyright (C) 1992 Drew Eckhardt | ||
7 | * Linux scsi disk driver by | ||
8 | * Drew Eckhardt <drew@colorado.edu> | ||
9 | * | ||
10 | * Modified by Eric Youngdale ericy@andante.org to | ||
11 | * add scatter-gather, multiple outstanding request, and other | ||
12 | * enhancements. | ||
13 | * | ||
14 | * Modified by Eric Youngdale eric@andante.org to support loadable | ||
15 | * low-level scsi drivers. | ||
16 | * | ||
17 | * Modified by Thomas Quinot thomas@melchior.cuivre.fdn.fr to | ||
18 | * provide auto-eject. | ||
19 | * | ||
20 | * Modified by Gerd Knorr <kraxel@cs.tu-berlin.de> to support the | ||
21 | * generic cdrom interface | ||
22 | * | ||
23 | * Modified by Jens Axboe <axboe@suse.de> - Uniform sr_packet() | ||
24 | * interface, capabilities probe additions, ioctl cleanups, etc. | ||
25 | * | ||
26 | * Modified by Richard Gooch <rgooch@atnf.csiro.au> to support devfs | ||
27 | * | ||
28 | * Modified by Jens Axboe <axboe@suse.de> - support DVD-RAM | ||
29 | * transparently and lose the GHOST hack | ||
30 | * | ||
31 | * Modified by Arnaldo Carvalho de Melo <acme@conectiva.com.br> | ||
32 | * check resource allocation in sr_init and some cleanups | ||
33 | */ | ||
34 | |||
35 | #include <linux/module.h> | ||
36 | #include <linux/fs.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <linux/mm.h> | ||
40 | #include <linux/bio.h> | ||
41 | #include <linux/string.h> | ||
42 | #include <linux/errno.h> | ||
43 | #include <linux/cdrom.h> | ||
44 | #include <linux/interrupt.h> | ||
45 | #include <linux/init.h> | ||
46 | #include <linux/blkdev.h> | ||
47 | #include <asm/uaccess.h> | ||
48 | |||
49 | #include <scsi/scsi.h> | ||
50 | #include <scsi/scsi_dbg.h> | ||
51 | #include <scsi/scsi_device.h> | ||
52 | #include <scsi/scsi_driver.h> | ||
53 | #include <scsi/scsi_eh.h> | ||
54 | #include <scsi/scsi_host.h> | ||
55 | #include <scsi/scsi_ioctl.h> /* For the door lock/unlock commands */ | ||
56 | #include <scsi/scsi_request.h> | ||
57 | |||
58 | #include "scsi_logging.h" | ||
59 | #include "sr.h" | ||
60 | |||
61 | |||
62 | #define SR_DISKS 256 | ||
63 | |||
64 | #define MAX_RETRIES 3 | ||
65 | #define SR_TIMEOUT (30 * HZ) | ||
66 | #define SR_CAPABILITIES \ | ||
67 | (CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|CDC_SELECT_SPEED| \ | ||
68 | CDC_SELECT_DISC|CDC_MULTI_SESSION|CDC_MCN|CDC_MEDIA_CHANGED| \ | ||
69 | CDC_PLAY_AUDIO|CDC_RESET|CDC_IOCTLS|CDC_DRIVE_STATUS| \ | ||
70 | CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \ | ||
71 | CDC_MRW|CDC_MRW_W|CDC_RAM) | ||
72 | |||
73 | static int sr_probe(struct device *); | ||
74 | static int sr_remove(struct device *); | ||
75 | static int sr_init_command(struct scsi_cmnd *); | ||
76 | |||
77 | static struct scsi_driver sr_template = { | ||
78 | .owner = THIS_MODULE, | ||
79 | .gendrv = { | ||
80 | .name = "sr", | ||
81 | .probe = sr_probe, | ||
82 | .remove = sr_remove, | ||
83 | }, | ||
84 | .init_command = sr_init_command, | ||
85 | }; | ||
86 | |||
87 | static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG]; | ||
88 | static DEFINE_SPINLOCK(sr_index_lock); | ||
89 | |||
90 | /* This semaphore is used to mediate the 0->1 reference get in the | ||
91 | * face of object destruction (i.e. we can't allow a get on an | ||
92 | * object after last put) */ | ||
93 | static DECLARE_MUTEX(sr_ref_sem); | ||
94 | |||
95 | static int sr_open(struct cdrom_device_info *, int); | ||
96 | static void sr_release(struct cdrom_device_info *); | ||
97 | |||
98 | static void get_sectorsize(struct scsi_cd *); | ||
99 | static void get_capabilities(struct scsi_cd *); | ||
100 | |||
101 | static int sr_media_change(struct cdrom_device_info *, int); | ||
102 | static int sr_packet(struct cdrom_device_info *, struct packet_command *); | ||
103 | |||
104 | static struct cdrom_device_ops sr_dops = { | ||
105 | .open = sr_open, | ||
106 | .release = sr_release, | ||
107 | .drive_status = sr_drive_status, | ||
108 | .media_changed = sr_media_change, | ||
109 | .tray_move = sr_tray_move, | ||
110 | .lock_door = sr_lock_door, | ||
111 | .select_speed = sr_select_speed, | ||
112 | .get_last_session = sr_get_last_session, | ||
113 | .get_mcn = sr_get_mcn, | ||
114 | .reset = sr_reset, | ||
115 | .audio_ioctl = sr_audio_ioctl, | ||
116 | .dev_ioctl = sr_dev_ioctl, | ||
117 | .capability = SR_CAPABILITIES, | ||
118 | .generic_packet = sr_packet, | ||
119 | }; | ||
120 | |||
121 | static void sr_kref_release(struct kref *kref); | ||
122 | |||
123 | static inline struct scsi_cd *scsi_cd(struct gendisk *disk) | ||
124 | { | ||
125 | return container_of(disk->private_data, struct scsi_cd, driver); | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * The get and put routines for the struct scsi_cd. Note this entity | ||
130 | * has a scsi_device pointer and owns a reference to this. | ||
131 | */ | ||
132 | static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) | ||
133 | { | ||
134 | struct scsi_cd *cd = NULL; | ||
135 | |||
136 | down(&sr_ref_sem); | ||
137 | if (disk->private_data == NULL) | ||
138 | goto out; | ||
139 | cd = scsi_cd(disk); | ||
140 | kref_get(&cd->kref); | ||
141 | if (scsi_device_get(cd->device)) | ||
142 | goto out_put; | ||
143 | goto out; | ||
144 | |||
145 | out_put: | ||
146 | kref_put(&cd->kref, sr_kref_release); | ||
147 | cd = NULL; | ||
148 | out: | ||
149 | up(&sr_ref_sem); | ||
150 | return cd; | ||
151 | } | ||
152 | |||
153 | static inline void scsi_cd_put(struct scsi_cd *cd) | ||
154 | { | ||
155 | struct scsi_device *sdev = cd->device; | ||
156 | |||
157 | down(&sr_ref_sem); | ||
158 | kref_put(&cd->kref, sr_kref_release); | ||
159 | scsi_device_put(sdev); | ||
160 | up(&sr_ref_sem); | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * This function checks to see if the media has been changed in the | ||
165 | * CDROM drive. It is possible that we have already sensed a change, | ||
166 | * or the drive may have sensed one and not yet reported it. We must | ||
167 | * be ready for either case. This function always reports the current | ||
168 | * value of the changed bit. If flag is 0, then the changed bit is reset. | ||
169 | * This function could be done as an ioctl, but we would need to have | ||
170 | * an inode for that to work, and we do not always have one. | ||
171 | */ | ||
172 | |||
173 | int sr_media_change(struct cdrom_device_info *cdi, int slot) | ||
174 | { | ||
175 | struct scsi_cd *cd = cdi->handle; | ||
176 | int retval; | ||
177 | |||
178 | if (CDSL_CURRENT != slot) { | ||
179 | /* no changer support */ | ||
180 | return -EINVAL; | ||
181 | } | ||
182 | |||
183 | retval = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES); | ||
184 | if (retval) { | ||
185 | /* Unable to test, unit probably not ready. This usually | ||
186 | * means there is no disc in the drive. Mark as changed, | ||
187 | * and we will figure it out later once the drive is | ||
188 | * available again. */ | ||
189 | cd->device->changed = 1; | ||
190 | return 1; /* This will force a flush, if called from | ||
191 | * check_disk_change */ | ||
192 | }; | ||
193 | |||
194 | retval = cd->device->changed; | ||
195 | cd->device->changed = 0; | ||
196 | /* If the disk changed, the capacity will now be different, | ||
197 | * so we force a re-read of this information */ | ||
198 | if (retval) { | ||
199 | /* check multisession offset etc */ | ||
200 | sr_cd_check(cdi); | ||
201 | |||
202 | /* | ||
203 | * If the disk changed, the capacity will now be different, | ||
204 | * so we force a re-read of this information | ||
205 | * Force 2048 for the sector size so that filesystems won't | ||
206 | * be trying to use something that is too small if the disc | ||
207 | * has changed. | ||
208 | */ | ||
209 | cd->needs_sector_size = 1; | ||
210 | cd->device->sector_size = 2048; | ||
211 | } | ||
212 | return retval; | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * rw_intr is the interrupt routine for the device driver. | ||
217 | * | ||
218 | * It will be notified on the end of a SCSI read / write, and will take on | ||
219 | * of several actions based on success or failure. | ||
220 | */ | ||
221 | static void rw_intr(struct scsi_cmnd * SCpnt) | ||
222 | { | ||
223 | int result = SCpnt->result; | ||
224 | int this_count = SCpnt->bufflen; | ||
225 | int good_bytes = (result == 0 ? this_count : 0); | ||
226 | int block_sectors = 0; | ||
227 | long error_sector; | ||
228 | struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk); | ||
229 | |||
230 | #ifdef DEBUG | ||
231 | printk("sr.c done: %x\n", result); | ||
232 | #endif | ||
233 | |||
234 | /* | ||
235 | * Handle MEDIUM ERRORs or VOLUME OVERFLOWs that indicate partial | ||
236 | * success. Since this is a relatively rare error condition, no | ||
237 | * care is taken to avoid unnecessary additional work such as | ||
238 | * memcpy's that could be avoided. | ||
239 | */ | ||
240 | if (driver_byte(result) != 0 && /* An error occurred */ | ||
241 | (SCpnt->sense_buffer[0] & 0x7f) == 0x70) { /* Sense current */ | ||
242 | switch (SCpnt->sense_buffer[2]) { | ||
243 | case MEDIUM_ERROR: | ||
244 | case VOLUME_OVERFLOW: | ||
245 | case ILLEGAL_REQUEST: | ||
246 | if (!(SCpnt->sense_buffer[0] & 0x90)) | ||
247 | break; | ||
248 | if (!blk_fs_request(SCpnt->request)) | ||
249 | break; | ||
250 | error_sector = (SCpnt->sense_buffer[3] << 24) | | ||
251 | (SCpnt->sense_buffer[4] << 16) | | ||
252 | (SCpnt->sense_buffer[5] << 8) | | ||
253 | SCpnt->sense_buffer[6]; | ||
254 | if (SCpnt->request->bio != NULL) | ||
255 | block_sectors = | ||
256 | bio_sectors(SCpnt->request->bio); | ||
257 | if (block_sectors < 4) | ||
258 | block_sectors = 4; | ||
259 | if (cd->device->sector_size == 2048) | ||
260 | error_sector <<= 2; | ||
261 | error_sector &= ~(block_sectors - 1); | ||
262 | good_bytes = (error_sector - SCpnt->request->sector) << 9; | ||
263 | if (good_bytes < 0 || good_bytes >= this_count) | ||
264 | good_bytes = 0; | ||
265 | /* | ||
266 | * The SCSI specification allows for the value | ||
267 | * returned by READ CAPACITY to be up to 75 2K | ||
268 | * sectors past the last readable block. | ||
269 | * Therefore, if we hit a medium error within the | ||
270 | * last 75 2K sectors, we decrease the saved size | ||
271 | * value. | ||
272 | */ | ||
273 | if (error_sector < get_capacity(cd->disk) && | ||
274 | cd->capacity - error_sector < 4 * 75) | ||
275 | set_capacity(cd->disk, error_sector); | ||
276 | break; | ||
277 | |||
278 | case RECOVERED_ERROR: | ||
279 | |||
280 | /* | ||
281 | * An error occured, but it recovered. Inform the | ||
282 | * user, but make sure that it's not treated as a | ||
283 | * hard error. | ||
284 | */ | ||
285 | scsi_print_sense("sr", SCpnt); | ||
286 | SCpnt->result = 0; | ||
287 | SCpnt->sense_buffer[0] = 0x0; | ||
288 | good_bytes = this_count; | ||
289 | break; | ||
290 | |||
291 | default: | ||
292 | break; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | /* | ||
297 | * This calls the generic completion function, now that we know | ||
298 | * how many actual sectors finished, and how many sectors we need | ||
299 | * to say have failed. | ||
300 | */ | ||
301 | scsi_io_completion(SCpnt, good_bytes, block_sectors << 9); | ||
302 | } | ||
303 | |||
304 | static int sr_init_command(struct scsi_cmnd * SCpnt) | ||
305 | { | ||
306 | int block=0, this_count, s_size, timeout = SR_TIMEOUT; | ||
307 | struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk); | ||
308 | |||
309 | SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n", | ||
310 | cd->disk->disk_name, block)); | ||
311 | |||
312 | if (!cd->device || !scsi_device_online(cd->device)) { | ||
313 | SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", | ||
314 | SCpnt->request->nr_sectors)); | ||
315 | SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | if (cd->device->changed) { | ||
320 | /* | ||
321 | * quietly refuse to do anything to a changed disc until the | ||
322 | * changed bit has been reset | ||
323 | */ | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | /* | ||
328 | * these are already setup, just copy cdb basically | ||
329 | */ | ||
330 | if (SCpnt->request->flags & REQ_BLOCK_PC) { | ||
331 | struct request *rq = SCpnt->request; | ||
332 | |||
333 | if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd)) | ||
334 | return 0; | ||
335 | |||
336 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); | ||
337 | if (!rq->data_len) | ||
338 | SCpnt->sc_data_direction = DMA_NONE; | ||
339 | else if (rq_data_dir(rq) == WRITE) | ||
340 | SCpnt->sc_data_direction = DMA_TO_DEVICE; | ||
341 | else | ||
342 | SCpnt->sc_data_direction = DMA_FROM_DEVICE; | ||
343 | |||
344 | this_count = rq->data_len; | ||
345 | if (rq->timeout) | ||
346 | timeout = rq->timeout; | ||
347 | |||
348 | SCpnt->transfersize = rq->data_len; | ||
349 | goto queue; | ||
350 | } | ||
351 | |||
352 | if (!(SCpnt->request->flags & REQ_CMD)) { | ||
353 | blk_dump_rq_flags(SCpnt->request, "sr unsup command"); | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | /* | ||
358 | * we do lazy blocksize switching (when reading XA sectors, | ||
359 | * see CDROMREADMODE2 ioctl) | ||
360 | */ | ||
361 | s_size = cd->device->sector_size; | ||
362 | if (s_size > 2048) { | ||
363 | if (!in_interrupt()) | ||
364 | sr_set_blocklength(cd, 2048); | ||
365 | else | ||
366 | printk("sr: can't switch blocksize: in interrupt\n"); | ||
367 | } | ||
368 | |||
369 | if (s_size != 512 && s_size != 1024 && s_size != 2048) { | ||
370 | printk("sr: bad sector size %d\n", s_size); | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | if (rq_data_dir(SCpnt->request) == WRITE) { | ||
375 | if (!cd->device->writeable) | ||
376 | return 0; | ||
377 | SCpnt->cmnd[0] = WRITE_10; | ||
378 | SCpnt->sc_data_direction = DMA_TO_DEVICE; | ||
379 | cd->cdi.media_written = 1; | ||
380 | } else if (rq_data_dir(SCpnt->request) == READ) { | ||
381 | SCpnt->cmnd[0] = READ_10; | ||
382 | SCpnt->sc_data_direction = DMA_FROM_DEVICE; | ||
383 | } else { | ||
384 | blk_dump_rq_flags(SCpnt->request, "Unknown sr command"); | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | { | ||
389 | struct scatterlist *sg = SCpnt->request_buffer; | ||
390 | int i, size = 0; | ||
391 | for (i = 0; i < SCpnt->use_sg; i++) | ||
392 | size += sg[i].length; | ||
393 | |||
394 | if (size != SCpnt->request_bufflen && SCpnt->use_sg) { | ||
395 | printk(KERN_ERR "sr: mismatch count %d, bytes %d\n", | ||
396 | size, SCpnt->request_bufflen); | ||
397 | if (SCpnt->request_bufflen > size) | ||
398 | SCpnt->request_bufflen = SCpnt->bufflen = size; | ||
399 | } | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * request doesn't start on hw block boundary, add scatter pads | ||
404 | */ | ||
405 | if (((unsigned int)SCpnt->request->sector % (s_size >> 9)) || | ||
406 | (SCpnt->request_bufflen % s_size)) { | ||
407 | printk("sr: unaligned transfer\n"); | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9); | ||
412 | |||
413 | |||
414 | SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", | ||
415 | cd->cdi.name, | ||
416 | (rq_data_dir(SCpnt->request) == WRITE) ? | ||
417 | "writing" : "reading", | ||
418 | this_count, SCpnt->request->nr_sectors)); | ||
419 | |||
420 | SCpnt->cmnd[1] = 0; | ||
421 | block = (unsigned int)SCpnt->request->sector / (s_size >> 9); | ||
422 | |||
423 | if (this_count > 0xffff) { | ||
424 | this_count = 0xffff; | ||
425 | SCpnt->request_bufflen = SCpnt->bufflen = | ||
426 | this_count * s_size; | ||
427 | } | ||
428 | |||
429 | SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; | ||
430 | SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; | ||
431 | SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; | ||
432 | SCpnt->cmnd[5] = (unsigned char) block & 0xff; | ||
433 | SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0; | ||
434 | SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; | ||
435 | SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; | ||
436 | |||
437 | /* | ||
438 | * We shouldn't disconnect in the middle of a sector, so with a dumb | ||
439 | * host adapter, it's safe to assume that we can at least transfer | ||
440 | * this many bytes between each connect / disconnect. | ||
441 | */ | ||
442 | SCpnt->transfersize = cd->device->sector_size; | ||
443 | SCpnt->underflow = this_count << 9; | ||
444 | |||
445 | queue: | ||
446 | SCpnt->allowed = MAX_RETRIES; | ||
447 | SCpnt->timeout_per_command = timeout; | ||
448 | |||
449 | /* | ||
450 | * This is the completion routine we use. This is matched in terms | ||
451 | * of capability to this function. | ||
452 | */ | ||
453 | SCpnt->done = rw_intr; | ||
454 | |||
455 | /* | ||
456 | * This indicates that the command is ready from our end to be | ||
457 | * queued. | ||
458 | */ | ||
459 | return 1; | ||
460 | } | ||
461 | |||
462 | static int sr_block_open(struct inode *inode, struct file *file) | ||
463 | { | ||
464 | struct gendisk *disk = inode->i_bdev->bd_disk; | ||
465 | struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk); | ||
466 | int ret = 0; | ||
467 | |||
468 | if(!(cd = scsi_cd_get(disk))) | ||
469 | return -ENXIO; | ||
470 | |||
471 | if((ret = cdrom_open(&cd->cdi, inode, file)) != 0) | ||
472 | scsi_cd_put(cd); | ||
473 | |||
474 | return ret; | ||
475 | } | ||
476 | |||
477 | static int sr_block_release(struct inode *inode, struct file *file) | ||
478 | { | ||
479 | int ret; | ||
480 | struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk); | ||
481 | ret = cdrom_release(&cd->cdi, file); | ||
482 | if(ret) | ||
483 | return ret; | ||
484 | |||
485 | scsi_cd_put(cd); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd, | ||
491 | unsigned long arg) | ||
492 | { | ||
493 | struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk); | ||
494 | struct scsi_device *sdev = cd->device; | ||
495 | |||
496 | /* | ||
497 | * Send SCSI addressing ioctls directly to mid level, send other | ||
498 | * ioctls to cdrom/block level. | ||
499 | */ | ||
500 | switch (cmd) { | ||
501 | case SCSI_IOCTL_GET_IDLUN: | ||
502 | case SCSI_IOCTL_GET_BUS_NUMBER: | ||
503 | return scsi_ioctl(sdev, cmd, (void __user *)arg); | ||
504 | } | ||
505 | return cdrom_ioctl(file, &cd->cdi, inode, cmd, arg); | ||
506 | } | ||
507 | |||
508 | static int sr_block_media_changed(struct gendisk *disk) | ||
509 | { | ||
510 | struct scsi_cd *cd = scsi_cd(disk); | ||
511 | return cdrom_media_changed(&cd->cdi); | ||
512 | } | ||
513 | |||
514 | static struct block_device_operations sr_bdops = | ||
515 | { | ||
516 | .owner = THIS_MODULE, | ||
517 | .open = sr_block_open, | ||
518 | .release = sr_block_release, | ||
519 | .ioctl = sr_block_ioctl, | ||
520 | .media_changed = sr_block_media_changed, | ||
521 | /* | ||
522 | * No compat_ioctl for now because sr_block_ioctl never | ||
523 | * seems to pass arbitary ioctls down to host drivers. | ||
524 | */ | ||
525 | }; | ||
526 | |||
527 | static int sr_open(struct cdrom_device_info *cdi, int purpose) | ||
528 | { | ||
529 | struct scsi_cd *cd = cdi->handle; | ||
530 | struct scsi_device *sdev = cd->device; | ||
531 | int retval; | ||
532 | |||
533 | /* | ||
534 | * If the device is in error recovery, wait until it is done. | ||
535 | * If the device is offline, then disallow any access to it. | ||
536 | */ | ||
537 | retval = -ENXIO; | ||
538 | if (!scsi_block_when_processing_errors(sdev)) | ||
539 | goto error_out; | ||
540 | |||
541 | /* | ||
542 | * If this device did not have media in the drive at boot time, then | ||
543 | * we would have been unable to get the sector size. Check to see if | ||
544 | * this is the case, and try again. | ||
545 | */ | ||
546 | if (cd->needs_sector_size) | ||
547 | get_sectorsize(cd); | ||
548 | return 0; | ||
549 | |||
550 | error_out: | ||
551 | return retval; | ||
552 | } | ||
553 | |||
554 | static void sr_release(struct cdrom_device_info *cdi) | ||
555 | { | ||
556 | struct scsi_cd *cd = cdi->handle; | ||
557 | |||
558 | if (cd->device->sector_size > 2048) | ||
559 | sr_set_blocklength(cd, 2048); | ||
560 | |||
561 | } | ||
562 | |||
563 | static int sr_probe(struct device *dev) | ||
564 | { | ||
565 | struct scsi_device *sdev = to_scsi_device(dev); | ||
566 | struct gendisk *disk; | ||
567 | struct scsi_cd *cd; | ||
568 | int minor, error; | ||
569 | |||
570 | error = -ENODEV; | ||
571 | if (sdev->type != TYPE_ROM && sdev->type != TYPE_WORM) | ||
572 | goto fail; | ||
573 | |||
574 | error = -ENOMEM; | ||
575 | cd = kmalloc(sizeof(*cd), GFP_KERNEL); | ||
576 | if (!cd) | ||
577 | goto fail; | ||
578 | memset(cd, 0, sizeof(*cd)); | ||
579 | |||
580 | kref_init(&cd->kref); | ||
581 | |||
582 | disk = alloc_disk(1); | ||
583 | if (!disk) | ||
584 | goto fail_free; | ||
585 | |||
586 | spin_lock(&sr_index_lock); | ||
587 | minor = find_first_zero_bit(sr_index_bits, SR_DISKS); | ||
588 | if (minor == SR_DISKS) { | ||
589 | spin_unlock(&sr_index_lock); | ||
590 | error = -EBUSY; | ||
591 | goto fail_put; | ||
592 | } | ||
593 | __set_bit(minor, sr_index_bits); | ||
594 | spin_unlock(&sr_index_lock); | ||
595 | |||
596 | disk->major = SCSI_CDROM_MAJOR; | ||
597 | disk->first_minor = minor; | ||
598 | sprintf(disk->disk_name, "sr%d", minor); | ||
599 | disk->fops = &sr_bdops; | ||
600 | disk->flags = GENHD_FL_CD; | ||
601 | |||
602 | cd->device = sdev; | ||
603 | cd->disk = disk; | ||
604 | cd->driver = &sr_template; | ||
605 | cd->disk = disk; | ||
606 | cd->capacity = 0x1fffff; | ||
607 | cd->needs_sector_size = 1; | ||
608 | cd->device->changed = 1; /* force recheck CD type */ | ||
609 | cd->use = 1; | ||
610 | cd->readcd_known = 0; | ||
611 | cd->readcd_cdda = 0; | ||
612 | |||
613 | cd->cdi.ops = &sr_dops; | ||
614 | cd->cdi.handle = cd; | ||
615 | cd->cdi.mask = 0; | ||
616 | cd->cdi.capacity = 1; | ||
617 | sprintf(cd->cdi.name, "sr%d", minor); | ||
618 | |||
619 | sdev->sector_size = 2048; /* A guess, just in case */ | ||
620 | |||
621 | /* FIXME: need to handle a get_capabilities failure properly ?? */ | ||
622 | get_capabilities(cd); | ||
623 | sr_vendor_init(cd); | ||
624 | |||
625 | snprintf(disk->devfs_name, sizeof(disk->devfs_name), | ||
626 | "%s/cd", sdev->devfs_name); | ||
627 | disk->driverfs_dev = &sdev->sdev_gendev; | ||
628 | set_capacity(disk, cd->capacity); | ||
629 | disk->private_data = &cd->driver; | ||
630 | disk->queue = sdev->request_queue; | ||
631 | cd->cdi.disk = disk; | ||
632 | |||
633 | if (register_cdrom(&cd->cdi)) | ||
634 | goto fail_put; | ||
635 | |||
636 | dev_set_drvdata(dev, cd); | ||
637 | disk->flags |= GENHD_FL_REMOVABLE; | ||
638 | add_disk(disk); | ||
639 | |||
640 | printk(KERN_DEBUG | ||
641 | "Attached scsi CD-ROM %s at scsi%d, channel %d, id %d, lun %d\n", | ||
642 | cd->cdi.name, sdev->host->host_no, sdev->channel, | ||
643 | sdev->id, sdev->lun); | ||
644 | return 0; | ||
645 | |||
646 | fail_put: | ||
647 | put_disk(disk); | ||
648 | fail_free: | ||
649 | kfree(cd); | ||
650 | fail: | ||
651 | return error; | ||
652 | } | ||
653 | |||
654 | |||
655 | static void get_sectorsize(struct scsi_cd *cd) | ||
656 | { | ||
657 | unsigned char cmd[10]; | ||
658 | unsigned char *buffer; | ||
659 | int the_result, retries = 3; | ||
660 | int sector_size; | ||
661 | struct scsi_request *SRpnt = NULL; | ||
662 | request_queue_t *queue; | ||
663 | |||
664 | buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); | ||
665 | if (!buffer) | ||
666 | goto Enomem; | ||
667 | SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL); | ||
668 | if (!SRpnt) | ||
669 | goto Enomem; | ||
670 | |||
671 | do { | ||
672 | cmd[0] = READ_CAPACITY; | ||
673 | memset((void *) &cmd[1], 0, 9); | ||
674 | /* Mark as really busy */ | ||
675 | SRpnt->sr_request->rq_status = RQ_SCSI_BUSY; | ||
676 | SRpnt->sr_cmd_len = 0; | ||
677 | |||
678 | memset(buffer, 0, 8); | ||
679 | |||
680 | /* Do the command and wait.. */ | ||
681 | SRpnt->sr_data_direction = DMA_FROM_DEVICE; | ||
682 | scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, | ||
683 | 8, SR_TIMEOUT, MAX_RETRIES); | ||
684 | |||
685 | the_result = SRpnt->sr_result; | ||
686 | retries--; | ||
687 | |||
688 | } while (the_result && retries); | ||
689 | |||
690 | |||
691 | scsi_release_request(SRpnt); | ||
692 | SRpnt = NULL; | ||
693 | |||
694 | if (the_result) { | ||
695 | cd->capacity = 0x1fffff; | ||
696 | sector_size = 2048; /* A guess, just in case */ | ||
697 | cd->needs_sector_size = 1; | ||
698 | } else { | ||
699 | #if 0 | ||
700 | if (cdrom_get_last_written(&cd->cdi, | ||
701 | &cd->capacity)) | ||
702 | #endif | ||
703 | cd->capacity = 1 + ((buffer[0] << 24) | | ||
704 | (buffer[1] << 16) | | ||
705 | (buffer[2] << 8) | | ||
706 | buffer[3]); | ||
707 | sector_size = (buffer[4] << 24) | | ||
708 | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; | ||
709 | switch (sector_size) { | ||
710 | /* | ||
711 | * HP 4020i CD-Recorder reports 2340 byte sectors | ||
712 | * Philips CD-Writers report 2352 byte sectors | ||
713 | * | ||
714 | * Use 2k sectors for them.. | ||
715 | */ | ||
716 | case 0: | ||
717 | case 2340: | ||
718 | case 2352: | ||
719 | sector_size = 2048; | ||
720 | /* fall through */ | ||
721 | case 2048: | ||
722 | cd->capacity *= 4; | ||
723 | /* fall through */ | ||
724 | case 512: | ||
725 | break; | ||
726 | default: | ||
727 | printk("%s: unsupported sector size %d.\n", | ||
728 | cd->cdi.name, sector_size); | ||
729 | cd->capacity = 0; | ||
730 | cd->needs_sector_size = 1; | ||
731 | } | ||
732 | |||
733 | cd->device->sector_size = sector_size; | ||
734 | |||
735 | /* | ||
736 | * Add this so that we have the ability to correctly gauge | ||
737 | * what the device is capable of. | ||
738 | */ | ||
739 | cd->needs_sector_size = 0; | ||
740 | set_capacity(cd->disk, cd->capacity); | ||
741 | } | ||
742 | |||
743 | queue = cd->device->request_queue; | ||
744 | blk_queue_hardsect_size(queue, sector_size); | ||
745 | out: | ||
746 | kfree(buffer); | ||
747 | return; | ||
748 | |||
749 | Enomem: | ||
750 | cd->capacity = 0x1fffff; | ||
751 | sector_size = 2048; /* A guess, just in case */ | ||
752 | cd->needs_sector_size = 1; | ||
753 | if (SRpnt) | ||
754 | scsi_release_request(SRpnt); | ||
755 | goto out; | ||
756 | } | ||
757 | |||
758 | static void get_capabilities(struct scsi_cd *cd) | ||
759 | { | ||
760 | unsigned char *buffer; | ||
761 | struct scsi_mode_data data; | ||
762 | struct scsi_request *SRpnt; | ||
763 | unsigned char cmd[MAX_COMMAND_SIZE]; | ||
764 | unsigned int the_result; | ||
765 | int retries, rc, n; | ||
766 | |||
767 | static char *loadmech[] = | ||
768 | { | ||
769 | "caddy", | ||
770 | "tray", | ||
771 | "pop-up", | ||
772 | "", | ||
773 | "changer", | ||
774 | "cartridge changer", | ||
775 | "", | ||
776 | "" | ||
777 | }; | ||
778 | |||
779 | /* allocate a request for the TEST_UNIT_READY */ | ||
780 | SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL); | ||
781 | if (!SRpnt) { | ||
782 | printk(KERN_WARNING "(get_capabilities:) Request allocation " | ||
783 | "failure.\n"); | ||
784 | return; | ||
785 | } | ||
786 | |||
787 | /* allocate transfer buffer */ | ||
788 | buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); | ||
789 | if (!buffer) { | ||
790 | printk(KERN_ERR "sr: out of memory.\n"); | ||
791 | scsi_release_request(SRpnt); | ||
792 | return; | ||
793 | } | ||
794 | |||
795 | /* issue TEST_UNIT_READY until the initial startup UNIT_ATTENTION | ||
796 | * conditions are gone, or a timeout happens | ||
797 | */ | ||
798 | retries = 0; | ||
799 | do { | ||
800 | memset((void *)cmd, 0, MAX_COMMAND_SIZE); | ||
801 | cmd[0] = TEST_UNIT_READY; | ||
802 | |||
803 | SRpnt->sr_cmd_len = 0; | ||
804 | SRpnt->sr_sense_buffer[0] = 0; | ||
805 | SRpnt->sr_sense_buffer[2] = 0; | ||
806 | SRpnt->sr_data_direction = DMA_NONE; | ||
807 | |||
808 | scsi_wait_req (SRpnt, (void *) cmd, buffer, | ||
809 | 0, SR_TIMEOUT, MAX_RETRIES); | ||
810 | |||
811 | the_result = SRpnt->sr_result; | ||
812 | retries++; | ||
813 | } while (retries < 5 && | ||
814 | (!scsi_status_is_good(the_result) || | ||
815 | ((driver_byte(the_result) & DRIVER_SENSE) && | ||
816 | SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION))); | ||
817 | |||
818 | /* ask for mode page 0x2a */ | ||
819 | rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128, | ||
820 | SR_TIMEOUT, 3, &data); | ||
821 | |||
822 | if (!scsi_status_is_good(rc)) { | ||
823 | /* failed, drive doesn't have capabilities mode page */ | ||
824 | cd->cdi.speed = 1; | ||
825 | cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | | ||
826 | CDC_DVD | CDC_DVD_RAM | | ||
827 | CDC_SELECT_DISC | CDC_SELECT_SPEED); | ||
828 | scsi_release_request(SRpnt); | ||
829 | kfree(buffer); | ||
830 | printk("%s: scsi-1 drive\n", cd->cdi.name); | ||
831 | return; | ||
832 | } | ||
833 | |||
834 | n = data.header_length + data.block_descriptor_length; | ||
835 | cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176; | ||
836 | cd->readcd_known = 1; | ||
837 | cd->readcd_cdda = buffer[n + 5] & 0x01; | ||
838 | /* print some capability bits */ | ||
839 | printk("%s: scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", cd->cdi.name, | ||
840 | ((buffer[n + 14] << 8) + buffer[n + 15]) / 176, | ||
841 | cd->cdi.speed, | ||
842 | buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */ | ||
843 | buffer[n + 3] & 0x20 ? "dvd-ram " : "", | ||
844 | buffer[n + 2] & 0x02 ? "cd/rw " : "", /* can read rewriteable */ | ||
845 | buffer[n + 4] & 0x20 ? "xa/form2 " : "", /* can read xa/from2 */ | ||
846 | buffer[n + 5] & 0x01 ? "cdda " : "", /* can read audio data */ | ||
847 | loadmech[buffer[n + 6] >> 5]); | ||
848 | if ((buffer[n + 6] >> 5) == 0) | ||
849 | /* caddy drives can't close tray... */ | ||
850 | cd->cdi.mask |= CDC_CLOSE_TRAY; | ||
851 | if ((buffer[n + 2] & 0x8) == 0) | ||
852 | /* not a DVD drive */ | ||
853 | cd->cdi.mask |= CDC_DVD; | ||
854 | if ((buffer[n + 3] & 0x20) == 0) | ||
855 | /* can't write DVD-RAM media */ | ||
856 | cd->cdi.mask |= CDC_DVD_RAM; | ||
857 | if ((buffer[n + 3] & 0x10) == 0) | ||
858 | /* can't write DVD-R media */ | ||
859 | cd->cdi.mask |= CDC_DVD_R; | ||
860 | if ((buffer[n + 3] & 0x2) == 0) | ||
861 | /* can't write CD-RW media */ | ||
862 | cd->cdi.mask |= CDC_CD_RW; | ||
863 | if ((buffer[n + 3] & 0x1) == 0) | ||
864 | /* can't write CD-R media */ | ||
865 | cd->cdi.mask |= CDC_CD_R; | ||
866 | if ((buffer[n + 6] & 0x8) == 0) | ||
867 | /* can't eject */ | ||
868 | cd->cdi.mask |= CDC_OPEN_TRAY; | ||
869 | |||
870 | if ((buffer[n + 6] >> 5) == mechtype_individual_changer || | ||
871 | (buffer[n + 6] >> 5) == mechtype_cartridge_changer) | ||
872 | cd->cdi.capacity = | ||
873 | cdrom_number_of_slots(&cd->cdi); | ||
874 | if (cd->cdi.capacity <= 1) | ||
875 | /* not a changer */ | ||
876 | cd->cdi.mask |= CDC_SELECT_DISC; | ||
877 | /*else I don't think it can close its tray | ||
878 | cd->cdi.mask |= CDC_CLOSE_TRAY; */ | ||
879 | |||
880 | /* | ||
881 | * if DVD-RAM, MRW-W or CD-RW, we are randomly writable | ||
882 | */ | ||
883 | if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) != | ||
884 | (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) { | ||
885 | cd->device->writeable = 1; | ||
886 | } | ||
887 | |||
888 | scsi_release_request(SRpnt); | ||
889 | kfree(buffer); | ||
890 | } | ||
891 | |||
892 | /* | ||
893 | * sr_packet() is the entry point for the generic commands generated | ||
894 | * by the Uniform CD-ROM layer. | ||
895 | */ | ||
896 | static int sr_packet(struct cdrom_device_info *cdi, | ||
897 | struct packet_command *cgc) | ||
898 | { | ||
899 | if (cgc->timeout <= 0) | ||
900 | cgc->timeout = IOCTL_TIMEOUT; | ||
901 | |||
902 | sr_do_ioctl(cdi->handle, cgc); | ||
903 | |||
904 | return cgc->stat; | ||
905 | } | ||
906 | |||
907 | /** | ||
908 | * sr_kref_release - Called to free the scsi_cd structure | ||
909 | * @kref: pointer to embedded kref | ||
910 | * | ||
911 | * sr_ref_sem must be held entering this routine. Because it is | ||
912 | * called on last put, you should always use the scsi_cd_get() | ||
913 | * scsi_cd_put() helpers which manipulate the semaphore directly | ||
914 | * and never do a direct kref_put(). | ||
915 | **/ | ||
916 | static void sr_kref_release(struct kref *kref) | ||
917 | { | ||
918 | struct scsi_cd *cd = container_of(kref, struct scsi_cd, kref); | ||
919 | struct gendisk *disk = cd->disk; | ||
920 | |||
921 | spin_lock(&sr_index_lock); | ||
922 | clear_bit(disk->first_minor, sr_index_bits); | ||
923 | spin_unlock(&sr_index_lock); | ||
924 | |||
925 | unregister_cdrom(&cd->cdi); | ||
926 | |||
927 | disk->private_data = NULL; | ||
928 | |||
929 | put_disk(disk); | ||
930 | |||
931 | kfree(cd); | ||
932 | } | ||
933 | |||
934 | static int sr_remove(struct device *dev) | ||
935 | { | ||
936 | struct scsi_cd *cd = dev_get_drvdata(dev); | ||
937 | |||
938 | del_gendisk(cd->disk); | ||
939 | |||
940 | down(&sr_ref_sem); | ||
941 | kref_put(&cd->kref, sr_kref_release); | ||
942 | up(&sr_ref_sem); | ||
943 | |||
944 | return 0; | ||
945 | } | ||
946 | |||
947 | static int __init init_sr(void) | ||
948 | { | ||
949 | int rc; | ||
950 | |||
951 | rc = register_blkdev(SCSI_CDROM_MAJOR, "sr"); | ||
952 | if (rc) | ||
953 | return rc; | ||
954 | return scsi_register_driver(&sr_template.gendrv); | ||
955 | } | ||
956 | |||
957 | static void __exit exit_sr(void) | ||
958 | { | ||
959 | scsi_unregister_driver(&sr_template.gendrv); | ||
960 | unregister_blkdev(SCSI_CDROM_MAJOR, "sr"); | ||
961 | } | ||
962 | |||
963 | module_init(init_sr); | ||
964 | module_exit(exit_sr); | ||
965 | MODULE_LICENSE("GPL"); | ||