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_ioctl.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_ioctl.c')
-rw-r--r-- | drivers/scsi/sr_ioctl.c | 568 |
1 files changed, 568 insertions, 0 deletions
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c new file mode 100644 index 000000000000..3471be05779a --- /dev/null +++ b/drivers/scsi/sr_ioctl.c | |||
@@ -0,0 +1,568 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/sched.h> | ||
3 | #include <linux/mm.h> | ||
4 | #include <linux/fs.h> | ||
5 | #include <linux/errno.h> | ||
6 | #include <linux/string.h> | ||
7 | #include <linux/blkdev.h> | ||
8 | #include <linux/blkpg.h> | ||
9 | #include <linux/cdrom.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <asm/io.h> | ||
12 | #include <asm/uaccess.h> | ||
13 | |||
14 | #include <scsi/scsi.h> | ||
15 | #include <scsi/scsi_dbg.h> | ||
16 | #include <scsi/scsi_device.h> | ||
17 | #include <scsi/scsi_eh.h> | ||
18 | #include <scsi/scsi_host.h> | ||
19 | #include <scsi/scsi_ioctl.h> | ||
20 | #include <scsi/scsi_request.h> | ||
21 | |||
22 | #include "sr.h" | ||
23 | |||
24 | #if 0 | ||
25 | #define DEBUG | ||
26 | #endif | ||
27 | |||
28 | /* The sr_is_xa() seems to trigger firmware bugs with some drives :-( | ||
29 | * It is off by default and can be turned on with this module parameter */ | ||
30 | static int xa_test = 0; | ||
31 | |||
32 | module_param(xa_test, int, S_IRUGO | S_IWUSR); | ||
33 | |||
34 | |||
35 | #define IOCTL_RETRIES 3 | ||
36 | |||
37 | /* ATAPI drives don't have a SCMD_PLAYAUDIO_TI command. When these drives | ||
38 | are emulating a SCSI device via the idescsi module, they need to have | ||
39 | CDROMPLAYTRKIND commands translated into CDROMPLAYMSF commands for them */ | ||
40 | |||
41 | static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti) | ||
42 | { | ||
43 | struct cdrom_tocentry trk0_te, trk1_te; | ||
44 | struct cdrom_tochdr tochdr; | ||
45 | struct packet_command cgc; | ||
46 | int ntracks, ret; | ||
47 | |||
48 | if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr))) | ||
49 | return ret; | ||
50 | |||
51 | ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1; | ||
52 | |||
53 | if (ti->cdti_trk1 == ntracks) | ||
54 | ti->cdti_trk1 = CDROM_LEADOUT; | ||
55 | else if (ti->cdti_trk1 != CDROM_LEADOUT) | ||
56 | ti->cdti_trk1 ++; | ||
57 | |||
58 | trk0_te.cdte_track = ti->cdti_trk0; | ||
59 | trk0_te.cdte_format = CDROM_MSF; | ||
60 | trk1_te.cdte_track = ti->cdti_trk1; | ||
61 | trk1_te.cdte_format = CDROM_MSF; | ||
62 | |||
63 | if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk0_te))) | ||
64 | return ret; | ||
65 | if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk1_te))) | ||
66 | return ret; | ||
67 | |||
68 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
69 | cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF; | ||
70 | cgc.cmd[3] = trk0_te.cdte_addr.msf.minute; | ||
71 | cgc.cmd[4] = trk0_te.cdte_addr.msf.second; | ||
72 | cgc.cmd[5] = trk0_te.cdte_addr.msf.frame; | ||
73 | cgc.cmd[6] = trk1_te.cdte_addr.msf.minute; | ||
74 | cgc.cmd[7] = trk1_te.cdte_addr.msf.second; | ||
75 | cgc.cmd[8] = trk1_te.cdte_addr.msf.frame; | ||
76 | cgc.data_direction = DMA_NONE; | ||
77 | cgc.timeout = IOCTL_TIMEOUT; | ||
78 | return sr_do_ioctl(cdi->handle, &cgc); | ||
79 | } | ||
80 | |||
81 | /* We do our own retries because we want to know what the specific | ||
82 | error code is. Normally the UNIT_ATTENTION code will automatically | ||
83 | clear after one error */ | ||
84 | |||
85 | int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) | ||
86 | { | ||
87 | struct scsi_request *SRpnt; | ||
88 | struct scsi_device *SDev; | ||
89 | struct request *req; | ||
90 | int result, err = 0, retries = 0; | ||
91 | |||
92 | SDev = cd->device; | ||
93 | SRpnt = scsi_allocate_request(SDev, GFP_KERNEL); | ||
94 | if (!SRpnt) { | ||
95 | printk(KERN_ERR "Unable to allocate SCSI request in sr_do_ioctl"); | ||
96 | err = -ENOMEM; | ||
97 | goto out; | ||
98 | } | ||
99 | SRpnt->sr_data_direction = cgc->data_direction; | ||
100 | |||
101 | retry: | ||
102 | if (!scsi_block_when_processing_errors(SDev)) { | ||
103 | err = -ENODEV; | ||
104 | goto out_free; | ||
105 | } | ||
106 | |||
107 | scsi_wait_req(SRpnt, cgc->cmd, cgc->buffer, cgc->buflen, | ||
108 | cgc->timeout, IOCTL_RETRIES); | ||
109 | |||
110 | req = SRpnt->sr_request; | ||
111 | if (SRpnt->sr_buffer && req->buffer && SRpnt->sr_buffer != req->buffer) { | ||
112 | memcpy(req->buffer, SRpnt->sr_buffer, SRpnt->sr_bufflen); | ||
113 | kfree(SRpnt->sr_buffer); | ||
114 | SRpnt->sr_buffer = req->buffer; | ||
115 | } | ||
116 | |||
117 | result = SRpnt->sr_result; | ||
118 | |||
119 | /* Minimal error checking. Ignore cases we know about, and report the rest. */ | ||
120 | if (driver_byte(result) != 0) { | ||
121 | switch (SRpnt->sr_sense_buffer[2] & 0xf) { | ||
122 | case UNIT_ATTENTION: | ||
123 | SDev->changed = 1; | ||
124 | if (!cgc->quiet) | ||
125 | printk(KERN_INFO "%s: disc change detected.\n", cd->cdi.name); | ||
126 | if (retries++ < 10) | ||
127 | goto retry; | ||
128 | err = -ENOMEDIUM; | ||
129 | break; | ||
130 | case NOT_READY: /* This happens if there is no disc in drive */ | ||
131 | if (SRpnt->sr_sense_buffer[12] == 0x04 && | ||
132 | SRpnt->sr_sense_buffer[13] == 0x01) { | ||
133 | /* sense: Logical unit is in process of becoming ready */ | ||
134 | if (!cgc->quiet) | ||
135 | printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name); | ||
136 | if (retries++ < 10) { | ||
137 | /* sleep 2 sec and try again */ | ||
138 | ssleep(2); | ||
139 | goto retry; | ||
140 | } else { | ||
141 | /* 20 secs are enough? */ | ||
142 | err = -ENOMEDIUM; | ||
143 | break; | ||
144 | } | ||
145 | } | ||
146 | if (!cgc->quiet) | ||
147 | printk(KERN_INFO "%s: CDROM not ready. Make sure there is a disc in the drive.\n", cd->cdi.name); | ||
148 | #ifdef DEBUG | ||
149 | scsi_print_req_sense("sr", SRpnt); | ||
150 | #endif | ||
151 | err = -ENOMEDIUM; | ||
152 | break; | ||
153 | case ILLEGAL_REQUEST: | ||
154 | err = -EIO; | ||
155 | if (SRpnt->sr_sense_buffer[12] == 0x20 && | ||
156 | SRpnt->sr_sense_buffer[13] == 0x00) | ||
157 | /* sense: Invalid command operation code */ | ||
158 | err = -EDRIVE_CANT_DO_THIS; | ||
159 | #ifdef DEBUG | ||
160 | __scsi_print_command(cgc->cmd); | ||
161 | scsi_print_req_sense("sr", SRpnt); | ||
162 | #endif | ||
163 | break; | ||
164 | default: | ||
165 | printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name); | ||
166 | __scsi_print_command(cgc->cmd); | ||
167 | scsi_print_req_sense("sr", SRpnt); | ||
168 | err = -EIO; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | if (cgc->sense) | ||
173 | memcpy(cgc->sense, SRpnt->sr_sense_buffer, sizeof(*cgc->sense)); | ||
174 | |||
175 | /* Wake up a process waiting for device */ | ||
176 | out_free: | ||
177 | scsi_release_request(SRpnt); | ||
178 | SRpnt = NULL; | ||
179 | out: | ||
180 | cgc->stat = err; | ||
181 | return err; | ||
182 | } | ||
183 | |||
184 | /* ---------------------------------------------------------------------- */ | ||
185 | /* interface to cdrom.c */ | ||
186 | |||
187 | static int test_unit_ready(Scsi_CD *cd) | ||
188 | { | ||
189 | struct packet_command cgc; | ||
190 | |||
191 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
192 | cgc.cmd[0] = GPCMD_TEST_UNIT_READY; | ||
193 | cgc.quiet = 1; | ||
194 | cgc.data_direction = DMA_NONE; | ||
195 | cgc.timeout = IOCTL_TIMEOUT; | ||
196 | return sr_do_ioctl(cd, &cgc); | ||
197 | } | ||
198 | |||
199 | int sr_tray_move(struct cdrom_device_info *cdi, int pos) | ||
200 | { | ||
201 | Scsi_CD *cd = cdi->handle; | ||
202 | struct packet_command cgc; | ||
203 | |||
204 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
205 | cgc.cmd[0] = GPCMD_START_STOP_UNIT; | ||
206 | cgc.cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ; | ||
207 | cgc.data_direction = DMA_NONE; | ||
208 | cgc.timeout = IOCTL_TIMEOUT; | ||
209 | return sr_do_ioctl(cd, &cgc); | ||
210 | } | ||
211 | |||
212 | int sr_lock_door(struct cdrom_device_info *cdi, int lock) | ||
213 | { | ||
214 | Scsi_CD *cd = cdi->handle; | ||
215 | |||
216 | return scsi_set_medium_removal(cd->device, lock ? | ||
217 | SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW); | ||
218 | } | ||
219 | |||
220 | int sr_drive_status(struct cdrom_device_info *cdi, int slot) | ||
221 | { | ||
222 | if (CDSL_CURRENT != slot) { | ||
223 | /* we have no changer support */ | ||
224 | return -EINVAL; | ||
225 | } | ||
226 | if (0 == test_unit_ready(cdi->handle)) | ||
227 | return CDS_DISC_OK; | ||
228 | |||
229 | return CDS_TRAY_OPEN; | ||
230 | } | ||
231 | |||
232 | int sr_disk_status(struct cdrom_device_info *cdi) | ||
233 | { | ||
234 | Scsi_CD *cd = cdi->handle; | ||
235 | struct cdrom_tochdr toc_h; | ||
236 | struct cdrom_tocentry toc_e; | ||
237 | int i, rc, have_datatracks = 0; | ||
238 | |||
239 | /* look for data tracks */ | ||
240 | if (0 != (rc = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h))) | ||
241 | return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO; | ||
242 | |||
243 | for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) { | ||
244 | toc_e.cdte_track = i; | ||
245 | toc_e.cdte_format = CDROM_LBA; | ||
246 | if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e)) | ||
247 | return CDS_NO_INFO; | ||
248 | if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) { | ||
249 | have_datatracks = 1; | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | if (!have_datatracks) | ||
254 | return CDS_AUDIO; | ||
255 | |||
256 | if (cd->xa_flag) | ||
257 | return CDS_XA_2_1; | ||
258 | else | ||
259 | return CDS_DATA_1; | ||
260 | } | ||
261 | |||
262 | int sr_get_last_session(struct cdrom_device_info *cdi, | ||
263 | struct cdrom_multisession *ms_info) | ||
264 | { | ||
265 | Scsi_CD *cd = cdi->handle; | ||
266 | |||
267 | ms_info->addr.lba = cd->ms_offset; | ||
268 | ms_info->xa_flag = cd->xa_flag || cd->ms_offset > 0; | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | /* primitive to determine whether we need to have GFP_DMA set based on | ||
274 | * the status of the unchecked_isa_dma flag in the host structure */ | ||
275 | #define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0) | ||
276 | |||
277 | int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) | ||
278 | { | ||
279 | Scsi_CD *cd = cdi->handle; | ||
280 | struct packet_command cgc; | ||
281 | char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); | ||
282 | int result; | ||
283 | |||
284 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
285 | cgc.cmd[0] = GPCMD_READ_SUBCHANNEL; | ||
286 | cgc.cmd[2] = 0x40; /* I do want the subchannel info */ | ||
287 | cgc.cmd[3] = 0x02; /* Give me medium catalog number info */ | ||
288 | cgc.cmd[8] = 24; | ||
289 | cgc.buffer = buffer; | ||
290 | cgc.buflen = 24; | ||
291 | cgc.data_direction = DMA_FROM_DEVICE; | ||
292 | cgc.timeout = IOCTL_TIMEOUT; | ||
293 | result = sr_do_ioctl(cd, &cgc); | ||
294 | |||
295 | memcpy(mcn->medium_catalog_number, buffer + 9, 13); | ||
296 | mcn->medium_catalog_number[13] = 0; | ||
297 | |||
298 | kfree(buffer); | ||
299 | return result; | ||
300 | } | ||
301 | |||
302 | int sr_reset(struct cdrom_device_info *cdi) | ||
303 | { | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | int sr_select_speed(struct cdrom_device_info *cdi, int speed) | ||
308 | { | ||
309 | Scsi_CD *cd = cdi->handle; | ||
310 | struct packet_command cgc; | ||
311 | |||
312 | if (speed == 0) | ||
313 | speed = 0xffff; /* set to max */ | ||
314 | else | ||
315 | speed *= 177; /* Nx to kbyte/s */ | ||
316 | |||
317 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
318 | cgc.cmd[0] = GPCMD_SET_SPEED; /* SET CD SPEED */ | ||
319 | cgc.cmd[2] = (speed >> 8) & 0xff; /* MSB for speed (in kbytes/sec) */ | ||
320 | cgc.cmd[3] = speed & 0xff; /* LSB */ | ||
321 | cgc.data_direction = DMA_NONE; | ||
322 | cgc.timeout = IOCTL_TIMEOUT; | ||
323 | |||
324 | if (sr_do_ioctl(cd, &cgc)) | ||
325 | return -EIO; | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | /* ----------------------------------------------------------------------- */ | ||
330 | /* this is called by the generic cdrom driver. arg is a _kernel_ pointer, */ | ||
331 | /* because the generic cdrom driver does the user access stuff for us. */ | ||
332 | /* only cdromreadtochdr and cdromreadtocentry are left - for use with the */ | ||
333 | /* sr_disk_status interface for the generic cdrom driver. */ | ||
334 | |||
335 | int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) | ||
336 | { | ||
337 | Scsi_CD *cd = cdi->handle; | ||
338 | struct packet_command cgc; | ||
339 | int result; | ||
340 | unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); | ||
341 | |||
342 | if (!buffer) | ||
343 | return -ENOMEM; | ||
344 | |||
345 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
346 | cgc.timeout = IOCTL_TIMEOUT; | ||
347 | |||
348 | switch (cmd) { | ||
349 | case CDROMREADTOCHDR: | ||
350 | { | ||
351 | struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; | ||
352 | |||
353 | cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; | ||
354 | cgc.cmd[8] = 12; /* LSB of length */ | ||
355 | cgc.buffer = buffer; | ||
356 | cgc.buflen = 12; | ||
357 | cgc.quiet = 1; | ||
358 | cgc.data_direction = DMA_FROM_DEVICE; | ||
359 | |||
360 | result = sr_do_ioctl(cd, &cgc); | ||
361 | |||
362 | tochdr->cdth_trk0 = buffer[2]; | ||
363 | tochdr->cdth_trk1 = buffer[3]; | ||
364 | |||
365 | break; | ||
366 | } | ||
367 | |||
368 | case CDROMREADTOCENTRY: | ||
369 | { | ||
370 | struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg; | ||
371 | |||
372 | cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; | ||
373 | cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; | ||
374 | cgc.cmd[6] = tocentry->cdte_track; | ||
375 | cgc.cmd[8] = 12; /* LSB of length */ | ||
376 | cgc.buffer = buffer; | ||
377 | cgc.buflen = 12; | ||
378 | cgc.data_direction = DMA_FROM_DEVICE; | ||
379 | |||
380 | result = sr_do_ioctl(cd, &cgc); | ||
381 | |||
382 | tocentry->cdte_ctrl = buffer[5] & 0xf; | ||
383 | tocentry->cdte_adr = buffer[5] >> 4; | ||
384 | tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0; | ||
385 | if (tocentry->cdte_format == CDROM_MSF) { | ||
386 | tocentry->cdte_addr.msf.minute = buffer[9]; | ||
387 | tocentry->cdte_addr.msf.second = buffer[10]; | ||
388 | tocentry->cdte_addr.msf.frame = buffer[11]; | ||
389 | } else | ||
390 | tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) | ||
391 | + buffer[10]) << 8) + buffer[11]; | ||
392 | |||
393 | break; | ||
394 | } | ||
395 | |||
396 | case CDROMPLAYTRKIND: { | ||
397 | struct cdrom_ti* ti = (struct cdrom_ti*)arg; | ||
398 | |||
399 | cgc.cmd[0] = GPCMD_PLAYAUDIO_TI; | ||
400 | cgc.cmd[4] = ti->cdti_trk0; | ||
401 | cgc.cmd[5] = ti->cdti_ind0; | ||
402 | cgc.cmd[7] = ti->cdti_trk1; | ||
403 | cgc.cmd[8] = ti->cdti_ind1; | ||
404 | cgc.data_direction = DMA_NONE; | ||
405 | |||
406 | result = sr_do_ioctl(cd, &cgc); | ||
407 | if (result == -EDRIVE_CANT_DO_THIS) | ||
408 | result = sr_fake_playtrkind(cdi, ti); | ||
409 | |||
410 | break; | ||
411 | } | ||
412 | |||
413 | default: | ||
414 | result = -EINVAL; | ||
415 | } | ||
416 | |||
417 | #if 0 | ||
418 | if (result) | ||
419 | printk("DEBUG: sr_audio: result for ioctl %x: %x\n", cmd, result); | ||
420 | #endif | ||
421 | |||
422 | kfree(buffer); | ||
423 | return result; | ||
424 | } | ||
425 | |||
426 | /* ----------------------------------------------------------------------- | ||
427 | * a function to read all sorts of funny cdrom sectors using the READ_CD | ||
428 | * scsi-3 mmc command | ||
429 | * | ||
430 | * lba: linear block address | ||
431 | * format: 0 = data (anything) | ||
432 | * 1 = audio | ||
433 | * 2 = data (mode 1) | ||
434 | * 3 = data (mode 2) | ||
435 | * 4 = data (mode 2 form1) | ||
436 | * 5 = data (mode 2 form2) | ||
437 | * blksize: 2048 | 2336 | 2340 | 2352 | ||
438 | */ | ||
439 | |||
440 | static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int blksize) | ||
441 | { | ||
442 | struct packet_command cgc; | ||
443 | |||
444 | #ifdef DEBUG | ||
445 | printk("%s: sr_read_cd lba=%d format=%d blksize=%d\n", | ||
446 | cd->cdi.name, lba, format, blksize); | ||
447 | #endif | ||
448 | |||
449 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
450 | cgc.cmd[0] = GPCMD_READ_CD; /* READ_CD */ | ||
451 | cgc.cmd[1] = ((format & 7) << 2); | ||
452 | cgc.cmd[2] = (unsigned char) (lba >> 24) & 0xff; | ||
453 | cgc.cmd[3] = (unsigned char) (lba >> 16) & 0xff; | ||
454 | cgc.cmd[4] = (unsigned char) (lba >> 8) & 0xff; | ||
455 | cgc.cmd[5] = (unsigned char) lba & 0xff; | ||
456 | cgc.cmd[8] = 1; | ||
457 | switch (blksize) { | ||
458 | case 2336: | ||
459 | cgc.cmd[9] = 0x58; | ||
460 | break; | ||
461 | case 2340: | ||
462 | cgc.cmd[9] = 0x78; | ||
463 | break; | ||
464 | case 2352: | ||
465 | cgc.cmd[9] = 0xf8; | ||
466 | break; | ||
467 | default: | ||
468 | cgc.cmd[9] = 0x10; | ||
469 | break; | ||
470 | } | ||
471 | cgc.buffer = dest; | ||
472 | cgc.buflen = blksize; | ||
473 | cgc.data_direction = DMA_FROM_DEVICE; | ||
474 | cgc.timeout = IOCTL_TIMEOUT; | ||
475 | return sr_do_ioctl(cd, &cgc); | ||
476 | } | ||
477 | |||
478 | /* | ||
479 | * read sectors with blocksizes other than 2048 | ||
480 | */ | ||
481 | |||
482 | static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest) | ||
483 | { | ||
484 | struct packet_command cgc; | ||
485 | int rc; | ||
486 | |||
487 | /* we try the READ CD command first... */ | ||
488 | if (cd->readcd_known) { | ||
489 | rc = sr_read_cd(cd, dest, lba, 0, blksize); | ||
490 | if (-EDRIVE_CANT_DO_THIS != rc) | ||
491 | return rc; | ||
492 | cd->readcd_known = 0; | ||
493 | printk("CDROM does'nt support READ CD (0xbe) command\n"); | ||
494 | /* fall & retry the other way */ | ||
495 | } | ||
496 | /* ... if this fails, we switch the blocksize using MODE SELECT */ | ||
497 | if (blksize != cd->device->sector_size) { | ||
498 | if (0 != (rc = sr_set_blocklength(cd, blksize))) | ||
499 | return rc; | ||
500 | } | ||
501 | #ifdef DEBUG | ||
502 | printk("%s: sr_read_sector lba=%d blksize=%d\n", cd->cdi.name, lba, blksize); | ||
503 | #endif | ||
504 | |||
505 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
506 | cgc.cmd[0] = GPCMD_READ_10; | ||
507 | cgc.cmd[2] = (unsigned char) (lba >> 24) & 0xff; | ||
508 | cgc.cmd[3] = (unsigned char) (lba >> 16) & 0xff; | ||
509 | cgc.cmd[4] = (unsigned char) (lba >> 8) & 0xff; | ||
510 | cgc.cmd[5] = (unsigned char) lba & 0xff; | ||
511 | cgc.cmd[8] = 1; | ||
512 | cgc.buffer = dest; | ||
513 | cgc.buflen = blksize; | ||
514 | cgc.data_direction = DMA_FROM_DEVICE; | ||
515 | cgc.timeout = IOCTL_TIMEOUT; | ||
516 | rc = sr_do_ioctl(cd, &cgc); | ||
517 | |||
518 | return rc; | ||
519 | } | ||
520 | |||
521 | /* | ||
522 | * read a sector in raw mode to check the sector format | ||
523 | * ret: 1 == mode2 (XA), 0 == mode1, <0 == error | ||
524 | */ | ||
525 | |||
526 | int sr_is_xa(Scsi_CD *cd) | ||
527 | { | ||
528 | unsigned char *raw_sector; | ||
529 | int is_xa; | ||
530 | |||
531 | if (!xa_test) | ||
532 | return 0; | ||
533 | |||
534 | raw_sector = (unsigned char *) kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd)); | ||
535 | if (!raw_sector) | ||
536 | return -ENOMEM; | ||
537 | if (0 == sr_read_sector(cd, cd->ms_offset + 16, | ||
538 | CD_FRAMESIZE_RAW1, raw_sector)) { | ||
539 | is_xa = (raw_sector[3] == 0x02) ? 1 : 0; | ||
540 | } else { | ||
541 | /* read a raw sector failed for some reason. */ | ||
542 | is_xa = -1; | ||
543 | } | ||
544 | kfree(raw_sector); | ||
545 | #ifdef DEBUG | ||
546 | printk("%s: sr_is_xa: %d\n", cd->cdi.name, is_xa); | ||
547 | #endif | ||
548 | return is_xa; | ||
549 | } | ||
550 | |||
551 | int sr_dev_ioctl(struct cdrom_device_info *cdi, | ||
552 | unsigned int cmd, unsigned long arg) | ||
553 | { | ||
554 | Scsi_CD *cd = cdi->handle; | ||
555 | int ret; | ||
556 | |||
557 | ret = scsi_nonblockable_ioctl(cd->device, cmd, | ||
558 | (void __user *)arg, NULL); | ||
559 | /* | ||
560 | * ENODEV means that we didn't recognise the ioctl, or that we | ||
561 | * cannot execute it in the current device state. In either | ||
562 | * case fall through to scsi_ioctl, which will return ENDOEV again | ||
563 | * if it doesn't recognise the ioctl | ||
564 | */ | ||
565 | if (ret != -ENODEV) | ||
566 | return ret; | ||
567 | return scsi_ioctl(cd->device, cmd, (void __user *)arg); | ||
568 | } | ||