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