Continue untangling the disklabel. Reorganize struct partinfo and the
[dragonfly/port-amd64.git] / sys / dev / disk / ata / atapi-cd.c
blob45cefbebf4c5c819d147226fa21d37efa8782c00
1 /*-
2 * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * $FreeBSD: src/sys/dev/ata/atapi-cd.c,v 1.48.2.20 2002/11/25 05:30:31 njl Exp $
29 * $DragonFly: src/sys/dev/disk/ata/atapi-cd.c,v 1.31 2007/05/15 17:50:51 dillon Exp $
32 #include "opt_ata.h"
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/ata.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/proc.h>
39 #include <sys/buf.h>
40 #include <sys/bus.h>
41 #include <sys/disklabel.h>
42 #include <sys/devicestat.h>
43 #include <sys/cdio.h>
44 #include <sys/cdrio.h>
45 #include <sys/dvdio.h>
46 #include <sys/fcntl.h>
47 #include <sys/conf.h>
48 #include <sys/ctype.h>
49 #include <sys/buf2.h>
50 #include <sys/thread2.h>
52 #include "ata-all.h"
53 #include "atapi-all.h"
54 #include "atapi-cd.h"
56 /* device structures */
57 static d_open_t acdopen;
58 static d_close_t acdclose;
59 static d_ioctl_t acdioctl;
60 static d_strategy_t acdstrategy;
62 static struct dev_ops acd_ops = {
63 { "acd", 117, D_DISK | D_TRACKCLOSE },
64 .d_open = acdopen,
65 .d_close = acdclose,
66 .d_read = physread,
67 .d_write = physwrite,
68 .d_ioctl = acdioctl,
69 .d_strategy = acdstrategy,
72 /* prototypes */
73 static struct acd_softc *acd_init_lun(struct ata_device *);
74 static void acd_make_dev(struct acd_softc *);
75 static void acd_set_ioparm(struct acd_softc *);
76 static void acd_describe(struct acd_softc *);
77 static void lba2msf(u_int32_t, u_int8_t *, u_int8_t *, u_int8_t *);
78 static u_int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t);
79 static int acd_done(struct atapi_request *);
80 static void acd_read_toc(struct acd_softc *);
81 static int acd_play(struct acd_softc *, int, int);
82 static int acd_setchan(struct acd_softc *, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
83 static void acd_select_slot(struct acd_softc *);
84 static int acd_init_writer(struct acd_softc *, int);
85 static int acd_fixate(struct acd_softc *, int);
86 static int acd_init_track(struct acd_softc *, struct cdr_track *);
87 static int acd_flush(struct acd_softc *);
88 static int acd_read_track_info(struct acd_softc *, int32_t, struct acd_track_info *);
89 static int acd_get_progress(struct acd_softc *, int *);
90 static int acd_send_cue(struct acd_softc *, struct cdr_cuesheet *);
91 static int acd_report_key(struct acd_softc *, struct dvd_authinfo *);
92 static int acd_send_key(struct acd_softc *, struct dvd_authinfo *);
93 static int acd_read_structure(struct acd_softc *, struct dvd_struct *);
94 static int acd_eject(struct acd_softc *, int);
95 static int acd_blank(struct acd_softc *, int);
96 static int acd_prevent_allow(struct acd_softc *, int);
97 static int acd_start_stop(struct acd_softc *, int);
98 static int acd_pause_resume(struct acd_softc *, int);
99 static int acd_mode_sense(struct acd_softc *, int, caddr_t, int);
100 static int acd_mode_select(struct acd_softc *, caddr_t, int);
101 static int acd_set_speed(struct acd_softc *, int, int);
102 static void acd_get_cap(struct acd_softc *);
104 /* internal vars */
105 static u_int32_t acd_lun_map = 0;
106 static MALLOC_DEFINE(M_ACD, "ACD driver", "ATAPI CD driver buffers");
109 acdattach(struct ata_device *atadev)
111 struct acd_softc *cdp;
112 struct changer *chp;
114 if ((cdp = acd_init_lun(atadev)) == NULL) {
115 ata_prtdev(atadev, "acd: out of memory\n");
116 return 0;
119 ata_set_name(atadev, "acd", cdp->lun);
120 ata_command(atadev, ATA_C_ATAPI_RESET, 0, 0, 0, ATA_IMMEDIATE);
121 acd_get_cap(cdp);
123 /* if this is a changer device, allocate the neeeded lun's */
124 if (cdp->cap.mech == MST_MECH_CHANGER) {
125 int8_t ccb[16] = { ATAPI_MECH_STATUS, 0, 0, 0, 0, 0, 0, 0,
126 sizeof(struct changer)>>8, sizeof(struct changer),
127 0, 0, 0, 0, 0, 0 };
129 chp = kmalloc(sizeof(struct changer), M_ACD, M_WAITOK | M_ZERO);
130 if (!atapi_queue_cmd(cdp->device, ccb, (caddr_t)chp,
131 sizeof(struct changer),
132 ATPR_F_READ, 60, NULL, NULL)) {
133 struct acd_softc *tmpcdp = cdp;
134 struct acd_softc **cdparr;
135 char *name;
136 int count;
138 chp->table_length = htons(chp->table_length);
139 cdparr = kmalloc(sizeof(struct acd_softc) * chp->slots,
140 M_ACD, M_WAITOK);
141 for (count = 0; count < chp->slots; count++) {
142 if (count > 0) {
143 tmpcdp = acd_init_lun(atadev);
144 if (!tmpcdp) {
145 ata_prtdev(atadev, "out of memory\n");
146 break;
149 cdparr[count] = tmpcdp;
150 tmpcdp->driver = cdparr;
151 tmpcdp->slot = count;
152 tmpcdp->changer_info = chp;
153 acd_make_dev(tmpcdp);
154 devstat_add_entry(tmpcdp->stats, "acd", tmpcdp->lun, DEV_BSIZE,
155 DEVSTAT_NO_ORDERED_TAGS,
156 DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE,
157 DEVSTAT_PRIORITY_CD);
159 name = kmalloc(strlen(atadev->name) + 2, M_ACD, M_WAITOK);
160 strcpy(name, atadev->name);
161 strcat(name, "-");
162 ata_free_name(atadev);
163 ata_set_name(atadev, name, cdp->lun + cdp->changer_info->slots - 1);
164 kfree(name, M_ACD);
167 else {
168 acd_make_dev(cdp);
169 devstat_add_entry(cdp->stats, "acd", cdp->lun, DEV_BSIZE,
170 DEVSTAT_NO_ORDERED_TAGS,
171 DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE,
172 DEVSTAT_PRIORITY_CD);
174 acd_describe(cdp);
175 atadev->driver = cdp;
176 return 1;
179 void
180 acddetach(struct ata_device *atadev)
182 struct acd_softc *cdp = atadev->driver;
183 struct acd_devlist *entry;
184 struct bio *bio;
185 int subdev;
187 if (cdp->changer_info) {
188 for (subdev = 0; subdev < cdp->changer_info->slots; subdev++) {
189 if (cdp->driver[subdev] == cdp)
190 continue;
191 while ((bio = bioq_first(&cdp->driver[subdev]->bio_queue))) {
192 bioq_remove(&cdp->driver[subdev]->bio_queue, bio);
193 bio->bio_buf->b_flags |= B_ERROR;
194 bio->bio_buf->b_error = ENXIO;
195 biodone(bio);
197 release_dev(cdp->driver[subdev]->dev);
198 while ((entry = TAILQ_FIRST(&cdp->driver[subdev]->dev_list))) {
199 release_dev(entry->dev);
200 TAILQ_REMOVE(&cdp->driver[subdev]->dev_list, entry, chain);
201 kfree(entry, M_ACD);
203 devstat_remove_entry(cdp->driver[subdev]->stats);
204 kfree(cdp->driver[subdev]->stats, M_ACD);
205 ata_free_lun(&acd_lun_map, cdp->driver[subdev]->lun);
206 kfree(cdp->driver[subdev], M_ACD);
208 kfree(cdp->driver, M_ACD);
209 kfree(cdp->changer_info, M_ACD);
211 while ((bio = bioq_first(&cdp->bio_queue))) {
212 bio->bio_buf->b_flags |= B_ERROR;
213 bio->bio_buf->b_error = ENXIO;
214 biodone(bio);
216 while ((entry = TAILQ_FIRST(&cdp->dev_list))) {
217 release_dev(entry->dev);
218 TAILQ_REMOVE(&cdp->dev_list, entry, chain);
219 kfree(entry, M_ACD);
221 release_dev(cdp->dev);
222 devstat_remove_entry(cdp->stats);
223 dev_ops_remove(&acd_ops, dkunitmask(), dkmakeunit(cdp->lun));
224 kfree(cdp->stats, M_ACD);
225 ata_free_name(atadev);
226 ata_free_lun(&acd_lun_map, cdp->lun);
227 kfree(cdp, M_ACD);
228 atadev->driver = NULL;
231 static struct acd_softc *
232 acd_init_lun(struct ata_device *atadev)
234 struct acd_softc *cdp;
236 cdp = kmalloc(sizeof(struct acd_softc), M_ACD, M_WAITOK | M_ZERO);
237 TAILQ_INIT(&cdp->dev_list);
238 bioq_init(&cdp->bio_queue);
239 cdp->device = atadev;
240 cdp->lun = ata_get_lun(&acd_lun_map);
241 cdp->block_size = 2048;
242 cdp->slot = -1;
243 cdp->changer_info = NULL;
244 cdp->stats = kmalloc(sizeof(struct devstat), M_ACD, M_WAITOK | M_ZERO);
245 return cdp;
248 static void
249 acd_make_dev(struct acd_softc *cdp)
251 cdev_t dev;
253 dev_ops_add(&acd_ops, dkunitmask(), dkmakeunit(cdp->lun));
254 dev = make_dev(&acd_ops, dkmakeminor(cdp->lun, 0, 0),
255 UID_ROOT, GID_OPERATOR, 0644, "acd%d", cdp->lun);
256 reference_dev(dev);
257 dev->si_drv1 = cdp;
258 cdp->dev = dev;
259 cdp->device->flags |= ATA_D_MEDIA_CHANGED;
260 acd_set_ioparm(cdp);
263 static void
264 acd_set_ioparm(struct acd_softc *cdp)
266 cdp->dev->si_iosize_max = ((256*DEV_BSIZE)/cdp->block_size)*cdp->block_size;
267 cdp->dev->si_bsize_phys = cdp->block_size;
270 static void
271 acd_describe(struct acd_softc *cdp)
273 int comma = 0;
274 char *mechanism;
276 if (bootverbose) {
277 ata_prtdev(cdp->device, "<%.40s/%.8s> %s drive at ata%d as %s\n",
278 cdp->device->param->model, cdp->device->param->revision,
279 (cdp->cap.write_dvdr) ? "DVD-R" :
280 (cdp->cap.write_dvdram) ? "DVD-RAM" :
281 (cdp->cap.write_cdrw) ? "CD-RW" :
282 (cdp->cap.write_cdr) ? "CD-R" :
283 (cdp->cap.read_dvdrom) ? "DVD-ROM" : "CDROM",
284 device_get_unit(cdp->device->channel->dev),
285 (cdp->device->unit == ATA_MASTER) ? "master" : "slave");
287 ata_prtdev(cdp->device, "%s", "");
288 if (cdp->cap.cur_read_speed) {
289 kprintf("read %dKB/s", cdp->cap.cur_read_speed * 1000 / 1024);
290 if (cdp->cap.max_read_speed)
291 kprintf(" (%dKB/s)", cdp->cap.max_read_speed * 1000 / 1024);
292 if ((cdp->cap.cur_write_speed) &&
293 (cdp->cap.write_cdr || cdp->cap.write_cdrw ||
294 cdp->cap.write_dvdr || cdp->cap.write_dvdram)) {
295 kprintf(" write %dKB/s", cdp->cap.cur_write_speed * 1000 / 1024);
296 if (cdp->cap.max_write_speed)
297 kprintf(" (%dKB/s)", cdp->cap.max_write_speed * 1000 / 1024);
299 comma = 1;
301 if (cdp->cap.buf_size) {
302 kprintf("%s %dKB buffer", comma ? "," : "", cdp->cap.buf_size);
303 comma = 1;
305 kprintf("%s %s\n", comma ? "," : "", ata_mode2str(cdp->device->mode));
307 ata_prtdev(cdp->device, "Reads:");
308 comma = 0;
309 if (cdp->cap.read_cdr) {
310 kprintf(" CD-R"); comma = 1;
312 if (cdp->cap.read_cdrw) {
313 kprintf("%s CD-RW", comma ? "," : ""); comma = 1;
315 if (cdp->cap.cd_da) {
316 if (cdp->cap.cd_da_stream)
317 kprintf("%s CD-DA stream", comma ? "," : "");
318 else
319 kprintf("%s CD-DA", comma ? "," : "");
320 comma = 1;
322 if (cdp->cap.read_dvdrom) {
323 kprintf("%s DVD-ROM", comma ? "," : ""); comma = 1;
325 if (cdp->cap.read_dvdr) {
326 kprintf("%s DVD-R", comma ? "," : ""); comma = 1;
328 if (cdp->cap.read_dvdram) {
329 kprintf("%s DVD-RAM", comma ? "," : ""); comma = 1;
331 if (cdp->cap.read_packet)
332 kprintf("%s packet", comma ? "," : "");
334 kprintf("\n");
335 ata_prtdev(cdp->device, "Writes:");
336 if (cdp->cap.write_cdr || cdp->cap.write_cdrw ||
337 cdp->cap.write_dvdr || cdp->cap.write_dvdram) {
338 comma = 0;
339 if (cdp->cap.write_cdr) {
340 kprintf(" CD-R" ); comma = 1;
342 if (cdp->cap.write_cdrw) {
343 kprintf("%s CD-RW", comma ? "," : ""); comma = 1;
345 if (cdp->cap.write_dvdr) {
346 kprintf("%s DVD-R", comma ? "," : ""); comma = 1;
348 if (cdp->cap.write_dvdram) {
349 kprintf("%s DVD-RAM", comma ? "," : ""); comma = 1;
351 if (cdp->cap.test_write) {
352 kprintf("%s test write", comma ? "," : ""); comma = 1;
354 if (cdp->cap.burnproof)
355 kprintf("%s burnproof", comma ? "," : "");
357 kprintf("\n");
358 if (cdp->cap.audio_play) {
359 ata_prtdev(cdp->device, "Audio: ");
360 if (cdp->cap.audio_play)
361 kprintf("play");
362 if (cdp->cap.max_vol_levels)
363 kprintf(", %d volume levels", cdp->cap.max_vol_levels);
364 kprintf("\n");
366 ata_prtdev(cdp->device, "Mechanism: ");
367 switch (cdp->cap.mech) {
368 case MST_MECH_CADDY:
369 mechanism = "caddy"; break;
370 case MST_MECH_TRAY:
371 mechanism = "tray"; break;
372 case MST_MECH_POPUP:
373 mechanism = "popup"; break;
374 case MST_MECH_CHANGER:
375 mechanism = "changer"; break;
376 case MST_MECH_CARTRIDGE:
377 mechanism = "cartridge"; break;
378 default:
379 mechanism = 0; break;
381 if (mechanism)
382 kprintf("%s%s", cdp->cap.eject ? "ejectable " : "", mechanism);
383 else if (cdp->cap.eject)
384 kprintf("ejectable");
386 if (cdp->cap.lock)
387 kprintf(cdp->cap.locked ? ", locked" : ", unlocked");
388 if (cdp->cap.prevent)
389 kprintf(", lock protected");
390 kprintf("\n");
392 if (cdp->cap.mech != MST_MECH_CHANGER) {
393 ata_prtdev(cdp->device, "Medium: ");
394 switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
395 case MST_CDROM:
396 kprintf("CD-ROM "); break;
397 case MST_CDR:
398 kprintf("CD-R "); break;
399 case MST_CDRW:
400 kprintf("CD-RW "); break;
401 case MST_DOOR_OPEN:
402 kprintf("door open"); break;
403 case MST_NO_DISC:
404 kprintf("no/blank disc"); break;
405 case MST_FMT_ERROR:
406 kprintf("medium format error"); break;
408 if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH)<MST_TYPE_MASK_HIGH){
409 switch (cdp->cap.medium_type & MST_TYPE_MASK_LOW) {
410 case MST_DATA_120:
411 kprintf("120mm data disc"); break;
412 case MST_AUDIO_120:
413 kprintf("120mm audio disc"); break;
414 case MST_COMB_120:
415 kprintf("120mm data/audio disc"); break;
416 case MST_PHOTO_120:
417 kprintf("120mm photo disc"); break;
418 case MST_DATA_80:
419 kprintf("80mm data disc"); break;
420 case MST_AUDIO_80:
421 kprintf("80mm audio disc"); break;
422 case MST_COMB_80:
423 kprintf("80mm data/audio disc"); break;
424 case MST_PHOTO_80:
425 kprintf("80mm photo disc"); break;
426 case MST_FMT_NONE:
427 switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
428 case MST_CDROM:
429 kprintf("unknown"); break;
430 case MST_CDR:
431 case MST_CDRW:
432 kprintf("blank"); break;
434 break;
435 default:
436 kprintf("unknown (0x%x)", cdp->cap.medium_type); break;
439 kprintf("\n");
442 else {
443 ata_prtdev(cdp->device, "%s ",
444 (cdp->cap.write_dvdr) ? "DVD-R" :
445 (cdp->cap.write_dvdram) ? "DVD-RAM" :
446 (cdp->cap.write_cdrw) ? "CD-RW" :
447 (cdp->cap.write_cdr) ? "CD-R" :
448 (cdp->cap.read_dvdrom) ? "DVD-ROM" : "CDROM");
450 if (cdp->changer_info)
451 kprintf("with %d CD changer ", cdp->changer_info->slots);
453 kprintf("<%.40s> at ata%d-%s %s\n", cdp->device->param->model,
454 device_get_unit(cdp->device->channel->dev),
455 (cdp->device->unit == ATA_MASTER) ? "master" : "slave",
456 ata_mode2str(cdp->device->mode) );
460 static __inline void
461 lba2msf(u_int32_t lba, u_int8_t *m, u_int8_t *s, u_int8_t *f)
463 lba += 150;
464 lba &= 0xffffff;
465 *m = lba / (60 * 75);
466 lba %= (60 * 75);
467 *s = lba / 75;
468 *f = lba % 75;
471 static __inline u_int32_t
472 msf2lba(u_int8_t m, u_int8_t s, u_int8_t f)
474 return (m * 60 + s) * 75 + f - 150;
477 static int
478 acdopen(struct dev_open_args *ap)
480 cdev_t dev = ap->a_head.a_dev;
481 struct acd_softc *cdp = dev->si_drv1;
482 int timeout = 60;
484 if (!cdp)
485 return ENXIO;
487 if (ap->a_oflags & FWRITE) {
488 if (count_dev(dev) > 1)
489 return EBUSY;
492 /* wait if drive is not finished loading the medium */
493 while (timeout--) {
494 struct atapi_reqsense *sense = cdp->device->result;
496 if (!atapi_test_ready(cdp->device))
497 break;
498 if (sense->sense_key == 2 && sense->asc == 4 && sense->ascq == 1)
499 tsleep(&timeout, 0, "acdld", hz / 2);
500 else
501 break;
504 if (count_dev(dev) == 1) {
505 if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
506 acd_select_slot(cdp);
507 tsleep(&cdp->changer_info, 0, "acdopn", 0);
509 acd_prevent_allow(cdp, 1);
510 cdp->flags |= F_LOCKED;
511 acd_read_toc(cdp);
513 return 0;
516 static int
517 acdclose(struct dev_close_args *ap)
519 cdev_t dev = ap->a_head.a_dev;
520 struct acd_softc *cdp = dev->si_drv1;
522 if (!cdp)
523 return ENXIO;
525 if (count_dev(dev) == 1) {
526 if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
527 acd_select_slot(cdp);
528 tsleep(&cdp->changer_info, 0, "acdclo", 0);
530 acd_prevent_allow(cdp, 0);
531 cdp->flags &= ~F_LOCKED;
533 return 0;
536 static int
537 acdioctl(struct dev_ioctl_args *ap)
539 cdev_t dev = ap->a_head.a_dev;
540 struct acd_softc *cdp = dev->si_drv1;
541 int error = 0;
543 if (!cdp)
544 return ENXIO;
546 if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
547 acd_select_slot(cdp);
548 tsleep(&cdp->changer_info, 0, "acdctl", 0);
550 if (cdp->device->flags & ATA_D_MEDIA_CHANGED)
551 switch (ap->a_cmd) {
552 case CDIOCRESET:
553 atapi_test_ready(cdp->device);
554 break;
556 default:
557 acd_read_toc(cdp);
558 acd_prevent_allow(cdp, 1);
559 cdp->flags |= F_LOCKED;
560 break;
562 switch (ap->a_cmd) {
564 case CDIOCRESUME:
565 error = acd_pause_resume(cdp, 1);
566 break;
568 case CDIOCPAUSE:
569 error = acd_pause_resume(cdp, 0);
570 break;
572 case CDIOCSTART:
573 error = acd_start_stop(cdp, 1);
574 break;
576 case CDIOCSTOP:
577 error = acd_start_stop(cdp, 0);
578 break;
580 case CDIOCALLOW:
581 error = acd_prevent_allow(cdp, 0);
582 cdp->flags &= ~F_LOCKED;
583 break;
585 case CDIOCPREVENT:
586 error = acd_prevent_allow(cdp, 1);
587 cdp->flags |= F_LOCKED;
588 break;
590 case CDIOCRESET:
591 ; /* note: if no proc EPERM will be returned */
592 error = suser_cred(ap->a_cred, 0);
593 if (error)
594 break;
595 error = atapi_test_ready(cdp->device);
596 break;
598 case CDIOCEJECT:
599 if (count_dev(dev) > 1) {
600 error = EBUSY;
601 break;
603 error = acd_eject(cdp, 0);
604 break;
606 case CDIOCCLOSE:
607 if (count_dev(dev) > 1)
608 break;
609 error = acd_eject(cdp, 1);
610 break;
612 case CDIOREADTOCHEADER:
613 if (!cdp->toc.hdr.ending_track) {
614 error = EIO;
615 break;
617 bcopy(&cdp->toc.hdr, ap->a_data, sizeof(cdp->toc.hdr));
618 break;
620 case CDIOREADTOCENTRYS:
622 struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)ap->a_data;
623 struct toc *toc = &cdp->toc;
624 int starting_track = te->starting_track;
625 int len;
627 if (!toc->hdr.ending_track) {
628 error = EIO;
629 break;
632 if (te->data_len < sizeof(toc->tab[0]) ||
633 (te->data_len % sizeof(toc->tab[0])) != 0 ||
634 (te->address_format != CD_MSF_FORMAT &&
635 te->address_format != CD_LBA_FORMAT)) {
636 error = EINVAL;
637 break;
640 if (!starting_track)
641 starting_track = toc->hdr.starting_track;
642 else if (starting_track == 170)
643 starting_track = toc->hdr.ending_track + 1;
644 else if (starting_track < toc->hdr.starting_track ||
645 starting_track > toc->hdr.ending_track + 1) {
646 error = EINVAL;
647 break;
650 len = ((toc->hdr.ending_track + 1 - starting_track) + 1) *
651 sizeof(toc->tab[0]);
652 if (te->data_len < len)
653 len = te->data_len;
654 if (len > sizeof(toc->tab)) {
655 error = EINVAL;
656 break;
659 if (te->address_format == CD_MSF_FORMAT) {
660 struct cd_toc_entry *entry;
662 toc = kmalloc(sizeof(struct toc), M_ACD, M_WAITOK | M_ZERO);
663 bcopy(&cdp->toc, toc, sizeof(struct toc));
664 entry = toc->tab + (toc->hdr.ending_track + 1 -
665 toc->hdr.starting_track) + 1;
666 while (--entry >= toc->tab)
667 lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute,
668 &entry->addr.msf.second, &entry->addr.msf.frame);
670 error = copyout(toc->tab + starting_track - toc->hdr.starting_track,
671 te->data, len);
672 if (te->address_format == CD_MSF_FORMAT)
673 kfree(toc, M_ACD);
674 break;
676 case CDIOREADTOCENTRY:
678 struct ioc_read_toc_single_entry *te =
679 (struct ioc_read_toc_single_entry *)ap->a_data;
680 struct toc *toc = &cdp->toc;
681 u_char track = te->track;
683 if (!toc->hdr.ending_track) {
684 error = EIO;
685 break;
688 if (te->address_format != CD_MSF_FORMAT &&
689 te->address_format != CD_LBA_FORMAT) {
690 error = EINVAL;
691 break;
694 if (!track)
695 track = toc->hdr.starting_track;
696 else if (track == 170)
697 track = toc->hdr.ending_track + 1;
698 else if (track < toc->hdr.starting_track ||
699 track > toc->hdr.ending_track + 1) {
700 error = EINVAL;
701 break;
704 if (te->address_format == CD_MSF_FORMAT) {
705 struct cd_toc_entry *entry;
707 toc = kmalloc(sizeof(struct toc), M_ACD, M_WAITOK | M_ZERO);
708 bcopy(&cdp->toc, toc, sizeof(struct toc));
710 entry = toc->tab + (track - toc->hdr.starting_track);
711 lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute,
712 &entry->addr.msf.second, &entry->addr.msf.frame);
714 bcopy(toc->tab + track - toc->hdr.starting_track,
715 &te->entry, sizeof(struct cd_toc_entry));
716 if (te->address_format == CD_MSF_FORMAT)
717 kfree(toc, M_ACD);
719 break;
721 case CDIOCREADSUBCHANNEL:
723 struct ioc_read_subchannel *args =
724 (struct ioc_read_subchannel *)ap->a_data;
725 u_int8_t format;
726 int8_t ccb[16] = { ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, 0, 0,
727 sizeof(cdp->subchan)>>8, sizeof(cdp->subchan),
728 0, 0, 0, 0, 0, 0, 0 };
730 if (args->data_len > sizeof(struct cd_sub_channel_info) ||
731 args->data_len < sizeof(struct cd_sub_channel_header)) {
732 error = EINVAL;
733 break;
736 format=args->data_format;
737 if ((format != CD_CURRENT_POSITION) &&
738 (format != CD_MEDIA_CATALOG) && (format != CD_TRACK_INFO)) {
739 error = EINVAL;
740 break;
743 ccb[1] = args->address_format & CD_MSF_FORMAT;
745 if ((error = atapi_queue_cmd(cdp->device,ccb,(caddr_t)&cdp->subchan,
746 sizeof(cdp->subchan), ATPR_F_READ, 10,
747 NULL, NULL)))
748 break;
750 if ((format == CD_MEDIA_CATALOG) || (format == CD_TRACK_INFO)) {
751 if (cdp->subchan.header.audio_status == 0x11) {
752 error = EINVAL;
753 break;
756 ccb[3] = format;
757 if (format == CD_TRACK_INFO)
758 ccb[6] = args->track;
760 if ((error = atapi_queue_cmd(cdp->device, ccb,
761 (caddr_t)&cdp->subchan,
762 sizeof(cdp->subchan), ATPR_F_READ,
763 10, NULL, NULL))) {
764 break;
767 error = copyout(&cdp->subchan, args->data, args->data_len);
768 break;
771 case CDIOCPLAYMSF:
773 struct ioc_play_msf *args = (struct ioc_play_msf *)ap->a_data;
775 error =
776 acd_play(cdp,
777 msf2lba(args->start_m, args->start_s, args->start_f),
778 msf2lba(args->end_m, args->end_s, args->end_f));
779 break;
782 case CDIOCPLAYBLOCKS:
784 struct ioc_play_blocks *args = (struct ioc_play_blocks *)ap->a_data;
786 error = acd_play(cdp, args->blk, args->blk + args->len);
787 break;
790 case CDIOCPLAYTRACKS:
792 struct ioc_play_track *args = (struct ioc_play_track *)ap->a_data;
793 int t1, t2;
795 if (!cdp->toc.hdr.ending_track) {
796 error = EIO;
797 break;
799 if (args->end_track < cdp->toc.hdr.ending_track + 1)
800 ++args->end_track;
801 if (args->end_track > cdp->toc.hdr.ending_track + 1)
802 args->end_track = cdp->toc.hdr.ending_track + 1;
803 t1 = args->start_track - cdp->toc.hdr.starting_track;
804 t2 = args->end_track - cdp->toc.hdr.starting_track;
805 if (t1 < 0 || t2 < 0 ||
806 t1 > (cdp->toc.hdr.ending_track-cdp->toc.hdr.starting_track)) {
807 error = EINVAL;
808 break;
810 error = acd_play(cdp, ntohl(cdp->toc.tab[t1].addr.lba),
811 ntohl(cdp->toc.tab[t2].addr.lba));
812 break;
815 case CDIOCREADAUDIO:
817 struct ioc_read_audio *args = (struct ioc_read_audio *)ap->a_data;
818 int32_t lba;
819 caddr_t buffer, ubuf = args->buffer;
820 int8_t ccb[16];
821 int frames;
823 if (!cdp->toc.hdr.ending_track) {
824 error = EIO;
825 break;
828 if ((frames = args->nframes) < 0) {
829 error = EINVAL;
830 break;
833 if (args->address_format == CD_LBA_FORMAT)
834 lba = args->address.lba;
835 else if (args->address_format == CD_MSF_FORMAT)
836 lba = msf2lba(args->address.msf.minute,
837 args->address.msf.second,
838 args->address.msf.frame);
839 else {
840 error = EINVAL;
841 break;
844 #ifndef CD_BUFFER_BLOCKS
845 #define CD_BUFFER_BLOCKS 13
846 #endif
847 if (!(buffer = kmalloc(CD_BUFFER_BLOCKS * 2352, M_ACD, M_WAITOK))){
848 error = ENOMEM;
849 break;
851 bzero(ccb, sizeof(ccb));
852 while (frames > 0) {
853 int8_t blocks;
854 int size;
856 blocks = (frames>CD_BUFFER_BLOCKS) ? CD_BUFFER_BLOCKS : frames;
857 size = blocks * 2352;
859 ccb[0] = ATAPI_READ_CD;
860 ccb[1] = 4;
861 ccb[2] = lba>>24;
862 ccb[3] = lba>>16;
863 ccb[4] = lba>>8;
864 ccb[5] = lba;
865 ccb[8] = blocks;
866 ccb[9] = 0xf0;
867 if ((error = atapi_queue_cmd(cdp->device, ccb, buffer, size,
868 ATPR_F_READ, 30, NULL,NULL)))
869 break;
871 if ((error = copyout(buffer, ubuf, size)))
872 break;
874 ubuf += size;
875 frames -= blocks;
876 lba += blocks;
878 kfree(buffer, M_ACD);
879 if (args->address_format == CD_LBA_FORMAT)
880 args->address.lba = lba;
881 else if (args->address_format == CD_MSF_FORMAT)
882 lba2msf(lba, &args->address.msf.minute,
883 &args->address.msf.second,
884 &args->address.msf.frame);
885 break;
888 case CDIOCGETVOL:
890 struct ioc_vol *arg = (struct ioc_vol *)ap->a_data;
892 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE,
893 (caddr_t)&cdp->au, sizeof(cdp->au))))
894 break;
896 if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) {
897 error = EIO;
898 break;
900 arg->vol[0] = cdp->au.port[0].volume;
901 arg->vol[1] = cdp->au.port[1].volume;
902 arg->vol[2] = cdp->au.port[2].volume;
903 arg->vol[3] = cdp->au.port[3].volume;
904 break;
907 case CDIOCSETVOL:
909 struct ioc_vol *arg = (struct ioc_vol *)ap->a_data;
911 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE,
912 (caddr_t)&cdp->au, sizeof(cdp->au))))
913 break;
914 if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) {
915 error = EIO;
916 break;
918 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE_MASK,
919 (caddr_t)&cdp->aumask,
920 sizeof(cdp->aumask))))
921 break;
922 cdp->au.data_length = 0;
923 cdp->au.port[0].channels = CHANNEL_0;
924 cdp->au.port[1].channels = CHANNEL_1;
925 cdp->au.port[0].volume = arg->vol[0] & cdp->aumask.port[0].volume;
926 cdp->au.port[1].volume = arg->vol[1] & cdp->aumask.port[1].volume;
927 cdp->au.port[2].volume = arg->vol[2] & cdp->aumask.port[2].volume;
928 cdp->au.port[3].volume = arg->vol[3] & cdp->aumask.port[3].volume;
929 error = acd_mode_select(cdp, (caddr_t)&cdp->au, sizeof(cdp->au));
930 break;
932 case CDIOCSETPATCH:
934 struct ioc_patch *arg = (struct ioc_patch *)ap->a_data;
936 error = acd_setchan(cdp, arg->patch[0], arg->patch[1],
937 arg->patch[2], arg->patch[3]);
938 break;
941 case CDIOCSETMONO:
942 error = acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0,0);
943 break;
945 case CDIOCSETSTEREO:
946 error = acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0);
947 break;
949 case CDIOCSETMUTE:
950 error = acd_setchan(cdp, 0, 0, 0, 0);
951 break;
953 case CDIOCSETLEFT:
954 error = acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0);
955 break;
957 case CDIOCSETRIGHT:
958 error = acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0);
959 break;
961 case CDRIOCBLANK:
962 error = acd_blank(cdp, (*(int *)ap->a_data));
963 break;
965 case CDRIOCNEXTWRITEABLEADDR:
967 struct acd_track_info track_info;
969 if ((error = acd_read_track_info(cdp, 0xff, &track_info)))
970 break;
972 if (!track_info.nwa_valid) {
973 error = EINVAL;
974 break;
976 *(int*)ap->a_data = track_info.next_writeable_addr;
978 break;
980 case CDRIOCINITWRITER:
981 error = acd_init_writer(cdp, (*(int *)ap->a_data));
982 break;
984 case CDRIOCINITTRACK:
985 error = acd_init_track(cdp, (struct cdr_track *)ap->a_data);
986 break;
988 case CDRIOCFLUSH:
989 error = acd_flush(cdp);
990 break;
992 case CDRIOCFIXATE:
993 error = acd_fixate(cdp, (*(int *)ap->a_data));
994 break;
996 case CDRIOCREADSPEED:
998 int speed = *(int *)ap->a_data;
1000 /* Preserve old behavior: units in multiples of CDROM speed */
1001 if (speed < 177)
1002 speed *= 177;
1003 error = acd_set_speed(cdp, speed, CDR_MAX_SPEED);
1005 break;
1007 case CDRIOCWRITESPEED:
1009 int speed = *(int *)ap->a_data;
1011 if (speed < 177)
1012 speed *= 177;
1013 error = acd_set_speed(cdp, CDR_MAX_SPEED, speed);
1015 break;
1017 case CDRIOCGETBLOCKSIZE:
1018 *(int *)ap->a_data = cdp->block_size;
1019 break;
1021 case CDRIOCSETBLOCKSIZE:
1022 cdp->block_size = *(int *)ap->a_data;
1023 acd_set_ioparm(cdp);
1024 break;
1026 case CDRIOCGETPROGRESS:
1027 error = acd_get_progress(cdp, (int *)ap->a_data);
1028 break;
1030 case CDRIOCSENDCUE:
1031 error = acd_send_cue(cdp, (struct cdr_cuesheet *)ap->a_data);
1032 break;
1034 case DVDIOCREPORTKEY:
1035 if (!cdp->cap.read_dvdrom)
1036 error = EINVAL;
1037 else
1038 error = acd_report_key(cdp, (struct dvd_authinfo *)ap->a_data);
1039 break;
1041 case DVDIOCSENDKEY:
1042 if (!cdp->cap.read_dvdrom)
1043 error = EINVAL;
1044 else
1045 error = acd_send_key(cdp, (struct dvd_authinfo *)ap->a_data);
1046 break;
1048 case DVDIOCREADSTRUCTURE:
1049 if (!cdp->cap.read_dvdrom)
1050 error = EINVAL;
1051 else
1052 error = acd_read_structure(cdp, (struct dvd_struct *)ap->a_data);
1053 break;
1055 case DIOCGDINFO:
1056 *(struct disklabel *)ap->a_data = cdp->disklabel;
1057 break;
1059 case DIOCWDINFO:
1060 case DIOCSDINFO:
1061 if ((ap->a_fflag & FWRITE) == 0)
1062 error = EBADF;
1063 else
1064 error = setdisklabel(&cdp->disklabel, (struct disklabel *)ap->a_data, 0);
1065 break;
1067 case DIOCWLABEL:
1068 error = EBADF;
1069 break;
1071 case DIOCGPART:
1073 struct partinfo *dpart = (void *)ap->a_data;
1075 bzero(dpart, sizeof(*dpart));
1076 dpart->media_offset = 0;
1077 dpart->media_size = (u_int64_t)cdp->disk_size * cdp->block_size;
1078 dpart->media_blocks = cdp->disk_size;
1079 dpart->media_blksize = cdp->block_size;
1080 dpart->fstype = FS_BSDFFS;
1081 ksnprintf(dpart->fstypestr, sizeof(dpart->fstypestr),
1082 "4.2BSD");
1084 break;
1086 default:
1087 error = ENOTTY;
1089 return error;
1092 static int
1093 acdstrategy(struct dev_strategy_args *ap)
1095 cdev_t dev = ap->a_head.a_dev;
1096 struct bio *bio = ap->a_bio;
1097 struct buf *bp = bio->bio_buf;
1098 struct acd_softc *cdp = dev->si_drv1;
1100 if (cdp->device->flags & ATA_D_DETACHING) {
1101 bp->b_flags |= B_ERROR;
1102 bp->b_error = ENXIO;
1103 biodone(bio);
1104 return(0);
1107 /* if it's a null transfer, return immediatly. */
1108 if (bp->b_bcount == 0) {
1109 bp->b_resid = 0;
1110 biodone(bio);
1111 return(0);
1114 KKASSERT(bio->bio_offset != NOOFFSET);
1115 bio->bio_driver_info = dev;
1116 bp->b_resid = bp->b_bcount;
1118 crit_enter();
1119 bioqdisksort(&cdp->bio_queue, bio);
1120 crit_exit();
1121 ata_start(cdp->device->channel);
1122 return(0);
1125 void
1126 acd_start(struct ata_device *atadev)
1128 struct acd_softc *cdp = atadev->driver;
1129 struct bio *bio = bioq_first(&cdp->bio_queue);
1130 struct buf *bp;
1131 cdev_t dev;
1132 u_int32_t lba, lastlba, count;
1133 int8_t ccb[16];
1134 int track, blocksize;
1136 if (cdp->changer_info) {
1137 int i;
1139 cdp = cdp->driver[cdp->changer_info->current_slot];
1140 bio = bioq_first(&cdp->bio_queue);
1142 /* check for work pending on any other slot */
1143 for (i = 0; i < cdp->changer_info->slots; i++) {
1144 if (i == cdp->changer_info->current_slot)
1145 continue;
1146 if (bioq_first(&(cdp->driver[i]->bio_queue))) {
1147 if (bio == NULL || time_second > (cdp->timestamp + 10)) {
1148 acd_select_slot(cdp->driver[i]);
1149 return;
1154 if (bio == NULL)
1155 return;
1156 bioq_remove(&cdp->bio_queue, bio);
1157 dev = bio->bio_driver_info;
1158 bp = bio->bio_buf;
1160 /* reject all queued entries if media changed */
1161 if (cdp->device->flags & ATA_D_MEDIA_CHANGED) {
1162 bp->b_flags |= B_ERROR;
1163 bp->b_error = EIO;
1164 biodone(bio);
1165 return;
1168 bzero(ccb, sizeof(ccb));
1170 track = (dev->si_uminor & 0x00ff0000) >> 16;
1172 if (track) {
1173 blocksize = (cdp->toc.tab[track - 1].control & 4) ? 2048 : 2352;
1174 lastlba = ntohl(cdp->toc.tab[track].addr.lba);
1175 lba = bio->bio_offset / blocksize;
1176 lba += ntohl(cdp->toc.tab[track - 1].addr.lba);
1178 else {
1179 blocksize = cdp->block_size;
1180 lastlba = cdp->disk_size;
1181 lba = bio->bio_offset / blocksize;
1184 if (bp->b_bcount % blocksize != 0) {
1185 bp->b_flags |= B_ERROR;
1186 bp->b_error = EINVAL;
1187 biodone(bio);
1188 return;
1190 count = bp->b_bcount / blocksize;
1192 if (bp->b_cmd == BUF_CMD_READ) {
1193 /* if transfer goes beyond range adjust it to be within limits */
1194 if (lba + count > lastlba) {
1195 /* if we are entirely beyond EOM return EOF */
1196 if (lastlba <= lba) {
1197 bp->b_resid = bp->b_bcount;
1198 biodone(bio);
1199 return;
1201 count = lastlba - lba;
1203 switch (blocksize) {
1204 case 2048:
1205 ccb[0] = ATAPI_READ_BIG;
1206 break;
1208 case 2352:
1209 ccb[0] = ATAPI_READ_CD;
1210 ccb[9] = 0xf8;
1211 break;
1213 default:
1214 ccb[0] = ATAPI_READ_CD;
1215 ccb[9] = 0x10;
1218 else
1219 ccb[0] = ATAPI_WRITE_BIG;
1221 ccb[1] = 0;
1222 ccb[2] = lba>>24;
1223 ccb[3] = lba>>16;
1224 ccb[4] = lba>>8;
1225 ccb[5] = lba;
1226 ccb[6] = count>>16;
1227 ccb[7] = count>>8;
1228 ccb[8] = count;
1230 devstat_start_transaction(cdp->stats);
1231 bio->bio_caller_info1.ptr = cdp;
1232 atapi_queue_cmd(cdp->device, ccb, bp->b_data, count * blocksize,
1233 ((bp->b_cmd == BUF_CMD_READ) ? ATPR_F_READ : 0),
1234 (ccb[0] == ATAPI_WRITE_BIG) ? 60 : 30, acd_done, bio);
1237 static int
1238 acd_done(struct atapi_request *request)
1240 struct bio *bio = request->driver;
1241 struct buf *bp = bio->bio_buf;
1242 struct acd_softc *cdp = bio->bio_caller_info1.ptr;
1244 if (request->error) {
1245 bp->b_error = request->error;
1246 bp->b_flags |= B_ERROR;
1247 } else {
1248 bp->b_resid = bp->b_bcount - request->donecount;
1250 devstat_end_transaction_buf(cdp->stats, bp);
1251 biodone(bio);
1252 return 0;
1255 static void
1256 acd_read_toc(struct acd_softc *cdp)
1258 struct acd_devlist *entry;
1259 int track, ntracks, len;
1260 u_int32_t sizes[2];
1261 int8_t ccb[16];
1263 bzero(&cdp->toc, sizeof(cdp->toc));
1264 bzero(ccb, sizeof(ccb));
1266 if (atapi_test_ready(cdp->device) != 0)
1267 return;
1269 cdp->device->flags &= ~ATA_D_MEDIA_CHANGED;
1271 len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry);
1272 ccb[0] = ATAPI_READ_TOC;
1273 ccb[7] = len>>8;
1274 ccb[8] = len;
1275 if (atapi_queue_cmd(cdp->device, ccb, (caddr_t)&cdp->toc, len,
1276 ATPR_F_READ | ATPR_F_QUIET, 30, NULL, NULL)) {
1277 bzero(&cdp->toc, sizeof(cdp->toc));
1278 return;
1280 ntracks = cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1;
1281 if (ntracks <= 0 || ntracks > MAXTRK) {
1282 bzero(&cdp->toc, sizeof(cdp->toc));
1283 return;
1286 len = sizeof(struct ioc_toc_header)+(ntracks+1)*sizeof(struct cd_toc_entry);
1287 bzero(ccb, sizeof(ccb));
1288 ccb[0] = ATAPI_READ_TOC;
1289 ccb[7] = len>>8;
1290 ccb[8] = len;
1291 if (atapi_queue_cmd(cdp->device, ccb, (caddr_t)&cdp->toc, len,
1292 ATPR_F_READ | ATPR_F_QUIET, 30, NULL, NULL)) {
1293 bzero(&cdp->toc, sizeof(cdp->toc));
1294 return;
1296 cdp->toc.hdr.len = ntohs(cdp->toc.hdr.len);
1298 cdp->block_size = (cdp->toc.tab[0].control & 4) ? 2048 : 2352;
1299 acd_set_ioparm(cdp);
1300 bzero(ccb, sizeof(ccb));
1301 ccb[0] = ATAPI_READ_CAPACITY;
1302 if (atapi_queue_cmd(cdp->device, ccb, (caddr_t)sizes, sizeof(sizes),
1303 ATPR_F_READ | ATPR_F_QUIET, 30, NULL, NULL)) {
1304 bzero(&cdp->toc, sizeof(cdp->toc));
1305 return;
1307 cdp->disk_size = ntohl(sizes[0]) + 1;
1309 bzero(&cdp->disklabel, sizeof(struct disklabel));
1310 strncpy(cdp->disklabel.d_typename, " ",
1311 sizeof(cdp->disklabel.d_typename));
1312 strncpy(cdp->disklabel.d_typename, cdp->device->name,
1313 min(strlen(cdp->device->name),sizeof(cdp->disklabel.d_typename)-1));
1314 strncpy(cdp->disklabel.d_packname, "unknown ",
1315 sizeof(cdp->disklabel.d_packname));
1316 cdp->disklabel.d_secsize = cdp->block_size;
1317 cdp->disklabel.d_nsectors = 100;
1318 cdp->disklabel.d_ntracks = 1;
1319 cdp->disklabel.d_ncylinders = (cdp->disk_size / 100) + 1;
1320 cdp->disklabel.d_secpercyl = 100;
1321 cdp->disklabel.d_secperunit = cdp->disk_size;
1322 cdp->disklabel.d_rpm = 300;
1323 cdp->disklabel.d_interleave = 1;
1324 cdp->disklabel.d_flags = 0;
1325 cdp->disklabel.d_npartitions = 1;
1326 cdp->disklabel.d_partitions[0].p_offset = 0;
1327 cdp->disklabel.d_partitions[0].p_size = cdp->disk_size;
1328 cdp->disklabel.d_partitions[0].p_fstype = FS_BSDFFS;
1329 cdp->disklabel.d_magic = DISKMAGIC;
1330 cdp->disklabel.d_magic2 = DISKMAGIC;
1331 cdp->disklabel.d_checksum = dkcksum(&cdp->disklabel);
1333 while ((entry = TAILQ_FIRST(&cdp->dev_list))) {
1334 destroy_dev(entry->dev);
1335 TAILQ_REMOVE(&cdp->dev_list, entry, chain);
1336 kfree(entry, M_ACD);
1338 for (track = 1; track <= ntracks; track ++) {
1339 char name[16];
1341 ksprintf(name, "acd%dt%d", cdp->lun, track);
1342 entry = kmalloc(sizeof(struct acd_devlist), M_ACD, M_WAITOK | M_ZERO);
1343 entry->dev = make_dev(&acd_ops, (cdp->lun << 3) | (track << 16),
1344 0, 0, 0644, name, NULL);
1345 entry->dev->si_drv1 = cdp->dev->si_drv1;
1346 reference_dev(entry->dev);
1347 TAILQ_INSERT_TAIL(&cdp->dev_list, entry, chain);
1350 #ifdef ACD_DEBUG
1351 if (cdp->disk_size && cdp->toc.hdr.ending_track) {
1352 ata_prtdev(cdp->device, "(%d sectors (%d bytes)), %d tracks ",
1353 cdp->disk_size, cdp->block_size,
1354 cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1);
1355 if (cdp->toc.tab[0].control & 4)
1356 kprintf("%dMB\n", cdp->disk_size / 512);
1357 else
1358 kprintf("%d:%d audio\n",
1359 cdp->disk_size / 75 / 60, cdp->disk_size / 75 % 60);
1361 #endif
1364 static int
1365 acd_play(struct acd_softc *cdp, int start, int end)
1367 int8_t ccb[16];
1369 bzero(ccb, sizeof(ccb));
1370 ccb[0] = ATAPI_PLAY_MSF;
1371 lba2msf(start, &ccb[3], &ccb[4], &ccb[5]);
1372 lba2msf(end, &ccb[6], &ccb[7], &ccb[8]);
1373 return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 10, NULL, NULL);
1376 static int
1377 acd_setchan(struct acd_softc *cdp,
1378 u_int8_t c0, u_int8_t c1, u_int8_t c2, u_int8_t c3)
1380 int error;
1382 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, (caddr_t)&cdp->au,
1383 sizeof(cdp->au))))
1384 return error;
1385 if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE)
1386 return EIO;
1387 cdp->au.data_length = 0;
1388 cdp->au.port[0].channels = c0;
1389 cdp->au.port[1].channels = c1;
1390 cdp->au.port[2].channels = c2;
1391 cdp->au.port[3].channels = c3;
1392 return acd_mode_select(cdp, (caddr_t)&cdp->au, sizeof(cdp->au));
1395 static int
1396 acd_select_done1(struct atapi_request *request)
1398 struct acd_softc *cdp = request->driver;
1400 cdp->changer_info->current_slot = cdp->slot;
1401 cdp->driver[cdp->changer_info->current_slot]->timestamp = time_second;
1402 wakeup(&cdp->changer_info);
1403 return 0;
1406 static int
1407 acd_select_done(struct atapi_request *request)
1409 struct acd_softc *cdp = request->driver;
1410 int8_t ccb[16] = { ATAPI_LOAD_UNLOAD, 0, 0, 0, 3, 0, 0, 0,
1411 cdp->slot, 0, 0, 0, 0, 0, 0, 0 };
1413 /* load the wanted slot */
1414 atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_AT_HEAD, 30,
1415 acd_select_done1, cdp);
1416 return 0;
1419 static void
1420 acd_select_slot(struct acd_softc *cdp)
1422 int8_t ccb[16] = { ATAPI_LOAD_UNLOAD, 0, 0, 0, 2, 0, 0, 0,
1423 cdp->changer_info->current_slot, 0, 0, 0, 0, 0, 0, 0 };
1425 /* unload the current media from player */
1426 atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_AT_HEAD, 30,
1427 acd_select_done, cdp);
1430 static int
1431 acd_init_writer(struct acd_softc *cdp, int test_write)
1433 int8_t ccb[16];
1435 bzero(ccb, sizeof(ccb));
1436 ccb[0] = ATAPI_REZERO;
1437 atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_QUIET, 60, NULL, NULL);
1438 ccb[0] = ATAPI_SEND_OPC_INFO;
1439 ccb[1] = 0x01;
1440 atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_QUIET, 30, NULL, NULL);
1441 return 0;
1444 static int
1445 acd_fixate(struct acd_softc *cdp, int multisession)
1447 int8_t ccb[16] = { ATAPI_CLOSE_TRACK, 0x01, 0x02, 0, 0, 0, 0, 0,
1448 0, 0, 0, 0, 0, 0, 0, 0 };
1449 int timeout = 5*60*2;
1450 int error;
1451 struct write_param param;
1453 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
1454 (caddr_t)&param, sizeof(param))))
1455 return error;
1457 param.data_length = 0;
1458 if (multisession)
1459 param.session_type = CDR_SESS_MULTI;
1460 else
1461 param.session_type = CDR_SESS_NONE;
1463 if ((error = acd_mode_select(cdp, (caddr_t)&param, param.page_length + 10)))
1464 return error;
1466 error = atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
1467 if (error)
1468 return error;
1470 /* some drives just return ready, wait for the expected fixate time */
1471 if ((error = atapi_test_ready(cdp->device)) != EBUSY) {
1472 timeout = timeout / (cdp->cap.cur_write_speed / 177);
1473 tsleep(&error, 0, "acdfix", timeout * hz / 2);
1474 return atapi_test_ready(cdp->device);
1477 while (timeout-- > 0) {
1478 if ((error = atapi_test_ready(cdp->device)) != EBUSY)
1479 return error;
1480 tsleep(&error, 0, "acdcld", hz/2);
1482 return EIO;
1485 static int
1486 acd_init_track(struct acd_softc *cdp, struct cdr_track *track)
1488 struct write_param param;
1489 int error;
1491 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
1492 (caddr_t)&param, sizeof(param))))
1493 return error;
1495 param.data_length = 0;
1496 param.page_code = ATAPI_CDROM_WRITE_PARAMETERS_PAGE;
1497 param.page_length = 0x32;
1498 param.test_write = track->test_write ? 1 : 0;
1499 param.write_type = CDR_WTYPE_TRACK;
1500 param.session_type = CDR_SESS_NONE;
1501 param.fp = 0;
1502 param.packet_size = 0;
1504 if (cdp->cap.burnproof)
1505 param.burnproof = 1;
1507 switch (track->datablock_type) {
1509 case CDR_DB_RAW:
1510 if (track->preemp)
1511 param.track_mode = CDR_TMODE_AUDIO_PREEMP;
1512 else
1513 param.track_mode = CDR_TMODE_AUDIO;
1514 cdp->block_size = 2352;
1515 param.datablock_type = CDR_DB_RAW;
1516 param.session_format = CDR_SESS_CDROM;
1517 break;
1519 case CDR_DB_ROM_MODE1:
1520 cdp->block_size = 2048;
1521 param.track_mode = CDR_TMODE_DATA;
1522 param.datablock_type = CDR_DB_ROM_MODE1;
1523 param.session_format = CDR_SESS_CDROM;
1524 break;
1526 case CDR_DB_ROM_MODE2:
1527 cdp->block_size = 2336;
1528 param.track_mode = CDR_TMODE_DATA;
1529 param.datablock_type = CDR_DB_ROM_MODE2;
1530 param.session_format = CDR_SESS_CDROM;
1531 break;
1533 case CDR_DB_XA_MODE1:
1534 cdp->block_size = 2048;
1535 param.track_mode = CDR_TMODE_DATA;
1536 param.datablock_type = CDR_DB_XA_MODE1;
1537 param.session_format = CDR_SESS_CDROM_XA;
1538 break;
1540 case CDR_DB_XA_MODE2_F1:
1541 cdp->block_size = 2056;
1542 param.track_mode = CDR_TMODE_DATA;
1543 param.datablock_type = CDR_DB_XA_MODE2_F1;
1544 param.session_format = CDR_SESS_CDROM_XA;
1545 break;
1547 case CDR_DB_XA_MODE2_F2:
1548 cdp->block_size = 2324;
1549 param.track_mode = CDR_TMODE_DATA;
1550 param.datablock_type = CDR_DB_XA_MODE2_F2;
1551 param.session_format = CDR_SESS_CDROM_XA;
1552 break;
1554 case CDR_DB_XA_MODE2_MIX:
1555 cdp->block_size = 2332;
1556 param.track_mode = CDR_TMODE_DATA;
1557 param.datablock_type = CDR_DB_XA_MODE2_MIX;
1558 param.session_format = CDR_SESS_CDROM_XA;
1559 break;
1561 acd_set_ioparm(cdp);
1562 return acd_mode_select(cdp, (caddr_t)&param, param.page_length + 10);
1565 static int
1566 acd_flush(struct acd_softc *cdp)
1568 int8_t ccb[16] = { ATAPI_SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0, 0,
1569 0, 0, 0, 0, 0, 0, 0, 0 };
1571 return atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_QUIET, 60,
1572 NULL, NULL);
1575 static int
1576 acd_read_track_info(struct acd_softc *cdp,
1577 int32_t lba, struct acd_track_info *info)
1579 int8_t ccb[16] = { ATAPI_READ_TRACK_INFO, 1,
1580 lba>>24, lba>>16, lba>>8, lba,
1582 sizeof(*info)>>8, sizeof(*info),
1583 0, 0, 0, 0, 0, 0, 0 };
1584 int error;
1586 if ((error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)info, sizeof(*info),
1587 ATPR_F_READ, 30, NULL, NULL)))
1588 return error;
1589 info->track_start_addr = ntohl(info->track_start_addr);
1590 info->next_writeable_addr = ntohl(info->next_writeable_addr);
1591 info->free_blocks = ntohl(info->free_blocks);
1592 info->fixed_packet_size = ntohl(info->fixed_packet_size);
1593 info->track_length = ntohl(info->track_length);
1594 return 0;
1597 static int
1598 acd_get_progress(struct acd_softc *cdp, int *finished)
1600 int8_t ccb[16] = { ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0,
1601 0, 0, 0, 0, 0, 0, 0, 0 };
1602 struct atapi_reqsense *sense = cdp->device->result;
1603 char tmp[8];
1605 if (atapi_test_ready(cdp->device) != EBUSY) {
1606 if (atapi_queue_cmd(cdp->device, ccb, tmp, sizeof(tmp),
1607 ATPR_F_READ, 30, NULL, NULL) != EBUSY) {
1608 *finished = 100;
1609 return 0;
1612 if (sense->sksv)
1613 *finished =
1614 ((sense->sk_specific2 | (sense->sk_specific1 << 8)) * 100) / 65535;
1615 else
1616 *finished = 0;
1617 return 0;
1620 static int
1621 acd_send_cue(struct acd_softc *cdp, struct cdr_cuesheet *cuesheet)
1623 struct write_param param;
1624 int8_t ccb[16] = { ATAPI_SEND_CUE_SHEET, 0, 0, 0, 0, 0,
1625 cuesheet->len>>16, cuesheet->len>>8, cuesheet->len,
1626 0, 0, 0, 0, 0, 0, 0 };
1627 int8_t *buffer;
1628 int32_t error;
1629 #ifdef ACD_DEBUG
1630 int i;
1631 #endif
1633 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
1634 (caddr_t)&param, sizeof(param))))
1635 return error;
1636 param.data_length = 0;
1637 param.page_code = ATAPI_CDROM_WRITE_PARAMETERS_PAGE;
1638 param.page_length = 0x32;
1639 param.test_write = cuesheet->test_write ? 1 : 0;
1640 param.write_type = CDR_WTYPE_SESSION;
1641 param.session_type = cuesheet->session_type;
1642 param.fp = 0;
1643 param.packet_size = 0;
1644 param.track_mode = CDR_TMODE_AUDIO;
1645 param.datablock_type = CDR_DB_RAW;
1646 param.session_format = cuesheet->session_format;
1647 if (cdp->cap.burnproof)
1648 param.burnproof = 1;
1649 if ((error = acd_mode_select(cdp, (caddr_t)&param, param.page_length + 10)))
1650 return error;
1652 buffer = kmalloc(cuesheet->len, M_ACD, M_WAITOK);
1653 if (!buffer)
1654 return ENOMEM;
1655 if ((error = copyin(cuesheet->entries, buffer, cuesheet->len)))
1656 return error;
1657 #ifdef ACD_DEBUG
1658 kprintf("acd: cuesheet lenght = %d\n", cuesheet->len);
1659 for (i=0; i<cuesheet->len; i++)
1660 if (i%8)
1661 kprintf(" %02x", buffer[i]);
1662 else
1663 kprintf("\n%02x", buffer[i]);
1664 kprintf("\n");
1665 #endif
1666 error = atapi_queue_cmd(cdp->device, ccb, buffer, cuesheet->len, 0,
1667 30, NULL, NULL);
1668 kfree(buffer, M_ACD);
1669 return error;
1672 static int
1673 acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
1675 struct dvd_miscauth *d;
1676 u_int32_t lba = 0;
1677 int16_t length;
1678 int8_t ccb[16];
1679 int error;
1681 /* this is common even for ai->format == DVD_INVALIDATE_AGID */
1682 bzero(ccb, sizeof(ccb));
1683 ccb[0] = ATAPI_REPORT_KEY;
1684 ccb[2] = (lba >> 24) & 0xff;
1685 ccb[3] = (lba >> 16) & 0xff;
1686 ccb[4] = (lba >> 8) & 0xff;
1687 ccb[5] = lba & 0xff;
1688 ccb[10] = (ai->agid << 6) | ai->format;
1690 switch (ai->format) {
1691 case DVD_REPORT_AGID:
1692 case DVD_REPORT_ASF:
1693 case DVD_REPORT_RPC:
1694 length = 8;
1695 break;
1696 case DVD_REPORT_KEY1:
1697 length = 12;
1698 break;
1699 case DVD_REPORT_TITLE_KEY:
1700 length = 12;
1701 lba = ai->lba;
1702 break;
1703 case DVD_REPORT_CHALLENGE:
1704 length = 16;
1705 break;
1706 case DVD_INVALIDATE_AGID:
1707 return(atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 10, NULL, NULL));
1708 default:
1709 return EINVAL;
1712 ccb[8] = (length >> 8) & 0xff;
1713 ccb[9] = length & 0xff;
1715 d = kmalloc(length, M_ACD, M_WAITOK | M_ZERO);
1716 d->length = htons(length - 2);
1718 error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)d, length,
1719 ATPR_F_READ, 10, NULL, NULL);
1720 if (error) {
1721 kfree(d, M_ACD);
1722 return(error);
1725 switch (ai->format) {
1726 case DVD_REPORT_AGID:
1727 ai->agid = d->data[3] >> 6;
1728 break;
1730 case DVD_REPORT_CHALLENGE:
1731 bcopy(&d->data[0], &ai->keychal[0], 10);
1732 break;
1734 case DVD_REPORT_KEY1:
1735 bcopy(&d->data[0], &ai->keychal[0], 5);
1736 break;
1738 case DVD_REPORT_TITLE_KEY:
1739 ai->cpm = (d->data[0] >> 7);
1740 ai->cp_sec = (d->data[0] >> 6) & 0x1;
1741 ai->cgms = (d->data[0] >> 4) & 0x3;
1742 bcopy(&d->data[1], &ai->keychal[0], 5);
1743 break;
1745 case DVD_REPORT_ASF:
1746 ai->asf = d->data[3] & 1;
1747 break;
1749 case DVD_REPORT_RPC:
1750 ai->reg_type = (d->data[0] >> 6);
1751 ai->vend_rsts = (d->data[0] >> 3) & 0x7;
1752 ai->user_rsts = d->data[0] & 0x7;
1753 ai->region = d->data[1];
1754 ai->rpc_scheme = d->data[2];
1755 break;
1757 case DVD_INVALIDATE_AGID:
1758 /* not reached */
1759 break;
1761 default:
1762 error = EINVAL;
1764 kfree(d, M_ACD);
1765 return error;
1768 static int
1769 acd_send_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
1771 struct dvd_miscauth *d;
1772 int16_t length;
1773 int8_t ccb[16];
1774 int error;
1776 switch (ai->format) {
1777 case DVD_SEND_CHALLENGE:
1778 length = 16;
1779 d = kmalloc(length, M_ACD, M_WAITOK | M_ZERO);
1780 bcopy(ai->keychal, &d->data[0], 10);
1781 break;
1783 case DVD_SEND_KEY2:
1784 length = 12;
1785 d = kmalloc(length, M_ACD, M_WAITOK | M_ZERO);
1786 bcopy(&ai->keychal[0], &d->data[0], 5);
1787 break;
1789 case DVD_SEND_RPC:
1790 length = 8;
1791 d = kmalloc(length, M_ACD, M_WAITOK | M_ZERO);
1792 d->data[0] = ai->region;
1793 break;
1795 default:
1796 return EINVAL;
1799 bzero(ccb, sizeof(ccb));
1800 ccb[0] = ATAPI_SEND_KEY;
1801 ccb[8] = (length >> 8) & 0xff;
1802 ccb[9] = length & 0xff;
1803 ccb[10] = (ai->agid << 6) | ai->format;
1804 d->length = htons(length - 2);
1805 error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)d, length, 0,
1806 10, NULL, NULL);
1807 kfree(d, M_ACD);
1808 return error;
1811 static int
1812 acd_read_structure(struct acd_softc *cdp, struct dvd_struct *s)
1814 struct dvd_miscauth *d;
1815 u_int16_t length;
1816 int8_t ccb[16];
1817 int error = 0;
1819 switch(s->format) {
1820 case DVD_STRUCT_PHYSICAL:
1821 length = 21;
1822 break;
1824 case DVD_STRUCT_COPYRIGHT:
1825 length = 8;
1826 break;
1828 case DVD_STRUCT_DISCKEY:
1829 length = 2052;
1830 break;
1832 case DVD_STRUCT_BCA:
1833 length = 192;
1834 break;
1836 case DVD_STRUCT_MANUFACT:
1837 length = 2052;
1838 break;
1840 case DVD_STRUCT_DDS:
1841 case DVD_STRUCT_PRERECORDED:
1842 case DVD_STRUCT_UNIQUEID:
1843 case DVD_STRUCT_LIST:
1844 case DVD_STRUCT_CMI:
1845 case DVD_STRUCT_RMD_LAST:
1846 case DVD_STRUCT_RMD_RMA:
1847 case DVD_STRUCT_DCB:
1848 return ENOSYS;
1850 default:
1851 return EINVAL;
1854 d = kmalloc(length, M_ACD, M_WAITOK | M_ZERO);
1855 d->length = htons(length - 2);
1857 bzero(ccb, sizeof(ccb));
1858 ccb[0] = ATAPI_READ_STRUCTURE;
1859 ccb[6] = s->layer_num;
1860 ccb[7] = s->format;
1861 ccb[8] = (length >> 8) & 0xff;
1862 ccb[9] = length & 0xff;
1863 ccb[10] = s->agid << 6;
1864 error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)d, length, ATPR_F_READ,
1865 30, NULL, NULL);
1866 if (error) {
1867 kfree(d, M_ACD);
1868 return error;
1871 switch (s->format) {
1872 case DVD_STRUCT_PHYSICAL: {
1873 struct dvd_layer *layer = (struct dvd_layer *)&s->data[0];
1875 layer->book_type = d->data[0] >> 4;
1876 layer->book_version = d->data[0] & 0xf;
1877 layer->disc_size = d->data[1] >> 4;
1878 layer->max_rate = d->data[1] & 0xf;
1879 layer->nlayers = (d->data[2] >> 5) & 3;
1880 layer->track_path = (d->data[2] >> 4) & 1;
1881 layer->layer_type = d->data[2] & 0xf;
1882 layer->linear_density = d->data[3] >> 4;
1883 layer->track_density = d->data[3] & 0xf;
1884 layer->start_sector = d->data[5] << 16 | d->data[6] << 8 | d->data[7];
1885 layer->end_sector = d->data[9] << 16 | d->data[10] << 8 | d->data[11];
1886 layer->end_sector_l0 = d->data[13] << 16 | d->data[14] << 8|d->data[15];
1887 layer->bca = d->data[16] >> 7;
1888 break;
1891 case DVD_STRUCT_COPYRIGHT:
1892 s->cpst = d->data[0];
1893 s->rmi = d->data[0];
1894 break;
1896 case DVD_STRUCT_DISCKEY:
1897 bcopy(&d->data[0], &s->data[0], 2048);
1898 break;
1900 case DVD_STRUCT_BCA:
1901 s->length = ntohs(d->length);
1902 bcopy(&d->data[0], &s->data[0], s->length);
1903 break;
1905 case DVD_STRUCT_MANUFACT:
1906 s->length = ntohs(d->length);
1907 bcopy(&d->data[0], &s->data[0], s->length);
1908 break;
1910 default:
1911 error = EINVAL;
1913 kfree(d, M_ACD);
1914 return error;
1917 static int
1918 acd_eject(struct acd_softc *cdp, int close)
1920 int error;
1922 if ((error = acd_start_stop(cdp, 0)) == EBUSY) {
1923 if (!close)
1924 return 0;
1925 if ((error = acd_start_stop(cdp, 3)))
1926 return error;
1927 acd_read_toc(cdp);
1928 acd_prevent_allow(cdp, 1);
1929 cdp->flags |= F_LOCKED;
1930 return 0;
1932 if (error)
1933 return error;
1934 if (close)
1935 return 0;
1936 acd_prevent_allow(cdp, 0);
1937 cdp->flags &= ~F_LOCKED;
1938 cdp->device->flags |= ATA_D_MEDIA_CHANGED;
1939 return acd_start_stop(cdp, 2);
1942 static int
1943 acd_blank(struct acd_softc *cdp, int blanktype)
1945 int8_t ccb[16] = { ATAPI_BLANK, 0x10 | (blanktype & 0x7), 0, 0, 0, 0, 0, 0,
1946 0, 0, 0, 0, 0, 0, 0, 0 };
1948 cdp->device->flags |= ATA_D_MEDIA_CHANGED;
1949 return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
1952 static int
1953 acd_prevent_allow(struct acd_softc *cdp, int lock)
1955 int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
1956 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1958 return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
1961 static int
1962 acd_start_stop(struct acd_softc *cdp, int start)
1964 int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
1965 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1967 return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
1970 static int
1971 acd_pause_resume(struct acd_softc *cdp, int pause)
1973 int8_t ccb[16] = { ATAPI_PAUSE, 0, 0, 0, 0, 0, 0, 0, pause,
1974 0, 0, 0, 0, 0, 0, 0 };
1976 return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
1979 static int
1980 acd_mode_sense(struct acd_softc *cdp, int page, caddr_t pagebuf, int pagesize)
1982 int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, page, 0, 0, 0, 0,
1983 pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 };
1984 int error;
1986 error = atapi_queue_cmd(cdp->device, ccb, pagebuf, pagesize, ATPR_F_READ,
1987 10, NULL, NULL);
1988 #ifdef ACD_DEBUG
1989 atapi_dump("acd: mode sense ", pagebuf, pagesize);
1990 #endif
1991 return error;
1994 static int
1995 acd_mode_select(struct acd_softc *cdp, caddr_t pagebuf, int pagesize)
1997 int8_t ccb[16] = { ATAPI_MODE_SELECT_BIG, 0x10, 0, 0, 0, 0, 0,
1998 pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 };
2000 #ifdef ACD_DEBUG
2001 ata_prtdev(cdp->device,
2002 "modeselect pagesize=%d\n", pagesize);
2003 atapi_dump("mode select ", pagebuf, pagesize);
2004 #endif
2005 return atapi_queue_cmd(cdp->device, ccb, pagebuf, pagesize, 0,
2006 30, NULL, NULL);
2009 static int
2010 acd_set_speed(struct acd_softc *cdp, int rdspeed, int wrspeed)
2012 int8_t ccb[16] = { ATAPI_SET_SPEED, 0, rdspeed >> 8, rdspeed,
2013 wrspeed >> 8, wrspeed, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2014 int error;
2016 error = atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
2017 if (!error)
2018 acd_get_cap(cdp);
2019 return error;
2022 static void
2023 acd_get_cap(struct acd_softc *cdp)
2025 int retry = 5;
2027 /* get drive capabilities, some drives needs this repeated */
2028 while (retry-- && acd_mode_sense(cdp, ATAPI_CDROM_CAP_PAGE,
2029 (caddr_t)&cdp->cap, sizeof(cdp->cap)))
2031 cdp->cap.max_read_speed = ntohs(cdp->cap.max_read_speed);
2032 cdp->cap.cur_read_speed = ntohs(cdp->cap.cur_read_speed);
2033 cdp->cap.max_write_speed = ntohs(cdp->cap.max_write_speed);
2034 cdp->cap.cur_write_speed = max(ntohs(cdp->cap.cur_write_speed), 177);
2035 cdp->cap.max_vol_levels = ntohs(cdp->cap.max_vol_levels);
2036 cdp->cap.buf_size = ntohs(cdp->cap.buf_size);