]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ata/atapi-cd.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / sys / dev / ata / atapi-cd.c
1 /*-
2  * Copyright (c) 1998,1999,2000 Søren Schmidt
3  * All rights reserved.
4  *
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.
16  *
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.
27  *
28  * $FreeBSD$
29  */
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/proc.h>
35 #include <sys/malloc.h>
36 #include <sys/buf.h>
37 #include <sys/bus.h>
38 #include <sys/disklabel.h>
39 #include <sys/devicestat.h>
40 #include <sys/cdio.h>
41 #include <sys/cdrio.h>
42 #include <sys/dvdio.h>
43 #include <sys/fcntl.h>
44 #include <sys/conf.h>
45 #include <sys/stat.h>
46 #include <dev/ata/ata-all.h>
47 #include <dev/ata/atapi-all.h>
48 #include <dev/ata/atapi-cd.h>
49
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 = {
56         /* open */      acdopen,
57         /* close */     acdclose,
58         /* read */      physread,
59         /* write */     physwrite,
60         /* ioctl */     acdioctl,
61         /* poll */      nopoll,
62         /* mmap */      nommap,
63         /* strategy */  acdstrategy,
64         /* name */      "acd",
65         /* maj */       117,
66         /* dump */      nodump,
67         /* psize */     nopsize,
68         /* flags */     D_DISK | D_TRACKCLOSE,
69         /* bmaj */      31
70 };
71
72 /* prototypes */
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);
98
99 /* internal vars */
100 static u_int32_t acd_lun_map = 0;
101 MALLOC_DEFINE(M_ACD, "ACD driver", "ATAPI CD driver buffers");
102
103 int
104 acdattach(struct atapi_softc *atp)
105 {
106     struct acd_softc *cdp;
107     struct changer *chp;
108     int32_t count, error = 0;
109     static int32_t acd_cdev_done = 0;
110
111     if (!acd_cdev_done) {
112         cdevsw_add(&acd_cdevsw);
113         acd_cdev_done++;
114     }
115
116     if ((cdp = acd_init_lun(atp, NULL)) == NULL) {
117         printf("acd: out of memory\n");
118         return -1;
119     }
120
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))))
125             break;
126     }
127     if (error) {
128         free(cdp, M_ACD);
129         return -1;
130     }
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);
137
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,
141                            0, 0, 0, 0, 0, 0, 0, 
142                            sizeof(struct changer)>>8, sizeof(struct changer),
143                            0, 0, 0, 0, 0, 0 };
144
145         chp = malloc(sizeof(struct changer), M_ACD, M_NOWAIT);
146         if (chp == NULL) {
147             printf("acd: out of memory\n");
148             return 0;
149         }
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);
153
154         if (!error) {
155             struct acd_softc *tmpcdp = cdp;
156             struct acd_softc **cdparr;
157             int32_t count;
158             int8_t string[16];
159
160             chp->table_length = htons(chp->table_length);
161             if (!(cdparr = malloc(sizeof(struct acd_softc) * chp->slots,
162                                  M_ACD, M_NOWAIT))) {
163                 printf("acd: out of memory\n");
164                 return -1;
165             }
166             for (count = 0; count < chp->slots; count++) {
167                 if (count > 0) {
168                     tmpcdp = acd_init_lun(atp, cdp->stats);
169                     if (!tmpcdp) {
170                         printf("acd: out of memory\n");
171                         return -1;
172                     }
173                 }
174                 cdparr[count] = tmpcdp;
175                 tmpcdp->driver = cdparr;
176                 tmpcdp->slot = count;
177                 tmpcdp->changer_info = chp;
178                 if (bootverbose)
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);
182             }
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);
192         }
193     }
194     else {
195         acd_make_dev(cdp);
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);
202     }
203     cdp->atp->driver = cdp;
204     acd_describe(cdp);
205     return 0;
206 }
207
208 void
209 acddetach(struct atapi_softc *atp)
210 {   
211     struct acd_softc *cdp = atp->driver;
212     
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);
218     }
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);
223     free(cdp, M_ACD);
224 }
225
226 static struct acd_softc *
227 acd_init_lun(struct atapi_softc *atp, struct devstat *stats)
228 {
229     struct acd_softc *cdp;
230
231     if (!(cdp = malloc(sizeof(struct acd_softc), M_ACD, M_NOWAIT)))
232         return NULL;
233     bzero(cdp, sizeof(struct acd_softc));
234     bufq_init(&cdp->buf_queue);
235     cdp->atp = atp;
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;
239     cdp->slot = -1;
240     cdp->changer_info = NULL;
241     if (stats == NULL) {
242         if (!(cdp->stats = malloc(sizeof(struct devstat), M_ACD, M_NOWAIT))) {
243             free(cdp, M_ACD);
244             return NULL;
245         }
246         bzero(cdp->stats, sizeof(struct devstat));
247     }
248     else
249         cdp->stats = stats;
250     return cdp;
251 }
252
253 static void
254 acd_make_dev(struct acd_softc *cdp)
255 {
256     dev_t dev;
257
258     dev = make_dev(&acd_cdevsw, dkmakeminor(cdp->lun, 0, 0),
259                    UID_ROOT, GID_OPERATOR, 0644, "acd%da", cdp->lun);
260     dev->si_drv1 = cdp;
261     dev->si_iosize_max = 252 * DEV_BSIZE;
262     dev->si_bsize_phys = 2048; /* XXX SOS */
263     cdp->dev1 = dev;
264     dev = make_dev(&acd_cdevsw, dkmakeminor(cdp->lun, 0, RAW_PART),
265                    UID_ROOT, GID_OPERATOR, 0644, "acd%dc", cdp->lun);
266     dev->si_drv1 = cdp;
267     dev->si_iosize_max = 252 * DEV_BSIZE;
268     dev->si_bsize_phys = 2048; /* XXX SOS */
269     cdp->dev2 = dev;
270     cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED;
271 }
272
273 static void 
274 acd_describe(struct acd_softc *cdp)
275 {
276     int32_t comma = 0;
277     int8_t *mechanism;
278
279     if (bootverbose) {
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");
290
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);
302             }
303             comma = 1;
304         }
305         if (cdp->cap.buf_size) {
306             printf("%s %dKB buffer", comma ? "," : "", cdp->cap.buf_size);
307             comma = 1;
308         }
309         printf("%s %s\n", 
310                comma ? "," : "", ata_mode2str(
311                 cdp->atp->controller->mode[ATA_DEV(cdp->atp->unit)]));
312
313         printf("acd%d: Reads:", cdp->lun);
314         comma = 0;
315         if (cdp->cap.read_cdr) {
316             printf(" CD-R"); comma = 1;
317         }
318         if (cdp->cap.read_cdrw) {
319             printf("%s CD-RW", comma ? "," : ""); comma = 1;
320         }
321         if (cdp->cap.cd_da) {
322             if (cdp->cap.cd_da_stream)
323             printf("%s CD-DA stream", comma ? "," : "");
324             else
325             printf("%s CD-DA", comma ? "," : "");
326             comma = 1;
327         }
328         if (cdp->cap.read_dvdrom) {
329             printf("%s DVD-ROM", comma ? "," : ""); comma = 1;
330         }
331         if (cdp->cap.read_dvdr) {
332             printf("%s DVD-R", comma ? "," : ""); comma = 1;
333         }
334         if (cdp->cap.read_dvdram) {
335             printf("%s DVD-RAM", comma ? "," : ""); comma = 1;
336         }
337         if (cdp->cap.read_packet)
338             printf("%s packet", comma ? "," : "");
339
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);
343             comma = 0;
344             if (cdp->cap.write_cdr) {
345                 printf(" CD-R" ); comma = 1;
346             }
347             if (cdp->cap.write_cdrw) {
348                 printf("%s CD-RW", comma ? "," : ""); comma = 1;
349             }
350             if (cdp->cap.write_dvdr) {
351                 printf("%s DVD-R", comma ? "," : ""); comma = 1;
352             }
353             if (cdp->cap.write_dvdram) {
354                 printf("%s DVD-RAM", comma ? "," : ""); comma = 1; 
355             }
356             if (cdp->cap.test_write)
357                 printf("%s test write", comma ? "," : "");
358         }
359         if (cdp->cap.audio_play) {
360             printf("\nacd%d: Audio: ", cdp->lun);
361             if (cdp->cap.audio_play)
362                 printf("play");
363             if (cdp->cap.max_vol_levels)
364                 printf(", %d volume levels", cdp->cap.max_vol_levels);
365         }
366         printf("\nacd%d: Mechanism: ", cdp->lun);
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;
380         }
381         if (mechanism)
382             printf("%s%s", cdp->cap.eject ? "ejectable " : "", mechanism);
383         else if (cdp->cap.eject)
384             printf("ejectable");
385
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) {
389             case MST_CDROM:
390                 printf("CD-ROM "); break;
391             case MST_CDR:
392                 printf("CD-R "); break;
393             case MST_CDRW:
394                 printf("CD-RW "); break;
395             case MST_DOOR_OPEN:
396                 printf("door open"); break;
397             case MST_NO_DISC:
398                 printf("no/blank disc inside"); break;
399             case MST_FMT_ERROR:
400                 printf("medium format error"); break;
401             }
402             if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH)<MST_TYPE_MASK_HIGH){
403                 switch (cdp->cap.medium_type & MST_TYPE_MASK_LOW) {
404                 case MST_DATA_120:
405                     printf("120mm data disc loaded"); break;
406                 case MST_AUDIO_120:
407                     printf("120mm audio disc loaded"); break;
408                 case MST_COMB_120:
409                     printf("120mm data/audio disc loaded"); break;
410                 case MST_PHOTO_120:
411                     printf("120mm photo disc loaded"); break;
412                 case MST_DATA_80:
413                     printf("80mm data disc loaded"); break;
414                 case MST_AUDIO_80:
415                     printf("80mm audio disc loaded"); break;
416                 case MST_COMB_80:
417                     printf("80mm data/audio disc loaded"); break;
418                 case MST_PHOTO_80:
419                     printf("80mm photo disc loaded"); break;
420                 case MST_FMT_NONE:
421                     switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
422                     case MST_CDROM:
423                         printf("unknown medium"); break;
424                     case MST_CDR:
425                     case MST_CDRW:
426                         printf("blank medium"); break;
427                     }
428                     break;
429                 default:
430                     printf("unknown type=0x%x", cdp->cap.medium_type); break;
431                 }
432             }
433         }
434         if (cdp->cap.lock)
435             printf(cdp->cap.locked ? ", locked" : ", unlocked");
436         if (cdp->cap.prevent)
437             printf(", lock protected");
438         printf("\n");
439     }
440     else {
441         char changer[32];
442         char devnum[8];
443
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);
449         }
450         else
451             sprintf(devnum, "%d", cdp->lun);
452
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)])
463                );
464     }
465 }
466
467 static __inline void 
468 lba2msf(int32_t lba, u_int8_t *m, u_int8_t *s, u_int8_t *f)
469 {
470     lba += 150;
471     lba &= 0xffffff;
472     *m = lba / (60 * 75);
473     lba %= (60 * 75);
474     *s = lba / 75;
475     *f = lba % 75;
476 }
477
478 static __inline int32_t 
479 msf2lba(u_int8_t m, u_int8_t s, u_int8_t f)
480 {
481     return (m * 60 + s) * 75 + f - 150;
482 }
483
484 static int
485 acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
486 {
487     struct acd_softc *cdp = dev->si_drv1;
488
489     if (!cdp)
490         return ENXIO;
491
492     if (flags & FWRITE) {
493         if (count_dev(dev) > 1)
494             return EBUSY;
495     }
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);
500         }
501         acd_prevent_allow(cdp, 1);
502         cdp->flags |= F_LOCKED;
503         if (!(flags & O_NONBLOCK) && !(flags & FWRITE))
504             acd_read_toc(cdp);
505         else
506             atapi_test_ready(cdp->atp);
507     }
508     acd_construct_label(cdp);
509     return 0;
510 }
511
512 static int 
513 acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
514 {
515     struct acd_softc *cdp = dev->si_drv1;
516     
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);
521         }
522         acd_prevent_allow(cdp, 0);
523     }
524     cdp->flags &= ~F_LOCKED;
525     return 0;
526 }
527
528 static int 
529 acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flags, struct proc *p)
530 {
531     struct acd_softc *cdp = dev->si_drv1;
532     int32_t error = 0;
533
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);
537     }
538     if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED)
539         switch (cmd) {
540         case CDIOCRESET:
541             atapi_test_ready(cdp->atp);
542             break;
543            
544         default:
545             acd_read_toc(cdp);
546             acd_prevent_allow(cdp, 1);
547             cdp->flags |= F_LOCKED;
548             break;
549         }
550     switch (cmd) {
551
552     case CDIOCRESUME:
553         error = acd_pause_resume(cdp, 1);
554         break;
555
556     case CDIOCPAUSE:
557         error = acd_pause_resume(cdp, 0);
558         break;
559
560     case CDIOCSTART:
561         error = acd_start_stop(cdp, 1);
562         break;
563
564     case CDIOCSTOP:
565         error = acd_start_stop(cdp, 0);
566         break;
567
568     case CDIOCALLOW:
569         cdp->flags &= ~F_LOCKED;
570         error = acd_prevent_allow(cdp, 0);
571         break;
572
573     case CDIOCPREVENT:
574         cdp->flags |= F_LOCKED;
575         error = acd_prevent_allow(cdp, 1);
576         break;
577
578     case CDIOCRESET:
579         error = suser(p);
580         if (error)
581             break;
582         error = atapi_test_ready(cdp->atp);
583         break;
584
585     case CDIOCEJECT:
586         if (count_dev(dev) > 1) {
587             error = EBUSY;
588             break;
589         }
590         error = acd_eject(cdp, 0);
591         break;
592
593     case CDIOCCLOSE:
594         if (count_dev(dev) > 1)
595             break;
596         error = acd_eject(cdp, 1);
597         break;
598
599     case CDIOREADTOCHEADER:
600         if (!cdp->toc.hdr.ending_track) {
601             error = EIO;
602             break;
603         }
604         bcopy(&cdp->toc.hdr, addr, sizeof(cdp->toc.hdr));
605         break;
606
607     case CDIOREADTOCENTRYS:
608         {
609             struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)addr;
610             struct toc *toc = &cdp->toc;
611             struct toc buf;
612             u_int32_t len;
613             u_int8_t starting_track = te->starting_track;
614
615             if (!cdp->toc.hdr.ending_track) {
616                 error = EIO;
617                 break;
618             }
619
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)) {
624                 error = EINVAL;
625                 break;
626             }
627
628             if (!starting_track)
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) {
634                 error = EINVAL;
635                 break;
636             }
637
638             len = ((toc->hdr.ending_track + 1 - starting_track) + 1) *
639                   sizeof(toc->tab[0]);
640             if (te->data_len < len)
641                 len = te->data_len;
642             if (len > sizeof(toc->tab)) {
643                 error = EINVAL;
644                 break;
645             }
646
647             if (te->address_format == CD_MSF_FORMAT) {
648                 struct cd_toc_entry *entry;
649
650                 buf = cdp->toc;
651                 toc = &buf;
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);
657             }
658             error = copyout(toc->tab + starting_track - toc->hdr.starting_track,
659                             te->data, len);
660             break;
661         }
662     case CDIOREADTOCENTRY:
663         {
664             struct ioc_read_toc_single_entry *te =
665                 (struct ioc_read_toc_single_entry *)addr;
666             struct toc *toc = &cdp->toc;
667             struct toc buf;
668             u_int8_t track = te->track;
669
670             if (!cdp->toc.hdr.ending_track) {
671                 error = EIO;
672                 break;
673             }
674
675             if (te->address_format != CD_MSF_FORMAT && 
676                 te->address_format != CD_LBA_FORMAT) {
677                 error = EINVAL;
678                 break;
679             }
680
681             if (!track)
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) {
687                 error = EINVAL;
688                 break;
689             }
690
691             if (te->address_format == CD_MSF_FORMAT) {
692                 struct cd_toc_entry *entry;
693
694                 buf = cdp->toc;
695                 toc = &buf;
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);
699             }
700             bcopy(toc->tab + track - toc->hdr.starting_track,
701                   &te->entry, sizeof(struct cd_toc_entry));
702         }
703         break;
704
705     case CDIOCREADSUBCHANNEL:
706         {
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 };
715
716             if (len > sizeof(data) ||
717                 len < sizeof(struct cd_sub_channel_header)) {
718                 error = EINVAL;
719                 break;
720             }
721
722             if ((error = atapi_queue_cmd(cdp->atp, ccb, &cdp->subchan, 
723                                          sizeof(cdp->subchan), ATPR_F_READ, 10,
724                                          NULL, NULL))) {
725                 break;
726             }
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);
738             } else {
739                 data.what.position.absaddr.lba = abslba;
740                 data.what.position.reladdr.lba = rellba;
741             }
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);
748             break;
749         }
750
751     case CDIOCPLAYMSF:
752         {
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 };
758
759             error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
760             break;
761         }
762
763     case CDIOCPLAYBLOCKS:
764         {
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,
770                                 0, 0, 0, 0, 0, 0 };
771
772             error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
773             break;
774         }
775
776     case CDIOCPLAYTRACKS:
777         {
778             struct ioc_play_track *args = (struct ioc_play_track *)addr;
779             u_int32_t start, len;
780             int32_t t1, t2;
781             int8_t ccb[16];
782
783             if (!cdp->toc.hdr.ending_track) {
784                 error = EIO;
785                 break;
786             }
787
788             if (args->end_track < cdp->toc.hdr.ending_track + 1)
789                 ++args->end_track;
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) {
795                 error = EINVAL;
796                 break;
797             }
798             start = ntohl(cdp->toc.tab[t1].addr.lba);
799             len = ntohl(cdp->toc.tab[t2].addr.lba) - start;
800
801             bzero(ccb, sizeof(ccb));
802             ccb[0] = ATAPI_PLAY_BIG;
803             ccb[2] = start>>24;
804             ccb[3] = start>>16;
805             ccb[4] = start>>8;
806             ccb[5] = start;
807             ccb[6] = len>>24;
808             ccb[7] = len>>16;
809             ccb[8] = len>>8;
810             ccb[9] = len;
811
812             error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
813             break;
814         }
815
816     case CDIOCREADAUDIO:
817         {
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;
821             int8_t ccb[16];
822
823             if (!cdp->toc.hdr.ending_track) {
824                 error = EIO;
825                 break;
826             }
827                 
828             if ((frames = args->nframes) < 0) {
829                 error = EINVAL;
830                 break;
831             }
832
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;
842             }
843
844 #ifndef CD_BUFFER_BLOCKS
845 #define CD_BUFFER_BLOCKS 13
846 #endif
847             if (!(buffer = malloc(CD_BUFFER_BLOCKS * 2352, M_ACD, M_NOWAIT))){
848                 error = ENOMEM;
849                 break;
850             }
851             bzero(ccb, sizeof(ccb));
852             while (frames > 0) {
853                 int32_t size;
854                 u_int8_t blocks;
855
856                 blocks = (frames>CD_BUFFER_BLOCKS) ? CD_BUFFER_BLOCKS : frames;
857                 size = blocks * 2352;
858
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->atp, ccb, buffer, size, 
868                                              ATPR_F_READ, 30, NULL,NULL)))
869                     break;
870
871                 if ((error = copyout(buffer, ubuf, size)))
872                     break;
873                     
874                 ubuf += size;
875                 frames -= blocks;
876                 lba += blocks;
877             }
878             free(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;
886         }
887
888     case CDIOCGETVOL:
889         {
890             struct ioc_vol *arg = (struct ioc_vol *)addr;
891
892             if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE,
893                                         &cdp->au, sizeof(cdp->au))))
894                 break;
895
896             if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) {
897                 error = EIO;
898                 break;
899             }
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;
905         }
906
907     case CDIOCSETVOL:
908         {
909             struct ioc_vol *arg = (struct ioc_vol *)addr;
910
911             if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE,
912                                         &cdp->au, sizeof(cdp->au))))
913                 break;
914             if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) {
915                 error = EIO;
916                 break;
917             }
918             if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE_MASK,
919                                         &cdp->aumask, sizeof(cdp->aumask))))
920                 break;
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));
929             break;
930         }
931     case CDIOCSETPATCH:
932         {
933             struct ioc_patch *arg = (struct ioc_patch *)addr;
934
935             error = acd_setchan(cdp, arg->patch[0], arg->patch[1],
936                                 arg->patch[2], arg->patch[3]);
937             break;
938         }
939
940     case CDIOCSETMONO:
941         error = acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0,0);
942         break;
943
944     case CDIOCSETSTEREO:
945         error = acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0);
946         break;
947
948     case CDIOCSETMUTE:
949         error = acd_setchan(cdp, 0, 0, 0, 0);
950         break;
951
952     case CDIOCSETLEFT:
953         error = acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0);
954         break;
955
956     case CDIOCSETRIGHT:
957         error = acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0);
958         break;
959
960     case CDRIOCBLANK:
961         error = acd_blank(cdp);
962         break;
963
964     case CDRIOCNEXTWRITEABLEADDR:
965         {
966             struct acd_track_info track_info;
967
968             if ((error = acd_read_track_info(cdp, 0xff, &track_info)))
969                 break;
970
971             if (!track_info.nwa_valid) {
972                 error = EINVAL;
973                 break;
974             }
975             *(int*)addr = track_info.next_writeable_addr;
976         }
977         break;
978  
979     case CDRIOCOPENDISK:
980         if ((cdp->flags & F_WRITTEN) || (cdp->flags & F_DISK_OPEN)) {
981             error = EINVAL;
982             printf("acd%d: sequence error (disk already open)\n", cdp->lun);
983         }
984         cdp->flags &= ~(F_WRITTEN | F_TRACK_OPEN);
985         cdp->flags |= F_DISK_OPEN;
986         break;
987
988     case CDRIOCOPENTRACK:
989         if (!(cdp->flags & F_DISK_OPEN)) {
990             error = EINVAL;
991             printf("acd%d: sequence error (disk not open)\n", cdp->lun);
992         } 
993         else {
994             if ((error = acd_open_track(cdp, (struct cdr_track *)addr)))
995                 break;
996             cdp->flags |= F_TRACK_OPEN;
997         }
998         break;
999
1000     case CDRIOCCLOSETRACK:
1001         if (!(cdp->flags & F_TRACK_OPEN)) {
1002             error = EINVAL;
1003             printf("acd%d: sequence error (no track open)\n", cdp->lun);
1004         }
1005         else {
1006             if (cdp->flags & F_WRITTEN) {
1007                 acd_close_track(cdp);
1008                 cdp->flags &= ~F_TRACK_OPEN;
1009             }
1010         }
1011         break;
1012
1013     case CDRIOCCLOSEDISK:
1014         if (!(cdp->flags & F_DISK_OPEN)) {
1015             error = EINVAL;
1016             printf("acd%d: sequence error (nothing to close)\n", cdp->lun);
1017         }
1018         else if (!(cdp->flags & F_WRITTEN)) {
1019             cdp->flags &= ~(F_DISK_OPEN | F_TRACK_OPEN);
1020         }
1021         else {
1022             error = acd_close_disk(cdp);
1023             cdp->flags &= ~(F_WRITTEN | F_DISK_OPEN | F_TRACK_OPEN);
1024         }
1025         break;
1026
1027     case CDRIOCWRITESPEED:
1028         error = acd_set_speed(cdp, (*(int32_t *)addr) * 177);
1029         break;
1030
1031     case CDRIOCGETBLOCKSIZE:
1032         *(int32_t *)addr = cdp->block_size;
1033         break;
1034
1035     case CDRIOCSETBLOCKSIZE:
1036         cdp->block_size = *(int32_t *)addr;
1037         break;
1038
1039     case DVDIOCREPORTKEY:
1040         if (!cdp->cap.read_dvdrom)
1041             error = EINVAL;
1042         else
1043             error = acd_report_key(cdp, (struct dvd_authinfo *)addr);
1044         break;
1045
1046     case DVDIOCSENDKEY:
1047         if (!cdp->cap.read_dvdrom)
1048             error = EINVAL;
1049         else
1050             error = acd_send_key(cdp, (struct dvd_authinfo *)addr);
1051         break;
1052
1053     case DVDIOCREADSTRUCTURE:
1054         if (!cdp->cap.read_dvdrom)
1055             error = EINVAL;
1056         else
1057             error = acd_read_structure(cdp, (struct dvd_struct *)addr);
1058         break;
1059
1060     case DIOCGDINFO:
1061         *(struct disklabel *)addr = cdp->disklabel;
1062         break;
1063
1064     case DIOCWDINFO:
1065     case DIOCSDINFO:
1066         if ((flags & FWRITE) == 0)
1067             error = EBADF;
1068         else
1069             error = setdisklabel(&cdp->disklabel, (struct disklabel *)addr, 0);
1070         break;
1071
1072     case DIOCWLABEL:
1073         error = EBADF;
1074         break;
1075
1076     case DIOCGPART:
1077         ((struct partinfo *)addr)->disklab = &cdp->disklabel;
1078         ((struct partinfo *)addr)->part = &cdp->disklabel.d_partitions[0];
1079         break;
1080
1081     default:
1082         error = ENOTTY;
1083     }
1084     return error;
1085 }
1086
1087 static void 
1088 acdstrategy(struct buf *bp)
1089 {
1090     struct acd_softc *cdp = bp->b_dev->si_drv1;
1091     int32_t s;
1092
1093     /* if it's a null transfer, return immediatly. */
1094     if (bp->b_bcount == 0) {
1095         bp->b_resid = 0;
1096         biodone(bp);
1097         return;
1098     }
1099     
1100     bp->b_pblkno = bp->b_blkno;
1101     bp->b_resid = bp->b_bcount;
1102
1103     s = splbio();
1104     bufqdisksort(&cdp->buf_queue, bp);
1105     ata_start(cdp->atp->controller);
1106     splx(s);
1107 }
1108
1109 void 
1110 acd_start(struct atapi_softc *atp)
1111 {
1112     struct acd_softc *cdp = atp->driver;
1113     struct buf *bp = bufq_first(&cdp->buf_queue);
1114     u_int32_t lba, count;
1115     int8_t ccb[16];
1116
1117     if (cdp->changer_info) {
1118         int i;
1119
1120         cdp = cdp->driver[cdp->changer_info->current_slot];
1121         bp = bufq_first(&cdp->buf_queue);
1122
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)
1126                 continue;
1127             if (bufq_first(&(cdp->driver[i]->buf_queue))) {
1128                 if (!bp || time_second > (cdp->timestamp + 10)) {
1129                     acd_select_slot(cdp->driver[i]);
1130                     return;
1131                 }
1132             }
1133         }
1134     }
1135     if (!bp)
1136         return;
1137     bufq_remove(&cdp->buf_queue, bp);
1138
1139     /* reject all queued entries if media changed */
1140     if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED) {
1141         bp->b_error = EIO;
1142         bp->b_flags |= B_ERROR;
1143         biodone(bp);
1144         return;
1145     }
1146
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;
1151     else
1152         lba = bp->b_blkno / (cdp->block_size / DEV_BSIZE);
1153
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;
1160                 biodone(bp);
1161                 return;
1162             }
1163         }
1164         if (cdp->block_size == 2048)
1165             ccb[0] = ATAPI_READ_BIG;
1166         else {
1167             ccb[0] = ATAPI_READ_CD;
1168             ccb[9] = 0x10;
1169         }
1170     }
1171     else
1172         ccb[0] = ATAPI_WRITE_BIG;
1173     ccb[1] = 0;
1174     ccb[2] = lba>>24;
1175     ccb[3] = lba>>16;
1176     ccb[4] = lba>>8;
1177     ccb[5] = lba;
1178     ccb[6] = count>>16;
1179     ccb[7] = count>>8;
1180     ccb[8] = count;
1181
1182     devstat_start_transaction(cdp->stats);
1183
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);
1186 }
1187
1188 static int32_t 
1189 acd_done(struct atapi_request *request)
1190 {
1191     struct buf *bp = request->driver;
1192     struct acd_softc *cdp = request->device->driver;
1193     
1194     if (request->error) {
1195         bp->b_error = request->error;
1196         bp->b_flags |= B_ERROR;
1197     }   
1198     else {
1199         bp->b_resid = bp->b_bcount - request->donecount;
1200         if (bp->b_iocmd == BIO_WRITE)
1201             cdp->flags |= F_WRITTEN;
1202     }
1203     devstat_end_transaction_buf(cdp->stats, bp);
1204     biodone(bp);
1205     return 0;
1206 }
1207
1208 static void 
1209 acd_read_toc(struct acd_softc *cdp)
1210 {
1211     int32_t ntracks, len;
1212     int8_t ccb[16];
1213
1214     bzero(&cdp->toc, sizeof(cdp->toc));
1215     bzero(&cdp->info, sizeof(cdp->info));
1216     bzero(ccb, sizeof(ccb));
1217
1218     atapi_test_ready(cdp->atp);
1219
1220     if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED)
1221         cdp->flags &= ~(F_WRITTEN | F_DISK_OPEN | F_TRACK_OPEN);
1222
1223     cdp->atp->flags &= ~ATAPI_F_MEDIA_CHANGED;
1224
1225     len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry);
1226     ccb[0] = ATAPI_READ_TOC;
1227     ccb[7] = len>>8;
1228     ccb[8] = len;
1229     if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, ATPR_F_READ, 30,
1230                         NULL, NULL)) {
1231         bzero(&cdp->toc, sizeof(cdp->toc));
1232         return;
1233     }
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));
1237         return;
1238     }
1239
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;
1243     ccb[7] = len>>8;
1244     ccb[8] = len;
1245     if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, ATPR_F_READ, 30,
1246                         NULL, NULL)) {
1247         bzero(&cdp->toc, sizeof(cdp->toc));
1248         return;
1249     }
1250
1251     cdp->toc.hdr.len = ntohs(cdp->toc.hdr.len);
1252
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));
1258
1259     cdp->info.volsize = ntohl(cdp->info.volsize);
1260     cdp->info.blksize = ntohl(cdp->info.blksize);
1261
1262 #ifdef ACD_DEBUG
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);
1267         else
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);
1273     }
1274 #endif
1275     return;
1276 }
1277
1278 static void
1279 acd_construct_label(struct acd_softc *cdp)
1280 {
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);
1305 }
1306
1307 static int32_t 
1308 acd_setchan(struct acd_softc *cdp,
1309             u_int8_t c0, u_int8_t c1, u_int8_t c2, u_int8_t c3)
1310 {
1311     int32_t error;
1312
1313     if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, &cdp->au, 
1314                                 sizeof(cdp->au))))
1315         return error;
1316     if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE)
1317         return EIO;
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));
1324 }
1325
1326 static int32_t 
1327 acd_select_done1(struct atapi_request *request)
1328 {
1329     struct acd_softc *cdp = request->driver;
1330
1331     cdp->changer_info->current_slot = cdp->slot;
1332     cdp->driver[cdp->changer_info->current_slot]->timestamp = time_second;
1333     wakeup(&cdp->changer_info);
1334     return 0;
1335 }
1336
1337 static int32_t 
1338 acd_select_done(struct atapi_request *request)
1339 {
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 };
1343
1344     /* load the wanted slot */
1345     atapi_queue_cmd(cdp->atp, ccb, NULL, 0, ATPR_F_AT_HEAD, 30, 
1346                     acd_select_done1, cdp);
1347     return 0;
1348 }
1349
1350 static void 
1351 acd_select_slot(struct acd_softc *cdp)
1352 {
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 };
1355
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);
1359 }
1360
1361 static int32_t
1362 acd_close_disk(struct acd_softc *cdp)
1363 {
1364     int8_t ccb[16] = { ATAPI_CLOSE_TRACK, 0x01, 0x02, 0, 0, 0, 0, 0, 
1365                        0, 0, 0, 0, 0, 0, 0, 0 };
1366     int32_t error;
1367
1368     error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
1369     if (error)
1370         return error;
1371     return atapi_wait_ready(cdp->atp, 10*60);
1372 }
1373
1374 static int32_t
1375 acd_open_track(struct acd_softc *cdp, struct cdr_track *track)
1376 {
1377     struct write_param param;
1378     int32_t error;
1379
1380     if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
1381                                 &param, sizeof(param))))
1382         return error;
1383
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;
1388
1389     switch (track->track_type) {
1390
1391     case CDR_DB_RAW:
1392         if (track->preemp)
1393             param.track_mode = CDR_TMODE_AUDIO_PREEMP;
1394         else
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;
1399         break;
1400
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;
1406         break;
1407
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;
1413         break;
1414
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;
1420         break;
1421
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;
1427         break;
1428
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;
1434         break;
1435
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;
1441         break;
1442     }
1443
1444 #if 1
1445     param.multi_session = CDR_MSES_MULTI;
1446 #else
1447     param.multi_session = CDR_MSES_NONE;
1448 #endif
1449     param.fp = 0;
1450     param.packet_size = 0;
1451     return acd_mode_select(cdp, &param, sizeof(param));
1452 }
1453
1454 static int32_t
1455 acd_close_track(struct acd_softc *cdp)
1456 {
1457     int8_t ccb1[16] = { ATAPI_SYNCHRONIZE_CACHE, 0x02, 0, 0, 0, 0, 0, 0,
1458                         0, 0, 0, 0, 0, 0, 0, 0 };
1459     int32_t error;
1460
1461     error = atapi_queue_cmd(cdp->atp, ccb1, NULL, 0, 0, 10, NULL, NULL);
1462     if (error)
1463         return error;
1464     return atapi_wait_ready(cdp->atp, 5*60);
1465 }
1466
1467 static int32_t
1468 acd_read_track_info(struct acd_softc *cdp,
1469                     int32_t lba, struct acd_track_info *info)
1470 {
1471     int8_t ccb[16] = { ATAPI_READ_TRACK_INFO, 1,
1472                      lba>>24, lba>>16, lba>>8, lba,
1473                      0,
1474                      sizeof(*info)>>8, sizeof(*info),
1475                      0, 0, 0, 0, 0, 0, 0 };
1476     int32_t error;
1477
1478     if ((error = atapi_queue_cmd(cdp->atp, ccb, info, sizeof(*info), 
1479                                  ATPR_F_READ, 30, NULL, NULL)))
1480         return error;
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);
1486     return 0;
1487 }
1488
1489 static int
1490 acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
1491 {
1492     struct {
1493         u_int16_t length;
1494         u_char reserved[2];
1495         u_char data[12];
1496     } d;
1497     u_int32_t lba = 0;
1498     int32_t error;
1499     int16_t length;
1500     int8_t ccb[16];
1501
1502     switch (ai->format) {
1503     case DVD_REPORT_AGID:
1504     case DVD_REPORT_ASF:
1505     case DVD_REPORT_RPC:
1506         length = 8;
1507         break;
1508     case DVD_REPORT_KEY1:
1509         length = 12;
1510         break;
1511     case DVD_REPORT_TITLE_KEY:
1512         length = 12;
1513         lba = ai->lba;
1514         break;
1515     case DVD_REPORT_CHALLENGE:
1516         length = 16;
1517         break;
1518     case DVD_INVALIDATE_AGID:
1519         length = 0;
1520         break;
1521     default:
1522         return EINVAL;
1523     }
1524
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,
1538                             10, NULL, NULL);
1539     if (error)
1540         return error;
1541
1542     switch (ai->format) {
1543     case DVD_REPORT_AGID:
1544         ai->agid = d.data[3] >> 6;
1545         break;
1546     
1547     case DVD_REPORT_CHALLENGE:
1548         bcopy(&d.data[0], &ai->keychal[0], 10);
1549         break;
1550     
1551     case DVD_REPORT_KEY1:
1552         bcopy(&d.data[0], &ai->keychal[0], 5);
1553         break;
1554     
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);
1560         break;
1561     
1562     case DVD_REPORT_ASF:
1563         ai->asf = d.data[3] & 1;
1564         break;
1565     
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;
1570         break;
1571     
1572     case DVD_INVALIDATE_AGID:
1573         break;
1574
1575     default:
1576         return EINVAL;
1577     }
1578     return 0;
1579 }
1580
1581 static int
1582 acd_send_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
1583 {
1584     struct {
1585         u_int16_t length;
1586         u_char reserved[2];
1587         u_char data[12];
1588     } d;
1589     int16_t length;
1590     int8_t ccb[16];
1591
1592     bzero(&d, sizeof(d));
1593
1594     switch (ai->format) {
1595     case DVD_SEND_CHALLENGE:
1596         length = 16;
1597         bcopy(ai->keychal, &d.data[0], 10);
1598         break;
1599
1600     case DVD_SEND_KEY2:
1601         length = 12;
1602         bcopy(&ai->keychal[0], &d.data[0], 5);
1603         break;
1604     
1605     case DVD_SEND_RPC:
1606         length = 8;
1607         break;
1608
1609     default:
1610         return EINVAL;
1611     }
1612
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);
1620 }
1621
1622 static int
1623 acd_read_structure(struct acd_softc *cdp, struct dvd_struct *s)
1624 {
1625     struct {
1626         u_int16_t length;
1627         u_char reserved[2];
1628         u_char data[2048];
1629     } d;
1630     u_int16_t length;
1631     int32_t error = 0;
1632     int8_t ccb[16];
1633
1634     bzero(&d, sizeof(d));
1635
1636     switch(s->format) {
1637     case DVD_STRUCT_PHYSICAL:
1638         length = 21;
1639         break;
1640
1641     case DVD_STRUCT_COPYRIGHT:
1642         length = 8;
1643         break;
1644
1645     case DVD_STRUCT_DISCKEY:
1646         length = 2052;
1647         break;
1648
1649     case DVD_STRUCT_BCA:
1650         length = 192;
1651         break;
1652
1653     case DVD_STRUCT_MANUFACT:
1654         length = 2052;
1655         break;
1656
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:
1665         return ENOSYS;
1666
1667     default:
1668         return EINVAL;
1669     }
1670
1671     bzero(ccb, sizeof(ccb));
1672     ccb[0] = ATAPI_READ_STRUCTURE;
1673     ccb[6] = s->layer_num;
1674     ccb[7] = s->format;
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,
1680                             NULL, NULL);
1681     if (error)
1682         return error;
1683
1684     switch (s->format) {
1685     case DVD_STRUCT_PHYSICAL: {
1686         struct dvd_layer *layer = (struct dvd_layer *)&s->data[0];
1687
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;
1701         break;
1702     }
1703
1704     case DVD_STRUCT_COPYRIGHT:
1705         s->cpst = d.data[0];
1706         s->rmi = d.data[0];
1707         break;
1708
1709     case DVD_STRUCT_DISCKEY:
1710         bcopy(&d.data[0], &s->data[0], 2048);
1711         break;
1712
1713     case DVD_STRUCT_BCA:
1714         s->length = ntohs(d.length);
1715         bcopy(&d.data[0], &s->data[0], s->length);
1716         break;
1717
1718     case DVD_STRUCT_MANUFACT:
1719         s->length = ntohs(d.length);
1720         bcopy(&d.data[0], &s->data[0], s->length);
1721         break;
1722                 
1723     default:
1724         return EINVAL;
1725     }
1726     return 0;
1727 }
1728
1729 static int32_t 
1730 acd_eject(struct acd_softc *cdp, int32_t close)
1731 {
1732     int32_t error;
1733
1734     if ((error = acd_start_stop(cdp, 0)) == EBUSY) {
1735         if (!close)
1736             return 0;
1737         if ((error = acd_start_stop(cdp, 3)))
1738             return error;
1739         acd_read_toc(cdp);
1740         acd_prevent_allow(cdp, 1);
1741         cdp->flags |= F_LOCKED;
1742         return 0;
1743     }
1744     if (error)
1745         return error;
1746     if (close)
1747         return 0;
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);
1753 }
1754
1755 static int32_t
1756 acd_blank(struct acd_softc *cdp)
1757 {
1758     int8_t ccb[16] = { ATAPI_BLANK, 1, 0, 0, 0, 0, 0, 0, 
1759                        0, 0, 0, 0, 0, 0, 0, 0 };
1760     int32_t error;
1761
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;
1765     return error;
1766 }
1767
1768 static int32_t
1769 acd_prevent_allow(struct acd_softc *cdp, int32_t lock)
1770 {
1771     int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
1772                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1773
1774     return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);
1775 }
1776
1777 static int32_t
1778 acd_start_stop(struct acd_softc *cdp, int32_t start)
1779 {
1780     int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
1781                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1782
1783     return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);
1784 }
1785
1786 static int32_t
1787 acd_pause_resume(struct acd_softc *cdp, int32_t pause)
1788 {
1789     int8_t ccb[16] = { ATAPI_PAUSE, 0, 0, 0, 0, 0, 0, 0, pause,
1790                        0, 0, 0, 0, 0, 0, 0 };
1791
1792     return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);
1793 }
1794
1795 static int32_t
1796 acd_mode_sense(struct acd_softc *cdp, u_int8_t page,
1797                void *pagebuf, int32_t pagesize)
1798 {
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 };
1801     int32_t error;
1802
1803     error = atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, ATPR_F_READ, 10, 
1804                             NULL, NULL);
1805 #ifdef ACD_DEBUG
1806     atapi_dump("acd: mode sense ", pagebuf, pagesize);
1807 #endif
1808     return error;
1809 }
1810
1811 static int32_t
1812 acd_mode_select(struct acd_softc *cdp, void *pagebuf, int32_t pagesize)
1813 {
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 };
1816
1817 #ifdef ACD_DEBUG
1818     printf("acd: modeselect pagesize=%d\n", pagesize);
1819     atapi_dump("acd: mode select ", pagebuf, pagesize);
1820 #endif
1821     return atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, 0, 30, NULL, NULL);
1822 }
1823
1824 static int32_t
1825 acd_set_speed(struct acd_softc *cdp, int32_t speed)
1826 {
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 };
1829
1830     return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);
1831 }