aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sr_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sr_ioctl.c')
-rw-r--r--drivers/scsi/sr_ioctl.c202
1 files changed, 111 insertions, 91 deletions
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 6e45ac3c43c5..5d02ff4db6cc 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -31,6 +31,79 @@ static int xa_test = 0;
31 31
32module_param(xa_test, int, S_IRUGO | S_IWUSR); 32module_param(xa_test, int, S_IRUGO | S_IWUSR);
33 33
34/* primitive to determine whether we need to have GFP_DMA set based on
35 * the status of the unchecked_isa_dma flag in the host structure */
36#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
37
38
39static int sr_read_tochdr(struct cdrom_device_info *cdi,
40 struct cdrom_tochdr *tochdr)
41{
42 struct scsi_cd *cd = cdi->handle;
43 struct packet_command cgc;
44 int result;
45 unsigned char *buffer;
46
47 buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
48 if (!buffer)
49 return -ENOMEM;
50
51 memset(&cgc, 0, sizeof(struct packet_command));
52 cgc.timeout = IOCTL_TIMEOUT;
53 cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
54 cgc.cmd[8] = 12; /* LSB of length */
55 cgc.buffer = buffer;
56 cgc.buflen = 12;
57 cgc.quiet = 1;
58 cgc.data_direction = DMA_FROM_DEVICE;
59
60 result = sr_do_ioctl(cd, &cgc);
61
62 tochdr->cdth_trk0 = buffer[2];
63 tochdr->cdth_trk1 = buffer[3];
64
65 kfree(buffer);
66 return result;
67}
68
69static int sr_read_tocentry(struct cdrom_device_info *cdi,
70 struct cdrom_tocentry *tocentry)
71{
72 struct scsi_cd *cd = cdi->handle;
73 struct packet_command cgc;
74 int result;
75 unsigned char *buffer;
76
77 buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
78 if (!buffer)
79 return -ENOMEM;
80
81 memset(&cgc, 0, sizeof(struct packet_command));
82 cgc.timeout = IOCTL_TIMEOUT;
83 cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
84 cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
85 cgc.cmd[6] = tocentry->cdte_track;
86 cgc.cmd[8] = 12; /* LSB of length */
87 cgc.buffer = buffer;
88 cgc.buflen = 12;
89 cgc.data_direction = DMA_FROM_DEVICE;
90
91 result = sr_do_ioctl(cd, &cgc);
92
93 tocentry->cdte_ctrl = buffer[5] & 0xf;
94 tocentry->cdte_adr = buffer[5] >> 4;
95 tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
96 if (tocentry->cdte_format == CDROM_MSF) {
97 tocentry->cdte_addr.msf.minute = buffer[9];
98 tocentry->cdte_addr.msf.second = buffer[10];
99 tocentry->cdte_addr.msf.frame = buffer[11];
100 } else
101 tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
102 + buffer[10]) << 8) + buffer[11];
103
104 kfree(buffer);
105 return result;
106}
34 107
35#define IOCTL_RETRIES 3 108#define IOCTL_RETRIES 3
36 109
@@ -45,7 +118,8 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
45 struct packet_command cgc; 118 struct packet_command cgc;
46 int ntracks, ret; 119 int ntracks, ret;
47 120
48 if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr))) 121 ret = sr_read_tochdr(cdi, &tochdr);
122 if (ret)
49 return ret; 123 return ret;
50 124
51 ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1; 125 ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
@@ -60,9 +134,11 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
60 trk1_te.cdte_track = ti->cdti_trk1; 134 trk1_te.cdte_track = ti->cdti_trk1;
61 trk1_te.cdte_format = CDROM_MSF; 135 trk1_te.cdte_format = CDROM_MSF;
62 136
63 if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk0_te))) 137 ret = sr_read_tocentry(cdi, &trk0_te);
138 if (ret)
64 return ret; 139 return ret;
65 if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk1_te))) 140 ret = sr_read_tocentry(cdi, &trk1_te);
141 if (ret)
66 return ret; 142 return ret;
67 143
68 memset(&cgc, 0, sizeof(struct packet_command)); 144 memset(&cgc, 0, sizeof(struct packet_command));
@@ -78,6 +154,30 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
78 return sr_do_ioctl(cdi->handle, &cgc); 154 return sr_do_ioctl(cdi->handle, &cgc);
79} 155}
80 156
157static int sr_play_trkind(struct cdrom_device_info *cdi,
158 struct cdrom_ti *ti)
159
160{
161 struct scsi_cd *cd = cdi->handle;
162 struct packet_command cgc;
163 int result;
164
165 memset(&cgc, 0, sizeof(struct packet_command));
166 cgc.timeout = IOCTL_TIMEOUT;
167 cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
168 cgc.cmd[4] = ti->cdti_trk0;
169 cgc.cmd[5] = ti->cdti_ind0;
170 cgc.cmd[7] = ti->cdti_trk1;
171 cgc.cmd[8] = ti->cdti_ind1;
172 cgc.data_direction = DMA_NONE;
173
174 result = sr_do_ioctl(cd, &cgc);
175 if (result == -EDRIVE_CANT_DO_THIS)
176 result = sr_fake_playtrkind(cdi, ti);
177
178 return result;
179}
180
81/* We do our own retries because we want to know what the specific 181/* We do our own retries because we want to know what the specific
82 error code is. Normally the UNIT_ATTENTION code will automatically 182 error code is. Normally the UNIT_ATTENTION code will automatically
83 clear after one error */ 183 clear after one error */
@@ -229,13 +329,14 @@ int sr_disk_status(struct cdrom_device_info *cdi)
229 int i, rc, have_datatracks = 0; 329 int i, rc, have_datatracks = 0;
230 330
231 /* look for data tracks */ 331 /* look for data tracks */
232 if (0 != (rc = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h))) 332 rc = sr_read_tochdr(cdi, &toc_h);
333 if (rc)
233 return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO; 334 return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO;
234 335
235 for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) { 336 for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) {
236 toc_e.cdte_track = i; 337 toc_e.cdte_track = i;
237 toc_e.cdte_format = CDROM_LBA; 338 toc_e.cdte_format = CDROM_LBA;
238 if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e)) 339 if (sr_read_tocentry(cdi, &toc_e))
239 return CDS_NO_INFO; 340 return CDS_NO_INFO;
240 if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) { 341 if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) {
241 have_datatracks = 1; 342 have_datatracks = 1;
@@ -262,10 +363,6 @@ int sr_get_last_session(struct cdrom_device_info *cdi,
262 return 0; 363 return 0;
263} 364}
264 365
265/* primitive to determine whether we need to have GFP_DMA set based on
266 * the status of the unchecked_isa_dma flag in the host structure */
267#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
268
269int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) 366int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
270{ 367{
271 Scsi_CD *cd = cdi->handle; 368 Scsi_CD *cd = cdi->handle;
@@ -329,93 +426,16 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
329 426
330int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) 427int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
331{ 428{
332 Scsi_CD *cd = cdi->handle;
333 struct packet_command cgc;
334 int result;
335 unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
336
337 if (!buffer)
338 return -ENOMEM;
339
340 memset(&cgc, 0, sizeof(struct packet_command));
341 cgc.timeout = IOCTL_TIMEOUT;
342
343 switch (cmd) { 429 switch (cmd) {
344 case CDROMREADTOCHDR: 430 case CDROMREADTOCHDR:
345 { 431 return sr_read_tochdr(cdi, arg);
346 struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
347
348 cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
349 cgc.cmd[8] = 12; /* LSB of length */
350 cgc.buffer = buffer;
351 cgc.buflen = 12;
352 cgc.quiet = 1;
353 cgc.data_direction = DMA_FROM_DEVICE;
354
355 result = sr_do_ioctl(cd, &cgc);
356
357 tochdr->cdth_trk0 = buffer[2];
358 tochdr->cdth_trk1 = buffer[3];
359
360 break;
361 }
362
363 case CDROMREADTOCENTRY: 432 case CDROMREADTOCENTRY:
364 { 433 return sr_read_tocentry(cdi, arg);
365 struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg; 434 case CDROMPLAYTRKIND:
366 435 return sr_play_trkind(cdi, arg);
367 cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
368 cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
369 cgc.cmd[6] = tocentry->cdte_track;
370 cgc.cmd[8] = 12; /* LSB of length */
371 cgc.buffer = buffer;
372 cgc.buflen = 12;
373 cgc.data_direction = DMA_FROM_DEVICE;
374
375 result = sr_do_ioctl(cd, &cgc);
376
377 tocentry->cdte_ctrl = buffer[5] & 0xf;
378 tocentry->cdte_adr = buffer[5] >> 4;
379 tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
380 if (tocentry->cdte_format == CDROM_MSF) {
381 tocentry->cdte_addr.msf.minute = buffer[9];
382 tocentry->cdte_addr.msf.second = buffer[10];
383 tocentry->cdte_addr.msf.frame = buffer[11];
384 } else
385 tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
386 + buffer[10]) << 8) + buffer[11];
387
388 break;
389 }
390
391 case CDROMPLAYTRKIND: {
392 struct cdrom_ti* ti = (struct cdrom_ti*)arg;
393
394 cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
395 cgc.cmd[4] = ti->cdti_trk0;
396 cgc.cmd[5] = ti->cdti_ind0;
397 cgc.cmd[7] = ti->cdti_trk1;
398 cgc.cmd[8] = ti->cdti_ind1;
399 cgc.data_direction = DMA_NONE;
400
401 result = sr_do_ioctl(cd, &cgc);
402 if (result == -EDRIVE_CANT_DO_THIS)
403 result = sr_fake_playtrkind(cdi, ti);
404
405 break;
406 }
407
408 default: 436 default:
409 result = -EINVAL; 437 return -EINVAL;
410 } 438 }
411
412#if 0
413 if (result)
414 printk("DEBUG: sr_audio: result for ioctl %x: %x\n", cmd, result);
415#endif
416
417 kfree(buffer);
418 return result;
419} 439}
420 440
421/* ----------------------------------------------------------------------- 441/* -----------------------------------------------------------------------