This source file includes following definitions.
- mcdattach
- mcdlock
- mcdunlock
- mcdopen
- mcdclose
- mcdstrategy
- mcdstart
- mcdread
- mcdwrite
- mcdioctl
- mcdgetdisklabel
- mcd_get_parms
- mcdsize
- mcddump
- mcd_find
- mcdprobe
- mcd_getreply
- mcd_getstat
- mcd_getresult
- mcd_setflags
- mcd_send
- hsg2msf
- msf2hsg
- mcd_pseudointr
- mcdintr
- mcd_soft_reset
- mcd_hard_reset
- mcd_setmode
- mcd_setupc
- mcd_toc_header
- mcd_read_toc
- mcd_toc_entries
- mcd_stop
- mcd_getqchan
- mcd_read_subchannel
- mcd_playtracks
- mcd_playmsf
- mcd_playblocks
- mcd_pause
- mcd_resume
- mcd_eject
- mcd_setlock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 #include <sys/param.h>
60 #include <sys/systm.h>
61 #include <sys/kernel.h>
62 #include <sys/proc.h>
63 #include <sys/conf.h>
64 #include <sys/file.h>
65 #include <sys/buf.h>
66 #include <sys/stat.h>
67 #include <sys/uio.h>
68 #include <sys/ioctl.h>
69 #include <sys/mtio.h>
70 #include <sys/cdio.h>
71 #include <sys/errno.h>
72 #include <sys/disklabel.h>
73 #include <sys/device.h>
74 #include <sys/disk.h>
75 #include <sys/timeout.h>
76
77 #include <machine/cpu.h>
78 #include <machine/intr.h>
79 #include <machine/bus.h>
80
81 #include <dev/isa/isavar.h>
82 #include <dev/isa/mcdreg.h>
83 #include <dev/isa/opti.h>
84
85 #ifndef MCDDEBUG
86 #define MCD_TRACE(fmt,a,b,c,d)
87 #else
88 #define MCD_TRACE(fmt,a,b,c,d) {if (sc->debug) {printf("%s: st=%02x: ", sc->sc_dev.dv_xname, sc->status); printf(fmt,a,b,c,d);}}
89 #endif
90
91
92 #define MCD_MAXTOCS 104
93
94 struct mcd_mbx {
95 int retry, count;
96 struct buf *bp;
97 daddr64_t blkno;
98 int nblk;
99 int sz;
100 u_long skip;
101 int state;
102 #define MCD_S_IDLE 0
103 #define MCD_S_BEGIN 1
104 #define MCD_S_WAITMODE 2
105 #define MCD_S_WAITREAD 3
106 int mode;
107 };
108
109 struct mcd_softc {
110 struct device sc_dev;
111 struct disk sc_dk;
112 void *sc_ih;
113 struct timeout sc_pi_tmo;
114
115 bus_space_tag_t sc_iot;
116 bus_space_handle_t sc_ioh;
117
118 int irq, drq;
119
120 char *type;
121 int flags;
122 #define MCDF_LOCKED 0x01
123 #define MCDF_WANTED 0x02
124 #define MCDF_WLABEL 0x04
125 #define MCDF_LABELLING 0x08
126 #define MCDF_LOADED 0x10
127 #define MCDF_EJECTING 0x20
128 short status;
129 short audio_status;
130 int blksize;
131 u_long disksize;
132 struct mcd_volinfo volinfo;
133 union mcd_qchninfo toc[MCD_MAXTOCS];
134 struct mcd_command lastpb;
135 struct mcd_mbx mbx;
136 int lastmode;
137 #define MCD_MD_UNKNOWN -1
138 int lastupc;
139 #define MCD_UPC_UNKNOWN -1
140 struct buf buf_queue;
141 u_char readcmd;
142 u_char debug;
143 u_char probe;
144 };
145
146
147
148 cdev_decl(mcd);
149 bdev_decl(mcd);
150
151 u_int8_t const __bcd2bin[] = {
152 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
153 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0,
154 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0,
155 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0,
156 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 0, 0, 0, 0, 0, 0,
157 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 0, 0, 0, 0, 0, 0,
158 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 0, 0, 0, 0, 0, 0,
159 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 0, 0, 0, 0, 0, 0,
160 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0, 0, 0, 0, 0, 0,
161 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
162 };
163
164 u_int8_t const __bin2bcd[] = {
165 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
166 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
167 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
168 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
169 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
170 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
171 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
172 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
173 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
174 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99
175 };
176 #define bcd2bin(b) (__bcd2bin[(b)&0xff])
177 #define bin2bcd(b) (__bin2bcd[(b)&0xff])
178
179 static void hsg2msf(int, bcd_t *);
180 static daddr64_t msf2hsg(bcd_t *, int);
181
182 int mcd_playtracks(struct mcd_softc *, struct ioc_play_track *);
183 int mcd_playmsf(struct mcd_softc *, struct ioc_play_msf *);
184 int mcd_playblocks(struct mcd_softc *, struct ioc_play_blocks *);
185 int mcd_stop(struct mcd_softc *);
186 int mcd_eject(struct mcd_softc *);
187 int mcd_read_subchannel(struct mcd_softc *, struct ioc_read_subchannel *);
188 int mcd_pause(struct mcd_softc *);
189 int mcd_resume(struct mcd_softc *);
190 int mcd_toc_header(struct mcd_softc *, struct ioc_toc_header *);
191 int mcd_toc_entries(struct mcd_softc *, struct ioc_read_toc_entry *);
192
193 int mcd_getreply(struct mcd_softc *);
194 int mcd_getstat(struct mcd_softc *);
195 int mcd_getresult(struct mcd_softc *, struct mcd_result *);
196 void mcd_setflags(struct mcd_softc *);
197 int mcd_get(struct mcd_softc *, char *, int);
198 int mcd_send(struct mcd_softc *, struct mcd_mbox *, int);
199 int mcdintr(void *);
200 void mcd_soft_reset(struct mcd_softc *);
201 int mcd_hard_reset(struct mcd_softc *);
202 int mcd_setmode(struct mcd_softc *, int);
203 int mcd_setupc(struct mcd_softc *, int);
204 int mcd_read_toc(struct mcd_softc *);
205 int mcd_getqchan(struct mcd_softc *, union mcd_qchninfo *, int);
206 int mcd_setlock(struct mcd_softc *, int);
207
208 int mcd_find(bus_space_tag_t, bus_space_handle_t, struct mcd_softc *);
209 int mcdprobe(struct device *, void *, void *);
210 void mcdattach(struct device *, struct device *, void *);
211
212 struct cfattach mcd_ca = {
213 sizeof(struct mcd_softc), mcdprobe, mcdattach
214 };
215
216 struct cfdriver mcd_cd = {
217 NULL, "mcd", DV_DISK
218 };
219
220 void mcdgetdisklabel(dev_t, struct mcd_softc *, struct disklabel *, int);
221 int mcd_get_parms(struct mcd_softc *);
222 void mcdstrategy(struct buf *);
223 void mcdstart(struct mcd_softc *);
224 int mcdlock(struct mcd_softc *);
225 void mcdunlock(struct mcd_softc *);
226 void mcd_pseudointr(void *);
227
228 struct dkdriver mcddkdriver = { mcdstrategy };
229
230 #define MCD_RETRIES 3
231 #define MCD_RDRETRIES 3
232
233
234 #define RDELAY_WAITMODE 300
235 #define RDELAY_WAITREAD 800
236
237 #define DELAY_GRANULARITY 25
238 #define DELAY_GETREPLY 100000
239
240 void
241 mcdattach(parent, self, aux)
242 struct device *parent, *self;
243 void *aux;
244 {
245 struct mcd_softc *sc = (void *)self;
246 struct isa_attach_args *ia = aux;
247 bus_space_tag_t iot = ia->ia_iot;
248 bus_space_handle_t ioh;
249 struct mcd_mbox mbx;
250
251
252 if (bus_space_map(iot, ia->ia_iobase, MCD_NPORT, 0, &ioh)) {
253 printf(": can't map i/o space\n");
254 return;
255 }
256
257 sc->sc_iot = iot;
258 sc->sc_ioh = ioh;
259
260 sc->probe = 0;
261 sc->debug = 0;
262
263 if (!mcd_find(iot, ioh, sc)) {
264 printf(": mcd_find failed\n");
265 return;
266 }
267
268 timeout_set(&sc->sc_pi_tmo, mcd_pseudointr, sc);
269
270
271
272
273 sc->sc_dk.dk_driver = &mcddkdriver;
274 sc->sc_dk.dk_name = sc->sc_dev.dv_xname;
275 disk_attach(&sc->sc_dk);
276
277 printf(": model %s\n", sc->type != 0 ? sc->type : "unknown");
278
279 (void) mcd_setlock(sc, MCD_LK_UNLOCK);
280
281 mbx.cmd.opcode = MCD_CMDCONFIGDRIVE;
282 mbx.cmd.length = sizeof(mbx.cmd.data.config) - 1;
283 mbx.cmd.data.config.subcommand = MCD_CF_IRQENABLE;
284 mbx.cmd.data.config.data1 = 0x01;
285 mbx.res.length = 0;
286 (void) mcd_send(sc, &mbx, 0);
287
288 mcd_soft_reset(sc);
289
290 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
291 IPL_BIO, mcdintr, sc, sc->sc_dev.dv_xname);
292 }
293
294
295
296
297
298
299
300 int
301 mcdlock(sc)
302 struct mcd_softc *sc;
303 {
304 int error;
305
306 while ((sc->flags & MCDF_LOCKED) != 0) {
307 sc->flags |= MCDF_WANTED;
308 if ((error = tsleep(sc, PRIBIO | PCATCH, "mcdlck", 0)) != 0)
309 return error;
310 }
311 sc->flags |= MCDF_LOCKED;
312 return 0;
313 }
314
315
316
317
318 void
319 mcdunlock(sc)
320 struct mcd_softc *sc;
321 {
322
323 sc->flags &= ~MCDF_LOCKED;
324 if ((sc->flags & MCDF_WANTED) != 0) {
325 sc->flags &= ~MCDF_WANTED;
326 wakeup(sc);
327 }
328 }
329
330 int
331 mcdopen(dev, flag, fmt, p)
332 dev_t dev;
333 int flag, fmt;
334 struct proc *p;
335 {
336 int error;
337 int unit, part;
338 struct mcd_softc *sc;
339
340 unit = DISKUNIT(dev);
341 if (unit >= mcd_cd.cd_ndevs)
342 return ENXIO;
343 sc = mcd_cd.cd_devs[unit];
344 if (!sc)
345 return ENXIO;
346
347 if ((error = mcdlock(sc)) != 0)
348 return error;
349
350 if (sc->sc_dk.dk_openmask != 0) {
351
352
353
354
355 if ((sc->flags & MCDF_LOADED) == 0) {
356 error = EIO;
357 goto bad3;
358 }
359 } else {
360
361
362
363
364
365 (void) mcd_setlock(sc, MCD_LK_LOCK);
366
367 if ((sc->flags & MCDF_LOADED) == 0) {
368
369 sc->lastmode = MCD_MD_UNKNOWN;
370 sc->lastupc = MCD_UPC_UNKNOWN;
371
372 sc->flags |= MCDF_LOADED;
373
374
375 if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
376 goto bad2;
377
378
379 if (mcd_get_parms(sc) != 0) {
380 error = ENXIO;
381 goto bad2;
382 }
383
384
385 if ((error = mcd_read_toc(sc)) != 0)
386 goto bad2;
387
388
389 mcdgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0);
390 }
391 }
392
393 MCD_TRACE("open: partition=%d disksize=%d blksize=%d\n", part,
394 sc->disksize, sc->blksize, 0);
395
396 part = DISKPART(dev);
397
398
399 if (part != RAW_PART &&
400 (part >= sc->sc_dk.dk_label->d_npartitions ||
401 sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
402 error = ENXIO;
403 goto bad;
404 }
405
406
407 switch (fmt) {
408 case S_IFCHR:
409 sc->sc_dk.dk_copenmask |= (1 << part);
410 break;
411 case S_IFBLK:
412 sc->sc_dk.dk_bopenmask |= (1 << part);
413 break;
414 }
415 sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
416
417 mcdunlock(sc);
418 return 0;
419
420 bad2:
421 sc->flags &= ~MCDF_LOADED;
422
423 bad:
424 if (sc->sc_dk.dk_openmask == 0) {
425 #if 0
426 (void) mcd_setmode(sc, MCD_MD_SLEEP);
427 #endif
428 (void) mcd_setlock(sc, MCD_LK_UNLOCK);
429 }
430
431 bad3:
432 mcdunlock(sc);
433 return error;
434 }
435
436 int
437 mcdclose(dev, flag, fmt, p)
438 dev_t dev;
439 int flag, fmt;
440 struct proc *p;
441 {
442 struct mcd_softc *sc = mcd_cd.cd_devs[DISKUNIT(dev)];
443 int part = DISKPART(dev);
444 int error;
445
446 MCD_TRACE("close: partition=%d\n", part, 0, 0, 0);
447
448 if ((error = mcdlock(sc)) != 0)
449 return error;
450
451 switch (fmt) {
452 case S_IFCHR:
453 sc->sc_dk.dk_copenmask &= ~(1 << part);
454 break;
455 case S_IFBLK:
456 sc->sc_dk.dk_bopenmask &= ~(1 << part);
457 break;
458 }
459 sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
460
461 if (sc->sc_dk.dk_openmask == 0) {
462
463
464 #if 0
465 (void) mcd_setmode(sc, MCD_MD_SLEEP);
466 #endif
467 (void) mcd_setlock(sc, MCD_LK_UNLOCK);
468 if (sc->flags & MCDF_EJECTING) {
469 mcd_eject(sc);
470 sc->flags &= ~MCDF_EJECTING;
471 }
472 }
473 mcdunlock(sc);
474 return 0;
475 }
476
477 void
478 mcdstrategy(bp)
479 struct buf *bp;
480 {
481 struct mcd_softc *sc = mcd_cd.cd_devs[DISKUNIT(bp->b_dev)];
482 int s;
483
484
485 MCD_TRACE("strategy: buf=0x%lx blkno=%ld bcount=%ld\n", bp,
486 bp->b_blkno, bp->b_bcount, 0);
487 if (bp->b_blkno < 0 ||
488 (bp->b_bcount % sc->blksize) != 0) {
489 printf("%s: strategy: blkno = %d bcount = %ld\n",
490 sc->sc_dev.dv_xname, bp->b_blkno, bp->b_bcount);
491 bp->b_error = EINVAL;
492 goto bad;
493 }
494
495
496 if ((sc->flags & MCDF_LOADED) == 0) {
497 MCD_TRACE("strategy: drive not valid\n", 0, 0, 0, 0);
498 bp->b_error = EIO;
499 goto bad;
500 }
501
502
503 if (bp->b_bcount == 0)
504 goto done;
505
506
507
508
509
510 if (DISKPART(bp->b_dev) != RAW_PART &&
511 bounds_check_with_label(bp, sc->sc_dk.dk_label,
512 (sc->flags & (MCDF_WLABEL|MCDF_LABELLING)) != 0) <= 0)
513 goto done;
514
515
516 s = splbio();
517 disksort(&sc->buf_queue, bp);
518 splx(s);
519 if (!sc->buf_queue.b_active)
520 mcdstart(sc);
521 return;
522
523 bad:
524 bp->b_flags |= B_ERROR;
525 done:
526 bp->b_resid = bp->b_bcount;
527 s = splbio();
528 biodone(bp);
529 splx(s);
530 }
531
532 void
533 mcdstart(sc)
534 struct mcd_softc *sc;
535 {
536 struct buf *bp, *dp = &sc->buf_queue;
537 int s;
538
539 loop:
540 s = splbio();
541
542 bp = dp->b_actf;
543 if (bp == NULL) {
544
545 dp->b_active = 0;
546 splx(s);
547 return;
548 }
549
550
551 MCD_TRACE("start: found block bp=0x%x\n", bp, 0, 0, 0);
552 dp->b_actf = bp->b_actf;
553 splx(s);
554
555
556 if ((sc->flags & MCDF_LOADED) == 0) {
557 MCD_TRACE("start: drive not valid\n", 0, 0, 0, 0);
558 bp->b_error = EIO;
559 bp->b_flags |= B_ERROR;
560 s = splbio();
561 biodone(bp);
562 splx(s);
563 goto loop;
564 }
565
566 dp->b_active = 1;
567
568
569 s = splbio();
570 disk_busy(&sc->sc_dk);
571 splx(s);
572
573 sc->mbx.retry = MCD_RDRETRIES;
574 sc->mbx.bp = bp;
575 sc->mbx.blkno = bp->b_blkno / (sc->blksize / DEV_BSIZE);
576 if (DISKPART(bp->b_dev) != RAW_PART) {
577 struct partition *p;
578 p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
579 sc->mbx.blkno += DL_GETPOFFSET(p);
580 }
581 sc->mbx.nblk = bp->b_bcount / sc->blksize;
582 sc->mbx.sz = sc->blksize;
583 sc->mbx.skip = 0;
584 sc->mbx.state = MCD_S_BEGIN;
585 sc->mbx.mode = MCD_MD_COOKED;
586
587 s = splbio();
588 (void) mcdintr(sc);
589 splx(s);
590 }
591
592 int
593 mcdread(dev, uio, flags)
594 dev_t dev;
595 struct uio *uio;
596 int flags;
597 {
598
599 return (physio(mcdstrategy, NULL, dev, B_READ, minphys, uio));
600 }
601
602 int
603 mcdwrite(dev, uio, flags)
604 dev_t dev;
605 struct uio *uio;
606 int flags;
607 {
608
609 return (physio(mcdstrategy, NULL, dev, B_WRITE, minphys, uio));
610 }
611
612 int
613 mcdioctl(dev, cmd, addr, flag, p)
614 dev_t dev;
615 u_long cmd;
616 caddr_t addr;
617 int flag;
618 struct proc *p;
619 {
620 struct mcd_softc *sc = mcd_cd.cd_devs[DISKUNIT(dev)];
621 struct disklabel *lp;
622 int error;
623
624 MCD_TRACE("ioctl: cmd=0x%x\n", cmd, 0, 0, 0);
625
626 if ((sc->flags & MCDF_LOADED) == 0)
627 return EIO;
628
629 switch (cmd) {
630 case DIOCRLDINFO:
631 lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
632 mcdgetdisklabel(dev, sc, lp, 0);
633 bcopy(lp, sc->sc_dk.dk_label, sizeof(*lp));
634 free(lp, M_TEMP);
635 return 0;
636
637 case DIOCGDINFO:
638 case DIOCGPDINFO:
639 *(struct disklabel *)addr = *(sc->sc_dk.dk_label);
640 return 0;
641
642 case DIOCGPART:
643 ((struct partinfo *)addr)->disklab = sc->sc_dk.dk_label;
644 ((struct partinfo *)addr)->part =
645 &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)];
646 return 0;
647
648 case DIOCWDINFO:
649 case DIOCSDINFO:
650 if ((flag & FWRITE) == 0)
651 return EBADF;
652
653 if ((error = mcdlock(sc)) != 0)
654 return error;
655 sc->flags |= MCDF_LABELLING;
656
657 error = setdisklabel(sc->sc_dk.dk_label,
658 (struct disklabel *)addr, 0);
659 if (error == 0) {
660 }
661
662 sc->flags &= ~MCDF_LABELLING;
663 mcdunlock(sc);
664 return error;
665
666 case DIOCWLABEL:
667 return EBADF;
668
669 case CDIOCPLAYTRACKS:
670 return mcd_playtracks(sc, (struct ioc_play_track *)addr);
671 case CDIOCPLAYMSF:
672 return mcd_playmsf(sc, (struct ioc_play_msf *)addr);
673 case CDIOCPLAYBLOCKS:
674 return mcd_playblocks(sc, (struct ioc_play_blocks *)addr);
675 case CDIOCREADSUBCHANNEL:
676 return mcd_read_subchannel(sc, (struct ioc_read_subchannel *)addr);
677 case CDIOREADTOCHEADER:
678 return mcd_toc_header(sc, (struct ioc_toc_header *)addr);
679 case CDIOREADTOCENTRYS:
680 return mcd_toc_entries(sc, (struct ioc_read_toc_entry *)addr);
681 case CDIOCSETPATCH:
682 case CDIOCGETVOL:
683 case CDIOCSETVOL:
684 case CDIOCSETMONO:
685 case CDIOCSETSTEREO:
686 case CDIOCSETMUTE:
687 case CDIOCSETLEFT:
688 case CDIOCSETRIGHT:
689 return EINVAL;
690 case CDIOCRESUME:
691 return mcd_resume(sc);
692 case CDIOCPAUSE:
693 return mcd_pause(sc);
694 case CDIOCSTART:
695 return EINVAL;
696 case CDIOCSTOP:
697 return mcd_stop(sc);
698 case MTIOCTOP:
699 if (((struct mtop *)addr)->mt_op != MTOFFL)
700 return EIO;
701
702 case CDIOCEJECT:
703 case DIOCEJECT:
704 sc->flags |= MCDF_EJECTING;
705 return (0);
706 case CDIOCALLOW:
707 return mcd_setlock(sc, MCD_LK_UNLOCK);
708 case CDIOCPREVENT:
709 return mcd_setlock(sc, MCD_LK_LOCK);
710 case DIOCLOCK:
711 return mcd_setlock(sc,
712 (*(int *)addr) ? MCD_LK_LOCK : MCD_LK_UNLOCK);
713 case CDIOCSETDEBUG:
714 sc->debug = 1;
715 return 0;
716 case CDIOCCLRDEBUG:
717 sc->debug = 0;
718 return 0;
719 case CDIOCRESET:
720 return mcd_hard_reset(sc);
721
722 default:
723 return ENOTTY;
724 }
725
726 #ifdef DIAGNOSTIC
727 panic("mcdioctl: impossible");
728 #endif
729 }
730
731 void
732 mcdgetdisklabel(dev, sc, lp, spoofonly)
733 dev_t dev;
734 struct mcd_softc *sc;
735 struct disklabel *lp;
736 int spoofonly;
737 {
738 char *errstring;
739
740 bzero(lp, sizeof(struct disklabel));
741
742 lp->d_secsize = sc->blksize;
743 lp->d_ntracks = 1;
744 lp->d_nsectors = 100;
745 lp->d_ncylinders = (sc->disksize / 100) + 1;
746 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
747 if (lp->d_secpercyl == 0) {
748 lp->d_secpercyl = 100;
749
750 }
751
752 strncpy(lp->d_typename, "Mitsumi CD-ROM", sizeof lp->d_typename);
753 lp->d_type = DTYPE_SCSI;
754 strncpy(lp->d_packname, "fictitious", sizeof lp->d_packname);
755 DL_SETDSIZE(lp, sc->disksize);
756 lp->d_rpm = 300;
757 lp->d_interleave = 1;
758 lp->d_version = 1;
759
760 lp->d_magic = DISKMAGIC;
761 lp->d_magic2 = DISKMAGIC;
762 lp->d_checksum = dkcksum(lp);
763
764
765
766
767 errstring = readdisklabel(DISKLABELDEV(dev), mcdstrategy, lp, spoofonly);
768 if (errstring) {
769
770 return;
771 }
772 }
773
774 int
775 mcd_get_parms(sc)
776 struct mcd_softc *sc;
777 {
778 struct mcd_mbox mbx;
779 daddr64_t size;
780 int error;
781
782
783 mbx.cmd.opcode = MCD_CMDGETVOLINFO;
784 mbx.cmd.length = 0;
785 mbx.res.length = sizeof(mbx.res.data.volinfo);
786 if ((error = mcd_send(sc, &mbx, 1)) != 0)
787 return error;
788
789 if (mbx.res.data.volinfo.trk_low == 0x00 &&
790 mbx.res.data.volinfo.trk_high == 0x00)
791 return EINVAL;
792
793
794 sc->volinfo = mbx.res.data.volinfo;
795 sc->blksize = MCD_BLKSIZE_COOKED;
796 size = msf2hsg(sc->volinfo.vol_msf, 0);
797 sc->disksize = size * (MCD_BLKSIZE_COOKED / DEV_BSIZE);
798 return 0;
799 }
800
801 daddr64_t
802 mcdsize(dev)
803 dev_t dev;
804 {
805
806
807 return -1;
808 }
809
810 int
811 mcddump(dev, blkno, va, size)
812 dev_t dev;
813 daddr64_t blkno;
814 caddr_t va;
815 size_t size;
816 {
817
818
819 return ENXIO;
820 }
821
822
823
824
825 int
826 mcd_find(iot, ioh, sc)
827 bus_space_tag_t iot;
828 bus_space_handle_t ioh;
829 struct mcd_softc *sc;
830 {
831 int i;
832 struct mcd_mbox mbx;
833
834 sc->sc_iot = iot;
835 sc->sc_ioh = ioh;
836
837
838 bus_space_write_1(iot, ioh, MCD_RESET, 0);
839 delay(1000000);
840
841 for (i = 10; i; i--)
842 bus_space_read_1(iot, ioh, MCD_STATUS);
843 delay(1000);
844
845
846 mbx.cmd.opcode = MCD_CMDGETSTAT;
847 mbx.cmd.length = 0;
848 mbx.res.length = 0;
849 if (mcd_send(sc, &mbx, 0) != 0)
850 return 0;
851
852
853 mbx.cmd.opcode = MCD_CMDCONTINFO;
854 mbx.cmd.length = 0;
855 mbx.res.length = sizeof(mbx.res.data.continfo);
856 if (mcd_send(sc, &mbx, 0) != 0)
857 return 0;
858
859
860
861
862
863
864
865
866
867
868 sc->readcmd = MCD_CMDREADSINGLESPEED;
869 switch (mbx.res.data.continfo.code) {
870 case 'M':
871 if (mbx.res.data.continfo.version <= 2)
872 sc->type = "LU002S";
873 else if (mbx.res.data.continfo.version <= 5)
874 sc->type = "LU005S";
875 else
876 sc->type = "LU006S";
877 break;
878 case 'F':
879 sc->type = "FX001";
880 break;
881 case 'D':
882 sc->type = "FX001D";
883 sc->readcmd = MCD_CMDREADDOUBLESPEED;
884 break;
885 default:
886 #ifdef MCDDEBUG
887 printf("%s: unrecognized drive version %c%02x; will try to use it anyway\n",
888 sc->sc_dev.dv_xname,
889 mbx.res.data.continfo.code, mbx.res.data.continfo.version);
890 #endif
891 sc->type = 0;
892 break;
893 }
894
895 return 1;
896
897 }
898
899 int
900 mcdprobe(parent, match, aux)
901 struct device *parent;
902 void *match;
903 void *aux;
904 {
905 struct isa_attach_args *ia = aux;
906 struct mcd_softc sc;
907 bus_space_tag_t iot = ia->ia_iot;
908 bus_space_handle_t ioh;
909 int rv;
910
911
912 if (ia->ia_iobase == -1 )
913 return (0);
914
915
916 if (bus_space_map(iot, ia->ia_iobase, MCD_NPORT, 0, &ioh))
917 return 0;
918
919 if (!opti_cd_setup(OPTI_MITSUMI, ia->ia_iobase, ia->ia_irq, ia->ia_drq))
920 ;
921
922 bzero(&sc, sizeof sc);
923 sc.debug = 0;
924 sc.probe = 1;
925
926 rv = mcd_find(iot, ioh, &sc);
927
928 bus_space_unmap(iot, ioh, MCD_NPORT);
929
930 if (rv) {
931 ia->ia_iosize = MCD_NPORT;
932 ia->ia_msize = 0;
933 }
934
935 return (rv);
936 }
937
938 int
939 mcd_getreply(sc)
940 struct mcd_softc *sc;
941 {
942 bus_space_tag_t iot = sc->sc_iot;
943 bus_space_handle_t ioh = sc->sc_ioh;
944 int i;
945
946
947 for (i = DELAY_GETREPLY; i; i--) {
948 if ((bus_space_read_1(iot, ioh, MCD_XFER) &
949 MCD_XF_STATUSUNAVAIL) == 0)
950 break;
951 delay(DELAY_GRANULARITY);
952 }
953 if (!i)
954 return -1;
955
956
957 return bus_space_read_1(iot, ioh, MCD_STATUS);
958 }
959
960 int
961 mcd_getstat(sc)
962 struct mcd_softc *sc;
963 {
964 struct mcd_mbox mbx;
965
966 mbx.cmd.opcode = MCD_CMDGETSTAT;
967 mbx.cmd.length = 0;
968 mbx.res.length = 0;
969 return mcd_send(sc, &mbx, 1);
970 }
971
972 int
973 mcd_getresult(sc, res)
974 struct mcd_softc *sc;
975 struct mcd_result *res;
976 {
977 int i, x;
978
979 if (sc->debug)
980 printf("%s: mcd_getresult: %d", sc->sc_dev.dv_xname,
981 res->length);
982
983 if ((x = mcd_getreply(sc)) < 0) {
984 if (sc->debug)
985 printf(" timeout\n");
986 else if (sc->probe == 0)
987 printf("%s: timeout in getresult\n", sc->sc_dev.dv_xname);
988 return EIO;
989 }
990 if (sc->debug)
991 printf(" %02x", (u_int)x);
992 sc->status = x;
993 mcd_setflags(sc);
994
995 if ((sc->status & MCD_ST_CMDCHECK) != 0)
996 return EINVAL;
997
998 for (i = 0; i < res->length; i++) {
999 if ((x = mcd_getreply(sc)) < 0) {
1000 if (sc->debug)
1001 printf(" timeout\n");
1002 else
1003 printf("%s: timeout in getresult\n", sc->sc_dev.dv_xname);
1004 return EIO;
1005 }
1006 if (sc->debug)
1007 printf(" %02x", (u_int)x);
1008 res->data.raw.data[i] = x;
1009 }
1010
1011 if (sc->debug)
1012 printf(" succeeded\n");
1013
1014 #ifdef MCDDEBUG
1015 delay(10);
1016 while ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, MCD_XFER) &
1017 MCD_XF_STATUSUNAVAIL) == 0) {
1018 x = bus_space_read_1(sc->sc_iot, sc->sc_ioh, MCD_STATUS);
1019 printf("%s: got extra byte %02x during getstatus\n",
1020 sc->sc_dev.dv_xname, (u_int)x);
1021 delay(10);
1022 }
1023 #endif
1024
1025 return 0;
1026 }
1027
1028 void
1029 mcd_setflags(sc)
1030 struct mcd_softc *sc;
1031 {
1032
1033
1034 if ((sc->flags & MCDF_LOADED) != 0 &&
1035 (sc->status & (MCD_ST_DSKCHNG | MCD_ST_DSKIN | MCD_ST_DOOROPEN)) !=
1036 MCD_ST_DSKIN) {
1037 if ((sc->status & MCD_ST_DOOROPEN) != 0)
1038 printf("%s: door open\n", sc->sc_dev.dv_xname);
1039 else if ((sc->status & MCD_ST_DSKIN) == 0)
1040 printf("%s: no disk present\n", sc->sc_dev.dv_xname);
1041 else if ((sc->status & MCD_ST_DSKCHNG) != 0)
1042 printf("%s: media change\n", sc->sc_dev.dv_xname);
1043 sc->flags &= ~MCDF_LOADED;
1044 }
1045
1046 if ((sc->status & MCD_ST_AUDIOBSY) != 0)
1047 sc->audio_status = CD_AS_PLAY_IN_PROGRESS;
1048 else if (sc->audio_status == CD_AS_PLAY_IN_PROGRESS ||
1049 sc->audio_status == CD_AS_AUDIO_INVALID)
1050 sc->audio_status = CD_AS_PLAY_COMPLETED;
1051 }
1052
1053 int
1054 mcd_send(sc, mbx, diskin)
1055 struct mcd_softc *sc;
1056 struct mcd_mbox *mbx;
1057 int diskin;
1058 {
1059 int retry, i, error;
1060 bus_space_tag_t iot = sc->sc_iot;
1061 bus_space_handle_t ioh = sc->sc_ioh;
1062
1063 if (sc->debug) {
1064 printf("%s: mcd_send: %d %02x", sc->sc_dev.dv_xname,
1065 mbx->cmd.length, (u_int)mbx->cmd.opcode);
1066 for (i = 0; i < mbx->cmd.length; i++)
1067 printf(" %02x", (u_int)mbx->cmd.data.raw.data[i]);
1068 printf("\n");
1069 }
1070
1071 for (retry = MCD_RETRIES; retry; retry--) {
1072 bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->cmd.opcode);
1073 for (i = 0; i < mbx->cmd.length; i++)
1074 bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->cmd.data.raw.data[i]);
1075 if ((error = mcd_getresult(sc, &mbx->res)) == 0)
1076 break;
1077 if (error == EINVAL)
1078 return error;
1079 }
1080 if (!retry)
1081 return error;
1082 if (diskin && (sc->flags & MCDF_LOADED) == 0)
1083 return EIO;
1084
1085 return 0;
1086 }
1087
1088 static void
1089 hsg2msf(hsg, msf)
1090 int hsg;
1091 bcd_t *msf;
1092 {
1093
1094 hsg += 150;
1095 F_msf(msf) = bin2bcd(hsg % 75);
1096 hsg /= 75;
1097 S_msf(msf) = bin2bcd(hsg % 60);
1098 hsg /= 60;
1099 M_msf(msf) = bin2bcd(hsg);
1100 }
1101
1102 static daddr64_t
1103 msf2hsg(msf, relative)
1104 bcd_t *msf;
1105 int relative;
1106 {
1107 daddr64_t blkno;
1108
1109 blkno = bcd2bin(M_msf(msf)) * 75 * 60 +
1110 bcd2bin(S_msf(msf)) * 75 +
1111 bcd2bin(F_msf(msf));
1112 if (!relative)
1113 blkno -= 150;
1114 return blkno;
1115 }
1116
1117 void
1118 mcd_pseudointr(v)
1119 void *v;
1120 {
1121 struct mcd_softc *sc = v;
1122 int s;
1123
1124 s = splbio();
1125 (void) mcdintr(sc);
1126 splx(s);
1127 }
1128
1129
1130
1131
1132
1133
1134
1135 int
1136 mcdintr(arg)
1137 void *arg;
1138 {
1139 struct mcd_softc *sc = arg;
1140 struct mcd_mbx *mbx = &sc->mbx;
1141 struct buf *bp = mbx->bp;
1142 bus_space_tag_t iot = sc->sc_iot;
1143 bus_space_handle_t ioh = sc->sc_ioh;
1144
1145 int i;
1146 u_char x;
1147 bcd_t msf[3];
1148
1149 switch (mbx->state) {
1150 case MCD_S_IDLE:
1151 return 0;
1152
1153 case MCD_S_BEGIN:
1154 tryagain:
1155 if (mbx->mode == sc->lastmode)
1156 goto firstblock;
1157
1158 sc->lastmode = MCD_MD_UNKNOWN;
1159 bus_space_write_1(iot, ioh, MCD_COMMAND, MCD_CMDSETMODE);
1160 bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->mode);
1161
1162 mbx->count = RDELAY_WAITMODE;
1163 mbx->state = MCD_S_WAITMODE;
1164
1165 case MCD_S_WAITMODE:
1166 timeout_del(&sc->sc_pi_tmo);
1167 for (i = 20; i; i--) {
1168 x = bus_space_read_1(iot, ioh, MCD_XFER);
1169 if ((x & MCD_XF_STATUSUNAVAIL) == 0)
1170 break;
1171 delay(50);
1172 }
1173 if (i == 0)
1174 goto hold;
1175 sc->status = bus_space_read_1(iot, ioh, MCD_STATUS);
1176 mcd_setflags(sc);
1177 if ((sc->flags & MCDF_LOADED) == 0)
1178 goto changed;
1179 MCD_TRACE("doread: got WAITMODE delay=%d\n",
1180 RDELAY_WAITMODE - mbx->count, 0, 0, 0);
1181
1182 sc->lastmode = mbx->mode;
1183
1184 firstblock:
1185 MCD_TRACE("doread: read blkno=%d for bp=0x%x\n", mbx->blkno,
1186 bp, 0, 0);
1187
1188
1189 hsg2msf(mbx->blkno, msf);
1190
1191
1192 bus_space_write_1(iot, ioh, MCD_COMMAND, sc->readcmd);
1193 bus_space_write_1(iot, ioh, MCD_COMMAND, msf[0]);
1194 bus_space_write_1(iot, ioh, MCD_COMMAND, msf[1]);
1195 bus_space_write_1(iot, ioh, MCD_COMMAND, msf[2]);
1196 bus_space_write_1(iot, ioh, MCD_COMMAND, 0);
1197 bus_space_write_1(iot, ioh, MCD_COMMAND, 0);
1198 bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->nblk);
1199
1200 mbx->count = RDELAY_WAITREAD;
1201 mbx->state = MCD_S_WAITREAD;
1202
1203 case MCD_S_WAITREAD:
1204 timeout_del(&sc->sc_pi_tmo);
1205 nextblock:
1206 loop:
1207 for (i = 20; i; i--) {
1208 x = bus_space_read_1(iot, ioh, MCD_XFER);
1209 if ((x & MCD_XF_DATAUNAVAIL) == 0)
1210 goto gotblock;
1211 if ((x & MCD_XF_STATUSUNAVAIL) == 0)
1212 break;
1213 delay(50);
1214 }
1215 if (i == 0)
1216 goto hold;
1217 sc->status = bus_space_read_1(iot, ioh, MCD_STATUS);
1218 mcd_setflags(sc);
1219 if ((sc->flags & MCDF_LOADED) == 0)
1220 goto changed;
1221 #if 0
1222 printf("%s: got status byte %02x during read\n",
1223 sc->sc_dev.dv_xname, (u_int)sc->status);
1224 #endif
1225 goto loop;
1226
1227 gotblock:
1228 MCD_TRACE("doread: got data delay=%d\n",
1229 RDELAY_WAITREAD - mbx->count, 0, 0, 0);
1230
1231
1232 bus_space_write_1(iot, ioh, MCD_CTL2, 0x04);
1233 bus_space_read_multi_1(iot, ioh, MCD_RDATA,
1234 bp->b_data + mbx->skip, mbx->sz);
1235 bus_space_write_1(iot, ioh, MCD_CTL2, 0x0c);
1236 mbx->blkno += 1;
1237 mbx->skip += mbx->sz;
1238 if (--mbx->nblk > 0)
1239 goto nextblock;
1240
1241 mbx->state = MCD_S_IDLE;
1242
1243
1244 bp->b_resid = 0;
1245 disk_unbusy(&sc->sc_dk, bp->b_bcount, (bp->b_flags & B_READ));
1246 biodone(bp);
1247
1248 mcdstart(sc);
1249 return 1;
1250
1251 hold:
1252 if (mbx->count-- < 0) {
1253 printf("%s: timeout in state %d",
1254 sc->sc_dev.dv_xname, mbx->state);
1255 goto readerr;
1256 }
1257
1258 #if 0
1259 printf("%s: sleep in state %d\n", sc->sc_dev.dv_xname,
1260 mbx->state);
1261 #endif
1262 timeout_add(&sc->sc_pi_tmo, hz / 100);
1263 return -1;
1264 }
1265
1266 readerr:
1267 if (mbx->retry-- > 0) {
1268 printf("; retrying\n");
1269 goto tryagain;
1270 } else
1271 printf("; giving up\n");
1272
1273 changed:
1274
1275 bp->b_flags |= B_ERROR;
1276 bp->b_resid = bp->b_bcount - mbx->skip;
1277 disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid),
1278 (bp->b_flags & B_READ));
1279 biodone(bp);
1280
1281 mcdstart(sc);
1282 return -1;
1283
1284 #ifdef notyet
1285 printf("%s: unit timeout; resetting\n", sc->sc_dev.dv_xname);
1286 bus_space_write_1(iot, ioh, MCD_RESET, MCD_CMDRESET);
1287 delay(300000);
1288 (void) mcd_getstat(sc, 1);
1289 (void) mcd_getstat(sc, 1);
1290
1291 sc->debug = 1;
1292 #endif
1293 }
1294
1295 void
1296 mcd_soft_reset(sc)
1297 struct mcd_softc *sc;
1298 {
1299
1300 sc->debug = 0;
1301 sc->flags = 0;
1302 sc->lastmode = MCD_MD_UNKNOWN;
1303 sc->lastupc = MCD_UPC_UNKNOWN;
1304 sc->audio_status = CD_AS_AUDIO_INVALID;
1305 bus_space_write_1(sc->sc_iot, sc->sc_ioh, MCD_CTL2, 0x0c);
1306 }
1307
1308 int
1309 mcd_hard_reset(sc)
1310 struct mcd_softc *sc;
1311 {
1312 struct mcd_mbox mbx;
1313
1314 mcd_soft_reset(sc);
1315
1316 mbx.cmd.opcode = MCD_CMDRESET;
1317 mbx.cmd.length = 0;
1318 mbx.res.length = 0;
1319 return mcd_send(sc, &mbx, 0);
1320 }
1321
1322 int
1323 mcd_setmode(sc, mode)
1324 struct mcd_softc *sc;
1325 int mode;
1326 {
1327 struct mcd_mbox mbx;
1328 int error;
1329
1330 if (sc->lastmode == mode)
1331 return 0;
1332 if (sc->debug)
1333 printf("%s: setting mode to %d\n", sc->sc_dev.dv_xname, mode);
1334 sc->lastmode = MCD_MD_UNKNOWN;
1335
1336 mbx.cmd.opcode = MCD_CMDSETMODE;
1337 mbx.cmd.length = sizeof(mbx.cmd.data.datamode);
1338 mbx.cmd.data.datamode.mode = mode;
1339 mbx.res.length = 0;
1340 if ((error = mcd_send(sc, &mbx, 1)) != 0)
1341 return error;
1342
1343 sc->lastmode = mode;
1344 return 0;
1345 }
1346
1347 int
1348 mcd_setupc(sc, upc)
1349 struct mcd_softc *sc;
1350 int upc;
1351 {
1352 struct mcd_mbox mbx;
1353 int error;
1354
1355 if (sc->lastupc == upc)
1356 return 0;
1357 if (sc->debug)
1358 printf("%s: setting upc to %d\n", sc->sc_dev.dv_xname, upc);
1359 sc->lastupc = MCD_UPC_UNKNOWN;
1360
1361 mbx.cmd.opcode = MCD_CMDCONFIGDRIVE;
1362 mbx.cmd.length = sizeof(mbx.cmd.data.config) - 1;
1363 mbx.cmd.data.config.subcommand = MCD_CF_READUPC;
1364 mbx.cmd.data.config.data1 = upc;
1365 mbx.res.length = 0;
1366 if ((error = mcd_send(sc, &mbx, 1)) != 0)
1367 return error;
1368
1369 sc->lastupc = upc;
1370 return 0;
1371 }
1372
1373 int
1374 mcd_toc_header(sc, th)
1375 struct mcd_softc *sc;
1376 struct ioc_toc_header *th;
1377 {
1378
1379 if (sc->debug)
1380 printf("%s: mcd_toc_header: reading toc header\n",
1381 sc->sc_dev.dv_xname);
1382
1383 th->len = msf2hsg(sc->volinfo.vol_msf, 0);
1384 th->starting_track = bcd2bin(sc->volinfo.trk_low);
1385 th->ending_track = bcd2bin(sc->volinfo.trk_high);
1386
1387 return 0;
1388 }
1389
1390 int
1391 mcd_read_toc(sc)
1392 struct mcd_softc *sc;
1393 {
1394 struct ioc_toc_header th;
1395 union mcd_qchninfo q;
1396 int error, trk, idx, retry;
1397
1398 if ((error = mcd_toc_header(sc, &th)) != 0)
1399 return error;
1400
1401 if ((error = mcd_stop(sc)) != 0)
1402 return error;
1403
1404 if (sc->debug)
1405 printf("%s: read_toc: reading qchannel info\n",
1406 sc->sc_dev.dv_xname);
1407
1408 for (trk = th.starting_track; trk <= th.ending_track; trk++)
1409 sc->toc[trk].toc.idx_no = 0x00;
1410 trk = th.ending_track - th.starting_track + 1;
1411 for (retry = 300; retry && trk > 0; retry--) {
1412 if (mcd_getqchan(sc, &q, CD_TRACK_INFO) != 0)
1413 break;
1414 if (q.toc.trk_no != 0x00 || q.toc.idx_no == 0x00)
1415 continue;
1416 idx = bcd2bin(q.toc.idx_no);
1417 if (idx < MCD_MAXTOCS &&
1418 sc->toc[idx].toc.idx_no == 0x00) {
1419 sc->toc[idx] = q;
1420 trk--;
1421 }
1422 }
1423
1424
1425 if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
1426 return error;
1427
1428 if (trk != 0)
1429 return EINVAL;
1430
1431
1432 idx = th.ending_track + 1;
1433 sc->toc[idx].toc.control = sc->toc[idx-1].toc.control;
1434 sc->toc[idx].toc.addr_type = sc->toc[idx-1].toc.addr_type;
1435 sc->toc[idx].toc.trk_no = 0x00;
1436 sc->toc[idx].toc.idx_no = 0xaa;
1437 sc->toc[idx].toc.absolute_pos[0] = sc->volinfo.vol_msf[0];
1438 sc->toc[idx].toc.absolute_pos[1] = sc->volinfo.vol_msf[1];
1439 sc->toc[idx].toc.absolute_pos[2] = sc->volinfo.vol_msf[2];
1440
1441 return 0;
1442 }
1443
1444 int
1445 mcd_toc_entries(sc, te)
1446 struct mcd_softc *sc;
1447 struct ioc_read_toc_entry *te;
1448 {
1449 int len = te->data_len;
1450 struct ret_toc {
1451 struct ioc_toc_header header;
1452 struct cd_toc_entry entries[MCD_MAXTOCS];
1453 } data;
1454 u_char trk;
1455 daddr64_t lba;
1456 int error, n;
1457
1458 if (len > sizeof(data.entries) ||
1459 len < sizeof(struct cd_toc_entry))
1460 return EINVAL;
1461 if (te->address_format != CD_MSF_FORMAT &&
1462 te->address_format != CD_LBA_FORMAT)
1463 return EINVAL;
1464
1465
1466 if ((error = mcd_toc_header(sc, &data.header)) != 0)
1467 return error;
1468
1469
1470 trk = te->starting_track;
1471 if (trk == 0x00)
1472 trk = data.header.starting_track;
1473 else if (trk == 0xaa)
1474 trk = data.header.ending_track + 1;
1475 else if (trk < data.header.starting_track ||
1476 trk > data.header.ending_track + 1)
1477 return EINVAL;
1478
1479
1480 for (n = 0; trk <= data.header.ending_track + 1; trk++) {
1481 if (sc->toc[trk].toc.idx_no == 0x00)
1482 continue;
1483 data.entries[n].control = sc->toc[trk].toc.control;
1484 data.entries[n].addr_type = sc->toc[trk].toc.addr_type;
1485 data.entries[n].track = bcd2bin(sc->toc[trk].toc.idx_no);
1486 switch (te->address_format) {
1487 case CD_MSF_FORMAT:
1488 data.entries[n].addr.addr[0] = 0;
1489 data.entries[n].addr.addr[1] =
1490 bcd2bin(sc->toc[trk].toc.absolute_pos[0]);
1491 data.entries[n].addr.addr[2] =
1492 bcd2bin(sc->toc[trk].toc.absolute_pos[1]);
1493 data.entries[n].addr.addr[3] =
1494 bcd2bin(sc->toc[trk].toc.absolute_pos[2]);
1495 break;
1496 case CD_LBA_FORMAT:
1497 lba = msf2hsg(sc->toc[trk].toc.absolute_pos, 0);
1498 data.entries[n].addr.addr[0] = lba >> 24;
1499 data.entries[n].addr.addr[1] = lba >> 16;
1500 data.entries[n].addr.addr[2] = lba >> 8;
1501 data.entries[n].addr.addr[3] = lba;
1502 break;
1503 }
1504 n++;
1505 }
1506
1507 len = min(len, n * sizeof(struct cd_toc_entry));
1508
1509
1510 return copyout(&data.entries[0], te->data, len);
1511 }
1512
1513 int
1514 mcd_stop(sc)
1515 struct mcd_softc *sc;
1516 {
1517 struct mcd_mbox mbx;
1518 int error;
1519
1520 if (sc->debug)
1521 printf("%s: mcd_stop: stopping play\n", sc->sc_dev.dv_xname);
1522
1523 mbx.cmd.opcode = MCD_CMDSTOPAUDIO;
1524 mbx.cmd.length = 0;
1525 mbx.res.length = 0;
1526 if ((error = mcd_send(sc, &mbx, 1)) != 0)
1527 return error;
1528
1529 sc->audio_status = CD_AS_PLAY_COMPLETED;
1530 return 0;
1531 }
1532
1533 int
1534 mcd_getqchan(sc, q, qchn)
1535 struct mcd_softc *sc;
1536 union mcd_qchninfo *q;
1537 int qchn;
1538 {
1539 struct mcd_mbox mbx;
1540 int error;
1541
1542 if (qchn == CD_TRACK_INFO) {
1543 if ((error = mcd_setmode(sc, MCD_MD_TOC)) != 0)
1544 return error;
1545 } else {
1546 if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
1547 return error;
1548 }
1549 if (qchn == CD_MEDIA_CATALOG) {
1550 if ((error = mcd_setupc(sc, MCD_UPC_ENABLE)) != 0)
1551 return error;
1552 } else {
1553 if ((error = mcd_setupc(sc, MCD_UPC_DISABLE)) != 0)
1554 return error;
1555 }
1556
1557 mbx.cmd.opcode = MCD_CMDGETQCHN;
1558 mbx.cmd.length = 0;
1559 mbx.res.length = sizeof(mbx.res.data.qchninfo);
1560 if ((error = mcd_send(sc, &mbx, 1)) != 0)
1561 return error;
1562
1563 *q = mbx.res.data.qchninfo;
1564 return 0;
1565 }
1566
1567 int
1568 mcd_read_subchannel(sc, ch)
1569 struct mcd_softc *sc;
1570 struct ioc_read_subchannel *ch;
1571 {
1572 int len = ch->data_len;
1573 union mcd_qchninfo q;
1574 struct cd_sub_channel_info data;
1575 daddr64_t lba;
1576 int error;
1577
1578 if (sc->debug)
1579 printf("%s: subchan: af=%d df=%d\n", sc->sc_dev.dv_xname,
1580 ch->address_format, ch->data_format);
1581
1582 if (len > sizeof(data) ||
1583 len < sizeof(struct cd_sub_channel_header))
1584 return EINVAL;
1585 if (ch->address_format != CD_MSF_FORMAT &&
1586 ch->address_format != CD_LBA_FORMAT)
1587 return EINVAL;
1588 if (ch->data_format != CD_CURRENT_POSITION &&
1589 ch->data_format != CD_MEDIA_CATALOG)
1590 return EINVAL;
1591
1592 if ((error = mcd_getqchan(sc, &q, ch->data_format)) != 0)
1593 return error;
1594
1595 data.header.audio_status = sc->audio_status;
1596 data.what.media_catalog.data_format = ch->data_format;
1597
1598 switch (ch->data_format) {
1599 case CD_MEDIA_CATALOG:
1600 data.what.media_catalog.mc_valid = 1;
1601 #if 0
1602 data.what.media_catalog.mc_number =
1603 #endif
1604 break;
1605
1606 case CD_CURRENT_POSITION:
1607 data.what.position.track_number = bcd2bin(q.current.trk_no);
1608 data.what.position.index_number = bcd2bin(q.current.idx_no);
1609 switch (ch->address_format) {
1610 case CD_MSF_FORMAT:
1611 data.what.position.reladdr.addr[0] = 0;
1612 data.what.position.reladdr.addr[1] =
1613 bcd2bin(q.current.relative_pos[0]);
1614 data.what.position.reladdr.addr[2] =
1615 bcd2bin(q.current.relative_pos[1]);
1616 data.what.position.reladdr.addr[3] =
1617 bcd2bin(q.current.relative_pos[2]);
1618 data.what.position.absaddr.addr[0] = 0;
1619 data.what.position.absaddr.addr[1] =
1620 bcd2bin(q.current.absolute_pos[0]);
1621 data.what.position.absaddr.addr[2] =
1622 bcd2bin(q.current.absolute_pos[1]);
1623 data.what.position.absaddr.addr[3] =
1624 bcd2bin(q.current.absolute_pos[2]);
1625 break;
1626 case CD_LBA_FORMAT:
1627 lba = msf2hsg(q.current.relative_pos, 1);
1628
1629
1630
1631
1632
1633 if (data.what.position.index_number == 0x00)
1634 lba = -lba;
1635 data.what.position.reladdr.addr[0] = lba >> 24;
1636 data.what.position.reladdr.addr[1] = lba >> 16;
1637 data.what.position.reladdr.addr[2] = lba >> 8;
1638 data.what.position.reladdr.addr[3] = lba;
1639 lba = msf2hsg(q.current.absolute_pos, 0);
1640 data.what.position.absaddr.addr[0] = lba >> 24;
1641 data.what.position.absaddr.addr[1] = lba >> 16;
1642 data.what.position.absaddr.addr[2] = lba >> 8;
1643 data.what.position.absaddr.addr[3] = lba;
1644 break;
1645 }
1646 break;
1647 }
1648
1649 return copyout(&data, ch->data, len);
1650 }
1651
1652 int
1653 mcd_playtracks(sc, p)
1654 struct mcd_softc *sc;
1655 struct ioc_play_track *p;
1656 {
1657 struct mcd_mbox mbx;
1658 int a = p->start_track;
1659 int z = p->end_track;
1660 int error;
1661
1662 if (sc->debug)
1663 printf("%s: playtracks: from %d:%d to %d:%d\n",
1664 sc->sc_dev.dv_xname,
1665 a, p->start_index, z, p->end_index);
1666
1667 if (a < bcd2bin(sc->volinfo.trk_low) ||
1668 a > bcd2bin(sc->volinfo.trk_high) ||
1669 a > z ||
1670 z < bcd2bin(sc->volinfo.trk_low) ||
1671 z > bcd2bin(sc->volinfo.trk_high))
1672 return EINVAL;
1673
1674 if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
1675 return error;
1676
1677 mbx.cmd.opcode = MCD_CMDREADSINGLESPEED;
1678 mbx.cmd.length = sizeof(mbx.cmd.data.play);
1679 mbx.cmd.data.play.start_msf[0] = sc->toc[a].toc.absolute_pos[0];
1680 mbx.cmd.data.play.start_msf[1] = sc->toc[a].toc.absolute_pos[1];
1681 mbx.cmd.data.play.start_msf[2] = sc->toc[a].toc.absolute_pos[2];
1682 mbx.cmd.data.play.end_msf[0] = sc->toc[z+1].toc.absolute_pos[0];
1683 mbx.cmd.data.play.end_msf[1] = sc->toc[z+1].toc.absolute_pos[1];
1684 mbx.cmd.data.play.end_msf[2] = sc->toc[z+1].toc.absolute_pos[2];
1685 sc->lastpb = mbx.cmd;
1686 mbx.res.length = 0;
1687 return mcd_send(sc, &mbx, 1);
1688 }
1689
1690 int
1691 mcd_playmsf(sc, p)
1692 struct mcd_softc *sc;
1693 struct ioc_play_msf *p;
1694 {
1695 struct mcd_mbox mbx;
1696 int error;
1697
1698 if (sc->debug)
1699 printf("%s: playmsf: from %d:%d.%d to %d:%d.%d\n",
1700 sc->sc_dev.dv_xname,
1701 p->start_m, p->start_s, p->start_f,
1702 p->end_m, p->end_s, p->end_f);
1703
1704 if ((p->start_m * 60 * 75 + p->start_s * 75 + p->start_f) >=
1705 (p->end_m * 60 * 75 + p->end_s * 75 + p->end_f))
1706 return EINVAL;
1707
1708 if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
1709 return error;
1710
1711 mbx.cmd.opcode = MCD_CMDREADSINGLESPEED;
1712 mbx.cmd.length = sizeof(mbx.cmd.data.play);
1713 mbx.cmd.data.play.start_msf[0] = bin2bcd(p->start_m);
1714 mbx.cmd.data.play.start_msf[1] = bin2bcd(p->start_s);
1715 mbx.cmd.data.play.start_msf[2] = bin2bcd(p->start_f);
1716 mbx.cmd.data.play.end_msf[0] = bin2bcd(p->end_m);
1717 mbx.cmd.data.play.end_msf[1] = bin2bcd(p->end_s);
1718 mbx.cmd.data.play.end_msf[2] = bin2bcd(p->end_f);
1719 sc->lastpb = mbx.cmd;
1720 mbx.res.length = 0;
1721 return mcd_send(sc, &mbx, 1);
1722 }
1723
1724 int
1725 mcd_playblocks(sc, p)
1726 struct mcd_softc *sc;
1727 struct ioc_play_blocks *p;
1728 {
1729 struct mcd_mbox mbx;
1730 int error;
1731
1732 if (sc->debug)
1733 printf("%s: playblocks: blkno %d length %d\n",
1734 sc->sc_dev.dv_xname, p->blk, p->len);
1735
1736 if (p->blk > sc->disksize || p->len > sc->disksize ||
1737 (p->blk + p->len) > sc->disksize)
1738 return 0;
1739
1740 if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
1741 return error;
1742
1743 mbx.cmd.opcode = MCD_CMDREADSINGLESPEED;
1744 mbx.cmd.length = sizeof(mbx.cmd.data.play);
1745 hsg2msf(p->blk, mbx.cmd.data.play.start_msf);
1746 hsg2msf(p->blk + p->len, mbx.cmd.data.play.end_msf);
1747 sc->lastpb = mbx.cmd;
1748 mbx.res.length = 0;
1749 return mcd_send(sc, &mbx, 1);
1750 }
1751
1752 int
1753 mcd_pause(sc)
1754 struct mcd_softc *sc;
1755 {
1756 union mcd_qchninfo q;
1757 int error;
1758
1759
1760 if (sc->audio_status != CD_AS_PLAY_IN_PROGRESS) {
1761 printf("%s: pause: attempted when not playing\n",
1762 sc->sc_dev.dv_xname);
1763 return EINVAL;
1764 }
1765
1766
1767 if ((error = mcd_getqchan(sc, &q, CD_CURRENT_POSITION)) != 0)
1768 return error;
1769
1770
1771 sc->lastpb.data.seek.start_msf[0] = q.current.absolute_pos[0];
1772 sc->lastpb.data.seek.start_msf[1] = q.current.absolute_pos[1];
1773 sc->lastpb.data.seek.start_msf[2] = q.current.absolute_pos[2];
1774
1775
1776 if ((error = mcd_stop(sc)) != 0)
1777 return error;
1778
1779
1780 sc->audio_status = CD_AS_PLAY_PAUSED;
1781 return 0;
1782 }
1783
1784 int
1785 mcd_resume(sc)
1786 struct mcd_softc *sc;
1787 {
1788 struct mcd_mbox mbx;
1789 int error;
1790
1791 if (sc->audio_status != CD_AS_PLAY_PAUSED)
1792 return EINVAL;
1793
1794 if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
1795 return error;
1796
1797 mbx.cmd = sc->lastpb;
1798 mbx.res.length = 0;
1799 return mcd_send(sc, &mbx, 1);
1800 }
1801
1802 int
1803 mcd_eject(sc)
1804 struct mcd_softc *sc;
1805 {
1806 struct mcd_mbox mbx;
1807
1808 mbx.cmd.opcode = MCD_CMDEJECTDISK;
1809 mbx.cmd.length = 0;
1810 mbx.res.length = 0;
1811 return mcd_send(sc, &mbx, 0);
1812 }
1813
1814 int
1815 mcd_setlock(sc, mode)
1816 struct mcd_softc *sc;
1817 int mode;
1818 {
1819 struct mcd_mbox mbx;
1820
1821 mbx.cmd.opcode = MCD_CMDSETLOCK;
1822 mbx.cmd.length = sizeof(mbx.cmd.data.lockmode);
1823 mbx.cmd.data.lockmode.mode = mode;
1824 mbx.res.length = 0;
1825 return mcd_send(sc, &mbx, 1);
1826 }