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