1/*- 2 * Copyright (c) 1995 Mikael Hybsch 3 * All rights reserved. 4 * 5 * Portions of this file are copied from mcd.c 6 * which has the following copyrights: 7 * 8 * Copyright 1993 by Holger Veit (data part) 9 * Copyright 1993 by Brian Moore (audio part) 10 * Changes Copyright 1993 by Gary Clark II 11 * Changes Copyright (C) 1994 by Andrew A. Chernov 12 * 13 * Rewrote probe routine to work on newer Mitsumi drives. 14 * Additional changes (C) 1994 by Jordan K. Hubbard 15 * 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer 23 * in this position and unchanged. 24 * 2. Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in the 26 * documentation and/or other materials provided with the distribution. 27 * 3. The name of the author may not be used to endorse or promote products 28 * derived from this software without specific prior written permission 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 33 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 35 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 39 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 */ 42 43#include <sys/cdefs.h> 44__FBSDID("$FreeBSD: releng/10.3/sys/dev/scd/scd.c 167086 2007-02-27 17:23:29Z jhb $"); 45 46 47#undef SCD_DEBUG 48 49#include <sys/param.h> 50#include <sys/systm.h> 51#include <sys/kernel.h> 52#include <sys/conf.h> 53#include <sys/fcntl.h> 54#include <sys/bio.h> 55#include <sys/cdio.h> 56#include <sys/disk.h> 57#include <sys/bus.h> 58 59#include <machine/stdarg.h> 60 61#include <machine/bus.h> 62#include <machine/resource.h> 63#include <sys/rman.h> 64 65#include <isa/isavar.h> 66 67#include <dev/scd/scdreg.h> 68#include <dev/scd/scdvar.h> 69 70/* flags */ 71#define SCDOPEN 0x0001 /* device opened */ 72#define SCDVALID 0x0002 /* parameters loaded */ 73#define SCDINIT 0x0004 /* device is init'd */ 74#define SCDPROBING 0x0020 /* probing */ 75#define SCDTOC 0x0100 /* already read toc */ 76#define SCDMBXBSY 0x0200 /* local mbx is busy */ 77#define SCDSPINNING 0x0400 /* drive is spun up */ 78 79#define SCD_S_BEGIN 0 80#define SCD_S_BEGIN1 1 81#define SCD_S_WAITSTAT 2 82#define SCD_S_WAITFIFO 3 83#define SCD_S_WAITSPIN 4 84#define SCD_S_WAITREAD 5 85#define SCD_S_WAITPARAM 6 86 87#define RDELAY_WAIT 300 88#define RDELAY_WAITREAD 300 89 90#define SCDBLKSIZE 2048 91 92#ifdef SCD_DEBUG 93 static int scd_debuglevel = SCD_DEBUG; 94# define XDEBUG(sc, level, fmt, args...) \ 95 do { \ 96 if (scd_debuglevel >= level) \ 97 device_printf(sc->dev, fmt, ## args); \ 98 } while (0) 99#else 100# define XDEBUG(sc, level, fmt, args...) 101#endif 102 103#define IS_ATTENTION(sc) ((SCD_READ(sc, IREG_STATUS) & SBIT_ATTENTION) != 0) 104#define IS_BUSY(sc) ((SCD_READ(sc, IREG_STATUS) & SBIT_BUSY) != 0) 105#define IS_DATA_RDY(sc) ((SCD_READ(sc, IREG_STATUS) & SBIT_DATA_READY) != 0) 106#define STATUS_BIT(sc, bit) ((SCD_READ(sc, IREG_STATUS) & (bit)) != 0) 107#define FSTATUS_BIT(sc, bit) ((SCD_READ(sc, IREG_FSTATUS) & (bit)) != 0) 108 109/* prototypes */ 110static void hsg2msf(int hsg, bcd_t *msf); 111static int msf2hsg(bcd_t *msf); 112 113static void process_attention(struct scd_softc *); 114static int waitfor_status_bits(struct scd_softc *, int bits_set, int bits_clear); 115static int send_cmd(struct scd_softc *, u_char cmd, u_int nargs, ...); 116static void init_drive(struct scd_softc *); 117static int spin_up(struct scd_softc *); 118static int read_toc(struct scd_softc *); 119static int get_result(struct scd_softc *, int result_len, u_char *result); 120static void print_error(struct scd_softc *, int errcode); 121 122static void scd_start(struct scd_softc *); 123static timeout_t scd_timeout; 124static void scd_doread(struct scd_softc *, int state, struct scd_mbx *mbxin); 125 126static int scd_eject(struct scd_softc *); 127static int scd_stop(struct scd_softc *); 128static int scd_pause(struct scd_softc *); 129static int scd_resume(struct scd_softc *); 130static int scd_playtracks(struct scd_softc *, struct ioc_play_track *pt); 131static int scd_playmsf(struct scd_softc *, struct ioc_play_msf *msf); 132static int scd_play(struct scd_softc *, struct ioc_play_msf *msf); 133static int scd_subchan(struct scd_softc *, struct ioc_read_subchannel *sch, int nocopyout); 134static int read_subcode(struct scd_softc *, struct sony_subchannel_position_data *sch); 135 136/* for xcdplayer */ 137static int scd_toc_header(struct scd_softc *, struct ioc_toc_header *th); 138static int scd_toc_entrys(struct scd_softc *, struct ioc_read_toc_entry *te); 139static int scd_toc_entry(struct scd_softc *, struct ioc_read_toc_single_entry *te); 140#define SCD_LASTPLUS1 170 /* don't ask, xcdplayer passes this in */ 141 142static d_open_t scdopen; 143static d_close_t scdclose; 144static d_ioctl_t scdioctl; 145static d_strategy_t scdstrategy; 146 147 148static struct cdevsw scd_cdevsw = { 149 .d_version = D_VERSION, 150 .d_open = scdopen, 151 .d_close = scdclose, 152 .d_read = physread, 153 .d_ioctl = scdioctl, 154 .d_strategy = scdstrategy, 155 .d_name = "scd", 156 .d_flags = D_DISK | D_NEEDGIANT, 157}; 158 159int 160scd_attach(struct scd_softc *sc) 161{ 162 int unit; 163 164 unit = device_get_unit(sc->dev); 165 166 init_drive(sc); 167 168 sc->data.flags = SCDINIT; 169 sc->data.audio_status = CD_AS_AUDIO_INVALID; 170 bioq_init(&sc->data.head); 171 172 sc->scd_dev_t = make_dev(&scd_cdevsw, 8 * unit, 173 UID_ROOT, GID_OPERATOR, 0640, "scd%d", unit); 174 sc->scd_dev_t->si_drv1 = (void *)sc; 175 176 return (0); 177} 178 179static int 180scdopen(struct cdev *dev, int flags, int fmt, struct thread *td) 181{ 182 struct scd_softc *sc; 183 int rc; 184 185 sc = (struct scd_softc *)dev->si_drv1; 186 187 /* not initialized*/ 188 if (!(sc->data.flags & SCDINIT)) 189 return (ENXIO); 190 191 /* invalidated in the meantime? mark all open part's invalid */ 192 if (sc->data.openflag) 193 return (ENXIO); 194 195 XDEBUG(sc, 1, "DEBUG: status = 0x%x\n", SCD_READ(sc, IREG_STATUS)); 196 197 if ((rc = spin_up(sc)) != 0) { 198 print_error(sc, rc); 199 return (EIO); 200 } 201 if (!(sc->data.flags & SCDTOC)) { 202 int loop_count = 3; 203 204 while (loop_count-- > 0 && (rc = read_toc(sc)) != 0) { 205 if (rc == ERR_NOT_SPINNING) { 206 rc = spin_up(sc); 207 if (rc) { 208 print_error(sc, rc);\ 209 return (EIO); 210 } 211 continue; 212 } 213 device_printf(sc->dev, "TOC read error 0x%x\n", rc); 214 return (EIO); 215 } 216 } 217 218 sc->data.openflag = 1; 219 sc->data.flags |= SCDVALID; 220 221 return (0); 222} 223 224static int 225scdclose(struct cdev *dev, int flags, int fmt, struct thread *td) 226{ 227 struct scd_softc *sc; 228 229 sc = (struct scd_softc *)dev->si_drv1; 230 231 if (!(sc->data.flags & SCDINIT) || !sc->data.openflag) 232 return (ENXIO); 233 234 if (sc->data.audio_status != CD_AS_PLAY_IN_PROGRESS) { 235 (void)send_cmd(sc, CMD_SPIN_DOWN, 0); 236 sc->data.flags &= ~SCDSPINNING; 237 } 238 239 240 /* close channel */ 241 sc->data.openflag = 0; 242 243 return (0); 244} 245 246static void 247scdstrategy(struct bio *bp) 248{ 249 int s; 250 struct scd_softc *sc; 251 252 sc = (struct scd_softc *)bp->bio_dev->si_drv1; 253 254 /* if device invalidated (e.g. media change, door open), error */ 255 if (!(sc->data.flags & SCDVALID)) { 256 device_printf(sc->dev, "media changed\n"); 257 bp->bio_error = EIO; 258 goto bad; 259 } 260 261 /* read only */ 262 if (!(bp->bio_cmd == BIO_READ)) { 263 bp->bio_error = EROFS; 264 goto bad; 265 } 266 267 /* no data to read */ 268 if (bp->bio_bcount == 0) 269 goto done; 270 271 if (!(sc->data.flags & SCDTOC)) { 272 bp->bio_error = EIO; 273 goto bad; 274 } 275 276 bp->bio_resid = 0; 277 278 /* queue it */ 279 s = splbio(); 280 bioq_disksort(&sc->data.head, bp); 281 splx(s); 282 283 /* now check whether we can perform processing */ 284 scd_start(sc); 285 return; 286 287bad: 288 bp->bio_flags |= BIO_ERROR; 289done: 290 bp->bio_resid = bp->bio_bcount; 291 biodone(bp); 292 return; 293} 294 295static void 296scd_start(struct scd_softc *sc) 297{ 298 struct bio *bp; 299 int s = splbio(); 300 301 if (sc->data.flags & SCDMBXBSY) { 302 splx(s); 303 return; 304 } 305 306 bp = bioq_takefirst(&sc->data.head); 307 if (bp != 0) { 308 /* block found to process, dequeue */ 309 sc->data.flags |= SCDMBXBSY; 310 splx(s); 311 } else { 312 /* nothing to do */ 313 splx(s); 314 return; 315 } 316 317 sc->data.mbx.retry = 3; 318 sc->data.mbx.bp = bp; 319 splx(s); 320 321 scd_doread(sc, SCD_S_BEGIN, &(sc->data.mbx)); 322 return; 323} 324 325static int 326scdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) 327{ 328 struct scd_softc *sc; 329 330 sc = (struct scd_softc *)dev->si_drv1; 331 332 XDEBUG(sc, 1, "ioctl: cmd=0x%lx\n", cmd); 333 334 if (!(sc->data.flags & SCDVALID)) 335 return (EIO); 336 337 switch (cmd) { 338 case DIOCGMEDIASIZE: 339 *(off_t *)addr = (off_t)sc->data.disksize * sc->data.blksize; 340 return (0); 341 break; 342 case DIOCGSECTORSIZE: 343 *(u_int *)addr = sc->data.blksize; 344 return (0); 345 break; 346 case CDIOCPLAYTRACKS: 347 return scd_playtracks(sc, (struct ioc_play_track *) addr); 348 case CDIOCPLAYBLOCKS: 349 return (EINVAL); 350 case CDIOCPLAYMSF: 351 return scd_playmsf(sc, (struct ioc_play_msf *) addr); 352 case CDIOCREADSUBCHANNEL_SYSSPACE: 353 return scd_subchan(sc, (struct ioc_read_subchannel *) addr, 1); 354 case CDIOCREADSUBCHANNEL: 355 return scd_subchan(sc, (struct ioc_read_subchannel *) addr, 0); 356 case CDIOREADTOCHEADER: 357 return scd_toc_header (sc, (struct ioc_toc_header *) addr); 358 case CDIOREADTOCENTRYS: 359 return scd_toc_entrys (sc, (struct ioc_read_toc_entry*) addr); 360 case CDIOREADTOCENTRY: 361 return scd_toc_entry (sc, (struct ioc_read_toc_single_entry*) addr); 362 case CDIOCSETPATCH: 363 case CDIOCGETVOL: 364 case CDIOCSETVOL: 365 case CDIOCSETMONO: 366 case CDIOCSETSTERIO: 367 case CDIOCSETMUTE: 368 case CDIOCSETLEFT: 369 case CDIOCSETRIGHT: 370 return (EINVAL); 371 case CDIOCRESUME: 372 return scd_resume(sc); 373 case CDIOCPAUSE: 374 return scd_pause(sc); 375 case CDIOCSTART: 376 return (EINVAL); 377 case CDIOCSTOP: 378 return scd_stop(sc); 379 case CDIOCEJECT: 380 return scd_eject(sc); 381 case CDIOCALLOW: 382 return (0); 383 case CDIOCSETDEBUG: 384#ifdef SCD_DEBUG 385 scd_debuglevel++; 386#endif 387 return (0); 388 case CDIOCCLRDEBUG: 389#ifdef SCD_DEBUG 390 scd_debuglevel = 0; 391 392#endif 393 return (0); 394 default: 395 device_printf(sc->dev, "unsupported ioctl (cmd=0x%lx)\n", cmd); 396 return (ENOTTY); 397 } 398} 399 400/*************************************************************** 401 * lower level of driver starts here 402 **************************************************************/ 403 404static int 405scd_playtracks(struct scd_softc *sc, struct ioc_play_track *pt) 406{ 407 struct ioc_play_msf msf; 408 int a = pt->start_track; 409 int z = pt->end_track; 410 int rc; 411 412 if (!(sc->data.flags & SCDTOC) && (rc = read_toc(sc)) != 0) { 413 if (rc == -ERR_NOT_SPINNING) { 414 if (spin_up(sc) != 0) 415 return (EIO); 416 rc = read_toc(sc); 417 } 418 if (rc != 0) { 419 print_error(sc, rc); 420 return (EIO); 421 } 422 } 423 424 XDEBUG(sc, 1, "playtracks from %d:%d to %d:%d\n", 425 a, pt->start_index, z, pt->end_index); 426 427 if ( a < sc->data.first_track 428 || a > sc->data.last_track 429 || a > z 430 || z > sc->data.last_track) 431 return (EINVAL); 432 433 bcopy(sc->data.toc[a].start_msf, &msf.start_m, 3); 434 hsg2msf(msf2hsg(sc->data.toc[z+1].start_msf)-1, &msf.end_m); 435 436 return scd_play(sc, &msf); 437} 438 439/* The start/end msf is expected to be in bin format */ 440static int 441scd_playmsf(struct scd_softc *sc, struct ioc_play_msf *msfin) 442{ 443 struct ioc_play_msf msf; 444 445 msf.start_m = bin2bcd(msfin->start_m); 446 msf.start_s = bin2bcd(msfin->start_s); 447 msf.start_f = bin2bcd(msfin->start_f); 448 msf.end_m = bin2bcd(msfin->end_m); 449 msf.end_s = bin2bcd(msfin->end_s); 450 msf.end_f = bin2bcd(msfin->end_f); 451 452 return scd_play(sc, &msf); 453} 454 455/* The start/end msf is expected to be in bcd format */ 456static int 457scd_play(struct scd_softc *sc, struct ioc_play_msf *msf) 458{ 459 int i, rc; 460 461 XDEBUG(sc, 1, "playing: %02x:%02x:%02x -> %02x:%02x:%02x\n", 462 msf->start_m, msf->start_s, msf->start_f, 463 msf->end_m, msf->end_s, msf->end_f); 464 465 for (i = 0; i < 2; i++) { 466 rc = send_cmd(sc, CMD_PLAY_AUDIO, 7, 467 0x03, 468 msf->start_m, msf->start_s, msf->start_f, 469 msf->end_m, msf->end_s, msf->end_f); 470 if (rc == -ERR_NOT_SPINNING) { 471 sc->data.flags &= ~SCDSPINNING; 472 if (spin_up(sc) != 0) 473 return (EIO); 474 } else if (rc < 0) { 475 print_error(sc, rc); 476 return (EIO); 477 } else { 478 break; 479 } 480 } 481 sc->data.audio_status = CD_AS_PLAY_IN_PROGRESS; 482 bcopy((char *)msf, (char *)&sc->data.last_play, sizeof(struct ioc_play_msf)); 483 return (0); 484} 485 486static int 487scd_stop(struct scd_softc *sc) 488{ 489 490 (void)send_cmd(sc, CMD_STOP_AUDIO, 0); 491 sc->data.audio_status = CD_AS_PLAY_COMPLETED; 492 return (0); 493} 494 495static int 496scd_pause(struct scd_softc *sc) 497{ 498 struct sony_subchannel_position_data subpos; 499 500 if (sc->data.audio_status != CD_AS_PLAY_IN_PROGRESS) 501 return (EINVAL); 502 503 if (read_subcode(sc, &subpos) != 0) 504 return (EIO); 505 506 if (send_cmd(sc, CMD_STOP_AUDIO, 0) != 0) 507 return (EIO); 508 509 sc->data.last_play.start_m = subpos.abs_msf[0]; 510 sc->data.last_play.start_s = subpos.abs_msf[1]; 511 sc->data.last_play.start_f = subpos.abs_msf[2]; 512 sc->data.audio_status = CD_AS_PLAY_PAUSED; 513 514 XDEBUG(sc, 1, "pause @ %02x:%02x:%02x\n", 515 sc->data.last_play.start_m, 516 sc->data.last_play.start_s, 517 sc->data.last_play.start_f); 518 519 return (0); 520} 521 522static int 523scd_resume(struct scd_softc *sc) 524{ 525 526 if (sc->data.audio_status != CD_AS_PLAY_PAUSED) 527 return (EINVAL); 528 return scd_play(sc, &sc->data.last_play); 529} 530 531static int 532scd_eject(struct scd_softc *sc) 533{ 534 535 sc->data.audio_status = CD_AS_AUDIO_INVALID; 536 sc->data.flags &= ~(SCDSPINNING|SCDTOC); 537 538 if (send_cmd(sc, CMD_STOP_AUDIO, 0) != 0 || 539 send_cmd(sc, CMD_SPIN_DOWN, 0) != 0 || 540 send_cmd(sc, CMD_EJECT, 0) != 0) 541 { 542 return (EIO); 543 } 544 return (0); 545} 546 547static int 548scd_subchan(struct scd_softc *sc, struct ioc_read_subchannel *sch, int nocopyout) 549{ 550 struct sony_subchannel_position_data q; 551 struct cd_sub_channel_info data; 552 553 XDEBUG(sc, 1, "subchan af=%d, df=%d\n", 554 sch->address_format, sch->data_format); 555 556 if (sch->address_format != CD_MSF_FORMAT) 557 return (EINVAL); 558 559 if (sch->data_format != CD_CURRENT_POSITION) 560 return (EINVAL); 561 562 if (read_subcode(sc, &q) != 0) 563 return (EIO); 564 565 data.header.audio_status = sc->data.audio_status; 566 data.what.position.data_format = CD_MSF_FORMAT; 567 data.what.position.track_number = bcd2bin(q.track_number); 568 data.what.position.reladdr.msf.unused = 0; 569 data.what.position.reladdr.msf.minute = bcd2bin(q.rel_msf[0]); 570 data.what.position.reladdr.msf.second = bcd2bin(q.rel_msf[1]); 571 data.what.position.reladdr.msf.frame = bcd2bin(q.rel_msf[2]); 572 data.what.position.absaddr.msf.unused = 0; 573 data.what.position.absaddr.msf.minute = bcd2bin(q.abs_msf[0]); 574 data.what.position.absaddr.msf.second = bcd2bin(q.abs_msf[1]); 575 data.what.position.absaddr.msf.frame = bcd2bin(q.abs_msf[2]); 576 577 if (nocopyout == 0) { 578 if (copyout(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len))!=0) 579 return (EFAULT); 580 } else { 581 bcopy(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len)); 582 } 583 return (0); 584} 585 586int 587scd_probe(struct scd_softc *sc) 588{ 589 struct sony_drive_configuration drive_config; 590 int rc; 591 static char namebuf[8+16+8+3]; 592 char *s = namebuf; 593 int loop_count = 0; 594 595 sc->data.flags = SCDPROBING; 596 597 bzero(&drive_config, sizeof(drive_config)); 598 599again: 600 /* Reset drive */ 601 SCD_WRITE(sc, OREG_CONTROL, CBIT_RESET_DRIVE); 602 603 /* Calm down */ 604 DELAY(300000); 605 606 /* Only the ATTENTION bit may be set */ 607 if ((SCD_READ(sc, IREG_STATUS) & ~1) != 0) { 608 XDEBUG(sc, 1, "too many bits set. probe failed.\n"); 609 return (ENXIO); 610 } 611 rc = send_cmd(sc, CMD_GET_DRIVE_CONFIG, 0); 612 if (rc != sizeof(drive_config)) { 613 /* Sometimes if the drive is playing audio I get */ 614 /* the bad result 82. Fix by repeating the reset */ 615 if (rc > 0 && loop_count++ == 0) 616 goto again; 617 return (ENXIO); 618 } 619 if (get_result(sc, rc, (u_char *)&drive_config) != 0) 620 return (ENXIO); 621 622 bcopy(drive_config.vendor, namebuf, 8); 623 s = namebuf+8; 624 while (*(s-1) == ' ') /* Strip trailing spaces */ 625 s--; 626 *s++ = ' '; 627 bcopy(drive_config.product, s, 16); 628 s += 16; 629 while (*(s-1) == ' ') 630 s--; 631 *s++ = ' '; 632 bcopy(drive_config.revision, s, 8); 633 s += 8; 634 while (*(s-1) == ' ') 635 s--; 636 *s = 0; 637 638 sc->data.name = namebuf; 639 640 if (drive_config.config & 0x10) 641 sc->data.double_speed = 1; 642 else 643 sc->data.double_speed = 0; 644 645 return (0); 646} 647 648static int 649read_subcode(struct scd_softc *sc, struct sony_subchannel_position_data *scp) 650{ 651 int rc; 652 653 rc = send_cmd(sc, CMD_GET_SUBCHANNEL_DATA, 0); 654 if (rc < 0 || rc < sizeof(*scp)) 655 return (EIO); 656 if (get_result(sc, rc, (u_char *)scp) != 0) 657 return (EIO); 658 return (0); 659} 660 661/* State machine copied from mcd.c */ 662 663/* This (and the code in mcd.c) will not work with more than one drive */ 664/* because there is only one sc->ch_mbxsave below. Should fix that some day. */ 665/* (sc->ch_mbxsave & state should probably be included in the scd_data struct and */ 666/* the unit number used as first argument to scd_doread().) /Micke */ 667 668/* state machine to process read requests 669 * initialize with SCD_S_BEGIN: reset state machine 670 * SCD_S_WAITSTAT: wait for ready (!busy) 671 * SCD_S_WAITSPIN: wait for drive to spin up (if not spinning) 672 * SCD_S_WAITFIFO: wait for param fifo to get ready, them exec. command. 673 * SCD_S_WAITREAD: wait for data ready, read data 674 * SCD_S_WAITPARAM: wait for command result params, read them, error if bad data read. 675 */ 676 677static void 678scd_timeout(void *arg) 679{ 680 struct scd_softc *sc; 681 sc = (struct scd_softc *)arg; 682 683 scd_doread(sc, sc->ch_state, sc->ch_mbxsave); 684} 685 686static void 687scd_doread(struct scd_softc *sc, int state, struct scd_mbx *mbxin) 688{ 689 struct scd_mbx *mbx = (state!=SCD_S_BEGIN) ? sc->ch_mbxsave : mbxin; 690 struct bio *bp = mbx->bp; 691 int i; 692 int blknum; 693 caddr_t addr; 694 static char sdata[3]; /* Must be preserved between calls to this function */ 695 696loop: 697 switch (state) { 698 case SCD_S_BEGIN: 699 mbx = sc->ch_mbxsave = mbxin; 700 701 case SCD_S_BEGIN1: 702 /* get status */ 703 mbx->count = RDELAY_WAIT; 704 705 process_attention(sc); 706 goto trystat; 707 708 case SCD_S_WAITSTAT: 709 sc->ch_state = SCD_S_WAITSTAT; 710 untimeout(scd_timeout, (caddr_t)sc, sc->ch); 711 if (mbx->count-- <= 0) { 712 device_printf(sc->dev, "timeout. drive busy.\n"); 713 goto harderr; 714 } 715 716trystat: 717 if (IS_BUSY(sc)) { 718 sc->ch_state = SCD_S_WAITSTAT; 719 sc->ch = timeout(scd_timeout, (caddr_t)sc, hz/100); /* XXX */ 720 return; 721 } 722 723 process_attention(sc); 724 725 /* reject, if audio active */ 726 if (sc->data.audio_status & CD_AS_PLAY_IN_PROGRESS) { 727 device_printf(sc->dev, "audio is active\n"); 728 goto harderr; 729 } 730 731 mbx->sz = sc->data.blksize; 732 733 /* for first block */ 734 mbx->nblk = (bp->bio_bcount + (mbx->sz-1)) / mbx->sz; 735 mbx->skip = 0; 736 737nextblock: 738 if (!(sc->data.flags & SCDVALID)) 739 goto changed; 740 741 blknum = bp->bio_offset / mbx->sz + mbx->skip/mbx->sz; 742 743 XDEBUG(sc, 2, "scd_doread: read blknum=%d\n", blknum); 744 745 /* build parameter block */ 746 hsg2msf(blknum, sdata); 747 748 SCD_WRITE(sc, OREG_CONTROL, CBIT_RESULT_READY_CLEAR); 749 SCD_WRITE(sc, OREG_CONTROL, CBIT_RPARAM_CLEAR); 750 SCD_WRITE(sc, OREG_CONTROL, CBIT_DATA_READY_CLEAR); 751 752 if (FSTATUS_BIT(sc, FBIT_WPARAM_READY)) 753 goto writeparam; 754 755 mbx->count = 100; 756 sc->ch_state = SCD_S_WAITFIFO; 757 sc->ch = timeout(scd_timeout, (caddr_t)sc, hz/100); /* XXX */ 758 return; 759 760 case SCD_S_WAITSPIN: 761 sc->ch_state = SCD_S_WAITSPIN; 762 untimeout(scd_timeout,(caddr_t)sc, sc->ch); 763 if (mbx->count-- <= 0) { 764 device_printf(sc->dev, "timeout waiting for drive to spin up.\n"); 765 goto harderr; 766 } 767 if (!STATUS_BIT(sc, SBIT_RESULT_READY)) { 768 sc->ch_state = SCD_S_WAITSPIN; 769 sc->ch = timeout(scd_timeout, (caddr_t)sc, hz/100); /* XXX */ 770 return; 771 } 772 SCD_WRITE(sc, OREG_CONTROL, CBIT_RESULT_READY_CLEAR); 773 switch ((i = SCD_READ(sc, IREG_RESULT)) & 0xf0) { 774 case 0x20: 775 i = SCD_READ(sc, IREG_RESULT); 776 print_error(sc, i); 777 goto harderr; 778 case 0x00: 779 (void)SCD_READ(sc, IREG_RESULT); 780 sc->data.flags |= SCDSPINNING; 781 break; 782 } 783 XDEBUG(sc, 1, "DEBUG: spin up complete\n"); 784 785 state = SCD_S_BEGIN1; 786 goto loop; 787 788 case SCD_S_WAITFIFO: 789 sc->ch_state = SCD_S_WAITFIFO; 790 untimeout(scd_timeout,(caddr_t)sc, sc->ch); 791 if (mbx->count-- <= 0) { 792 device_printf(sc->dev, "timeout. write param not ready.\n"); 793 goto harderr; 794 } 795 if (!FSTATUS_BIT(sc, FBIT_WPARAM_READY)) { 796 sc->ch_state = SCD_S_WAITFIFO; 797 sc->ch = timeout(scd_timeout, (caddr_t)sc,hz/100); /* XXX */ 798 return; 799 } 800 XDEBUG(sc, 1, "mbx->count (writeparamwait) = %d(%d)\n", mbx->count, 100); 801 802writeparam: 803 /* The reason this test isn't done 'till now is to make sure */ 804 /* that it is ok to send the SPIN_UP cmd below. */ 805 if (!(sc->data.flags & SCDSPINNING)) { 806 XDEBUG(sc, 1, "spinning up drive ...\n"); 807 SCD_WRITE(sc, OREG_COMMAND, CMD_SPIN_UP); 808 mbx->count = 300; 809 sc->ch_state = SCD_S_WAITSPIN; 810 sc->ch = timeout(scd_timeout, (caddr_t)sc, hz/100); /* XXX */ 811 return; 812 } 813 814 /* send the read command */ 815 critical_enter(); 816 SCD_WRITE(sc, OREG_WPARAMS, sdata[0]); 817 SCD_WRITE(sc, OREG_WPARAMS, sdata[1]); 818 SCD_WRITE(sc, OREG_WPARAMS, sdata[2]); 819 SCD_WRITE(sc, OREG_WPARAMS, 0); 820 SCD_WRITE(sc, OREG_WPARAMS, 0); 821 SCD_WRITE(sc, OREG_WPARAMS, 1); 822 SCD_WRITE(sc, OREG_COMMAND, CMD_READ); 823 critical_exit(); 824 825 mbx->count = RDELAY_WAITREAD; 826 for (i = 0; i < 50; i++) { 827 if (STATUS_BIT(sc, SBIT_DATA_READY)) 828 goto got_data; 829 DELAY(100); 830 } 831 832 sc->ch_state = SCD_S_WAITREAD; 833 sc->ch = timeout(scd_timeout, (caddr_t)sc, hz/100); /* XXX */ 834 return; 835 836 case SCD_S_WAITREAD: 837 sc->ch_state = SCD_S_WAITREAD; 838 untimeout(scd_timeout,(caddr_t)sc, sc->ch); 839 if (mbx->count-- <= 0) { 840 if (STATUS_BIT(sc, SBIT_RESULT_READY)) 841 goto got_param; 842 device_printf(sc->dev, "timeout while reading data\n"); 843 goto readerr; 844 } 845 if (!STATUS_BIT(sc, SBIT_DATA_READY)) { 846 process_attention(sc); 847 if (!(sc->data.flags & SCDVALID)) 848 goto changed; 849 sc->ch_state = SCD_S_WAITREAD; 850 sc->ch = timeout(scd_timeout, (caddr_t)sc, hz/100); /* XXX */ 851 return; 852 } 853 XDEBUG(sc, 2, "mbx->count (after RDY_BIT) = %d(%d)\n", mbx->count, RDELAY_WAITREAD); 854 855got_data: 856 /* data is ready */ 857 addr = bp->bio_data + mbx->skip; 858 SCD_WRITE(sc, OREG_CONTROL, CBIT_DATA_READY_CLEAR); 859 SCD_READ_MULTI(sc, IREG_DATA, addr, mbx->sz); 860 861 mbx->count = 100; 862 for (i = 0; i < 20; i++) { 863 if (STATUS_BIT(sc, SBIT_RESULT_READY)) 864 goto waitfor_param; 865 DELAY(100); 866 } 867 goto waitfor_param; 868 869 case SCD_S_WAITPARAM: 870 sc->ch_state = SCD_S_WAITPARAM; 871 untimeout(scd_timeout,(caddr_t)sc, sc->ch); 872 if (mbx->count-- <= 0) { 873 device_printf(sc->dev, "timeout waiting for params\n"); 874 goto readerr; 875 } 876 877waitfor_param: 878 if (!STATUS_BIT(sc, SBIT_RESULT_READY)) { 879 sc->ch_state = SCD_S_WAITPARAM; 880 sc->ch = timeout(scd_timeout, (caddr_t)sc, hz/100); /* XXX */ 881 return; 882 } 883#ifdef SCD_DEBUG 884 if (mbx->count < 100 && scd_debuglevel > 0) 885 device_printf(sc->dev, "mbx->count (paramwait) = %d(%d)\n", mbx->count, 100); 886#endif 887 888got_param: 889 SCD_WRITE(sc, OREG_CONTROL, CBIT_RESULT_READY_CLEAR); 890 switch ((i = SCD_READ(sc, IREG_RESULT)) & 0xf0) { 891 case 0x50: 892 switch (i) { 893 case ERR_FATAL_READ_ERROR1: 894 case ERR_FATAL_READ_ERROR2: 895 device_printf(sc->dev, "unrecoverable read error 0x%x\n", i); 896 goto harderr; 897 } 898 break; 899 case 0x20: 900 i = SCD_READ(sc, IREG_RESULT); 901 switch (i) { 902 case ERR_NOT_SPINNING: 903 XDEBUG(sc, 1, "read error: drive not spinning\n"); 904 if (mbx->retry-- > 0) { 905 state = SCD_S_BEGIN1; 906 sc->data.flags &= ~SCDSPINNING; 907 goto loop; 908 } 909 goto harderr; 910 default: 911 print_error(sc, i); 912 goto readerr; 913 } 914 case 0x00: 915 i = SCD_READ(sc, IREG_RESULT); 916 break; 917 } 918 919 if (--mbx->nblk > 0) { 920 mbx->skip += mbx->sz; 921 goto nextblock; 922 } 923 924 /* return buffer */ 925 bp->bio_resid = 0; 926 biodone(bp); 927 928 sc->data.flags &= ~SCDMBXBSY; 929 scd_start(sc); 930 return; 931 } 932 933readerr: 934 if (mbx->retry-- > 0) { 935 device_printf(sc->dev, "retrying ...\n"); 936 state = SCD_S_BEGIN1; 937 goto loop; 938 } 939harderr: 940 /* invalidate the buffer */ 941 bp->bio_error = EIO; 942 bp->bio_flags |= BIO_ERROR; 943 bp->bio_resid = bp->bio_bcount; 944 biodone(bp); 945 946 sc->data.flags &= ~SCDMBXBSY; 947 scd_start(sc); 948 return; 949 950changed: 951 device_printf(sc->dev, "media changed\n"); 952 goto harderr; 953} 954 955static void 956hsg2msf(int hsg, bcd_t *msf) 957{ 958 959 hsg += 150; 960 M_msf(msf) = bin2bcd(hsg / 4500); 961 hsg %= 4500; 962 S_msf(msf) = bin2bcd(hsg / 75); 963 F_msf(msf) = bin2bcd(hsg % 75); 964} 965 966static int 967msf2hsg(bcd_t *msf) 968{ 969 970 return (bcd2bin(M_msf(msf)) * 60 + 971 bcd2bin(S_msf(msf))) * 75 + 972 bcd2bin(F_msf(msf)) - 150; 973} 974 975static void 976process_attention(struct scd_softc *sc) 977{ 978 unsigned char code; 979 int count = 0; 980 981 while (IS_ATTENTION(sc) && count++ < 30) { 982 SCD_WRITE(sc, OREG_CONTROL, CBIT_ATTENTION_CLEAR); 983 code = SCD_READ(sc, IREG_RESULT); 984 985#ifdef SCD_DEBUG 986 if (scd_debuglevel > 0) { 987 if (count == 1) 988 device_printf(sc->dev, "DEBUG: ATTENTIONS = 0x%x", code); 989 else 990 printf(",0x%x", code); 991 } 992#endif 993 994 switch (code) { 995 case ATTEN_SPIN_DOWN: 996 sc->data.flags &= ~SCDSPINNING; 997 break; 998 999 case ATTEN_SPIN_UP_DONE: 1000 sc->data.flags |= SCDSPINNING; 1001 break; 1002 1003 case ATTEN_AUDIO_DONE: 1004 sc->data.audio_status = CD_AS_PLAY_COMPLETED; 1005 break; 1006 1007 case ATTEN_DRIVE_LOADED: 1008 sc->data.flags &= ~(SCDTOC|SCDSPINNING|SCDVALID); 1009 sc->data.audio_status = CD_AS_AUDIO_INVALID; 1010 break; 1011 1012 case ATTEN_EJECT_PUSHED: 1013 sc->data.flags &= ~SCDVALID; 1014 break; 1015 } 1016 DELAY(100); 1017 } 1018#ifdef SCD_DEBUG 1019 if (scd_debuglevel > 0 && count > 0) 1020 printf("\n"); 1021#endif 1022} 1023 1024/* Returns 0 OR sony error code */ 1025static int 1026spin_up(struct scd_softc *sc) 1027{ 1028 unsigned char res_reg[12]; 1029 unsigned int res_size; 1030 int rc; 1031 int loop_count = 0; 1032 1033again: 1034 rc = send_cmd(sc, CMD_SPIN_UP, 0, 0, res_reg, &res_size); 1035 if (rc != 0) { 1036 XDEBUG(sc, 2, "CMD_SPIN_UP error 0x%x\n", rc); 1037 return (rc); 1038 } 1039 1040 if (!(sc->data.flags & SCDTOC)) { 1041 rc = send_cmd(sc, CMD_READ_TOC, 0); 1042 if (rc == ERR_NOT_SPINNING) { 1043 if (loop_count++ < 3) 1044 goto again; 1045 return (rc); 1046 } 1047 if (rc != 0) 1048 return (rc); 1049 } 1050 1051 sc->data.flags |= SCDSPINNING; 1052 1053 return (0); 1054} 1055 1056static struct sony_tracklist * 1057get_tl(struct sony_toc *toc, int size) 1058{ 1059 struct sony_tracklist *tl = &toc->tracks[0]; 1060 1061 if (tl->track != 0xb0) 1062 return (tl); 1063 if (tl->track != 0xb1) 1064 return (tl); 1065 tl = (struct sony_tracklist *)((char *)tl + 9); 1066 if (tl->track != 0xb2) 1067 return (tl); 1068 tl = (struct sony_tracklist *)((char *)tl + 9); 1069 if (tl->track != 0xb3) 1070 return (tl); 1071 tl = (struct sony_tracklist *)((char *)tl + 9); 1072 if (tl->track != 0xb4) 1073 return (tl); 1074 tl = (struct sony_tracklist *)((char *)tl + 9); 1075 if (tl->track != 0xc0) 1076 return (tl); 1077 tl = (struct sony_tracklist *)((char *)tl + 9); 1078 return (tl); 1079} 1080 1081static int 1082read_toc(struct scd_softc *sc) 1083{ 1084 struct sony_toc toc; 1085 struct sony_tracklist *tl; 1086 int rc, i, j; 1087 u_long first, last; 1088 1089 rc = send_cmd(sc, CMD_GET_TOC, 1, 1); 1090 if (rc < 0) 1091 return (rc); 1092 if (rc > sizeof(toc)) { 1093 device_printf(sc->dev, "program error: toc too large (%d)\n", rc); 1094 return (EIO); 1095 } 1096 if (get_result(sc, rc, (u_char *)&toc) != 0) 1097 return (EIO); 1098 1099 XDEBUG(sc, 1, "toc read. len = %d, sizeof(toc) = %d\n", rc, sizeof(toc)); 1100 1101 tl = get_tl(&toc, rc); 1102 first = msf2hsg(tl->start_msf); 1103 last = msf2hsg(toc.lead_out_start_msf); 1104 sc->data.blksize = SCDBLKSIZE; 1105 sc->data.disksize = last*sc->data.blksize/DEV_BSIZE; 1106 1107 XDEBUG(sc, 1, "firstsector = %ld, lastsector = %ld", first, last); 1108 1109 sc->data.first_track = bcd2bin(toc.first_track); 1110 sc->data.last_track = bcd2bin(toc.last_track); 1111 if (sc->data.last_track > (MAX_TRACKS-2)) 1112 sc->data.last_track = MAX_TRACKS-2; 1113 for (j = 0, i = sc->data.first_track; i <= sc->data.last_track; i++, j++) { 1114 sc->data.toc[i].adr = tl[j].adr; 1115 sc->data.toc[i].ctl = tl[j].ctl; /* for xcdplayer */ 1116 bcopy(tl[j].start_msf, sc->data.toc[i].start_msf, 3); 1117#ifdef SCD_DEBUG 1118 if (scd_debuglevel > 0) { 1119 if ((j % 3) == 0) { 1120 printf("\n"); 1121 device_printf(sc->dev, "tracks "); 1122 } 1123 printf("[%03d: %2d %2d %2d] ", i, 1124 bcd2bin(sc->data.toc[i].start_msf[0]), 1125 bcd2bin(sc->data.toc[i].start_msf[1]), 1126 bcd2bin(sc->data.toc[i].start_msf[2])); 1127 } 1128#endif 1129 } 1130 bcopy(toc.lead_out_start_msf, sc->data.toc[sc->data.last_track+1].start_msf, 3); 1131#ifdef SCD_DEBUG 1132 if (scd_debuglevel > 0) { 1133 i = sc->data.last_track+1; 1134 printf("[END: %2d %2d %2d]\n", 1135 bcd2bin(sc->data.toc[i].start_msf[0]), 1136 bcd2bin(sc->data.toc[i].start_msf[1]), 1137 bcd2bin(sc->data.toc[i].start_msf[2])); 1138 } 1139#endif 1140 1141 sc->data.flags |= SCDTOC; 1142 1143 return (0); 1144} 1145 1146static void 1147init_drive(struct scd_softc *sc) 1148{ 1149 int rc; 1150 1151 rc = send_cmd(sc, CMD_SET_DRIVE_PARAM, 2, 1152 0x05, 0x03 | ((sc->data.double_speed) ? 0x04: 0)); 1153 if (rc != 0) 1154 device_printf(sc->dev, "Unable to set parameters. Errcode = 0x%x\n", rc); 1155} 1156 1157/* Returns 0 or errno */ 1158static int 1159get_result(struct scd_softc *sc, int result_len, u_char *result) 1160{ 1161 int loop_index = 2; /* send_cmd() reads two bytes ... */ 1162 1163 XDEBUG(sc, 1, "DEBUG: get_result: bytes=%d\n", result_len); 1164 1165 while (result_len-- > 0) { 1166 if (loop_index++ >= 10) { 1167 loop_index = 1; 1168 if (waitfor_status_bits(sc, SBIT_RESULT_READY, 0)) 1169 return (EIO); 1170 SCD_WRITE(sc, OREG_CONTROL, CBIT_RESULT_READY_CLEAR); 1171 } 1172 if (result) 1173 *result++ = SCD_READ(sc, IREG_RESULT); 1174 else 1175 (void)SCD_READ(sc, IREG_RESULT); 1176 } 1177 return (0); 1178} 1179 1180/* Returns -0x100 for timeout, -(drive error code) OR number of result bytes */ 1181static int 1182send_cmd(struct scd_softc *sc, u_char cmd, u_int nargs, ...) 1183{ 1184 va_list ap; 1185 u_char c; 1186 int rc; 1187 int i; 1188 1189 if (waitfor_status_bits(sc, 0, SBIT_BUSY)) { 1190 device_printf(sc->dev, "drive busy\n"); 1191 return (-0x100); 1192 } 1193 1194 XDEBUG(sc, 1, "DEBUG: send_cmd: cmd=0x%x nargs=%d", cmd, nargs); 1195 1196 SCD_WRITE(sc, OREG_CONTROL, CBIT_RESULT_READY_CLEAR); 1197 SCD_WRITE(sc, OREG_CONTROL, CBIT_RPARAM_CLEAR); 1198 1199 for (i = 0; i < 100; i++) 1200 if (FSTATUS_BIT(sc, FBIT_WPARAM_READY)) 1201 break; 1202 if (!FSTATUS_BIT(sc, FBIT_WPARAM_READY)) { 1203 XDEBUG(sc, 1, "\nwparam timeout\n"); 1204 return (-EIO); 1205 } 1206 1207 va_start(ap, nargs); 1208 for (i = 0; i < nargs; i++) { 1209 c = (u_char)va_arg(ap, int); 1210 SCD_WRITE(sc, OREG_WPARAMS, c); 1211 XDEBUG(sc, 1, ",{0x%x}", c); 1212 } 1213 va_end(ap); 1214 XDEBUG(sc, 1, "\n"); 1215 1216 SCD_WRITE(sc, OREG_COMMAND, cmd); 1217 1218 rc = waitfor_status_bits(sc, SBIT_RESULT_READY, SBIT_BUSY); 1219 if (rc) 1220 return (-0x100); 1221 1222 SCD_WRITE(sc, OREG_CONTROL, CBIT_RESULT_READY_CLEAR); 1223 switch ((rc = SCD_READ(sc, IREG_RESULT)) & 0xf0) { 1224 case 0x20: 1225 rc = SCD_READ(sc, IREG_RESULT); 1226 /* FALLTHROUGH */ 1227 case 0x50: 1228 XDEBUG(sc, 1, "DEBUG: send_cmd: drive_error=0x%x\n", rc); 1229 return (-rc); 1230 case 0x00: 1231 default: 1232 rc = SCD_READ(sc, IREG_RESULT); 1233 XDEBUG(sc, 1, "DEBUG: send_cmd: result_len=%d\n", rc); 1234 return (rc); 1235 } 1236} 1237 1238static void 1239print_error(struct scd_softc *sc, int errcode) 1240{ 1241 1242 switch (errcode) { 1243 case -ERR_CD_NOT_LOADED: 1244 device_printf(sc->dev, "door is open\n"); 1245 break; 1246 case -ERR_NO_CD_INSIDE: 1247 device_printf(sc->dev, "no cd inside\n"); 1248 break; 1249 default: 1250 if (errcode == -0x100 || errcode > 0) 1251 device_printf(sc->dev, "device timeout\n"); 1252 else 1253 device_printf(sc->dev, "unexpected error 0x%x\n", -errcode); 1254 break; 1255 } 1256} 1257 1258/* Returns 0 or errno value */ 1259static int 1260waitfor_status_bits(struct scd_softc *sc, int bits_set, int bits_clear) 1261{ 1262 u_int flags = sc->data.flags; 1263 u_int max_loop; 1264 u_char c = 0; 1265 1266 if (flags & SCDPROBING) { 1267 max_loop = 0; 1268 while (max_loop++ < 1000) { 1269 c = SCD_READ(sc, IREG_STATUS); 1270 if (c == 0xff) 1271 return (EIO); 1272 if (c & SBIT_ATTENTION) { 1273 process_attention(sc); 1274 continue; 1275 } 1276 if ((c & bits_set) == bits_set && 1277 (c & bits_clear) == 0) 1278 { 1279 break; 1280 } 1281 DELAY(10000); 1282 } 1283 } else { 1284 max_loop = 100; 1285 while (max_loop-- > 0) { 1286 c = SCD_READ(sc, IREG_STATUS); 1287 if (c & SBIT_ATTENTION) { 1288 process_attention(sc); 1289 continue; 1290 } 1291 if ((c & bits_set) == bits_set && 1292 (c & bits_clear) == 0) 1293 { 1294 break; 1295 } 1296 pause("waitfor", hz/10); 1297 } 1298 } 1299 if ((c & bits_set) == bits_set && 1300 (c & bits_clear) == 0) 1301 { 1302 return (0); 1303 } 1304#ifdef SCD_DEBUG 1305 if (scd_debuglevel > 0) 1306 device_printf(sc->dev, "DEBUG: waitfor: TIMEOUT (0x%x,(0x%x,0x%x))\n", c, bits_set, bits_clear); 1307 else 1308#endif 1309 device_printf(sc->dev, "timeout.\n"); 1310 return (EIO); 1311} 1312 1313/* these two routines for xcdplayer - "borrowed" from mcd.c */ 1314static int 1315scd_toc_header (struct scd_softc *sc, struct ioc_toc_header* th) 1316{ 1317 int rc; 1318 1319 if (!(sc->data.flags & SCDTOC) && (rc = read_toc(sc)) != 0) { 1320 print_error(sc, rc); 1321 return (EIO); 1322 } 1323 1324 th->starting_track = sc->data.first_track; 1325 th->ending_track = sc->data.last_track; 1326 th->len = 0; /* not used */ 1327 1328 return (0); 1329} 1330 1331static int 1332scd_toc_entrys (struct scd_softc *sc, struct ioc_read_toc_entry *te) 1333{ 1334 struct cd_toc_entry toc_entry; 1335 int rc, i, len = te->data_len; 1336 1337 if (!(sc->data.flags & SCDTOC) && (rc = read_toc(sc)) != 0) { 1338 print_error(sc, rc); 1339 return (EIO); 1340 } 1341 1342 /* find the toc to copy*/ 1343 i = te->starting_track; 1344 if (i == SCD_LASTPLUS1) 1345 i = sc->data.last_track + 1; 1346 1347 /* verify starting track */ 1348 if (i < sc->data.first_track || i > sc->data.last_track+1) 1349 return (EINVAL); 1350 1351 /* valid length ? */ 1352 if (len < sizeof(struct cd_toc_entry) 1353 || (len % sizeof(struct cd_toc_entry)) != 0) 1354 return (EINVAL); 1355 1356 /* copy the toc data */ 1357 toc_entry.control = sc->data.toc[i].ctl; 1358 toc_entry.addr_type = te->address_format; 1359 toc_entry.track = i; 1360 if (te->address_format == CD_MSF_FORMAT) { 1361 toc_entry.addr.msf.unused = 0; 1362 toc_entry.addr.msf.minute = bcd2bin(sc->data.toc[i].start_msf[0]); 1363 toc_entry.addr.msf.second = bcd2bin(sc->data.toc[i].start_msf[1]); 1364 toc_entry.addr.msf.frame = bcd2bin(sc->data.toc[i].start_msf[2]); 1365 } 1366 1367 /* copy the data back */ 1368 if (copyout(&toc_entry, te->data, sizeof(struct cd_toc_entry)) != 0) 1369 return (EFAULT); 1370 1371 return (0); 1372} 1373 1374 1375static int 1376scd_toc_entry (struct scd_softc *sc, struct ioc_read_toc_single_entry *te) 1377{ 1378 struct cd_toc_entry toc_entry; 1379 int rc, i; 1380 1381 if (!(sc->data.flags & SCDTOC) && (rc = read_toc(sc)) != 0) { 1382 print_error(sc, rc); 1383 return (EIO); 1384 } 1385 1386 /* find the toc to copy*/ 1387 i = te->track; 1388 if (i == SCD_LASTPLUS1) 1389 i = sc->data.last_track + 1; 1390 1391 /* verify starting track */ 1392 if (i < sc->data.first_track || i > sc->data.last_track+1) 1393 return (EINVAL); 1394 1395 /* copy the toc data */ 1396 toc_entry.control = sc->data.toc[i].ctl; 1397 toc_entry.addr_type = te->address_format; 1398 toc_entry.track = i; 1399 if (te->address_format == CD_MSF_FORMAT) { 1400 toc_entry.addr.msf.unused = 0; 1401 toc_entry.addr.msf.minute = bcd2bin(sc->data.toc[i].start_msf[0]); 1402 toc_entry.addr.msf.second = bcd2bin(sc->data.toc[i].start_msf[1]); 1403 toc_entry.addr.msf.frame = bcd2bin(sc->data.toc[i].start_msf[2]); 1404 } 1405 1406 /* copy the data back */ 1407 bcopy(&toc_entry, &te->entry, sizeof(struct cd_toc_entry)); 1408 1409 return (0); 1410} 1411