2 * Copyright (c) 1998,1999,2000 Søren Schmidt
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
35 #include <sys/malloc.h>
38 #include <sys/disklabel.h>
39 #include <sys/devicestat.h>
41 #include <sys/cdrio.h>
42 #include <sys/dvdio.h>
43 #include <sys/fcntl.h>
46 #include <dev/ata/ata-all.h>
47 #include <dev/ata/atapi-all.h>
48 #include <dev/ata/atapi-cd.h>
50 /* device structures */
51 static d_open_t acdopen;
52 static d_close_t acdclose;
53 static d_ioctl_t acdioctl;
54 static d_strategy_t acdstrategy;
55 static struct cdevsw acd_cdevsw = {
59 /* write */ physwrite,
63 /* strategy */ acdstrategy,
68 /* flags */ D_DISK | D_TRACKCLOSE,
73 static struct acd_softc *acd_init_lun(struct atapi_softc *, struct devstat *);
74 static void acd_make_dev(struct acd_softc *);
75 static void acd_describe(struct acd_softc *);
76 static void lba2msf(int32_t, u_int8_t *, u_int8_t *, u_int8_t *);
77 static int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t);
78 static int32_t acd_done(struct atapi_request *);
79 static void acd_read_toc(struct acd_softc *);
80 static void acd_construct_label(struct acd_softc *);
81 static int32_t acd_setchan(struct acd_softc *, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
82 static void acd_select_slot(struct acd_softc *);
83 static int32_t acd_open_track(struct acd_softc *, struct cdr_track *);
84 static int32_t acd_close_track(struct acd_softc *);
85 static int32_t acd_close_disk(struct acd_softc *);
86 static int32_t acd_read_track_info(struct acd_softc *, int32_t, struct acd_track_info*);
87 static int acd_report_key(struct acd_softc *, struct dvd_authinfo *);
88 static int acd_send_key(struct acd_softc *, struct dvd_authinfo *);
89 static int acd_read_structure(struct acd_softc *, struct dvd_struct *);
90 static int32_t acd_eject(struct acd_softc *, int32_t);
91 static int32_t acd_blank(struct acd_softc *);
92 static int32_t acd_prevent_allow(struct acd_softc *, int32_t);
93 static int32_t acd_start_stop(struct acd_softc *, int32_t);
94 static int32_t acd_pause_resume(struct acd_softc *, int32_t);
95 static int32_t acd_mode_sense(struct acd_softc *, u_int8_t, void *, int32_t);
96 static int32_t acd_mode_select(struct acd_softc *, void *, int32_t);
97 static int32_t acd_set_speed(struct acd_softc *cdp, int32_t);
100 static u_int32_t acd_lun_map = 0;
101 MALLOC_DEFINE(M_ACD, "ACD driver", "ATAPI CD driver buffers");
104 acdattach(struct atapi_softc *atp)
106 struct acd_softc *cdp;
108 int32_t count, error = 0;
109 static int32_t acd_cdev_done = 0;
111 if (!acd_cdev_done) {
112 cdevsw_add(&acd_cdevsw);
116 if ((cdp = acd_init_lun(atp, NULL)) == NULL) {
117 printf("acd: out of memory\n");
121 /* get drive capabilities, some drives needs this repeated */
122 for (count = 0 ; count < 5 ; count++) {
123 if (!(error = acd_mode_sense(cdp, ATAPI_CDROM_CAP_PAGE,
124 &cdp->cap, sizeof(cdp->cap))))
131 cdp->cap.max_read_speed = ntohs(cdp->cap.max_read_speed);
132 cdp->cap.cur_read_speed = ntohs(cdp->cap.cur_read_speed);
133 cdp->cap.max_write_speed = ntohs(cdp->cap.max_write_speed);
134 cdp->cap.cur_write_speed = ntohs(cdp->cap.cur_write_speed);
135 cdp->cap.max_vol_levels = ntohs(cdp->cap.max_vol_levels);
136 cdp->cap.buf_size = ntohs(cdp->cap.buf_size);
138 /* if this is a changer device, allocate the neeeded lun's */
139 if (cdp->cap.mech == MST_MECH_CHANGER) {
140 int8_t ccb[16] = { ATAPI_MECH_STATUS,
142 sizeof(struct changer)>>8, sizeof(struct changer),
145 chp = malloc(sizeof(struct changer), M_ACD, M_NOWAIT);
147 printf("acd: out of memory\n");
150 bzero(chp, sizeof(struct changer));
151 error = atapi_queue_cmd(cdp->atp, ccb, chp, sizeof(struct changer),
152 ATPR_F_READ, 60, NULL, NULL);
155 struct acd_softc *tmpcdp = cdp;
156 struct acd_softc **cdparr;
160 chp->table_length = htons(chp->table_length);
161 if (!(cdparr = malloc(sizeof(struct acd_softc) * chp->slots,
163 printf("acd: out of memory\n");
166 for (count = 0; count < chp->slots; count++) {
168 tmpcdp = acd_init_lun(atp, cdp->stats);
170 printf("acd: out of memory\n");
174 cdparr[count] = tmpcdp;
175 tmpcdp->driver = cdparr;
176 tmpcdp->slot = count;
177 tmpcdp->changer_info = chp;
179 printf("acd%d: changer slot %d %s\n", tmpcdp->lun, count,
180 (chp->slot[count].present ? "CD present" : "empty"));
181 acd_make_dev(tmpcdp);
183 sprintf(string, "acd%d-%d", cdp->lun,
184 cdp->lun + cdp->changer_info->slots - 1);
185 devstat_add_entry(cdp->stats, string, tmpcdp->lun, DEV_BSIZE,
186 DEVSTAT_NO_ORDERED_TAGS,
187 DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE,
188 DEVSTAT_PRIORITY_CD);
189 if ((cdp->atp->devname = malloc(8, M_ACD, M_NOWAIT)))
190 sprintf(cdp->atp->devname, "acd%d-%d", cdp->lun,
191 cdp->lun + cdp->changer_info->slots - 1);
196 devstat_add_entry(cdp->stats, "acd", cdp->lun, DEV_BSIZE,
197 DEVSTAT_NO_ORDERED_TAGS,
198 DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE,
199 DEVSTAT_PRIORITY_CD);
200 if ((cdp->atp->devname = malloc(8, M_ACD, M_NOWAIT)))
201 sprintf(cdp->atp->devname, "acd%d", cdp->lun);
203 cdp->atp->driver = cdp;
209 acddetach(struct atapi_softc *atp)
211 struct acd_softc *cdp = atp->driver;
213 destroy_dev(cdp->dev1);
214 destroy_dev(cdp->dev2);
215 if (cdp->changer_info) {
216 /* should free all cdp's here, not possible yet SOS XXX */
217 free(cdp->changer_info, M_ACD);
219 devstat_remove_entry(cdp->stats);
220 free(cdp->stats, M_ACD);
221 free(cdp->atp->devname, M_ACD);
222 ata_free_lun(&acd_lun_map, cdp->lun);
226 static struct acd_softc *
227 acd_init_lun(struct atapi_softc *atp, struct devstat *stats)
229 struct acd_softc *cdp;
231 if (!(cdp = malloc(sizeof(struct acd_softc), M_ACD, M_NOWAIT)))
233 bzero(cdp, sizeof(struct acd_softc));
234 bufq_init(&cdp->buf_queue);
236 cdp->lun = ata_get_lun(&acd_lun_map);
237 cdp->flags &= ~(F_WRITTEN|F_DISK_OPEN|F_TRACK_OPEN);
238 cdp->block_size = 2048;
240 cdp->changer_info = NULL;
242 if (!(cdp->stats = malloc(sizeof(struct devstat), M_ACD, M_NOWAIT))) {
246 bzero(cdp->stats, sizeof(struct devstat));
254 acd_make_dev(struct acd_softc *cdp)
258 dev = make_dev(&acd_cdevsw, dkmakeminor(cdp->lun, 0, 0),
259 UID_ROOT, GID_OPERATOR, 0644, "acd%da", cdp->lun);
261 dev->si_iosize_max = 252 * DEV_BSIZE;
262 dev->si_bsize_phys = 2048; /* XXX SOS */
264 dev = make_dev(&acd_cdevsw, dkmakeminor(cdp->lun, 0, RAW_PART),
265 UID_ROOT, GID_OPERATOR, 0644, "acd%dc", cdp->lun);
267 dev->si_iosize_max = 252 * DEV_BSIZE;
268 dev->si_bsize_phys = 2048; /* XXX SOS */
270 cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED;
274 acd_describe(struct acd_softc *cdp)
280 printf("acd%d: <%.40s/%.8s> %s drive at ata%d as %s\n",
281 cdp->lun, ATA_PARAM(cdp->atp->controller, cdp->atp->unit)->model,
282 ATA_PARAM(cdp->atp->controller, cdp->atp->unit)->revision,
283 (cdp->cap.write_dvdr) ? "DVD-R" :
284 (cdp->cap.write_dvdram) ? "DVD-RAM" :
285 (cdp->cap.write_cdrw) ? "CD-RW" :
286 (cdp->cap.write_cdr) ? "CD-R" :
287 (cdp->cap.read_dvdrom) ? "DVD-ROM" : "CDROM",
288 device_get_unit(cdp->atp->controller->dev),
289 (cdp->atp->unit == ATA_MASTER) ? "master" : "slave");
291 printf("acd%d:", cdp->lun);
292 if (cdp->cap.cur_read_speed) {
293 printf(" read %dKB/s", cdp->cap.cur_read_speed * 1000 / 1024);
294 if (cdp->cap.max_read_speed)
295 printf(" (%dKB/s)", cdp->cap.max_read_speed * 1000 / 1024);
296 if ((cdp->cap.cur_write_speed) &&
297 (cdp->cap.write_cdr || cdp->cap.write_cdrw ||
298 cdp->cap.write_dvdr || cdp->cap.write_dvdram)) {
299 printf(" write %dKB/s", cdp->cap.cur_write_speed * 1000 / 1024);
300 if (cdp->cap.max_write_speed)
301 printf(" (%dKB/s)", cdp->cap.max_write_speed * 1000 / 1024);
305 if (cdp->cap.buf_size) {
306 printf("%s %dKB buffer", comma ? "," : "", cdp->cap.buf_size);
310 comma ? "," : "", ata_mode2str(
311 cdp->atp->controller->mode[ATA_DEV(cdp->atp->unit)]));
313 printf("acd%d: Reads:", cdp->lun);
315 if (cdp->cap.read_cdr) {
316 printf(" CD-R"); comma = 1;
318 if (cdp->cap.read_cdrw) {
319 printf("%s CD-RW", comma ? "," : ""); comma = 1;
321 if (cdp->cap.cd_da) {
322 if (cdp->cap.cd_da_stream)
323 printf("%s CD-DA stream", comma ? "," : "");
325 printf("%s CD-DA", comma ? "," : "");
328 if (cdp->cap.read_dvdrom) {
329 printf("%s DVD-ROM", comma ? "," : ""); comma = 1;
331 if (cdp->cap.read_dvdr) {
332 printf("%s DVD-R", comma ? "," : ""); comma = 1;
334 if (cdp->cap.read_dvdram) {
335 printf("%s DVD-RAM", comma ? "," : ""); comma = 1;
337 if (cdp->cap.read_packet)
338 printf("%s packet", comma ? "," : "");
340 if (cdp->cap.write_cdr || cdp->cap.write_cdrw ||
341 cdp->cap.write_dvdr || cdp->cap.write_dvdram) {
342 printf("\nacd%d: Writes:", cdp->lun);
344 if (cdp->cap.write_cdr) {
345 printf(" CD-R" ); comma = 1;
347 if (cdp->cap.write_cdrw) {
348 printf("%s CD-RW", comma ? "," : ""); comma = 1;
350 if (cdp->cap.write_dvdr) {
351 printf("%s DVD-R", comma ? "," : ""); comma = 1;
353 if (cdp->cap.write_dvdram) {
354 printf("%s DVD-RAM", comma ? "," : ""); comma = 1;
356 if (cdp->cap.test_write)
357 printf("%s test write", comma ? "," : "");
359 if (cdp->cap.audio_play) {
360 printf("\nacd%d: Audio: ", cdp->lun);
361 if (cdp->cap.audio_play)
363 if (cdp->cap.max_vol_levels)
364 printf(", %d volume levels", cdp->cap.max_vol_levels);
366 printf("\nacd%d: Mechanism: ", cdp->lun);
367 switch (cdp->cap.mech) {
369 mechanism = "caddy"; break;
371 mechanism = "tray"; break;
373 mechanism = "popup"; break;
374 case MST_MECH_CHANGER:
375 mechanism = "changer"; break;
376 case MST_MECH_CARTRIDGE:
377 mechanism = "cartridge"; break;
379 mechanism = 0; break;
382 printf("%s%s", cdp->cap.eject ? "ejectable " : "", mechanism);
383 else if (cdp->cap.eject)
386 if (cdp->cap.mech != MST_MECH_CHANGER) {
387 printf("\nacd%d: Medium: ", cdp->lun);
388 switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
390 printf("CD-ROM "); break;
392 printf("CD-R "); break;
394 printf("CD-RW "); break;
396 printf("door open"); break;
398 printf("no/blank disc inside"); break;
400 printf("medium format error"); break;
402 if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH)<MST_TYPE_MASK_HIGH){
403 switch (cdp->cap.medium_type & MST_TYPE_MASK_LOW) {
405 printf("120mm data disc loaded"); break;
407 printf("120mm audio disc loaded"); break;
409 printf("120mm data/audio disc loaded"); break;
411 printf("120mm photo disc loaded"); break;
413 printf("80mm data disc loaded"); break;
415 printf("80mm audio disc loaded"); break;
417 printf("80mm data/audio disc loaded"); break;
419 printf("80mm photo disc loaded"); break;
421 switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
423 printf("unknown medium"); break;
426 printf("blank medium"); break;
430 printf("unknown type=0x%x", cdp->cap.medium_type); break;
435 printf(cdp->cap.locked ? ", locked" : ", unlocked");
436 if (cdp->cap.prevent)
437 printf(", lock protected");
444 bzero(changer, sizeof(changer));
445 if (cdp->changer_info) {
446 sprintf(devnum, "%d-%d",
447 cdp->lun, cdp->lun + cdp->changer_info->slots - 1);
448 sprintf(changer, " with %d CD changer", cdp->changer_info->slots);
451 sprintf(devnum, "%d", cdp->lun);
453 printf("acd%s: %s%s <%.40s> at ata%d-%s using %s\n",
454 devnum, (cdp->cap.write_dvdr) ? "DVD-R" :
455 (cdp->cap.write_dvdram) ? "DVD-RAM" :
456 (cdp->cap.write_cdrw) ? "CD-RW" :
457 (cdp->cap.write_cdr) ? "CD-R" :
458 (cdp->cap.read_dvdrom) ? "DVD-ROM" : "CDROM",
459 changer, ATA_PARAM(cdp->atp->controller, cdp->atp->unit)->model,
460 device_get_unit(cdp->atp->controller->dev),
461 (cdp->atp->unit == ATA_MASTER) ? "master" : "slave",
462 ata_mode2str(cdp->atp->controller->mode[ATA_DEV(cdp->atp->unit)])
468 lba2msf(int32_t lba, u_int8_t *m, u_int8_t *s, u_int8_t *f)
472 *m = lba / (60 * 75);
478 static __inline int32_t
479 msf2lba(u_int8_t m, u_int8_t s, u_int8_t f)
481 return (m * 60 + s) * 75 + f - 150;
485 acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
487 struct acd_softc *cdp = dev->si_drv1;
492 if (flags & FWRITE) {
493 if (count_dev(dev) > 1)
496 if (count_dev(dev) == 1) {
497 if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
498 acd_select_slot(cdp);
499 tsleep(&cdp->changer_info, PRIBIO, "acdopn", 0);
501 acd_prevent_allow(cdp, 1);
502 cdp->flags |= F_LOCKED;
503 if (!(flags & O_NONBLOCK) && !(flags & FWRITE))
506 atapi_test_ready(cdp->atp);
508 acd_construct_label(cdp);
513 acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
515 struct acd_softc *cdp = dev->si_drv1;
517 if (count_dev(dev) == 1) {
518 if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
519 acd_select_slot(cdp);
520 tsleep(&cdp->changer_info, PRIBIO, "acdclo", 0);
522 acd_prevent_allow(cdp, 0);
524 cdp->flags &= ~F_LOCKED;
529 acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flags, struct proc *p)
531 struct acd_softc *cdp = dev->si_drv1;
534 if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
535 acd_select_slot(cdp);
536 tsleep(&cdp->changer_info, PRIBIO, "acdctl", 0);
538 if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED)
541 atapi_test_ready(cdp->atp);
546 acd_prevent_allow(cdp, 1);
547 cdp->flags |= F_LOCKED;
553 error = acd_pause_resume(cdp, 1);
557 error = acd_pause_resume(cdp, 0);
561 error = acd_start_stop(cdp, 1);
565 error = acd_start_stop(cdp, 0);
569 cdp->flags &= ~F_LOCKED;
570 error = acd_prevent_allow(cdp, 0);
574 cdp->flags |= F_LOCKED;
575 error = acd_prevent_allow(cdp, 1);
582 error = atapi_test_ready(cdp->atp);
586 if (count_dev(dev) > 1) {
590 error = acd_eject(cdp, 0);
594 if (count_dev(dev) > 1)
596 error = acd_eject(cdp, 1);
599 case CDIOREADTOCHEADER:
600 if (!cdp->toc.hdr.ending_track) {
604 bcopy(&cdp->toc.hdr, addr, sizeof(cdp->toc.hdr));
607 case CDIOREADTOCENTRYS:
609 struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)addr;
610 struct toc *toc = &cdp->toc;
613 u_int8_t starting_track = te->starting_track;
615 if (!cdp->toc.hdr.ending_track) {
620 if (te->data_len < sizeof(toc->tab[0]) ||
621 (te->data_len % sizeof(toc->tab[0])) != 0 ||
622 (te->address_format != CD_MSF_FORMAT &&
623 te->address_format != CD_LBA_FORMAT)) {
629 starting_track = toc->hdr.starting_track;
630 else if (starting_track == 170)
631 starting_track = toc->hdr.ending_track + 1;
632 else if (starting_track < toc->hdr.starting_track ||
633 starting_track > toc->hdr.ending_track + 1) {
638 len = ((toc->hdr.ending_track + 1 - starting_track) + 1) *
640 if (te->data_len < len)
642 if (len > sizeof(toc->tab)) {
647 if (te->address_format == CD_MSF_FORMAT) {
648 struct cd_toc_entry *entry;
652 entry = toc->tab + (toc->hdr.ending_track + 1 -
653 toc->hdr.starting_track) + 1;
654 while (--entry >= toc->tab)
655 lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute,
656 &entry->addr.msf.second, &entry->addr.msf.frame);
658 error = copyout(toc->tab + starting_track - toc->hdr.starting_track,
662 case CDIOREADTOCENTRY:
664 struct ioc_read_toc_single_entry *te =
665 (struct ioc_read_toc_single_entry *)addr;
666 struct toc *toc = &cdp->toc;
668 u_int8_t track = te->track;
670 if (!cdp->toc.hdr.ending_track) {
675 if (te->address_format != CD_MSF_FORMAT &&
676 te->address_format != CD_LBA_FORMAT) {
682 track = toc->hdr.starting_track;
683 else if (track == 170)
684 track = toc->hdr.ending_track + 1;
685 else if (track < toc->hdr.starting_track ||
686 track > toc->hdr.ending_track + 1) {
691 if (te->address_format == CD_MSF_FORMAT) {
692 struct cd_toc_entry *entry;
696 entry = toc->tab + (track - toc->hdr.starting_track);
697 lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute,
698 &entry->addr.msf.second, &entry->addr.msf.frame);
700 bcopy(toc->tab + track - toc->hdr.starting_track,
701 &te->entry, sizeof(struct cd_toc_entry));
705 case CDIOCREADSUBCHANNEL:
707 struct ioc_read_subchannel *args =
708 (struct ioc_read_subchannel *)addr;
709 struct cd_sub_channel_info data;
710 u_int32_t len = args->data_len;
711 int32_t abslba, rellba;
712 int8_t ccb[16] = { ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, 0, 0,
713 sizeof(cdp->subchan)>>8, sizeof(cdp->subchan),
714 0, 0, 0, 0, 0, 0, 0 };
716 if (len > sizeof(data) ||
717 len < sizeof(struct cd_sub_channel_header)) {
722 if ((error = atapi_queue_cmd(cdp->atp, ccb, &cdp->subchan,
723 sizeof(cdp->subchan), ATPR_F_READ, 10,
727 abslba = cdp->subchan.abslba;
728 rellba = cdp->subchan.rellba;
729 if (args->address_format == CD_MSF_FORMAT) {
730 lba2msf(ntohl(abslba),
731 &data.what.position.absaddr.msf.minute,
732 &data.what.position.absaddr.msf.second,
733 &data.what.position.absaddr.msf.frame);
734 lba2msf(ntohl(rellba),
735 &data.what.position.reladdr.msf.minute,
736 &data.what.position.reladdr.msf.second,
737 &data.what.position.reladdr.msf.frame);
739 data.what.position.absaddr.lba = abslba;
740 data.what.position.reladdr.lba = rellba;
742 data.header.audio_status = cdp->subchan.audio_status;
743 data.what.position.control = cdp->subchan.control & 0xf;
744 data.what.position.addr_type = cdp->subchan.control >> 4;
745 data.what.position.track_number = cdp->subchan.track;
746 data.what.position.index_number = cdp->subchan.indx;
747 error = copyout(&data, args->data, len);
753 struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
754 int8_t ccb[16] = { ATAPI_PLAY_MSF, 0, 0,
755 args->start_m, args->start_s, args->start_f,
756 args->end_m, args->end_s, args->end_f,
757 0, 0, 0, 0, 0, 0, 0 };
759 error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
763 case CDIOCPLAYBLOCKS:
765 struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
766 int8_t ccb[16] = { ATAPI_PLAY_BIG, 0,
767 args->blk>>24, args->blk>>16, args->blk>>8,
768 args->blk, args->len>>24, args->len>>16,
769 args->len>>8, args->len,
772 error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
776 case CDIOCPLAYTRACKS:
778 struct ioc_play_track *args = (struct ioc_play_track *)addr;
779 u_int32_t start, len;
783 if (!cdp->toc.hdr.ending_track) {
788 if (args->end_track < cdp->toc.hdr.ending_track + 1)
790 if (args->end_track > cdp->toc.hdr.ending_track + 1)
791 args->end_track = cdp->toc.hdr.ending_track + 1;
792 t1 = args->start_track - cdp->toc.hdr.starting_track;
793 t2 = args->end_track - cdp->toc.hdr.starting_track;
794 if (t1 < 0 || t2 < 0) {
798 start = ntohl(cdp->toc.tab[t1].addr.lba);
799 len = ntohl(cdp->toc.tab[t2].addr.lba) - start;
801 bzero(ccb, sizeof(ccb));
802 ccb[0] = ATAPI_PLAY_BIG;
812 error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
818 struct ioc_read_audio *args = (struct ioc_read_audio *)addr;
819 int32_t lba, frames, error = 0;
820 u_int8_t *buffer, *ubuf = args->buffer;
823 if (!cdp->toc.hdr.ending_track) {
828 if ((frames = args->nframes) < 0) {
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);
844 #ifndef CD_BUFFER_BLOCKS
845 #define CD_BUFFER_BLOCKS 13
847 if (!(buffer = malloc(CD_BUFFER_BLOCKS * 2352, M_ACD, M_NOWAIT))){
851 bzero(ccb, sizeof(ccb));
856 blocks = (frames>CD_BUFFER_BLOCKS) ? CD_BUFFER_BLOCKS : frames;
857 size = blocks * 2352;
859 ccb[0] = ATAPI_READ_CD;
867 if ((error = atapi_queue_cmd(cdp->atp, ccb, buffer, size,
868 ATPR_F_READ, 30, NULL,NULL)))
871 if ((error = copyout(buffer, ubuf, size)))
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);
890 struct ioc_vol *arg = (struct ioc_vol *)addr;
892 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE,
893 &cdp->au, sizeof(cdp->au))))
896 if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) {
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;
909 struct ioc_vol *arg = (struct ioc_vol *)addr;
911 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE,
912 &cdp->au, sizeof(cdp->au))))
914 if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) {
918 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE_MASK,
919 &cdp->aumask, sizeof(cdp->aumask))))
921 cdp->au.data_length = 0;
922 cdp->au.port[0].channels = CHANNEL_0;
923 cdp->au.port[1].channels = CHANNEL_1;
924 cdp->au.port[0].volume = arg->vol[0] & cdp->aumask.port[0].volume;
925 cdp->au.port[1].volume = arg->vol[1] & cdp->aumask.port[1].volume;
926 cdp->au.port[2].volume = arg->vol[2] & cdp->aumask.port[2].volume;
927 cdp->au.port[3].volume = arg->vol[3] & cdp->aumask.port[3].volume;
928 error = acd_mode_select(cdp, &cdp->au, sizeof(cdp->au));
933 struct ioc_patch *arg = (struct ioc_patch *)addr;
935 error = acd_setchan(cdp, arg->patch[0], arg->patch[1],
936 arg->patch[2], arg->patch[3]);
941 error = acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0,0);
945 error = acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0);
949 error = acd_setchan(cdp, 0, 0, 0, 0);
953 error = acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0);
957 error = acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0);
961 error = acd_blank(cdp);
964 case CDRIOCNEXTWRITEABLEADDR:
966 struct acd_track_info track_info;
968 if ((error = acd_read_track_info(cdp, 0xff, &track_info)))
971 if (!track_info.nwa_valid) {
975 *(int*)addr = track_info.next_writeable_addr;
980 if ((cdp->flags & F_WRITTEN) || (cdp->flags & F_DISK_OPEN)) {
982 printf("acd%d: sequence error (disk already open)\n", cdp->lun);
984 cdp->flags &= ~(F_WRITTEN | F_TRACK_OPEN);
985 cdp->flags |= F_DISK_OPEN;
988 case CDRIOCOPENTRACK:
989 if (!(cdp->flags & F_DISK_OPEN)) {
991 printf("acd%d: sequence error (disk not open)\n", cdp->lun);
994 if ((error = acd_open_track(cdp, (struct cdr_track *)addr)))
996 cdp->flags |= F_TRACK_OPEN;
1000 case CDRIOCCLOSETRACK:
1001 if (!(cdp->flags & F_TRACK_OPEN)) {
1003 printf("acd%d: sequence error (no track open)\n", cdp->lun);
1006 if (cdp->flags & F_WRITTEN) {
1007 acd_close_track(cdp);
1008 cdp->flags &= ~F_TRACK_OPEN;
1013 case CDRIOCCLOSEDISK:
1014 if (!(cdp->flags & F_DISK_OPEN)) {
1016 printf("acd%d: sequence error (nothing to close)\n", cdp->lun);
1018 else if (!(cdp->flags & F_WRITTEN)) {
1019 cdp->flags &= ~(F_DISK_OPEN | F_TRACK_OPEN);
1022 error = acd_close_disk(cdp);
1023 cdp->flags &= ~(F_WRITTEN | F_DISK_OPEN | F_TRACK_OPEN);
1027 case CDRIOCWRITESPEED:
1028 error = acd_set_speed(cdp, (*(int32_t *)addr) * 177);
1031 case CDRIOCGETBLOCKSIZE:
1032 *(int32_t *)addr = cdp->block_size;
1035 case CDRIOCSETBLOCKSIZE:
1036 cdp->block_size = *(int32_t *)addr;
1039 case DVDIOCREPORTKEY:
1040 if (!cdp->cap.read_dvdrom)
1043 error = acd_report_key(cdp, (struct dvd_authinfo *)addr);
1047 if (!cdp->cap.read_dvdrom)
1050 error = acd_send_key(cdp, (struct dvd_authinfo *)addr);
1053 case DVDIOCREADSTRUCTURE:
1054 if (!cdp->cap.read_dvdrom)
1057 error = acd_read_structure(cdp, (struct dvd_struct *)addr);
1061 *(struct disklabel *)addr = cdp->disklabel;
1066 if ((flags & FWRITE) == 0)
1069 error = setdisklabel(&cdp->disklabel, (struct disklabel *)addr, 0);
1077 ((struct partinfo *)addr)->disklab = &cdp->disklabel;
1078 ((struct partinfo *)addr)->part = &cdp->disklabel.d_partitions[0];
1088 acdstrategy(struct buf *bp)
1090 struct acd_softc *cdp = bp->b_dev->si_drv1;
1093 /* if it's a null transfer, return immediatly. */
1094 if (bp->b_bcount == 0) {
1100 bp->b_pblkno = bp->b_blkno;
1101 bp->b_resid = bp->b_bcount;
1104 bufqdisksort(&cdp->buf_queue, bp);
1105 ata_start(cdp->atp->controller);
1110 acd_start(struct atapi_softc *atp)
1112 struct acd_softc *cdp = atp->driver;
1113 struct buf *bp = bufq_first(&cdp->buf_queue);
1114 u_int32_t lba, count;
1117 if (cdp->changer_info) {
1120 cdp = cdp->driver[cdp->changer_info->current_slot];
1121 bp = bufq_first(&cdp->buf_queue);
1123 /* check for work pending on any other slot */
1124 for (i = 0; i < cdp->changer_info->slots; i++) {
1125 if (i == cdp->changer_info->current_slot)
1127 if (bufq_first(&(cdp->driver[i]->buf_queue))) {
1128 if (!bp || time_second > (cdp->timestamp + 10)) {
1129 acd_select_slot(cdp->driver[i]);
1137 bufq_remove(&cdp->buf_queue, bp);
1139 /* reject all queued entries if media changed */
1140 if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED) {
1142 bp->b_flags |= B_ERROR;
1147 bzero(ccb, sizeof(ccb));
1148 count = (bp->b_bcount + (cdp->block_size - 1)) / cdp->block_size;
1149 if (bp->b_flags & B_PHYS)
1150 lba = bp->b_offset / cdp->block_size;
1152 lba = bp->b_blkno / (cdp->block_size / DEV_BSIZE);
1154 if (bp->b_iocmd == BIO_READ) {
1155 /* if transfer goes beyond EOM adjust it to be within limits */
1156 if (lba + count > cdp->info.volsize) {
1157 /* if we are entirely beyond EOM return EOF */
1158 if ((count = cdp->info.volsize - lba) <= 0) {
1159 bp->b_resid = bp->b_bcount;
1164 if (cdp->block_size == 2048)
1165 ccb[0] = ATAPI_READ_BIG;
1167 ccb[0] = ATAPI_READ_CD;
1172 ccb[0] = ATAPI_WRITE_BIG;
1182 devstat_start_transaction(cdp->stats);
1184 atapi_queue_cmd(cdp->atp, ccb, bp->b_data, count * cdp->block_size,
1185 (bp->b_iocmd == BIO_READ)?ATPR_F_READ : 0, 30, acd_done, bp);
1189 acd_done(struct atapi_request *request)
1191 struct buf *bp = request->driver;
1192 struct acd_softc *cdp = request->device->driver;
1194 if (request->error) {
1195 bp->b_error = request->error;
1196 bp->b_flags |= B_ERROR;
1199 bp->b_resid = bp->b_bcount - request->donecount;
1200 if (bp->b_iocmd == BIO_WRITE)
1201 cdp->flags |= F_WRITTEN;
1203 devstat_end_transaction_buf(cdp->stats, bp);
1209 acd_read_toc(struct acd_softc *cdp)
1211 int32_t ntracks, len;
1214 bzero(&cdp->toc, sizeof(cdp->toc));
1215 bzero(&cdp->info, sizeof(cdp->info));
1216 bzero(ccb, sizeof(ccb));
1218 atapi_test_ready(cdp->atp);
1220 if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED)
1221 cdp->flags &= ~(F_WRITTEN | F_DISK_OPEN | F_TRACK_OPEN);
1223 cdp->atp->flags &= ~ATAPI_F_MEDIA_CHANGED;
1225 len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry);
1226 ccb[0] = ATAPI_READ_TOC;
1229 if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, ATPR_F_READ, 30,
1231 bzero(&cdp->toc, sizeof(cdp->toc));
1234 ntracks = cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1;
1235 if (ntracks <= 0 || ntracks > MAXTRK) {
1236 bzero(&cdp->toc, sizeof(cdp->toc));
1240 len = sizeof(struct ioc_toc_header)+(ntracks+1)*sizeof(struct cd_toc_entry);
1241 bzero(ccb, sizeof(ccb));
1242 ccb[0] = ATAPI_READ_TOC;
1245 if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, ATPR_F_READ, 30,
1247 bzero(&cdp->toc, sizeof(cdp->toc));
1251 cdp->toc.hdr.len = ntohs(cdp->toc.hdr.len);
1253 bzero(ccb, sizeof(ccb));
1254 ccb[0] = ATAPI_READ_CAPACITY;
1255 if (atapi_queue_cmd(cdp->atp, ccb, &cdp->info, sizeof(cdp->info),
1256 ATPR_F_READ, 30, NULL, NULL))
1257 bzero(&cdp->info, sizeof(cdp->info));
1259 cdp->info.volsize = ntohl(cdp->info.volsize);
1260 cdp->info.blksize = ntohl(cdp->info.blksize);
1263 if (cdp->info.volsize && cdp->toc.hdr.ending_track) {
1264 printf("acd%d: ", cdp->lun);
1265 if (cdp->toc.tab[0].control & 4)
1266 printf("%dMB ", cdp->info.volsize / 512);
1268 printf("%d:%d audio ", cdp->info.volsize / 75 / 60,
1269 cdp->info.volsize / 75 % 60);
1270 printf("(%d sectors (%d bytes)), %d tracks\n",
1271 cdp->info.volsize, cdp->info.blksize,
1272 cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1);
1279 acd_construct_label(struct acd_softc *cdp)
1281 bzero(&cdp->disklabel, sizeof(struct disklabel));
1282 strncpy(cdp->disklabel.d_typename, " ",
1283 sizeof(cdp->disklabel.d_typename));
1284 strncpy(cdp->disklabel.d_typename, cdp->atp->devname,
1285 min(strlen(cdp->atp->devname),
1286 sizeof(cdp->disklabel.d_typename) - 1));
1287 strncpy(cdp->disklabel.d_packname, "unknown ",
1288 sizeof(cdp->disklabel.d_packname));
1289 cdp->disklabel.d_secsize = cdp->info.blksize;
1290 cdp->disklabel.d_nsectors = 100;
1291 cdp->disklabel.d_ntracks = 1;
1292 cdp->disklabel.d_ncylinders = (cdp->info.volsize/100)+1;
1293 cdp->disklabel.d_secpercyl = 100;
1294 cdp->disklabel.d_secperunit = cdp->info.volsize;
1295 cdp->disklabel.d_rpm = 300;
1296 cdp->disklabel.d_interleave = 1;
1297 cdp->disklabel.d_flags = D_REMOVABLE;
1298 cdp->disklabel.d_npartitions = 1;
1299 cdp->disklabel.d_partitions[0].p_offset = 0;
1300 cdp->disklabel.d_partitions[0].p_size = cdp->info.volsize;
1301 cdp->disklabel.d_partitions[0].p_fstype = FS_BSDFFS;
1302 cdp->disklabel.d_magic = DISKMAGIC;
1303 cdp->disklabel.d_magic2 = DISKMAGIC;
1304 cdp->disklabel.d_checksum = dkcksum(&cdp->disklabel);
1308 acd_setchan(struct acd_softc *cdp,
1309 u_int8_t c0, u_int8_t c1, u_int8_t c2, u_int8_t c3)
1313 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, &cdp->au,
1316 if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE)
1318 cdp->au.data_length = 0;
1319 cdp->au.port[0].channels = c0;
1320 cdp->au.port[1].channels = c1;
1321 cdp->au.port[2].channels = c2;
1322 cdp->au.port[3].channels = c3;
1323 return acd_mode_select(cdp, &cdp->au, sizeof(cdp->au));
1327 acd_select_done1(struct atapi_request *request)
1329 struct acd_softc *cdp = request->driver;
1331 cdp->changer_info->current_slot = cdp->slot;
1332 cdp->driver[cdp->changer_info->current_slot]->timestamp = time_second;
1333 wakeup(&cdp->changer_info);
1338 acd_select_done(struct atapi_request *request)
1340 struct acd_softc *cdp = request->driver;
1341 int8_t ccb[16] = { ATAPI_LOAD_UNLOAD, 0, 0, 0, 3, 0, 0, 0,
1342 cdp->slot, 0, 0, 0, 0, 0, 0, 0 };
1344 /* load the wanted slot */
1345 atapi_queue_cmd(cdp->atp, ccb, NULL, 0, ATPR_F_AT_HEAD, 30,
1346 acd_select_done1, cdp);
1351 acd_select_slot(struct acd_softc *cdp)
1353 int8_t ccb[16] = { ATAPI_LOAD_UNLOAD, 0, 0, 0, 2, 0, 0, 0,
1354 cdp->changer_info->current_slot, 0, 0, 0, 0, 0, 0, 0 };
1356 /* unload the current media from player */
1357 atapi_queue_cmd(cdp->atp, ccb, NULL, 0, ATPR_F_AT_HEAD, 30,
1358 acd_select_done, cdp);
1362 acd_close_disk(struct acd_softc *cdp)
1364 int8_t ccb[16] = { ATAPI_CLOSE_TRACK, 0x01, 0x02, 0, 0, 0, 0, 0,
1365 0, 0, 0, 0, 0, 0, 0, 0 };
1368 error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
1371 return atapi_wait_ready(cdp->atp, 10*60);
1375 acd_open_track(struct acd_softc *cdp, struct cdr_track *track)
1377 struct write_param param;
1380 if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
1381 ¶m, sizeof(param))))
1384 param.page_code = ATAPI_CDROM_WRITE_PARAMETERS_PAGE;
1385 param.page_length = 0x32;
1386 param.test_write = track->test_write ? 1 : 0;
1387 param.write_type = CDR_WTYPE_TRACK;
1389 switch (track->track_type) {
1393 param.track_mode = CDR_TMODE_AUDIO_PREEMP;
1395 param.track_mode = CDR_TMODE_AUDIO;
1396 cdp->block_size = 2352;
1397 param.data_block_type = CDR_DB_RAW;
1398 param.session_format = CDR_SESS_CDROM;
1401 case CDR_DB_ROM_MODE1:
1402 cdp->block_size = 2048;
1403 param.track_mode = CDR_TMODE_DATA;
1404 param.data_block_type = CDR_DB_ROM_MODE1;
1405 param.session_format = CDR_SESS_CDROM;
1408 case CDR_DB_ROM_MODE2:
1409 cdp->block_size = 2336;
1410 param.track_mode = CDR_TMODE_DATA;
1411 param.data_block_type = CDR_DB_ROM_MODE2;
1412 param.session_format = CDR_SESS_CDROM;
1415 case CDR_DB_XA_MODE1:
1416 cdp->block_size = 2048;
1417 param.track_mode = CDR_TMODE_DATA;
1418 param.data_block_type = CDR_DB_XA_MODE1;
1419 param.session_format = CDR_SESS_CDROM_XA;
1422 case CDR_DB_XA_MODE2_F1:
1423 cdp->block_size = 2056;
1424 param.track_mode = CDR_TMODE_DATA;
1425 param.data_block_type = CDR_DB_XA_MODE2_F1;
1426 param.session_format = CDR_SESS_CDROM_XA;
1429 case CDR_DB_XA_MODE2_F2:
1430 cdp->block_size = 2324;
1431 param.track_mode = CDR_TMODE_DATA;
1432 param.data_block_type = CDR_DB_XA_MODE2_F2;
1433 param.session_format = CDR_SESS_CDROM_XA;
1436 case CDR_DB_XA_MODE2_MIX:
1437 cdp->block_size = 2332;
1438 param.track_mode = CDR_TMODE_DATA;
1439 param.data_block_type = CDR_DB_XA_MODE2_MIX;
1440 param.session_format = CDR_SESS_CDROM_XA;
1445 param.multi_session = CDR_MSES_MULTI;
1447 param.multi_session = CDR_MSES_NONE;
1450 param.packet_size = 0;
1451 return acd_mode_select(cdp, ¶m, sizeof(param));
1455 acd_close_track(struct acd_softc *cdp)
1457 int8_t ccb1[16] = { ATAPI_SYNCHRONIZE_CACHE, 0x02, 0, 0, 0, 0, 0, 0,
1458 0, 0, 0, 0, 0, 0, 0, 0 };
1461 error = atapi_queue_cmd(cdp->atp, ccb1, NULL, 0, 0, 10, NULL, NULL);
1464 return atapi_wait_ready(cdp->atp, 5*60);
1468 acd_read_track_info(struct acd_softc *cdp,
1469 int32_t lba, struct acd_track_info *info)
1471 int8_t ccb[16] = { ATAPI_READ_TRACK_INFO, 1,
1472 lba>>24, lba>>16, lba>>8, lba,
1474 sizeof(*info)>>8, sizeof(*info),
1475 0, 0, 0, 0, 0, 0, 0 };
1478 if ((error = atapi_queue_cmd(cdp->atp, ccb, info, sizeof(*info),
1479 ATPR_F_READ, 30, NULL, NULL)))
1481 info->track_start_addr = ntohl(info->track_start_addr);
1482 info->next_writeable_addr = ntohl(info->next_writeable_addr);
1483 info->free_blocks = ntohl(info->free_blocks);
1484 info->fixed_packet_size = ntohl(info->fixed_packet_size);
1485 info->track_length = ntohl(info->track_length);
1490 acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
1502 switch (ai->format) {
1503 case DVD_REPORT_AGID:
1504 case DVD_REPORT_ASF:
1505 case DVD_REPORT_RPC:
1508 case DVD_REPORT_KEY1:
1511 case DVD_REPORT_TITLE_KEY:
1515 case DVD_REPORT_CHALLENGE:
1518 case DVD_INVALIDATE_AGID:
1525 bzero(ccb, sizeof(ccb));
1526 ccb[0] = ATAPI_REPORT_KEY;
1527 ccb[2] = (lba >> 24) & 0xff;
1528 ccb[3] = (lba >> 16) & 0xff;
1529 ccb[4] = (lba >> 8) & 0xff;
1530 ccb[5] = lba & 0xff;
1531 ccb[8] = (length >> 8) & 0xff;
1532 ccb[9] = length & 0xff;
1533 ccb[10] = (ai->agid << 6) | ai->format;
1534 bzero(&d, sizeof(d));
1535 d.length = htons(length - 2);
1536 error = atapi_queue_cmd(cdp->atp, ccb, &d, length,
1537 ai->format == DVD_INVALIDATE_AGID ? 0 : ATPR_F_READ,
1542 switch (ai->format) {
1543 case DVD_REPORT_AGID:
1544 ai->agid = d.data[3] >> 6;
1547 case DVD_REPORT_CHALLENGE:
1548 bcopy(&d.data[0], &ai->keychal[0], 10);
1551 case DVD_REPORT_KEY1:
1552 bcopy(&d.data[0], &ai->keychal[0], 5);
1555 case DVD_REPORT_TITLE_KEY:
1556 ai->cpm = (d.data[0] >> 7);
1557 ai->cp_sec = (d.data[0] >> 6) & 0x1;
1558 ai->cgms = (d.data[0] >> 4) & 0x3;
1559 bcopy(&d.data[1], &ai->keychal[0], 5);
1562 case DVD_REPORT_ASF:
1563 ai->asf = d.data[3] & 1;
1566 case DVD_REPORT_RPC:
1567 ai->reg_type = (d.data[0] >> 6);
1568 ai->vend_rsts = (d.data[0] >> 3) & 0x7;
1569 ai->user_rsts = d.data[0] & 0x7;
1572 case DVD_INVALIDATE_AGID:
1582 acd_send_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
1592 bzero(&d, sizeof(d));
1594 switch (ai->format) {
1595 case DVD_SEND_CHALLENGE:
1597 bcopy(ai->keychal, &d.data[0], 10);
1602 bcopy(&ai->keychal[0], &d.data[0], 5);
1613 bzero(ccb, sizeof(ccb));
1614 ccb[0] = ATAPI_SEND_KEY;
1615 ccb[8] = (length >> 8) & 0xff;
1616 ccb[9] = length & 0xff;
1617 ccb[10] = (ai->agid << 6) | ai->format;
1618 d.length = htons(length - 2);
1619 return atapi_queue_cmd(cdp->atp, ccb, &d, length, 0, 10, NULL, NULL);
1623 acd_read_structure(struct acd_softc *cdp, struct dvd_struct *s)
1634 bzero(&d, sizeof(d));
1637 case DVD_STRUCT_PHYSICAL:
1641 case DVD_STRUCT_COPYRIGHT:
1645 case DVD_STRUCT_DISCKEY:
1649 case DVD_STRUCT_BCA:
1653 case DVD_STRUCT_MANUFACT:
1657 case DVD_STRUCT_DDS:
1658 case DVD_STRUCT_PRERECORDED:
1659 case DVD_STRUCT_UNIQUEID:
1660 case DVD_STRUCT_LIST:
1661 case DVD_STRUCT_CMI:
1662 case DVD_STRUCT_RMD_LAST:
1663 case DVD_STRUCT_RMD_RMA:
1664 case DVD_STRUCT_DCB:
1671 bzero(ccb, sizeof(ccb));
1672 ccb[0] = ATAPI_READ_STRUCTURE;
1673 ccb[6] = s->layer_num;
1675 ccb[8] = (length >> 8) & 0xff;
1676 ccb[9] = length & 0xff;
1677 ccb[10] = s->agid << 6;
1678 d.length = htons(length - 2);
1679 error = atapi_queue_cmd(cdp->atp, ccb, &d, length, ATPR_F_READ, 30,
1684 switch (s->format) {
1685 case DVD_STRUCT_PHYSICAL: {
1686 struct dvd_layer *layer = (struct dvd_layer *)&s->data[0];
1688 layer->book_type = d.data[0] >> 4;
1689 layer->book_version = d.data[0] & 0xf;
1690 layer->disc_size = d.data[1] >> 4;
1691 layer->max_rate = d.data[1] & 0xf;
1692 layer->nlayers = (d.data[2] >> 5) & 3;
1693 layer->track_path = (d.data[2] >> 4) & 1;
1694 layer->layer_type = d.data[2] & 0xf;
1695 layer->linear_density = d.data[3] >> 4;
1696 layer->track_density = d.data[3] & 0xf;
1697 layer->start_sector = d.data[5] << 16 | d.data[6] << 8 | d.data[7];
1698 layer->end_sector = d.data[9] << 16 | d.data[10] << 8 | d.data[11];
1699 layer->end_sector_l0 = d.data[13] << 16 | d.data[14] << 8 | d.data[15];
1700 layer->bca = d.data[16] >> 7;
1704 case DVD_STRUCT_COPYRIGHT:
1705 s->cpst = d.data[0];
1709 case DVD_STRUCT_DISCKEY:
1710 bcopy(&d.data[0], &s->data[0], 2048);
1713 case DVD_STRUCT_BCA:
1714 s->length = ntohs(d.length);
1715 bcopy(&d.data[0], &s->data[0], s->length);
1718 case DVD_STRUCT_MANUFACT:
1719 s->length = ntohs(d.length);
1720 bcopy(&d.data[0], &s->data[0], s->length);
1730 acd_eject(struct acd_softc *cdp, int32_t close)
1734 if ((error = acd_start_stop(cdp, 0)) == EBUSY) {
1737 if ((error = acd_start_stop(cdp, 3)))
1740 acd_prevent_allow(cdp, 1);
1741 cdp->flags |= F_LOCKED;
1748 acd_prevent_allow(cdp, 0);
1749 cdp->flags &= ~F_LOCKED;
1750 cdp->flags &= ~(F_WRITTEN | F_DISK_OPEN | F_TRACK_OPEN);
1751 cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED;
1752 return acd_start_stop(cdp, 2);
1756 acd_blank(struct acd_softc *cdp)
1758 int8_t ccb[16] = { ATAPI_BLANK, 1, 0, 0, 0, 0, 0, 0,
1759 0, 0, 0, 0, 0, 0, 0, 0 };
1762 error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 60*60, NULL, NULL);
1763 cdp->flags &= ~(F_WRITTEN | F_DISK_OPEN | F_TRACK_OPEN);
1764 cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED;
1769 acd_prevent_allow(struct acd_softc *cdp, int32_t lock)
1771 int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
1772 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1774 return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);
1778 acd_start_stop(struct acd_softc *cdp, int32_t start)
1780 int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
1781 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1783 return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);
1787 acd_pause_resume(struct acd_softc *cdp, int32_t pause)
1789 int8_t ccb[16] = { ATAPI_PAUSE, 0, 0, 0, 0, 0, 0, 0, pause,
1790 0, 0, 0, 0, 0, 0, 0 };
1792 return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);
1796 acd_mode_sense(struct acd_softc *cdp, u_int8_t page,
1797 void *pagebuf, int32_t pagesize)
1799 int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, page, 0, 0, 0, 0,
1800 pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 };
1803 error = atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, ATPR_F_READ, 10,
1806 atapi_dump("acd: mode sense ", pagebuf, pagesize);
1812 acd_mode_select(struct acd_softc *cdp, void *pagebuf, int32_t pagesize)
1814 int8_t ccb[16] = { ATAPI_MODE_SELECT_BIG, 0x10, 0, 0, 0, 0, 0,
1815 pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 };
1818 printf("acd: modeselect pagesize=%d\n", pagesize);
1819 atapi_dump("acd: mode select ", pagebuf, pagesize);
1821 return atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, 0, 30, NULL, NULL);
1825 acd_set_speed(struct acd_softc *cdp, int32_t speed)
1827 int8_t ccb[16] = { ATAPI_SET_SPEED, 0, 0xff, 0xff, speed>>8, speed,
1828 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1830 return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);