Initial import from FreeBSD RELENG_4:
[games.git] / sys / dev / disk / wcd / wd_cd.c
1 /*-
2  * Copyright (c) 1998, 1999 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: src/sys/i386/isa/wd_cd.c,v 1.29 2000/01/29 16:00:33 peter Exp $
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/disklabel.h>
38 #include <sys/devicestat.h>
39 #include <sys/cdio.h>
40 #include <sys/wormio.h>
41 #include <sys/fcntl.h>
42 #include <sys/conf.h>
43 #include <sys/stat.h>
44 #include <i386/isa/atapi.h>
45 #include <i386/isa/wd_cd.h>
46
47 static d_open_t         acdopen;
48 static d_close_t        acdclose;
49 static d_ioctl_t        acdioctl;
50 static d_strategy_t     acdstrategy;
51
52 #define CDEV_MAJOR 69
53 #define BDEV_MAJOR 19
54 static struct cdevsw acd_cdevsw = {
55         /* open */      acdopen,
56         /* close */     acdclose,
57         /* read */      physread,
58         /* write */     physwrite,
59         /* ioctl */     acdioctl,
60         /* poll */      nopoll,
61         /* mmap */      nommap,
62         /* strategy */  acdstrategy,
63         /* name */      "wcd",
64         /* maj */       CDEV_MAJOR,
65         /* dump */      nodump,
66         /* psize */     nopsize,
67         /* flags */     D_DISK,
68         /* bmaj */      BDEV_MAJOR
69 };
70
71 #define NUNIT   16              /* Max # of devices */
72
73 #define F_BOPEN         0x0001  /* The block device is opened */
74 #define F_MEDIA_CHANGED 0x0002  /* The media have changed since open */
75 #define F_DEBUG         0x0004  /* Print debug info */
76 #define F_LOCKED        0x0008  /* This unit is locked (or should be) */
77 #define F_TRACK_PREP    0x0010  /* Track should be prep'ed */
78 #define F_TRACK_PREPED  0x0020  /* Track has been prep'ed */
79 #define F_DISK_PREPED   0x0040  /* Disk has been prep'ed */
80 #define F_WRITTEN       0x0080  /* The medium has been written to */
81
82 static struct acd *acdtab[NUNIT];
83 static int acdnlun = 0;         /* Number of configured drives */
84
85 int acdattach(struct atapi *, int, struct atapi_params *, int);
86 static struct acd *acd_init_lun(struct atapi *, int, struct atapi_params *, int,
87 struct devstat *);
88 static void acd_start(struct acd *);
89 static void acd_done(struct acd *, struct buf *, int, struct atapires);
90 static int acd_read_toc(struct acd *);
91 static int acd_request_wait(struct acd *, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, char *, int);
92 static void acd_describe(struct acd *);
93 static int acd_setchan(struct acd *, u_char, u_char, u_char, u_char);
94 static int acd_eject(struct acd *, int);
95 static void acd_select_slot(struct acd *);
96 static int acd_open_disk(struct acd *, int);
97 static int acd_open_track(struct acd *, struct wormio_prepare_track *);
98 static int acd_close_track(struct acd *);
99 static int acd_close_disk(struct acd *);
100 static int acd_read_track_info(struct acd *cdp, int lba, struct acd_track_info *info);
101 static int acd_blank_disk(struct acd *);
102 static void atapi_dump(int ctrlr, int lun, char *label, void *data, int len);
103 static void atapi_error(struct atapi *ata, int unit, struct atapires result);
104
105 struct acd *
106 acd_init_lun(struct atapi *ata, int unit, struct atapi_params *ap, int lun,
107              struct devstat *device_stats)
108 {
109     struct acd *ptr;
110
111     if (!(ptr = malloc(sizeof(struct acd), M_TEMP, M_NOWAIT)))
112         return NULL;
113     bzero(ptr, sizeof(struct acd));
114     bufq_init(&ptr->buf_queue);
115     ptr->ata = ata;
116     ptr->unit = unit;
117     ptr->lun = lun;
118     ptr->param = ap;
119     ptr->flags = F_MEDIA_CHANGED;
120     ptr->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED);
121     ptr->block_size = 2048;
122     ptr->refcnt = 0;
123     ptr->slot = -1;
124     ptr->changer_info = NULL;
125     if (device_stats == NULL) {
126         if (!(ptr->device_stats = malloc(sizeof(struct devstat), 
127                                          M_TEMP, M_NOWAIT)))
128             return NULL;
129         bzero(ptr->device_stats, sizeof(struct devstat));
130     }
131     else
132         ptr->device_stats = device_stats;
133     make_dev(&acd_cdevsw, dkmakeminor(lun, 0, 0),
134         UID_ROOT, GID_OPERATOR, 0640, "rwcd%da", lun);
135     make_dev(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART),
136         UID_ROOT, GID_OPERATOR, 0640, "rwcd%dc", lun);
137     make_dev(&acd_cdevsw, dkmakeminor(lun, 0, 0),
138         UID_ROOT, GID_OPERATOR, 0640, "wcd%da", lun);
139     make_dev(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART),
140         UID_ROOT, GID_OPERATOR, 0640, "wcd%dc", lun);
141     return ptr;
142 }
143
144 int
145 acdattach(struct atapi *ata, int unit, struct atapi_params *ap, int debug)
146 {
147     struct acd *cdp;
148     struct atapires result;
149     struct changer *chp;
150     int i, count;
151
152     if (acdnlun >= NUNIT) {
153         printf("wcd: too many units\n");
154         return 0;
155     }
156     if (!atapi_request_immediate) {
157         printf("wcd: configuration error, ATAPI code not present!\n");
158         return 0;
159     }
160     if ((cdp = acd_init_lun(ata, unit, ap, acdnlun, NULL)) == NULL) {
161         printf("wcd: out of memory\n");
162         return 0;
163     }
164     acdtab[acdnlun] = cdp;
165
166     if (debug) {
167         cdp->flags |= F_DEBUG;
168         atapi_dump(cdp->ata->ctrlr, cdp->lun, "info", ap, sizeof(*ap));
169     }
170
171     /* Get drive capabilities, some drives needs this repeated */
172     for (count = 0 ; count < 5 ; count++) {
173         result = atapi_request_immediate(ata, unit,
174                                          ATAPI_MODE_SENSE,
175                                          0, ATAPI_CDROM_CAP_PAGE,
176                                          0, 0, 0, 0, 
177                                          sizeof(cdp->cap)>>8, sizeof(cdp->cap),
178                                          0, 0, 0, 0, 0, 0, 0, 
179                                          (char *)&cdp->cap, sizeof(cdp->cap));
180         if (result.code == 0 || result.code == RES_UNDERRUN)
181             break;
182     }
183
184     /* Some drives have shorter capabilities page. */
185     if (result.code == RES_UNDERRUN)
186         result.code = 0;
187
188     if (result.code == 0) {
189         cdp->cap.max_speed = ntohs(cdp->cap.max_speed);
190         cdp->cap.max_vol_levels = ntohs(cdp->cap.max_vol_levels);
191         cdp->cap.buf_size = ntohs(cdp->cap.buf_size);
192         cdp->cap.cur_speed = ntohs(cdp->cap.cur_speed);
193         acd_describe(cdp);
194         if (cdp->flags & F_DEBUG)
195             atapi_dump(cdp->ata->ctrlr, cdp->lun, "cap", &cdp->cap,
196                        sizeof(cdp->cap));
197     }
198     /* If this is a changer device, allocate the neeeded lun's */
199     if (cdp->cap.mech == MST_MECH_CHANGER) {
200         char string[16];
201         struct acd *tmpcdp = cdp;
202
203         chp = malloc(sizeof(struct changer), M_TEMP, M_NOWAIT);
204         if (chp == NULL) {
205             printf("wcd: out of memory\n");
206             return 0;
207         }
208         bzero(chp, sizeof(struct changer));
209         result = atapi_request_immediate(ata, unit, ATAPI_MECH_STATUS,
210                                          0, 0, 0, 0, 0, 0, 0,
211                                          sizeof(struct changer)>>8,
212                                          sizeof(struct changer),
213                                          0, 0, 0, 0, 0, 0,
214                                          (char *)chp, sizeof(struct changer));
215         if (cdp->flags & F_DEBUG) {
216             printf("result.code=%d curr=%02x slots=%d len=%d\n",
217                 result.code, chp->current_slot, chp->slots,
218                 htons(chp->table_length));
219         }
220         if (result.code == RES_UNDERRUN)
221             result.code = 0;
222
223         if (result.code == 0) {
224             chp->table_length = htons(chp->table_length);
225             for (i = 0; i < chp->slots && acdnlun < NUNIT; i++) {
226                 if (i > 0) {
227                     tmpcdp = acd_init_lun(ata, unit, ap, acdnlun, 
228                                           cdp->device_stats);
229                     if (!tmpcdp) {
230                         printf("wcd: out of memory\n");
231                         return 0;
232                     }
233                 }
234                 tmpcdp->slot = i;
235                 tmpcdp->changer_info = chp;
236                 printf("wcd%d: changer slot %d %s\n", acdnlun, i,
237                        (chp->slot[i].present ? "disk present" : "no disk"));
238                 acdtab[acdnlun++] = tmpcdp;
239             }
240             if (acdnlun >= NUNIT) {
241                 printf("wcd: too many units\n");
242                 return 0;
243             }
244         }
245         sprintf(string, "wcd%d-", cdp->lun);
246         devstat_add_entry(cdp->device_stats, string, tmpcdp->lun, DEV_BSIZE,
247                           DEVSTAT_NO_ORDERED_TAGS,
248                           DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE,
249                           DEVSTAT_PRIORITY_CD);
250     }
251     else {
252         acdnlun++;
253         devstat_add_entry(cdp->device_stats, "wcd", cdp->lun, DEV_BSIZE,
254                           DEVSTAT_NO_ORDERED_TAGS,
255                           DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE,
256                           DEVSTAT_PRIORITY_CD);
257     }
258     return 1;
259 }
260
261 void 
262 acd_describe(struct acd *cdp)
263 {
264     int comma;
265     char *mechanism;
266
267     printf("wcd%d: drive speed ", cdp->lun);
268     if (cdp->cap.cur_speed != cdp->cap.max_speed)
269         printf("%d - ", cdp->cap.cur_speed * 1000 / 1024);
270     printf("%dKB/sec", cdp->cap.max_speed * 1000 / 1024);
271     if (cdp->cap.buf_size)
272         printf(", %dKB cache\n", cdp->cap.buf_size);
273
274     printf("wcd%d: supported read types:", cdp->lun);
275     comma = 0;
276     if (cdp->cap.read_cdr) {
277         printf(" CD-R"); comma = 1;
278     }
279     if (cdp->cap.read_cdrw) {
280         printf("%s CD-RW", comma ? "," : ""); comma = 1;
281     }
282     if (cdp->cap.cd_da) {
283         printf("%s CD-DA", comma ? "," : ""); comma = 1;
284     }
285     if (cdp->cap.method2)
286         printf("%s packet track", comma ? "," : "");
287     if (cdp->cap.write_cdr || cdp->cap.write_cdrw) {
288         printf("\nwcd%d: supported write types:", cdp->lun);
289         comma = 0;
290         if (cdp->cap.write_cdr) {
291             printf(" CD-R" ); comma = 1;
292         }
293         if (cdp->cap.write_cdrw) {
294             printf("%s CD-RW", comma ? "," : ""); comma = 1;
295         }
296         if (cdp->cap.test_write) {
297             printf("%s test write", comma ? "," : ""); comma = 1;
298         }
299     }
300     if (cdp->cap.audio_play) {
301         printf("\nwcd%d: Audio: ", cdp->lun);
302         if (cdp->cap.audio_play)
303             printf("play");
304         if (cdp->cap.max_vol_levels)
305             printf(", %d volume levels", cdp->cap.max_vol_levels);
306     }
307     printf("\nwcd%d: Mechanism: ", cdp->lun);
308     switch (cdp->cap.mech) {
309     case MST_MECH_CADDY:
310         mechanism = "caddy"; break;
311     case MST_MECH_TRAY:
312         mechanism = "tray"; break;
313     case MST_MECH_POPUP:
314         mechanism = "popup"; break;
315     case MST_MECH_CHANGER:
316         mechanism = "changer"; break;
317     case MST_MECH_CARTRIDGE:
318         mechanism = "cartridge"; break;
319     default:
320         mechanism = 0; break;
321     }
322     if (mechanism)
323         printf("%s%s", cdp->cap.eject ? "ejectable " : "", mechanism);
324     else if (cdp->cap.eject)
325         printf("ejectable");
326
327     if (cdp->cap.mech != MST_MECH_CHANGER) {
328         printf("\nwcd%d: Medium: ", cdp->lun);
329         switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
330         case MST_CDROM:
331             printf("CD-ROM "); break;
332         case MST_CDR:
333             printf("CD-R "); break;
334         case MST_CDRW:
335             printf("CD-RW "); break;
336         case MST_DOOR_OPEN:
337             printf("door open"); break;
338         case MST_NO_DISC:
339             printf("no/blank disc inside"); break;
340         case MST_FMT_ERROR:
341             printf("medium format error"); break;
342         }
343         if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH) < MST_TYPE_MASK_HIGH) {
344             switch (cdp->cap.medium_type & MST_TYPE_MASK_LOW) {
345             case MST_DATA_120:
346                 printf("120mm data disc loaded"); break;
347             case MST_AUDIO_120:
348                 printf("120mm audio disc loaded"); break;
349             case MST_COMB_120:
350                 printf("120mm data/audio disc loaded"); break;
351             case MST_PHOTO_120:
352                 printf("120mm photo disc loaded"); break;
353             case MST_DATA_80:
354                 printf("80mm data disc loaded"); break;
355             case MST_AUDIO_80:
356                 printf("80mm audio disc loaded"); break;
357             case MST_COMB_80:
358                 printf("80mm data/audio disc loaded"); break;
359             case MST_PHOTO_80:
360                 printf("80mm photo disc loaded"); break;
361             case MST_FMT_NONE:
362                 switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
363                 case MST_CDROM:
364                     printf("unknown medium"); break;
365                 case MST_CDR:
366                 case MST_CDRW:
367                     printf("blank medium"); break;
368                 }
369                 break;
370             default:
371                 printf("unknown type=0x%x", cdp->cap.medium_type); break;
372             }
373         }
374     }
375     if (cdp->cap.lock)
376         printf(cdp->cap.locked ? ", locked" : ", unlocked");
377     if (cdp->cap.prevent)
378         printf(", lock protected");
379     printf("\n");
380 }
381
382 static int
383 acdopen(dev_t dev, int flags, int fmt, struct proc *p)
384 {
385     int lun = dkunit(dev);
386     struct acd *cdp;
387
388     if (lun >= acdnlun || !atapi_request_immediate)
389         return ENXIO;
390     cdp = acdtab[lun];
391
392     if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) {
393         /* Prevent user eject */
394         acd_request_wait(cdp, ATAPI_PREVENT_ALLOW,
395             0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0);
396         cdp->flags |= F_LOCKED;
397     }
398     if (fmt == S_IFBLK)
399         cdp->flags |= F_BOPEN;
400     else
401         ++cdp->refcnt;
402     dev->si_bsize_phys = cdp->block_size;
403     if (!(flags & O_NONBLOCK) && acd_read_toc(cdp) && !(flags & FWRITE))
404         printf("acd%d: read_toc failed\n", lun);
405     return 0;
406 }
407
408 int 
409 acdclose(dev_t dev, int flags, int fmt, struct proc *p)
410 {
411     struct acd *cdp = acdtab[dkunit(dev)];
412
413     if (fmt == S_IFBLK)
414         cdp->flags &= ~F_BOPEN;
415     else
416         --cdp->refcnt;
417
418     /* Are we the last open ?? */
419     if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) {
420         /* Yup, do we need to close any written tracks */
421         if ((flags & FWRITE) != 0) {
422             if ((cdp->flags & F_TRACK_PREPED) != 0) {
423                 acd_close_track(cdp);
424                 cdp->flags &= ~(F_TRACK_PREPED | F_TRACK_PREP);
425             }
426         }
427         /* Allow the user eject */
428         acd_request_wait(cdp, ATAPI_PREVENT_ALLOW,
429                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
430     }
431     cdp->flags &= ~F_LOCKED;
432     return 0;
433 }
434
435 void 
436 acdstrategy(struct buf *bp)
437 {
438     int lun = dkunit(bp->b_dev);
439     struct acd *cdp = acdtab[lun];
440     int x;
441
442 #ifdef NOTYET
443     /* allow write only on CD-R/RW media */   /* all for now SOS */
444     if (!(bp->b_flags & B_READ) && !(writeable_media)) {
445         bp->b_error = EROFS;
446         bp->b_flags |= B_ERROR;
447         biodone(bp);
448         return;
449     }
450 #endif
451
452     if (bp->b_bcount == 0) {
453         bp->b_resid = 0;
454         biodone(bp);
455         return;
456     }
457     
458     bp->b_pblkno = bp->b_blkno;
459     bp->b_resid = bp->b_bcount;
460
461     x = splbio();
462     bufqdisksort(&cdp->buf_queue, bp);
463     acd_start(cdp);
464     splx(x);
465 }
466
467 static void 
468 acd_start(struct acd *cdp)
469 {
470     struct buf *bp = bufq_first(&cdp->buf_queue);
471     u_long lba, blocks;
472     int cmd;
473     int count;
474
475     if (!bp)
476         return;
477
478     bufq_remove(&cdp->buf_queue, bp);
479
480     /* Should reject all queued entries if media have changed. */
481     if (cdp->flags & F_MEDIA_CHANGED) {
482         bp->b_error = EIO;
483         bp->b_flags |= B_ERROR;
484         biodone(bp);
485         return;
486     }
487
488     acd_select_slot(cdp);
489
490     if ((bp->b_flags & B_READ) == B_WRITE) {
491         if ((cdp->flags & F_TRACK_PREPED) == 0) {
492             if ((cdp->flags & F_TRACK_PREP) == 0) {
493                 printf("wcd%d: sequence error\n", cdp->lun);
494                 bp->b_error = EIO;
495                 bp->b_flags |= B_ERROR;
496                 biodone(bp);
497                 return;
498             } else {
499                 if (acd_open_track(cdp, &cdp->preptrack) != 0) {
500                     biodone(bp);
501                     return;
502                 }
503                 cdp->flags |= F_TRACK_PREPED;
504             }
505         }
506     }
507
508     if (bp->b_flags & B_READ)
509 #ifdef NOTYET
510         lba = bp->b_offset / cdp->block_size;
511 #else
512         lba = bp->b_blkno / (cdp->block_size / DEV_BSIZE);
513 #endif
514     else 
515         lba = cdp->next_writeable_lba + (bp->b_offset / cdp->block_size);
516     blocks = (bp->b_bcount + (cdp->block_size - 1)) / cdp->block_size;
517
518     if ((bp->b_flags & B_READ) == B_WRITE) {
519         cmd = ATAPI_WRITE_BIG;
520         count = -bp->b_bcount;
521     } else {
522         cmd = ATAPI_READ_BIG;
523         count = bp->b_bcount;
524     }
525
526     devstat_start_transaction(cdp->device_stats);
527
528     atapi_request_callback(cdp->ata, cdp->unit, cmd, 0,
529                            lba>>24, lba>>16, lba>>8, lba, 0, 
530                            blocks>>8, blocks, 0, 0, 0, 0, 0, 0, 0, 
531                            (u_char *)bp->b_data, count, 
532                            (atapi_callback_t *)acd_done, cdp, bp);
533 }
534
535 static void 
536 acd_done(struct acd *cdp, struct buf *bp, int resid, struct atapires result)
537 {
538
539     if (result.code) {
540         atapi_error(cdp->ata, cdp->unit, result);
541         bp->b_error = EIO;
542         bp->b_flags |= B_ERROR;
543     } else {
544         bp->b_resid = resid;
545         if ((bp->b_flags & B_READ) == B_WRITE)
546             cdp->flags |= F_WRITTEN;
547     }
548     devstat_end_transaction_buf(cdp->device_stats, bp);
549     biodone(bp);
550     acd_start(cdp);
551 }
552
553 static int 
554 acd_request_wait(struct acd *cdp, u_char cmd, u_char a1, u_char a2,
555     u_char a3, u_char a4, u_char a5, u_char a6, u_char a7, u_char a8,
556     u_char a9, char *addr, int count)
557 {
558     struct atapires result;
559
560     result = atapi_request_wait(cdp->ata, cdp->unit, cmd, a1, a2, a3, a4, a5,
561                                 a6, a7, a8, a9, 0, 0, 0, 0, 0, 0, addr, count);
562     if (result.code) {
563         atapi_error(cdp->ata, cdp->unit, result);
564         return EIO;
565     }
566     return 0;
567 }
568
569 static __inline void 
570 lba2msf(int lba, u_char *m, u_char *s, u_char *f)
571 {
572     lba += 150;
573     lba &= 0xffffff;
574     *m = lba / (60 * 75);
575     lba %= (60 * 75);
576     *s = lba / 75;
577     *f = lba % 75;
578 }
579
580 static __inline int 
581 msf2lba(u_char m, u_char s, u_char f)
582 {
583     return (m * 60 + s) * 75 + f - 150;
584 }
585
586 int 
587 acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
588 {
589     int lun = dkunit(dev);
590     struct acd *cdp = acdtab[lun];
591     int error = 0;
592
593     if (cdp->flags & F_MEDIA_CHANGED)
594         switch (cmd) {
595         case CDIOCRESET:
596             break;
597         default:
598             acd_read_toc(cdp);
599             acd_request_wait(cdp, ATAPI_PREVENT_ALLOW,
600                              0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0);
601             cdp->flags |= F_LOCKED;
602             break;
603         }
604     switch (cmd) {
605 /*
606     case CDIOCRESUME:
607         bzero(cdb);
608         cdb->cmd = ATAPI_PAUSE;
609         cdb->b8 = 0x01;
610         return atapi_cmd_wait(cdp->ata, cdp->unit, cdb, 0, 0, timout, 0);
611 */
612     case CDIOCRESUME:
613         return acd_request_wait(cdp, ATAPI_PAUSE, 
614                                 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
615
616     case CDIOCPAUSE:
617         return acd_request_wait(cdp, ATAPI_PAUSE, 
618                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
619
620     case CDIOCSTART:
621         return acd_request_wait(cdp, ATAPI_START_STOP,
622                                 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0);
623
624     case CDIOCSTOP:
625         return acd_request_wait(cdp, ATAPI_START_STOP,
626                                 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
627
628     case CDIOCALLOW:
629         acd_select_slot(cdp);
630         cdp->flags &= ~F_LOCKED;
631         return acd_request_wait(cdp, ATAPI_PREVENT_ALLOW,
632                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
633
634     case CDIOCPREVENT:
635         acd_select_slot(cdp);
636         cdp->flags |= F_LOCKED;
637         return acd_request_wait(cdp, ATAPI_PREVENT_ALLOW,
638                                 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0);
639
640     case CDIOCRESET:
641         error = suser(p);
642         if (error)
643             return (error);
644         return acd_request_wait(cdp, ATAPI_TEST_UNIT_READY,
645                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
646
647     case CDIOCEJECT:
648         if ((cdp->flags & F_BOPEN) && cdp->refcnt)
649             return EBUSY;
650         return acd_eject(cdp, 0);
651
652     case CDIOCCLOSE:
653         if ((cdp->flags & F_BOPEN) && cdp->refcnt)
654             return 0;
655         return acd_eject(cdp, 1);
656
657     case CDIOREADTOCHEADER:
658         if (!cdp->toc.hdr.ending_track)
659             return EIO;
660         bcopy(&cdp->toc.hdr, addr, sizeof(cdp->toc.hdr));
661         break;
662
663     case CDIOREADTOCENTRYS:
664         {
665             struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)addr;
666             struct toc *toc = &cdp->toc;
667             struct toc buf;
668             u_long len;
669             u_char starting_track = te->starting_track;
670
671             if (!cdp->toc.hdr.ending_track)
672                 return EIO;
673
674             if (te->data_len < sizeof(toc->tab[0]) || 
675                 (te->data_len % sizeof(toc->tab[0])) != 0 || 
676                 (te->address_format != CD_MSF_FORMAT &&
677                 te->address_format != CD_LBA_FORMAT))
678                 return EINVAL;
679
680             if (!starting_track)
681                 starting_track = toc->hdr.starting_track;
682             else if (starting_track == 170) 
683                 starting_track = toc->hdr.ending_track + 1;
684             else if (starting_track < toc->hdr.starting_track ||
685                      starting_track > toc->hdr.ending_track + 1)
686                 return EINVAL;
687
688             len = ((toc->hdr.ending_track + 1 - starting_track) + 1) *
689                   sizeof(toc->tab[0]);
690             if (te->data_len < len)
691                 len = te->data_len;
692             if (len > sizeof(toc->tab))
693                 return EINVAL;
694
695             if (te->address_format == CD_MSF_FORMAT) {
696                 struct cd_toc_entry *entry;
697
698                 buf = cdp->toc;
699                 toc = &buf;
700                 entry = toc->tab + (toc->hdr.ending_track + 1 -
701                         toc->hdr.starting_track) + 1;
702                 while (--entry >= toc->tab)
703                     lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute,
704                             &entry->addr.msf.second, &entry->addr.msf.frame);
705             }
706             return copyout(toc->tab + starting_track - toc->hdr.starting_track,
707                            te->data, len);
708         }
709
710     case CDIOREADTOCENTRY:
711         {
712             struct ioc_read_toc_single_entry *te =
713                 (struct ioc_read_toc_single_entry *)addr;
714             struct toc *toc = &cdp->toc;
715             struct toc buf;
716             u_char track = te->track;
717
718             if (!cdp->toc.hdr.ending_track)
719                 return EIO;
720
721             if (te->address_format != CD_MSF_FORMAT && 
722                 te->address_format != CD_LBA_FORMAT)
723                 return EINVAL;
724
725             if (!track)
726                 track = toc->hdr.starting_track;
727             else if (track == 170)
728                 track = toc->hdr.ending_track + 1;
729             else if (track < toc->hdr.starting_track ||
730                      track > toc->hdr.ending_track + 1)
731                 return EINVAL;
732
733             if (te->address_format == CD_MSF_FORMAT) {
734                 struct cd_toc_entry *entry;
735
736                 buf = cdp->toc;
737                 toc = &buf;
738                 entry = toc->tab + (track - toc->hdr.starting_track);
739                 lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute,
740                         &entry->addr.msf.second, &entry->addr.msf.frame);
741             }
742             bcopy(toc->tab + track - toc->hdr.starting_track,
743                   &te->entry, sizeof(struct cd_toc_entry));
744         }
745         break;
746
747     case CDIOCREADSUBCHANNEL:
748         {
749             struct ioc_read_subchannel *args =
750                 (struct ioc_read_subchannel *)addr;
751             struct cd_sub_channel_info data;
752             u_long len = args->data_len;
753             int abslba, rellba;
754
755             if (len > sizeof(data) ||
756                 len < sizeof(struct cd_sub_channel_header))
757                 return EINVAL;
758
759             if (acd_request_wait(cdp, ATAPI_READ_SUBCHANNEL,
760                                  0, 0x40, 1, 0, 0, 0, 
761                                  sizeof(cdp->subchan)>>8, sizeof(cdp->subchan),
762                                  0,
763                                  (char *)&cdp->subchan, 
764                                  sizeof(cdp->subchan)) != 0)
765                 return EIO;
766             if (cdp->flags & F_DEBUG)
767                 atapi_dump(cdp->ata->ctrlr, cdp->lun, "subchan", &cdp->subchan, 
768                            sizeof(cdp->subchan));
769
770             abslba = cdp->subchan.abslba;
771             rellba = cdp->subchan.rellba;
772             if (args->address_format == CD_MSF_FORMAT) {
773                 lba2msf(ntohl(abslba),
774                     &data.what.position.absaddr.msf.minute,
775                     &data.what.position.absaddr.msf.second,
776                     &data.what.position.absaddr.msf.frame);
777                 lba2msf(ntohl(rellba),
778                     &data.what.position.reladdr.msf.minute,
779                     &data.what.position.reladdr.msf.second,
780                     &data.what.position.reladdr.msf.frame);
781             } else {
782                 data.what.position.absaddr.lba = abslba;
783                 data.what.position.reladdr.lba = rellba;
784             }
785             data.header.audio_status = cdp->subchan.audio_status;
786             data.what.position.control = cdp->subchan.control & 0xf;
787             data.what.position.addr_type = cdp->subchan.control >> 4;
788             data.what.position.track_number = cdp->subchan.track;
789             data.what.position.index_number = cdp->subchan.indx;
790             return copyout(&data, args->data, len);
791         }
792
793     case CDIOCPLAYMSF:
794         {
795             struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
796
797             return acd_request_wait(cdp, ATAPI_PLAY_MSF, 0, 0,
798                                     args->start_m, args->start_s, args->start_f,
799                                     args->end_m, args->end_s, args->end_f,
800                                     0, 0, 0);
801         }
802
803     case CDIOCPLAYBLOCKS:
804         {
805             struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
806
807             return acd_request_wait(cdp, ATAPI_PLAY_BIG, 0,
808                                     args->blk>>24 & 0xff, args->blk>>16 & 0xff,
809                                     args->blk>>8 & 0xff, args->blk & 0xff,
810                                     args->len>>24 & 0xff, args->len>>16 & 0xff,
811                                     args->len>>8 & 0xff, args->len & 0xff,
812                                     0, 0);
813         }
814
815     case CDIOCPLAYTRACKS:
816         {
817             struct ioc_play_track *args = (struct ioc_play_track *)addr;
818             u_long start, len;
819             int t1, t2;
820
821             if (!cdp->toc.hdr.ending_track)
822                 return EIO;
823
824             if (args->end_track < cdp->toc.hdr.ending_track + 1)
825                 ++args->end_track;
826             if (args->end_track > cdp->toc.hdr.ending_track + 1)
827                 args->end_track = cdp->toc.hdr.ending_track + 1;
828             t1 = args->start_track - cdp->toc.hdr.starting_track;
829             t2 = args->end_track - cdp->toc.hdr.starting_track;
830             if (t1 < 0 || t2 < 0)
831                 return EINVAL;
832             start = ntohl(cdp->toc.tab[t1].addr.lba);
833             len = ntohl(cdp->toc.tab[t2].addr.lba) - start;
834
835             return acd_request_wait(cdp, ATAPI_PLAY_BIG, 0,
836                                     start>>24 & 0xff, start>>16 & 0xff,
837                                     start>>8 & 0xff, start & 0xff,
838                                     len>>24 & 0xff, len>>16 & 0xff,
839                                     len>>8 & 0xff, len & 0xff, 0, 0);
840         }
841
842     case CDIOCREADAUDIO:
843         {
844             struct ioc_read_audio* args = (struct ioc_read_audio*) addr;
845             int lba, frames, result = 0;
846             u_char *buffer, *ubuf = args->buffer;
847
848             if (!cdp->toc.hdr.ending_track)
849                 return EIO;
850                 
851             if ((frames = args->nframes) < 0)
852                 return EINVAL;
853
854             if (args->address_format == CD_LBA_FORMAT)
855                 lba = args->address.lba;
856             else if (args->address_format == CD_MSF_FORMAT)
857                 lba = msf2lba(args->address.msf.minute,
858                              args->address.msf.second,
859                              args->address.msf.frame);
860             else
861                 return EINVAL;
862 #ifndef CD_BUFFER_BLOCKS
863 #define CD_BUFFER_BLOCKS 8
864 #endif
865             if (!(buffer = malloc(CD_BUFFER_BLOCKS * 2352, M_TEMP, M_NOWAIT)))
866                 return ENOMEM;
867
868             while (frames > 0) {
869                 u_char blocks;
870                 int size;
871
872                 blocks = (frames>CD_BUFFER_BLOCKS) ? CD_BUFFER_BLOCKS : frames;
873                 size = blocks * 2352;
874
875                 result = acd_request_wait(cdp, ATAPI_READ_CD, 4,
876                                           lba>>24, (lba>>16)&0xff,
877                                           (lba>>8)&0xff, lba&0xff, 0, 0,
878                                           blocks, 0xf0, buffer, size);
879                 if (result != 0)
880                     break;
881
882                 result = copyout(buffer, ubuf, size);
883                 if (result != 0)
884                     break;
885                     
886                 ubuf += size;
887                 frames -= blocks;
888                 lba += blocks;
889             }
890
891             free(buffer, M_TEMP);
892             return result;
893         }
894
895     case CDIOCGETVOL:
896         {
897             struct ioc_vol *arg = (struct ioc_vol *)addr;
898
899             error = acd_request_wait(cdp, ATAPI_MODE_SENSE, 0, CDROM_AUDIO_PAGE,
900                                      0, 0, 0, 0, 
901                                      sizeof(cdp->au)>>8, sizeof(cdp->au), 0,
902                                      (char *)&cdp->au, sizeof(cdp->au));
903             if (error)
904                 return error;
905             if (cdp->flags & F_DEBUG)
906                 atapi_dump(cdp->ata->ctrlr, cdp->lun, "au", &cdp->au,
907                            sizeof(cdp->au));
908             if (cdp->au.page_code != CDROM_AUDIO_PAGE)
909                 return EIO;
910             arg->vol[0] = cdp->au.port[0].volume;
911             arg->vol[1] = cdp->au.port[1].volume;
912             arg->vol[2] = cdp->au.port[2].volume;
913             arg->vol[3] = cdp->au.port[3].volume;
914         }
915         break;
916
917     case CDIOCSETVOL:
918         {
919             struct ioc_vol *arg = (struct ioc_vol *)addr;
920
921             error = acd_request_wait(cdp, ATAPI_MODE_SENSE, 0, CDROM_AUDIO_PAGE,
922                                      0, 0, 0, 0, 
923                                      sizeof(cdp->au)>>8, sizeof(cdp->au), 0,
924                                      (char *)&cdp->au, sizeof(cdp->au));
925             if (error)
926                 return error;
927             if (cdp->flags & F_DEBUG)
928                 atapi_dump(cdp->ata->ctrlr, cdp->lun, "au", &cdp->au, 
929                            sizeof(cdp->au));
930             if (cdp->au.page_code != CDROM_AUDIO_PAGE)
931                 return EIO;
932
933             error = acd_request_wait(cdp, ATAPI_MODE_SENSE, 0, 
934                                      CDROM_AUDIO_PAGE_MASK, 0, 0, 0, 0, 
935                                      sizeof(cdp->aumask)>>8,sizeof(cdp->aumask),
936                                      0,
937                                      (char *)&cdp->aumask, sizeof(cdp->aumask));
938             if (error)
939                 return error;
940             if (cdp->flags & F_DEBUG)
941                 atapi_dump(cdp->ata->ctrlr, cdp->lun, "mask", &cdp->aumask, 
942                            sizeof(cdp->aumask));
943
944             cdp->au.data_length = 0;
945             cdp->au.port[0].channels = CHANNEL_0;
946             cdp->au.port[1].channels = CHANNEL_1;
947             cdp->au.port[0].volume = arg->vol[0] & cdp->aumask.port[0].volume;
948             cdp->au.port[1].volume = arg->vol[1] & cdp->aumask.port[1].volume;
949             cdp->au.port[2].volume = arg->vol[2] & cdp->aumask.port[2].volume;
950             cdp->au.port[3].volume = arg->vol[3] & cdp->aumask.port[3].volume;
951             return acd_request_wait(cdp, ATAPI_MODE_SELECT, 0x10,
952                                     0, 0, 0, 0, 0, 
953                                     sizeof(cdp->au)>>8, sizeof(cdp->au),
954                                     0, (char *)&cdp->au, -sizeof(cdp->au));
955         }
956
957     case CDIOCSETPATCH:
958         {
959             struct ioc_patch *arg = (struct ioc_patch *)addr;
960
961             return acd_setchan(cdp, arg->patch[0], arg->patch[1],
962                                arg->patch[2], arg->patch[3]);
963         }
964
965     case CDIOCSETMONO:
966         return acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0, 0);
967
968     case CDIOCSETSTEREO:
969         return acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0);
970
971     case CDIOCSETMUTE:
972         return acd_setchan(cdp, 0, 0, 0, 0);
973
974     case CDIOCSETLEFT:
975         return acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0);
976
977     case CDIOCSETRIGHT:
978         return acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0);
979
980     case CDRIOCNEXTWRITEABLEADDR:
981         {
982             struct acd_track_info track_info;
983
984             if ((error = acd_read_track_info(cdp, 0xff, &track_info)))
985                 break;
986             if (!track_info.nwa_valid)
987                 return EINVAL;
988             cdp->next_writeable_lba = track_info.next_writeable_addr;
989             *(int*)addr = track_info.next_writeable_addr;
990         }
991         break;
992  
993     case WORMIOCPREPDISK:
994         {
995             struct wormio_prepare_disk *w = (struct wormio_prepare_disk *)addr;
996
997             if (w->dummy != 0 && w->dummy != 1)
998                 error = EINVAL;
999             else {
1000                 error = acd_open_disk(cdp, w->dummy);
1001                 if (error == 0) {
1002                     cdp->flags |= F_DISK_PREPED;
1003                     cdp->dummy = w->dummy;
1004                     cdp->speed = w->speed;
1005                 }
1006             }
1007         }
1008         break;
1009
1010     case WORMIOCPREPTRACK:
1011         {
1012             struct wormio_prepare_track *w =(struct wormio_prepare_track *)addr;
1013
1014             if (w->audio != 0 && w->audio != 1)
1015                 error = EINVAL;
1016             else if (w->audio == 0 && w->preemp)
1017                 error = EINVAL;
1018             else if ((cdp->flags & F_DISK_PREPED) == 0) {
1019                 error = EINVAL;
1020                 printf("wcd%d: sequence error (PREP_TRACK)\n", cdp->lun);
1021             } else {
1022                 cdp->flags |= F_TRACK_PREP;
1023                 cdp->preptrack = *w;
1024             }
1025         }
1026         break;
1027
1028     case WORMIOCFINISHTRACK:
1029         if ((cdp->flags & F_TRACK_PREPED) != 0)
1030             error = acd_close_track(cdp);
1031         cdp->flags &= ~(F_TRACK_PREPED | F_TRACK_PREP);
1032         break;
1033
1034     case WORMIOCFIXATION:
1035         {
1036             struct wormio_fixation *w =
1037             (struct wormio_fixation *)addr;
1038
1039             if ((cdp->flags & F_WRITTEN) == 0)
1040                 error = EINVAL;
1041             else if (w->toc_type < 0 /* WORM_TOC_TYPE_AUDIO */ ||
1042                 w->toc_type > 4 /* WORM_TOC_TYPE_CDI */ )
1043                 error = EINVAL;
1044             else if (w->onp != 0 && w->onp != 1)
1045                 error = EINVAL;
1046             else {
1047                 /* no fixation needed if dummy write */
1048                 if (cdp->dummy == 0)
1049                     error = acd_close_disk(cdp);
1050                 cdp->flags &=
1051                     ~(F_WRITTEN|F_DISK_PREPED|F_TRACK_PREP|F_TRACK_PREPED);
1052             }
1053         }
1054         break;
1055
1056     case CDRIOCBLANK:
1057         return acd_blank_disk(cdp);
1058
1059     default:
1060         return ENOTTY;
1061     }
1062     return error;
1063 }
1064
1065 static int 
1066 acd_read_toc(struct acd *cdp)
1067 {
1068     int ntracks, len;
1069     struct atapires result;
1070
1071     bzero(&cdp->toc, sizeof(cdp->toc));
1072     bzero(&cdp->info, sizeof(cdp->info));
1073
1074     acd_select_slot(cdp);
1075
1076     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_TEST_UNIT_READY,
1077                                 0, 0, 0, 0, 0, 0, 0, 0,
1078                                 0, 0, 0, 0, 0, 0, 0, 0, 0);
1079
1080     if (result.code == RES_ERR &&
1081         (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION) {
1082         cdp->flags |= F_MEDIA_CHANGED;
1083         cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED);
1084         result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_TEST_UNIT_READY,
1085                                     0, 0, 0, 0, 0, 0, 0, 0,
1086                                     0, 0, 0, 0, 0, 0, 0, 0, 0);
1087     }
1088
1089     if (result.code) {
1090         atapi_error(cdp->ata, cdp->unit, result);
1091         return EIO;
1092     }
1093
1094     cdp->flags &= ~F_MEDIA_CHANGED;
1095
1096     len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry);
1097     if (acd_request_wait(cdp, ATAPI_READ_TOC, 0, 0, 0, 0, 0, 0,
1098                          len>>8, len & 0xff, 0, (char *)&cdp->toc, len) != 0) {
1099         bzero(&cdp->toc, sizeof(cdp->toc));
1100         return 0;
1101     }
1102     ntracks = cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1;
1103     if (ntracks <= 0 || ntracks > MAXTRK) {
1104         bzero(&cdp->toc, sizeof(cdp->toc));
1105         return 0;
1106     }
1107
1108     len = sizeof(struct ioc_toc_header) + ntracks * sizeof(struct cd_toc_entry);
1109     if (acd_request_wait(cdp, ATAPI_READ_TOC, 0, 0, 0, 0, 0, 0,
1110                          len>>8, len & 0xff, 0, (char *)&cdp->toc, len) & 0xff){
1111         bzero(&cdp->toc, sizeof(cdp->toc));
1112         return 0;
1113     }
1114
1115     cdp->toc.hdr.len = ntohs(cdp->toc.hdr.len);
1116
1117     if (acd_request_wait(cdp, ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1118                          (char *)&cdp->info, sizeof(cdp->info)) != 0)
1119         bzero(&cdp->info, sizeof(cdp->info));
1120
1121     cdp->toc.tab[ntracks].control = cdp->toc.tab[ntracks - 1].control;
1122     cdp->toc.tab[ntracks].addr_type = cdp->toc.tab[ntracks - 1].addr_type;
1123     cdp->toc.tab[ntracks].track = 170;
1124     cdp->toc.tab[ntracks].addr.lba = cdp->info.volsize;
1125
1126     cdp->info.volsize = ntohl(cdp->info.volsize);
1127     cdp->info.blksize = ntohl(cdp->info.blksize);
1128
1129     if (cdp->info.volsize && cdp->toc.hdr.ending_track
1130         && (cdp->flags & F_DEBUG)) {
1131         printf("wcd%d: ", cdp->lun);
1132         if (cdp->toc.tab[0].control & 4)
1133             printf("%ldMB ", cdp->info.volsize / 512);
1134         else
1135             printf("%ld:%ld audio ", cdp->info.volsize / 75 / 60,
1136                 cdp->info.volsize / 75 % 60);
1137         printf("(%ld sectors (%ld bytes)), %d tracks\n", 
1138             cdp->info.volsize, cdp->info.blksize,
1139             cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1);
1140     }
1141     return 0;
1142 }
1143
1144 /*
1145  * Set up the audio channel masks.
1146  */
1147 static int 
1148 acd_setchan(struct acd *cdp, u_char c0, u_char c1, u_char c2, u_char c3)
1149 {
1150     int error;
1151
1152     error = acd_request_wait(cdp, ATAPI_MODE_SENSE, 0, CDROM_AUDIO_PAGE,
1153                              0, 0, 0, 0, 
1154                              sizeof(cdp->au)>>8, sizeof(cdp->au), 0,
1155                              (char *)&cdp->au, sizeof(cdp->au));
1156     if (error)
1157         return error;
1158     if (cdp->flags & F_DEBUG)
1159         atapi_dump(cdp->ata->ctrlr, cdp->lun, "au", &cdp->au, sizeof(cdp->au));
1160     if (cdp->au.page_code != CDROM_AUDIO_PAGE)
1161         return EIO;
1162
1163     cdp->au.data_length = 0;
1164     cdp->au.port[0].channels = c0;
1165     cdp->au.port[1].channels = c1;
1166     cdp->au.port[2].channels = c2;
1167     cdp->au.port[3].channels = c3;
1168     return acd_request_wait(cdp, ATAPI_MODE_SELECT, 0x10,
1169                             0, 0, 0, 0, 0, 
1170                             sizeof(cdp->au)>>8, sizeof(cdp->au), 0,
1171                             (char *)&cdp->au, -sizeof(cdp->au));
1172 }
1173
1174 static int 
1175 acd_eject(struct acd *cdp, int close)
1176 {
1177     struct atapires result;
1178
1179     acd_select_slot(cdp);
1180
1181     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_START_STOP, 1,
1182                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1183
1184     if (result.code == RES_ERR &&
1185         ((result.error & AER_SKEY) == AER_SK_NOT_READY ||
1186         (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION)) {
1187         int err;
1188
1189         if (!close)
1190             return 0;
1191         err = acd_request_wait(cdp, ATAPI_START_STOP, 0, 0, 0, 3,
1192                                0, 0, 0, 0, 0, 0, 0);
1193         if (err)
1194             return err;
1195
1196         acd_read_toc(cdp);
1197
1198         acd_request_wait(cdp, ATAPI_PREVENT_ALLOW, 0, 0, 0, 1,
1199                          0, 0, 0, 0, 0, 0, 0);
1200         cdp->flags |= F_LOCKED;
1201         return 0;
1202     }
1203     if (result.code) {
1204         atapi_error(cdp->ata, cdp->unit, result);
1205         return EIO;
1206     }
1207     if (close)
1208         return 0;
1209
1210     tsleep((caddr_t) &lbolt, PRIBIO, "wcdej1", 0);
1211     tsleep((caddr_t) &lbolt, PRIBIO, "wcdej2", 0);
1212
1213     acd_request_wait(cdp, ATAPI_PREVENT_ALLOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1214     cdp->flags &= ~F_LOCKED;
1215
1216     cdp->flags |= F_MEDIA_CHANGED;
1217     cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED);
1218     return acd_request_wait(cdp, ATAPI_START_STOP, 0, 0, 0, 2,
1219                             0, 0, 0, 0, 0, 0, 0);
1220 }
1221
1222 static void
1223 acd_select_slot(struct acd *cdp)
1224 {
1225     if (cdp->slot < 0 || cdp->changer_info->current_slot == cdp->slot)
1226         return;
1227
1228     /* Unlock (might not be needed but its cheaper than asking) */
1229     acd_request_wait(cdp, ATAPI_PREVENT_ALLOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1230
1231     /* Unload the current media from player */
1232     acd_request_wait(cdp, ATAPI_LOAD_UNLOAD, 0, 0, 0, 2,
1233                      0, 0, 0, cdp->changer_info->current_slot, 0, 0, 0);
1234
1235     /* load the wanted slot */
1236     acd_request_wait(cdp, ATAPI_LOAD_UNLOAD, 0, 0, 0, 3,
1237                      0, 0, 0, cdp->slot, 0, 0, 0);
1238
1239     cdp->changer_info->current_slot = cdp->slot;
1240
1241     /* Lock the media if needed */
1242     if (cdp->flags & F_LOCKED) {
1243         acd_request_wait(cdp, ATAPI_PREVENT_ALLOW, 0, 0, 0, 1,
1244                          0, 0, 0, 0, 0, 0, 0);
1245     }
1246 }
1247
1248 static int
1249 acd_open_disk(struct acd *cdp, int test)
1250 {
1251     cdp->next_writeable_lba = 0;
1252     return 0;
1253 }
1254
1255 static int
1256 acd_close_disk(struct acd *cdp)
1257 {
1258     return acd_request_wait(cdp, ATAPI_CLOSE_TRACK, 0x00,
1259                             0x02, 0, 0, 0/*track*/, 0, 0, 0, 0, 0, 0);
1260 }
1261
1262 static int
1263 acd_open_track(struct acd *cdp, struct wormio_prepare_track *ptp)
1264 {
1265     struct write_param param;
1266     struct atapires result;
1267
1268     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_MODE_SENSE,
1269                                 0, 0x05, 0, 0, 0, 0, 
1270                                 sizeof(param)>>8, sizeof(param),
1271                                 0, 0, 0, 0, 0, 0, 0,
1272                                 (char *)&param, sizeof(param));
1273
1274     if (cdp->flags & F_DEBUG)
1275         atapi_dump(cdp->ata->ctrlr, cdp->lun, "0x05", &param, sizeof(param));
1276
1277     if (result.code == RES_UNDERRUN)
1278         result.code = 0;
1279
1280     if (result.code) {
1281         atapi_error(cdp->ata, cdp->unit, result);
1282         return EIO;
1283     }
1284     param.page_code = 0x05;
1285     param.page_length = 0x32;
1286     param.test_write = cdp->dummy ? 1 : 0;
1287     param.write_type = CDR_WTYPE_TRACK;
1288
1289     switch (ptp->audio) {
1290 /*    switch (data_type) { */
1291
1292     case 0:
1293 /*    case CDR_DATA: */
1294         cdp->block_size = 2048;
1295         param.track_mode = CDR_TMODE_DATA;
1296         param.data_block_type = CDR_DB_ROM_MODE1;
1297         param.session_format = CDR_SESS_CDROM;
1298         break;
1299
1300     default:
1301 /*    case CDR_AUDIO: */
1302         cdp->block_size = 2352;
1303         if (ptp->preemp)
1304             param.track_mode = CDR_TMODE_AUDIO;
1305         else
1306             param.track_mode = 0;
1307         param.data_block_type = CDR_DB_RAW;
1308         param.session_format = CDR_SESS_CDROM;
1309         break;
1310
1311 /*
1312     case CDR_MODE2:
1313         param.track_mode = CDR_TMODE_DATA;
1314         param.data_block_type = CDR_DB_ROM_MODE2;
1315         param.session_format = CDR_SESS_CDROM;
1316         break;
1317
1318     case CDR_XA1:
1319         param.track_mode = CDR_TMODE_DATA;
1320         param.data_block_type = CDR_DB_XA_MODE1;
1321         param.session_format = CDR_SESS_CDROM_XA;
1322         break;
1323
1324     case CDR_XA2:
1325         param.track_mode = CDR_TMODE_DATA;
1326         param.data_block_type = CDR_DB_XA_MODE2_F1;
1327         param.session_format = CDR_SESS_CDROM_XA;
1328         break;
1329
1330     case CDR_CDI:
1331         param.track_mode = CDR_TMODE_DATA;
1332         param.data_block_type = CDR_DB_XA_MODE2_F1;
1333         param.session_format = CDR_SESS_CDI;
1334         break;
1335 */
1336     }
1337
1338     param.multi_session = CDR_MSES_NONE;
1339     param.fp = 0;
1340     param.packet_size = 0;
1341
1342     if (cdp->flags & F_DEBUG)
1343         atapi_dump(cdp->ata->ctrlr, cdp->lun, "0x05", &param, sizeof(param));
1344
1345     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_MODE_SELECT,
1346                                 0x10, 0, 0, 0, 0, 0, 
1347                                 sizeof(param)>>8, sizeof(param),
1348                                 0, 0, 0, 0, 0, 0, 0,
1349                                 (char *)&param, -sizeof(param));
1350
1351     if (result.code == RES_UNDERRUN)
1352         result.code = 0;
1353
1354     if (result.code) {
1355         atapi_error(cdp->ata, cdp->unit, result);
1356         return EIO;
1357     }
1358     return 0;
1359 }
1360
1361 static int
1362 acd_close_track(struct acd *cdp)
1363 {
1364     return acd_request_wait(cdp, ATAPI_SYNCHRONIZE_CACHE, 0,
1365                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1366 }
1367
1368 static int
1369 acd_read_track_info(struct acd *cdp, int lba, struct acd_track_info *info)
1370 {
1371     int error;
1372
1373     error = acd_request_wait(cdp, ATAPI_READ_TRACK_INFO, 0x01,
1374                              lba>>24, (lba>>16)&0xff,
1375                              (lba>>8)&0xff, lba&0xff,
1376                              0, 
1377                              sizeof(*info)>>8, sizeof(*info), 0,
1378                              (char *)info, sizeof(*info));
1379     if (error)
1380         return error;
1381     info->track_start_addr = ntohl(info->track_start_addr);
1382     info->next_writeable_addr = ntohl(info->next_writeable_addr);
1383     info->free_blocks = ntohl(info->free_blocks);
1384     info->fixed_packet_size = ntohl(info->fixed_packet_size);
1385     info->track_length = ntohl(info->track_length);
1386     return 0;
1387 }
1388
1389 static int
1390 acd_blank_disk(struct acd *cdp)
1391 {
1392     int error;
1393
1394     error = acd_request_wait(cdp, 0xa1, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1395     cdp->flags |= F_MEDIA_CHANGED;
1396     cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED);
1397     return error;
1398 }
1399
1400 static void
1401 atapi_error(struct atapi *ata, int unit, struct atapires result)
1402 {
1403     if (result.code != RES_ERR) {
1404         printf("atapi%d:%d: ERROR %d, status=%b, error=%b\n", 
1405                ata->ctrlr, unit, result.code, result.status, 
1406                ARS_BITS, result.error, AER_BITS);
1407         return;
1408     }
1409     switch (result.error & AER_SKEY) {
1410     case AER_SK_NOT_READY:
1411         if (ata->debug)
1412             printf("atapi%d:%d: not ready\n", ata->ctrlr, unit);
1413         break;
1414
1415     case AER_SK_BLANK_CHECK:
1416         if (ata->debug)
1417             printf("atapi%d:%d: blank check\n", ata->ctrlr, unit);
1418         break;
1419
1420     case AER_SK_MEDIUM_ERROR:
1421         if (ata->debug)
1422             printf("atapi%d:%d: medium error\n", ata->ctrlr, unit);
1423         break;
1424
1425     case AER_SK_HARDWARE_ERROR:
1426         if (ata->debug)
1427             printf("atapi%d:%d: hardware error\n", ata->ctrlr, unit);
1428         break;
1429
1430     case AER_SK_ILLEGAL_REQUEST:
1431         if (ata->debug)
1432             printf("atapi%d:%d: illegal request\n", ata->ctrlr, unit);
1433         break;
1434
1435     case AER_SK_UNIT_ATTENTION:
1436         if (ata->debug)
1437             printf("atapi%d:%d: unit attention\n", ata->ctrlr, unit);
1438         break;
1439
1440     case AER_SK_DATA_PROTECT:
1441         if (ata->debug)
1442             printf("atapi%d:%d: reading protected data\n", ata->ctrlr, unit);
1443         break;
1444
1445     case AER_SK_ABORTED_COMMAND:
1446         if (ata->debug)
1447             printf("atapi%d:%d: command aborted\n", ata->ctrlr, unit);
1448         break;
1449
1450     case AER_SK_MISCOMPARE:
1451         if (ata->debug)
1452             printf("atapi%d:%d: data don't match medium\n", ata->ctrlr, unit);
1453         break;
1454
1455     default:
1456         if (ata->debug)
1457             printf("atapi%d:%d: unknown error, status=%b, error=%b\n", 
1458                    ata->ctrlr, unit, result.status, ARS_BITS, 
1459                    result.error, AER_BITS);
1460     }
1461 }
1462
1463 static void 
1464 atapi_dump(int ctrlr, int lun, char *label, void *data, int len)
1465 {
1466         u_char *p = data;
1467
1468         printf ("atapi%d%d: %s %x", ctrlr, lun, label, *p++);
1469         while (--len > 0) printf ("-%x", *p++);
1470         printf ("\n");
1471 }
1472
1473 static void 
1474 acd_drvinit(void *unused)
1475 {
1476     cdevsw_add(&acd_cdevsw);
1477 }
1478
1479 SYSINIT(acddev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, acd_drvinit, NULL)