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