1 /* 2 * Copyright (c) 1993, 1994 Charles Hannum. 3 * Copyright 1993 by Holger Veit (data part) 4 * Copyright 1993 by Brian Moore (audio part) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This software was developed by Holger Veit and Brian Moore 18 * for use with "386BSD" and similar operating systems. 19 * "Similar operating systems" includes mainly non-profit oriented 20 * systems for research and education, including but not restricted to 21 * "NetBSD", "FreeBSD", "Mach" (by CMU). 22 * 4. Neither the name of the developer(s) nor the name "386BSD" 23 * may be used to endorse or promote products derived from this 24 * software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY 27 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE 30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 31 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 32 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 33 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 34 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 * 38 * $Id: mcd.c,v 1.16 1994/06/16 01:08:23 mycroft Exp $ 39 */ 40 41 /*static char COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore";*/ 42 43 #include <sys/types.h> 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/proc.h> 48 #include <sys/conf.h> 49 #include <sys/file.h> 50 #include <sys/buf.h> 51 #include <sys/stat.h> 52 #include <sys/uio.h> 53 #include <sys/ioctl.h> 54 #include <sys/cdio.h> 55 #include <sys/errno.h> 56 #include <sys/dkbad.h> 57 #include <sys/disklabel.h> 58 #include <sys/device.h> 59 60 #include <machine/cpu.h> 61 #include <machine/pio.h> 62 63 #include <i386/isa/isavar.h> 64 #include <i386/isa/mcdreg.h> 65 66 #ifndef MCDDEBUG 67 #define MCD_TRACE(fmt,a,b,c,d) 68 #else 69 #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);}} 70 #endif 71 72 #define MCDPART(dev) (((minor(dev)) & 0x07) ) 73 #define MCDUNIT(dev) (((minor(dev)) & 0x78) >> 3) 74 #define MCDPHYS(dev) (((minor(dev)) & 0x80) >> 7) 75 #define RAW_PART 3 76 77 /* flags */ 78 #define MCDOPEN 0x0001 /* device opened */ 79 #define MCDVALID 0x0002 /* parameters loaded */ 80 #define MCDWAIT 0x0004 /* waiting for something */ 81 #define MCDLABEL 0x0008 /* label is read */ 82 #define MCDREADRAW 0x0010 /* read raw mode (2352 bytes) */ 83 #define MCDVOLINFO 0x0020 /* already read volinfo */ 84 #define MCDTOC 0x0040 /* already read toc */ 85 #define MCDMBXBSY 0x0080 /* local mbx is busy */ 86 87 /* status */ 88 #define MCDAUDIOBSY MCD_ST_AUDIOBSY /* playing audio */ 89 #define MCDDSKCHNG MCD_ST_DSKCHNG /* sensed change of disk */ 90 #define MCDDSKIN MCD_ST_DSKIN /* sensed disk in drive */ 91 #define MCDDOOROPEN MCD_ST_DOOROPEN /* sensed door open */ 92 93 /* toc */ 94 #define MCD_MAXTOCS 104 /* from the Linux driver */ 95 #define MCD_LASTPLUS1 170 /* special toc entry */ 96 97 struct mcd_mbx { 98 short unit; 99 short retry; 100 short nblk; 101 int sz; 102 u_long skip; 103 struct buf *bp; 104 int p_offset; 105 short count; 106 short state; 107 }; 108 109 struct mcd_softc { 110 struct device sc_dev; 111 struct intrhand sc_ih; 112 113 u_short iobase; 114 short config; 115 short flags; 116 short status; 117 int blksize; 118 u_long disksize; 119 struct disklabel dlabel; 120 int partflags[MAXPARTITIONS]; 121 int openflags; 122 struct mcd_volinfo volinfo; 123 struct mcd_qchninfo toc[MCD_MAXTOCS]; 124 short audio_status; 125 struct mcd_read2 lastpb; 126 short debug; 127 struct buf head; /* head of buf queue */ 128 struct mcd_mbx mbx; 129 }; 130 131 /* prototypes */ 132 int mcdopen __P((dev_t)); 133 int mcdclose __P((dev_t)); 134 int mcd_start __P((struct mcd_softc *)); 135 int mcdioctl __P((dev_t, int, caddr_t, int, struct proc *)); 136 int mcd_getdisklabel __P((struct mcd_softc *)); 137 int mcdsize __P((dev_t)); 138 void mcd_configure __P((struct mcd_softc *)); 139 int mcd_waitrdy __P((u_short, int)); 140 int mcd_getreply __P((struct mcd_softc *, int)); 141 int mcd_getstat __P((struct mcd_softc *, int)); 142 void mcd_setflags __P((struct mcd_softc *)); 143 int mcd_get __P((struct mcd_softc *, char *, int)); 144 int mcd_send __P((struct mcd_softc *, int, int)); 145 int bcd2bin __P((bcd_t)); 146 bcd_t bin2bcd __P((int)); 147 void hsg2msf __P((int, bcd_t *)); 148 int msf2hsg __P((bcd_t *)); 149 int mcd_volinfo __P((struct mcd_softc *)); 150 int mcdintr __P((struct mcd_softc *)); 151 int mcd_setmode __P((struct mcd_softc *, int)); 152 void mcd_doread __P((void *)); 153 int mcd_toc_header __P((struct mcd_softc *, struct ioc_toc_header *)); 154 int mcd_read_toc __P((struct mcd_softc *)); 155 int mcd_toc_entry __P((struct mcd_softc *, struct ioc_read_toc_entry *)); 156 int mcd_stop __P((struct mcd_softc *)); 157 int mcd_getqchan __P((struct mcd_softc *, struct mcd_qchninfo *)); 158 int mcd_subchan __P((struct mcd_softc *, struct ioc_read_subchannel *)); 159 int mcd_playtracks __P((struct mcd_softc *, struct ioc_play_track *)); 160 int mcd_play __P((struct mcd_softc *, struct mcd_read2 *)); 161 int mcd_pause __P((struct mcd_softc *)); 162 int mcd_resume __P((struct mcd_softc *)); 163 164 int mcdprobe(); 165 void mcdattach(); 166 167 struct cfdriver mcdcd = { 168 NULL, "mcd", mcdprobe, mcdattach, DV_DISK, sizeof(struct mcd_softc) 169 }; 170 171 #define mcd_put(port,byte) outb(port,byte) 172 173 #define MCD_RETRIES 5 174 #define MCD_RDRETRIES 8 175 176 #define MCDBLK 2048 /* for cooked mode */ 177 #define MCDRBLK 2352 /* for raw mode */ 178 179 /* several delays */ 180 #define RDELAY_WAITSTAT 300 181 #define RDELAY_WAITMODE 300 182 #define RDELAY_WAITREAD 800 183 184 #define DELAY_STATUS 10000l /* 10000 * 1us */ 185 #define DELAY_GETREPLY 200000l /* 200000 * 2us */ 186 #define DELAY_SEEKREAD 20000l /* 20000 * 1us */ 187 188 /* reader state machine */ 189 #define MCD_S_BEGIN 0 190 #define MCD_S_WAITSTAT 1 191 #define MCD_S_WAITMODE 2 192 #define MCD_S_WAITREAD 3 193 194 void 195 mcdattach(parent, self, aux) 196 struct device *parent, *self; 197 void *aux; 198 { 199 struct mcd_softc *sc = (void *)self; 200 struct isa_attach_args *ia = aux; 201 202 #ifdef notyet 203 /* Wire controller for interrupts and DMA. */ 204 mcd_configure(sc); 205 #endif 206 207 printf("\n"); 208 209 sc->flags = 0; 210 211 sc->sc_ih.ih_fun = mcdintr; 212 sc->sc_ih.ih_arg = sc; 213 sc->sc_ih.ih_level = IPL_BIO; 214 intr_establish(ia->ia_irq, &sc->sc_ih); 215 } 216 217 int 218 mcdopen(dev) 219 dev_t dev; 220 { 221 int unit, part, phys; 222 struct mcd_softc *sc; 223 224 unit = MCDUNIT(dev); 225 if (unit >= mcdcd.cd_ndevs) 226 return ENXIO; 227 sc = mcdcd.cd_devs[unit]; 228 if (!sc) 229 return ENXIO; 230 231 part = MCDPART(dev); 232 phys = MCDPHYS(dev); 233 234 /* Invalidated in the meantime? Mark all open part's invalid. */ 235 if (!(sc->flags & MCDVALID) && sc->openflags) 236 return ENXIO; 237 238 if (mcd_getstat(sc, 1) < 0) 239 return ENXIO; 240 241 /* XXX Get a default disklabel. */ 242 mcd_getdisklabel(sc); 243 244 if (mcdsize(dev) < 0) { 245 printf("%s: failed to get disk size\n", sc->sc_dev.dv_xname); 246 return ENXIO; 247 } else 248 sc->flags |= MCDVALID; 249 250 MCD_TRACE("open: partition=%d disksize=%d blksize=%d\n", part, 251 sc->disksize, sc->blksize, 0); 252 253 if (part != RAW_PART && 254 (part >= sc->dlabel.d_npartitions || 255 sc->dlabel.d_partitions[part].p_fstype == FS_UNUSED)) 256 return ENXIO; 257 258 sc->partflags[part] |= MCDOPEN; 259 sc->openflags |= (1 << part); 260 if (part == RAW_PART && phys != 0) 261 sc->partflags[part] |= MCDREADRAW; 262 return 0; 263 } 264 265 int 266 mcdclose(dev) 267 dev_t dev; 268 { 269 int unit, part; 270 struct mcd_softc *sc; 271 272 unit = MCDUNIT(dev); 273 part = MCDPART(dev); 274 sc = mcdcd.cd_devs[unit]; 275 276 /* Get status. */ 277 mcd_getstat(sc, 1); 278 279 /* Close channel. */ 280 sc->partflags[part] &= ~(MCDOPEN | MCDREADRAW); 281 sc->openflags &= ~(1 << part); 282 MCD_TRACE("close: partition=%d\n", part, 0, 0, 0); 283 284 return 0; 285 } 286 287 void 288 mcdstrategy(bp) 289 struct buf *bp; 290 { 291 struct mcd_softc *sc = mcdcd.cd_devs[MCDUNIT(bp->b_dev)]; 292 struct buf *qp; 293 int s; 294 295 /* Test validity. */ 296 MCD_TRACE("strategy: buf=0x%lx blkno=%ld bcount=%ld\n", bp, 297 bp->b_blkno, bp->b_bcount, 0); 298 if (bp->b_blkno < 0) { 299 printf("%s: strategy: blkno=%d bcount=%d\n", 300 sc->sc_dev.dv_xname, bp->b_blkno, bp->b_bcount); 301 bp->b_error = EINVAL; 302 bp->b_flags |= B_ERROR; 303 goto bad; 304 } 305 306 /* If device invalidated (e.g. media change, door open), error. */ 307 if (!(sc->flags & MCDVALID)) { 308 MCD_TRACE("strategy: drive not valid\n", 0, 0, 0, 0); 309 bp->b_error = EIO; 310 goto bad; 311 } 312 313 /* Check for read only. */ 314 if (!(bp->b_flags & B_READ)) { 315 bp->b_error = EROFS; 316 goto bad; 317 } 318 319 /* No data to read. */ 320 if (bp->b_bcount == 0) 321 goto done; 322 323 /* For non raw access, check partition limits. */ 324 if (MCDPART(bp->b_dev) != RAW_PART) { 325 if (!(sc->flags & MCDLABEL)) { 326 bp->b_error = EIO; 327 goto bad; 328 } 329 /* Adjust transfer if necessary. */ 330 if (bounds_check_with_label(bp, &sc->dlabel, 1) <= 0) 331 goto done; 332 } 333 334 /* Queue it. */ 335 qp = &sc->head; 336 s = splbio(); 337 disksort(qp, bp); 338 splx(s); 339 340 /* Now check whether we can perform processing. */ 341 mcd_start(sc); 342 return; 343 344 bad: 345 bp->b_flags |= B_ERROR; 346 done: 347 bp->b_resid = bp->b_bcount; 348 biodone(bp); 349 return; 350 } 351 352 int 353 mcd_start(sc) 354 struct mcd_softc *sc; 355 { 356 struct buf *bp, *qp = &sc->head; 357 struct partition *p; 358 int s = splbio(); 359 360 if (sc->flags & MCDMBXBSY) 361 return; 362 363 if ((bp = qp->b_actf) != 0) { 364 /* Block found to process; dequeue. */ 365 MCD_TRACE("start: found block bp=0x%x\n", bp, 0, 0, 0); 366 qp->b_actf = bp->b_actf; 367 splx(s); 368 } else { 369 /* Nothing to do; */ 370 splx(s); 371 return; 372 } 373 374 /* Changed media? */ 375 if (!(sc->flags & MCDVALID)) { 376 MCD_TRACE("start: drive not valid\n", 0, 0, 0, 0); 377 return; 378 } 379 380 p = &sc->dlabel.d_partitions[MCDPART(bp->b_dev)]; 381 382 sc->flags |= MCDMBXBSY; 383 sc->mbx.unit = sc->sc_dev.dv_unit; 384 sc->mbx.retry = MCD_RETRIES; 385 sc->mbx.bp = bp; 386 sc->mbx.p_offset = p->p_offset; 387 388 /* Calling the read routine. */ 389 sc->mbx.state = MCD_S_BEGIN; 390 mcd_doread(&sc->mbx); 391 /* triggers mcd_start, when successful finished. */ 392 } 393 394 int 395 mcdioctl(dev, cmd, addr, flags, p) 396 dev_t dev; 397 int cmd; 398 caddr_t addr; 399 int flags; 400 struct proc *p; 401 { 402 struct mcd_softc *sc = mcdcd.cd_devs[MCDUNIT(dev)]; 403 404 if (!(sc->flags & MCDVALID)) 405 return EIO; 406 MCD_TRACE("ioctl: cmd=0x%x\n", cmd, 0, 0, 0); 407 408 switch (cmd) { 409 case DIOCSBAD: 410 return EINVAL; 411 case DIOCGDINFO: 412 case DIOCGPART: 413 case DIOCWDINFO: 414 case DIOCSDINFO: 415 case DIOCWLABEL: 416 return ENOTTY; 417 case CDIOCPLAYTRACKS: 418 return mcd_playtracks(sc, (struct ioc_play_track *) addr); 419 case CDIOCPLAYBLOCKS: 420 return mcd_play(sc, (struct mcd_read2 *) addr); 421 case CDIOCREADSUBCHANNEL: 422 return mcd_subchan(sc, (struct ioc_read_subchannel *) addr); 423 case CDIOREADTOCHEADER: 424 return mcd_toc_header(sc, (struct ioc_toc_header *) addr); 425 case CDIOREADTOCENTRYS: 426 return mcd_toc_entry(sc, (struct ioc_read_toc_entry *) addr); 427 case CDIOCSETPATCH: 428 case CDIOCGETVOL: 429 case CDIOCSETVOL: 430 case CDIOCSETMONO: 431 case CDIOCSETSTERIO: 432 case CDIOCSETMUTE: 433 case CDIOCSETLEFT: 434 case CDIOCSETRIGHT: 435 return EINVAL; 436 case CDIOCRESUME: 437 return mcd_resume(sc); 438 case CDIOCPAUSE: 439 return mcd_pause(sc); 440 case CDIOCSTART: 441 return EINVAL; 442 case CDIOCSTOP: 443 return mcd_stop(sc); 444 case CDIOCEJECT: 445 return EINVAL; 446 case CDIOCSETDEBUG: 447 sc->debug = 1; 448 return 0; 449 case CDIOCCLRDEBUG: 450 sc->debug = 0; 451 return 0; 452 case CDIOCRESET: 453 return EINVAL; 454 default: 455 return ENOTTY; 456 } 457 #ifdef DIAGNOSTIC 458 panic("mcdioctl: impossible"); 459 #endif 460 } 461 462 /* 463 * This could have been taken from scsi/cd.c, but it is not clear 464 * whether the scsi cd driver is linked in. 465 */ 466 int 467 mcd_getdisklabel(sc) 468 struct mcd_softc *sc; 469 { 470 471 if (sc->flags & MCDLABEL) 472 return -1; 473 474 bzero(&sc->dlabel, sizeof(struct disklabel)); 475 strncpy(sc->dlabel.d_typename, "Mitsumi CD ROM ", 16); 476 strncpy(sc->dlabel.d_packname, "unknown ", 16); 477 sc->dlabel.d_secsize = sc->blksize; 478 sc->dlabel.d_nsectors = 100; 479 sc->dlabel.d_ntracks = 1; 480 sc->dlabel.d_ncylinders = (sc->disksize /100) + 1; 481 sc->dlabel.d_secpercyl = 100; 482 sc->dlabel.d_secperunit = sc->disksize; 483 sc->dlabel.d_rpm = 300; 484 sc->dlabel.d_interleave = 1; 485 sc->dlabel.d_flags = D_REMOVABLE; 486 sc->dlabel.d_npartitions= 1; 487 sc->dlabel.d_partitions[0].p_offset = 0; 488 sc->dlabel.d_partitions[0].p_size = sc->disksize; 489 sc->dlabel.d_partitions[0].p_fstype = 9; 490 sc->dlabel.d_magic = DISKMAGIC; 491 sc->dlabel.d_magic2 = DISKMAGIC; 492 sc->dlabel.d_checksum = dkcksum(&sc->dlabel); 493 494 sc->flags |= MCDLABEL; 495 return 0; 496 } 497 498 int 499 mcdsize(dev) 500 dev_t dev; 501 { 502 int size; 503 struct mcd_softc *sc = mcdcd.cd_devs[MCDUNIT(dev)]; 504 505 if (mcd_volinfo(sc) >= 0) { 506 sc->blksize = MCDBLK; 507 size = msf2hsg(sc->volinfo.vol_msf); 508 sc->disksize = size * (MCDBLK / DEV_BSIZE); 509 return 0; 510 } 511 return -1; 512 } 513 514 int 515 mcddump() 516 { 517 518 /* Not implemented. */ 519 return EINVAL; 520 } 521 522 /*************************************************************** 523 * lower level of driver starts here 524 **************************************************************/ 525 526 #ifdef notyet 527 static char irqs[] = { 528 0x00, 0x00, 0x10, 0x20, 0x00, 0x30, 0x00, 0x00, 529 0x00, 0x10, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00 530 }; 531 532 static char drqs[] = { 533 0x00, 0x01, 0x00, 0x03, 0x00, 0x05, 0x06, 0x07 534 }; 535 #endif 536 537 void 538 mcd_configure(sc) 539 struct mcd_softc *sc; 540 { 541 542 outb(sc->iobase + mcd_config, sc->config); 543 } 544 545 int 546 mcdprobe(parent, self, aux) 547 struct device *parent, *self; 548 void *aux; 549 { 550 struct mcd_softc *sc = (void *)self; 551 struct isa_attach_args *ia = aux; 552 u_short iobase = ia->ia_iobase; 553 int i; 554 int st, check; 555 556 #ifdef notyet 557 /* Get irq/drq configuration word. */ 558 sc->config = irqs[ia->ia_irq]; 559 #endif 560 sc->iobase = iobase; 561 562 /* Send a reset. */ 563 outb(iobase + mcd_reset, 0); 564 delay(300000); 565 /* Get any pending status and throw away. */ 566 for (i = 10; i; i--) 567 inb(iobase + mcd_status); 568 delay(1000); 569 570 /* Send get status command. */ 571 outb(iobase + mcd_command, MCD_CMDGETSTAT); 572 i = mcd_getreply(sc, DELAY_GETREPLY); 573 574 if (i < 0) { 575 #ifdef DEBUG 576 printf("Mitsumi drive NOT detected\n"); 577 #endif 578 return 0; 579 } 580 581 /* 582 * The following code uses the 0xDC command, it returns a M from the 583 * second byte and a number in the third. 584 * (I hope you have the right drive for that, most drives don't do!) 585 * Whole code entirely rewriten by veit@gmd.de, the changes accessed 586 * the drive in an illegal way. Proper way is to use the timeout 587 * driven routines mcd_getreply etc. rather than arbitrary delays. 588 */ 589 590 delay(2000); 591 outb(iobase + mcd_command, MCD_CMDCONTINFO); 592 i = mcd_getreply(sc, DELAY_GETREPLY); 593 594 if (i < 0) { 595 #ifdef DEBUG 596 printf("Mitsumi drive error\n"); 597 #endif 598 return 0; 599 } 600 st = mcd_getreply(sc, DELAY_GETREPLY); 601 if (st < 0) 602 return 0; 603 check = mcd_getreply(sc, DELAY_GETREPLY); 604 if (check < 0) 605 return 0; 606 /* Flush junk. */ 607 (void) mcd_getreply(sc, DELAY_GETREPLY); 608 609 /* 610 * The following is code which is not guaranteed to work for all 611 * drives, because the meaning of the expected 'M' is not clear 612 * (M_itsumi is an obvious assumption, but I don't trust that). 613 * Also, the original hack had a bogus condition that always 614 * returned true. 615 */ 616 #ifdef notdef 617 if (check != 'M') { 618 #ifdef DEBUG 619 printf("Mitsumi drive NOT detected\n"); 620 #endif 621 return 0; 622 } 623 #endif 624 625 #ifdef DEBUG 626 printf("Mitsumi drive detected\n"); 627 #endif 628 ia->ia_iosize = 4; 629 ia->ia_msize = 0; 630 return 1; 631 } 632 633 int 634 mcd_waitrdy(iobase, dly) 635 u_short iobase; 636 int dly; 637 { 638 int i; 639 640 /* Wait until xfer port senses data ready. */ 641 for (i = dly; i; i--) { 642 if ((inb(iobase + mcd_xfer) & MCD_ST_BUSY) == 0) 643 return 0; 644 delay(1); 645 } 646 return -1; 647 } 648 649 int 650 mcd_getreply(sc, dly) 651 struct mcd_softc *sc; 652 int dly; 653 { 654 u_short iobase = sc->iobase; 655 656 /* Wait data to become ready. */ 657 if (mcd_waitrdy(iobase, dly) < 0) { 658 printf("%s: timeout in getreply\n", sc->sc_dev.dv_xname); 659 return -1; 660 } 661 662 /* Get the data. */ 663 return inb(iobase + mcd_status); 664 } 665 666 int 667 mcd_getstat(sc, sflg) 668 struct mcd_softc *sc; 669 int sflg; 670 { 671 int i; 672 u_short iobase = sc->iobase; 673 674 /* Get the status. */ 675 if (sflg) 676 outb(iobase + mcd_command, MCD_CMDGETSTAT); 677 i = mcd_getreply(sc, DELAY_GETREPLY); 678 if (i < 0) { 679 printf("%s: timeout in getstat\n", sc->sc_dev.dv_xname); 680 return -1; 681 } 682 683 sc->status = i; 684 685 mcd_setflags(sc); 686 return sc->status; 687 } 688 689 void 690 mcd_setflags(sc) 691 struct mcd_softc *sc; 692 { 693 694 /* Check flags. */ 695 if (sc->status & (MCDDSKCHNG | MCDDOOROPEN)) { 696 MCD_TRACE("getstat: sensed DSKCHNG or DOOROPEN\n", 0, 0, 0, 0); 697 sc->flags &= ~MCDVALID; 698 } 699 700 if (sc->status & MCDAUDIOBSY) 701 sc->audio_status = CD_AS_PLAY_IN_PROGRESS; 702 else if (sc->audio_status == CD_AS_PLAY_IN_PROGRESS) 703 sc->audio_status = CD_AS_PLAY_COMPLETED; 704 } 705 706 int 707 mcd_get(sc, buf, nmax) 708 struct mcd_softc *sc; 709 char *buf; 710 int nmax; 711 { 712 int i, k; 713 714 for (i = 0; i < nmax; i++) { 715 /* Wait for data. */ 716 if ((k = mcd_getreply(sc, DELAY_GETREPLY)) < 0) { 717 printf("%s: timeout in get\n", sc->sc_dev.dv_xname); 718 return -1; 719 } 720 buf[i] = k; 721 } 722 return i; 723 } 724 725 int 726 mcd_send(sc, cmd, nretries) 727 struct mcd_softc *sc; 728 int cmd, nretries; 729 { 730 int i, k; 731 u_short iobase = sc->iobase; 732 733 MCD_TRACE("send: cmd=0x%x\n", cmd, 0, 0, 0); 734 735 for (i = nretries; i; i--) { 736 outb(iobase + mcd_command, cmd); 737 if ((k = mcd_getstat(sc, 0)) != -1) 738 break; 739 } 740 if (!i) { 741 printf("%s: send: retry count exceeded\n", sc->sc_dev.dv_xname); 742 return -1; 743 } 744 745 MCD_TRACE("send: status=0x%x\n", k, 0, 0, 0); 746 747 return 0; 748 } 749 750 int 751 bcd2bin(b) 752 bcd_t b; 753 { 754 755 return (b >> 4) * 10 + (b & 15); 756 } 757 758 bcd_t 759 bin2bcd(b) 760 int b; 761 { 762 763 return ((b / 10) << 4) | (b % 10); 764 } 765 766 void 767 hsg2msf(hsg, msf) 768 int hsg; 769 bcd_t *msf; 770 { 771 772 hsg += 150; 773 M_msf(msf) = bin2bcd(hsg / 4500); 774 hsg %= 4500; 775 S_msf(msf) = bin2bcd(hsg / 75); 776 F_msf(msf) = bin2bcd(hsg % 75); 777 } 778 779 int 780 msf2hsg(msf) 781 bcd_t *msf; 782 { 783 784 return (bcd2bin(M_msf(msf)) * 60 + 785 bcd2bin(S_msf(msf))) * 75 + 786 bcd2bin(F_msf(msf)) - 150; 787 } 788 789 int 790 mcd_volinfo(sc) 791 struct mcd_softc *sc; 792 { 793 794 MCD_TRACE("volinfo: enter\n", 0, 0, 0, 0); 795 796 /* Get the status, in case the disc has been changed. */ 797 if (mcd_getstat(sc, 1) < 0) 798 return EIO; 799 800 /* Just return if we already have it. */ 801 if (sc->flags & MCDVOLINFO) 802 return 0; 803 804 /* Send volume info command. */ 805 if (mcd_send(sc, MCD_CMDGETVOLINFO, MCD_RETRIES) < 0) 806 return -1; 807 808 /* Get the data. */ 809 if (mcd_get(sc, (char*) &sc->volinfo, sizeof(struct mcd_volinfo)) < 0) { 810 printf("%s: volinfo: error reading data\n", 811 sc->sc_dev.dv_xname); 812 return -1; 813 } 814 815 if (sc->volinfo.trk_low != 0 || sc->volinfo.trk_high != 0) { 816 /* Volinfo is OK. */ 817 sc->flags |= MCDVOLINFO; 818 return 0; 819 } 820 821 return -1; 822 } 823 824 int 825 mcdintr(sc) 826 struct mcd_softc *sc; 827 { 828 u_short iobase = sc->iobase; 829 830 MCD_TRACE("stray interrupt xfer=0x%x\n", inb(iobase + mcd_xfer), 831 0, 0, 0); 832 833 /* Just read out status and ignore the rest. */ 834 if (inb(iobase + mcd_xfer) != 0xff) 835 (void) inb(iobase + mcd_status); 836 837 return -1; 838 } 839 840 /* 841 * State machine to process read requests. 842 * Initialize with MCD_S_BEGIN: calculate sizes, and read status 843 * MCD_S_WAITSTAT: wait for status reply, set mode 844 * MCD_S_WAITMODE: waits for status reply from set mode, set read command 845 * MCD_S_WAITREAD: wait for read ready, read data. 846 */ 847 void 848 mcd_doread(arg) 849 void *arg; 850 { 851 struct mcd_mbx *mbx = arg; 852 struct mcd_softc *sc = mcdcd.cd_devs[mbx->unit]; 853 u_short iobase = sc->iobase; 854 struct buf *bp = mbx->bp; 855 856 int rm, i, k; 857 struct mcd_read2 rbuf; 858 int blkno; 859 caddr_t addr; 860 861 loop: 862 switch (mbx->state) { 863 case MCD_S_BEGIN: 864 /* Get status. */ 865 outb(iobase + mcd_command, MCD_CMDGETSTAT); 866 867 mbx->count = RDELAY_WAITSTAT; 868 mbx->state = MCD_S_WAITSTAT; 869 timeout(mcd_doread, mbx, hz / 100); 870 return; 871 872 case MCD_S_WAITSTAT: 873 untimeout(mcd_doread, mbx); 874 if (mbx->count-- < 0) { 875 printf("%s: timeout getting status\n", 876 sc->sc_dev.dv_xname); 877 goto readerr; 878 } 879 if (inb(iobase + mcd_xfer) & MCD_ST_BUSY) { 880 timeout(mcd_doread, mbx, hz / 100); 881 return; 882 } 883 mcd_setflags(sc); 884 MCD_TRACE("doread: got WAITSTAT delay=%d\n", 885 RDELAY_WAITSTAT - mbx->count, 0, 0, 0); 886 887 /* Reject, if audio active. */ 888 if (sc->status & MCDAUDIOBSY) { 889 printf("%s: audio is active\n", 890 sc->sc_dev.dv_xname); 891 goto readerr; 892 } 893 894 /* Check for raw/cooked mode. */ 895 if (sc->flags & MCDREADRAW) { 896 rm = MCD_MD_RAW; 897 mbx->sz = MCDRBLK; 898 } else { 899 rm = MCD_MD_COOKED; 900 mbx->sz = sc->blksize; 901 } 902 903 mcd_put(iobase + mcd_command, MCD_CMDSETMODE); 904 mcd_put(iobase + mcd_command, rm); 905 906 mbx->count = RDELAY_WAITMODE; 907 mbx->state = MCD_S_WAITMODE; 908 timeout(mcd_doread, mbx, hz / 100); 909 return; 910 911 case MCD_S_WAITMODE: 912 untimeout(mcd_doread, mbx); 913 if (mbx->count-- < 0) { 914 printf("%s: timeout setting mode\n", 915 sc->sc_dev.dv_xname); 916 goto readerr; 917 } 918 if (inb(iobase + mcd_xfer) & MCD_ST_BUSY) { 919 timeout(mcd_doread, mbx, hz / 100); 920 return; 921 } 922 mcd_setflags(sc); 923 MCD_TRACE("doread: got WAITMODE delay=%d\n", 924 RDELAY_WAITMODE - mbx->count, 0, 0, 0); 925 926 /* For first block. */ 927 mbx->nblk = (bp->b_bcount + (mbx->sz - 1)) / mbx->sz; 928 mbx->skip = 0; 929 930 nextblock: 931 blkno = (bp->b_blkno / (mbx->sz / DEV_BSIZE)) + mbx->p_offset + 932 (mbx->skip / mbx->sz); 933 934 MCD_TRACE("doread: read blkno=%d for bp=0x%x\n", blkno, bp, 0, 935 0); 936 937 /* Build parameter block. */ 938 hsg2msf(blkno, rbuf.start_msf); 939 940 /* Send the read command. */ 941 mcd_put(iobase + mcd_command, MCD_CMDREAD2); 942 mcd_put(iobase + mcd_command, rbuf.start_msf[0]); 943 mcd_put(iobase + mcd_command, rbuf.start_msf[1]); 944 mcd_put(iobase + mcd_command, rbuf.start_msf[2]); 945 mcd_put(iobase + mcd_command, 0); 946 mcd_put(iobase + mcd_command, 0); 947 mcd_put(iobase + mcd_command, 1); 948 949 mbx->count = RDELAY_WAITREAD; 950 mbx->state = MCD_S_WAITREAD; 951 timeout(mcd_doread, mbx, hz / 100); 952 return; 953 954 case MCD_S_WAITREAD: 955 untimeout(mcd_doread, mbx); 956 if (mbx->count-- < 0) { 957 printf("%s: timeout reading data\n", 958 sc->sc_dev.dv_xname); 959 goto readerr; 960 } 961 962 k = inb(iobase + mcd_xfer); 963 if ((k & 2) == 0) { /* XXX MCD_ST_AUDIOBSY? */ 964 MCD_TRACE("doread: got data delay=%d\n", 965 RDELAY_WAITREAD - mbx->count, 0, 0, 0); 966 /* Data is ready. */ 967 addr = bp->b_data + mbx->skip; 968 outb(iobase + mcd_ctl2, 0x04); /* XXX */ 969 for (i = 0; i < mbx->sz; i++) 970 *addr++ = inb(iobase + mcd_rdata); 971 outb(iobase + mcd_ctl2, 0x0c); /* XXX */ 972 973 if (--mbx->nblk > 0) { 974 mbx->skip += mbx->sz; 975 goto nextblock; 976 } 977 978 /* Return buffer. */ 979 bp->b_resid = 0; 980 biodone(bp); 981 982 sc->flags &= ~MCDMBXBSY; 983 mcd_start(sc); 984 return; 985 } 986 if ((k & MCD_ST_BUSY) == 0) 987 mcd_getstat(sc, 0); 988 timeout(mcd_doread, mbx, hz / 100); 989 return; 990 } 991 992 readerr: 993 if (mbx->retry-- > 0) { 994 printf("%s: retrying\n", sc->sc_dev.dv_xname); 995 mbx->state = MCD_S_BEGIN; 996 goto loop; 997 } 998 999 /* Invalidate the buffer. */ 1000 bp->b_flags |= B_ERROR; 1001 bp->b_resid = bp->b_bcount; 1002 biodone(bp); 1003 mcd_start(sc); 1004 1005 #ifdef notyet 1006 printf("%s: unit timeout; resetting\n", sc->sc_dev.dv_xname); 1007 outb(mbx->iobase + mcd_reset, MCD_CMDRESET); 1008 delay(300000); 1009 (void)mcd_getstat(sc, 1); 1010 (void)mcd_getstat(sc, 1); 1011 /*sc->status &= ~MCDDSKCHNG; */ 1012 sc->debug = 1; /* preventive set debug mode */ 1013 #endif 1014 } 1015 1016 int 1017 mcd_setmode(sc, mode) 1018 struct mcd_softc *sc; 1019 int mode; 1020 { 1021 u_short iobase = sc->iobase; 1022 int retry; 1023 1024 printf("%s: setting mode to %d\n", sc->sc_dev.dv_xname, mode); 1025 for (retry = MCD_RETRIES; retry; retry--) { 1026 outb(iobase + mcd_command, MCD_CMDSETMODE); 1027 outb(iobase + mcd_command, mode); 1028 if (mcd_getstat(sc, 0) != -1) 1029 return 0; 1030 } 1031 1032 return -1; 1033 } 1034 1035 int 1036 mcd_toc_header(sc, th) 1037 struct mcd_softc *sc; 1038 struct ioc_toc_header *th; 1039 { 1040 1041 if (mcd_volinfo(sc) < 0) 1042 return ENXIO; 1043 1044 th->len = msf2hsg(sc->volinfo.vol_msf); 1045 th->starting_track = bcd2bin(sc->volinfo.trk_low); 1046 th->ending_track = bcd2bin(sc->volinfo.trk_high); 1047 1048 return 0; 1049 } 1050 1051 int 1052 mcd_read_toc(sc) 1053 struct mcd_softc *sc; 1054 { 1055 struct ioc_toc_header th; 1056 struct mcd_qchninfo q; 1057 int rc, trk, idx, retry; 1058 1059 /* Only read TOC if needed. */ 1060 if (sc->flags & MCDTOC) 1061 return 0; 1062 1063 if (sc->debug) 1064 printf("%s: read_toc: reading toc header\n", 1065 sc->sc_dev.dv_xname); 1066 if (mcd_toc_header(sc, &th) != 0) 1067 return ENXIO; 1068 1069 if (sc->debug) 1070 printf("%s: read_toc: stopping play\n", sc->sc_dev.dv_xname); 1071 if ((rc = mcd_stop(sc)) != 0) 1072 return rc; 1073 1074 /* Try setting the mode twice. */ 1075 if (mcd_setmode(sc, MCD_MD_TOC) != 0) 1076 return EIO; 1077 if (mcd_setmode(sc, MCD_MD_TOC) != 0) 1078 return EIO; 1079 1080 if (sc->debug) 1081 printf("%s: read_toc: reading qchannel info\n", 1082 sc->sc_dev.dv_xname); 1083 for (trk = th.starting_track; trk <= th.ending_track; trk++) 1084 sc->toc[trk].idx_no = 0; 1085 trk = th.ending_track - th.starting_track + 1; 1086 for (retry = 300; retry && trk > 0; retry--) { 1087 if (mcd_getqchan(sc, &q) < 0) 1088 break; 1089 idx = bcd2bin(q.idx_no); 1090 if (idx > 0 && idx < MCD_MAXTOCS && q.trk_no == 0 && 1091 sc->toc[idx].idx_no == 0) { 1092 sc->toc[idx] = q; 1093 trk--; 1094 } 1095 } 1096 1097 if (mcd_setmode(sc, MCD_MD_COOKED) != 0) 1098 return EIO; 1099 1100 if (trk != 0) 1101 return ENXIO; 1102 1103 /* Add a fake last+1. */ 1104 idx = th.ending_track + 1; 1105 sc->toc[idx].ctrl_adr = sc->toc[idx-1].ctrl_adr; 1106 sc->toc[idx].trk_no = 0; 1107 sc->toc[idx].idx_no = 0xaa; 1108 sc->toc[idx].hd_pos_msf[0] = sc->volinfo.vol_msf[0]; 1109 sc->toc[idx].hd_pos_msf[1] = sc->volinfo.vol_msf[1]; 1110 sc->toc[idx].hd_pos_msf[2] = sc->volinfo.vol_msf[2]; 1111 1112 sc->flags |= MCDTOC; 1113 1114 return 0; 1115 } 1116 1117 int 1118 mcd_toc_entry(sc, te) 1119 struct mcd_softc *sc; 1120 struct ioc_read_toc_entry *te; 1121 { 1122 struct ret_toc { 1123 struct ioc_toc_header th; 1124 struct cd_toc_entry rt; 1125 } ret_toc; 1126 struct ioc_toc_header th; 1127 int rc, i; 1128 1129 /* Make sure we have a valid TOC. */ 1130 if ((rc = mcd_read_toc(sc)) != 0) 1131 return rc; 1132 1133 /* Find the TOC to copy. */ 1134 i = te->starting_track; 1135 if (i == MCD_LASTPLUS1) 1136 i = bcd2bin(sc->volinfo.trk_high) + 1; 1137 1138 /* Verify starting track. */ 1139 if (i < bcd2bin(sc->volinfo.trk_low) || 1140 i > bcd2bin(sc->volinfo.trk_high) + 1) 1141 return EINVAL; 1142 1143 /* Do we have room? */ 1144 if (te->data_len < sizeof(struct ioc_toc_header) + 1145 sizeof(struct cd_toc_entry)) 1146 return EINVAL; 1147 1148 /* Copy the TOC header. */ 1149 if (mcd_toc_header(sc, &th) < 0) 1150 return EIO; 1151 ret_toc.th = th; 1152 1153 /* Copy the TOC data. */ 1154 ret_toc.rt.control = sc->toc[i].ctrl_adr; 1155 ret_toc.rt.addr_type = te->address_format; 1156 ret_toc.rt.track = i; 1157 if (te->address_format == CD_MSF_FORMAT) { 1158 ret_toc.rt.addr[1] = sc->toc[i].hd_pos_msf[0]; 1159 ret_toc.rt.addr[2] = sc->toc[i].hd_pos_msf[1]; 1160 ret_toc.rt.addr[3] = sc->toc[i].hd_pos_msf[2]; 1161 } 1162 1163 /* Copy the data back. */ 1164 copyout(&ret_toc, te->data, 1165 sizeof(struct cd_toc_entry) + sizeof(struct ioc_toc_header)); 1166 1167 return 0; 1168 } 1169 1170 int 1171 mcd_stop(sc) 1172 struct mcd_softc *sc; 1173 { 1174 1175 if (mcd_send(sc, MCD_CMDSTOPAUDIO, MCD_RETRIES) < 0) 1176 return ENXIO; 1177 sc->audio_status = CD_AS_PLAY_COMPLETED; 1178 return 0; 1179 } 1180 1181 int 1182 mcd_getqchan(sc, q) 1183 struct mcd_softc *sc; 1184 struct mcd_qchninfo *q; 1185 { 1186 1187 if (mcd_send(sc, MCD_CMDGETQCHN, MCD_RETRIES) < 0) 1188 return -1; 1189 if (mcd_get(sc, (char *) q, sizeof(struct mcd_qchninfo)) < 0) 1190 return -1; 1191 if (sc->debug) 1192 printf("%s: getqchan: ctl=%d t=%d i=%d ttm=%d:%d.%d dtm=%d:%d.%d\n", 1193 sc->sc_dev.dv_xname, q->ctrl_adr, q->trk_no, q->idx_no, 1194 q->trk_size_msf[0], q->trk_size_msf[1], q->trk_size_msf[2], 1195 q->trk_size_msf[0], q->trk_size_msf[1], q->trk_size_msf[2]); 1196 return 0; 1197 } 1198 1199 int 1200 mcd_subchan(sc, ch) 1201 struct mcd_softc *sc; 1202 struct ioc_read_subchannel *ch; 1203 { 1204 struct mcd_qchninfo q; 1205 struct cd_sub_channel_info data; 1206 1207 if (sc->debug) 1208 printf("%s: subchan: af=%d df=%d\n", sc->sc_dev.dv_xname, 1209 ch->address_format, ch->data_format); 1210 1211 if (ch->address_format != CD_MSF_FORMAT) 1212 return EIO; 1213 if (ch->data_format != CD_CURRENT_POSITION) 1214 return EIO; 1215 if (mcd_getqchan(sc, &q) < 0) 1216 return EIO; 1217 1218 data.header.audio_status = sc->audio_status; 1219 data.what.position.data_format = CD_MSF_FORMAT; 1220 data.what.position.track_number = bcd2bin(q.trk_no); 1221 1222 if (copyout(&data, ch->data, sizeof(struct cd_sub_channel_info)) != 0) 1223 return EFAULT; 1224 return 0; 1225 } 1226 1227 int 1228 mcd_playtracks(sc, pt) 1229 struct mcd_softc *sc; 1230 struct ioc_play_track *pt; 1231 { 1232 struct mcd_read2 pb; 1233 int a = pt->start_track; 1234 int z = pt->end_track; 1235 int rc; 1236 1237 if ((rc = mcd_read_toc(sc)) != 0) 1238 return rc; 1239 1240 printf("%s: playtracks: from %d:%d to %d:%d\n", sc->sc_dev.dv_xname, 1241 a, pt->start_index, z, pt->end_index); 1242 1243 if (a < sc->volinfo.trk_low || a > sc->volinfo.trk_high || a > z || 1244 z < sc->volinfo.trk_low || z > sc->volinfo.trk_high) 1245 return EINVAL; 1246 1247 pb.start_msf[0] = sc->toc[a].hd_pos_msf[0]; 1248 pb.start_msf[1] = sc->toc[a].hd_pos_msf[1]; 1249 pb.start_msf[2] = sc->toc[a].hd_pos_msf[2]; 1250 pb.end_msf[0] = sc->toc[z+1].hd_pos_msf[0]; 1251 pb.end_msf[1] = sc->toc[z+1].hd_pos_msf[1]; 1252 pb.end_msf[2] = sc->toc[z+1].hd_pos_msf[2]; 1253 1254 return mcd_play(sc, &pb); 1255 } 1256 1257 int 1258 mcd_play(sc, pb) 1259 struct mcd_softc *sc; 1260 struct mcd_read2 *pb; 1261 { 1262 u_short iobase = sc->iobase; 1263 int retry, st; 1264 1265 sc->lastpb = *pb; 1266 for (retry = MCD_RETRIES; retry; retry--) { 1267 outb(iobase + mcd_command, MCD_CMDREAD2); 1268 outb(iobase + mcd_command, pb->start_msf[0]); 1269 outb(iobase + mcd_command, pb->start_msf[1]); 1270 outb(iobase + mcd_command, pb->start_msf[2]); 1271 outb(iobase + mcd_command, pb->end_msf[0]); 1272 outb(iobase + mcd_command, pb->end_msf[1]); 1273 outb(iobase + mcd_command, pb->end_msf[2]); 1274 if ((st = mcd_getstat(sc, 0)) != -1) 1275 break; 1276 } 1277 if (sc->debug) 1278 printf("%s: play: retry=%d status=%d\n", sc->sc_dev.dv_xname, 1279 retry, st); 1280 if (!retry) 1281 return ENXIO; 1282 1283 sc->audio_status = CD_AS_PLAY_IN_PROGRESS; 1284 return 0; 1285 } 1286 1287 int 1288 mcd_pause(sc) 1289 struct mcd_softc *sc; 1290 { 1291 struct mcd_qchninfo q; 1292 int rc; 1293 1294 /* Verify current status. */ 1295 if (sc->audio_status != CD_AS_PLAY_IN_PROGRESS) { 1296 printf("%s: pause: attempted when not playing\n", 1297 sc->sc_dev.dv_xname); 1298 return EINVAL; 1299 } 1300 1301 /* Get the current position. */ 1302 if (mcd_getqchan(sc, &q) < 0) 1303 return EIO; 1304 1305 /* Copy it into lastpb. */ 1306 sc->lastpb.start_msf[0] = q.hd_pos_msf[0]; 1307 sc->lastpb.start_msf[1] = q.hd_pos_msf[1]; 1308 sc->lastpb.start_msf[2] = q.hd_pos_msf[2]; 1309 1310 /* Stop playing. */ 1311 if ((rc = mcd_stop(sc)) != 0) 1312 return rc; 1313 1314 /* Set the proper status and exit. */ 1315 sc->audio_status = CD_AS_PLAY_PAUSED; 1316 return 0; 1317 } 1318 1319 int 1320 mcd_resume(sc) 1321 struct mcd_softc *sc; 1322 { 1323 1324 if (sc->audio_status != CD_AS_PLAY_PAUSED) 1325 return EINVAL; 1326 return mcd_play(sc, &sc->lastpb); 1327 } 1328