The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/scd/scd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 3dc5a5b077b76f55cf2c6ecfd2c536dd


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.