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/scsi/cd.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  * Written by Julian Elischer (julian@tfs.com)
    3  * for TRW Financial Systems for use under the MACH(2.5) operating system.
    4  *
    5  * TRW Financial Systems, in accordance with their agreement with Carnegie
    6  * Mellon University, makes this software available to CMU to distribute
    7  * or use in any manner that they see fit as long as this message is kept with
    8  * the software. For this reason TFS also grants any other persons or
    9  * organisations permission to use or modify this software.
   10  *
   11  * TFS supplies this software to be publicly redistributed
   12  * on the understanding that TFS is not responsible for the correct
   13  * functioning of this software in any circumstances.
   14  *
   15  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
   16  *
   17  * $FreeBSD: src/sys/scsi/cd.c,v 1.73.2.8 1999/09/05 08:21:33 peter Exp $
   18  */
   19 
   20 #include "opt_bounce.h"
   21 #include "opt_scsi.h"
   22 
   23 #define SPLCD splbio
   24 #define ESUCCESS 0
   25 #include <sys/types.h>
   26 #include <sys/param.h>
   27 #include <sys/dkbad.h>
   28 #include <sys/systm.h>
   29 #include <sys/conf.h>
   30 #include <sys/file.h>
   31 #include <sys/stat.h>
   32 #include <sys/ioctl.h>
   33 #include <sys/buf.h>
   34 #include <sys/uio.h>
   35 #include <sys/malloc.h>
   36 #include <sys/cdio.h>
   37 #include <sys/errno.h>
   38 #include <sys/disklabel.h>
   39 #include <sys/dkstat.h>
   40 #include <sys/kernel.h>
   41 #ifdef DEVFS
   42 #include <sys/devfsext.h>
   43 #endif /*DEVFS*/
   44 
   45 #include <scsi/scsi_all.h>
   46 #include <scsi/scsi_cd.h>
   47 #include <scsi/scsi_disk.h>     /* rw_big and start_stop come from there */
   48 #include <scsi/scsiconf.h>
   49 
   50 static errval cd_get_parms __P((int, int));
   51 static u_int32_t cd_size __P((int unit, int flags));
   52 static errval cd_get_mode __P((u_int32_t, struct cd_mode_data *, u_int32_t));
   53 static errval cd_set_mode __P((u_int32_t unit, struct cd_mode_data *));
   54 static errval cd_read_toc __P((u_int32_t, u_int32_t, u_int32_t, struct cd_toc_entry *,
   55                           u_int32_t));
   56 
   57 static errval cd_pause __P((u_int32_t, u_int32_t));
   58 static errval cd_reset __P((u_int32_t));
   59 static errval cd_play_msf __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t));
   60 static errval cd_play __P((u_int32_t, u_int32_t, u_int32_t));
   61 #ifdef notyet
   62 static errval cd_play_big __P((u_int32_t unit, u_int32_t blk, u_int32_t len));
   63 #endif
   64 static errval cd_play_tracks __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t));
   65 static errval cd_read_subchannel __P((u_int32_t, u_int32_t, u_int32_t, int, struct cd_sub_channel_info *, u_int32_t));
   66 static errval cd_getdisklabel __P((u_int8_t));
   67 
   68 static  d_open_t        cdopen;
   69 static  d_close_t       cdclose;
   70 static  d_ioctl_t       cdioctl;
   71 static  d_strategy_t    cdstrategy;
   72 
   73 #define CDEV_MAJOR 15
   74 #define BDEV_MAJOR 6
   75 static struct cdevsw cd_cdevsw;
   76 static struct bdevsw cd_bdevsw = 
   77         { cdopen,       cdclose,        cdstrategy,     cdioctl,        /*6*/
   78           nodump,       nopsize,        0,      "cd",   &cd_cdevsw,     -1 };
   79 
   80 
   81 static int32_t cdstrats, cdqueues;
   82 
   83 #define CDUNIT(DEV)      ((minor(DEV)&0xF8) >> 3)    /* 5 bit unit */
   84 #define CDSETUNIT(DEV, U) makedev(major(DEV), ((U) << 3))
   85 
   86 #define PAGESIZ         4096
   87 #define SECSIZE 2048    /* XXX */       /* default only */
   88 #define CDOUTSTANDING   2
   89 #define CDRETRIES       1
   90 #define LEADOUT         0xaa            /* leadout toc entry */
   91 
   92 #define PARTITION(z)    (minor(z) & 0x07)
   93 #define RAW_PART        2
   94 
   95 static void     cdstart(u_int32_t unit, u_int32_t flags);
   96 
   97 struct scsi_data {
   98         u_int32_t flags;
   99 #define CDINIT          0x04    /* device has been init'd */
  100         struct cd_parms {
  101                 u_int32_t blksize;
  102                 u_long  disksize;       /* total number sectors */
  103         } params;
  104         struct disklabel disklabel;
  105         u_int32_t partflags[MAXPARTITIONS];     /* per partition flags */
  106 #define CDOPEN  0x01
  107         u_int32_t openparts;    /* one bit for each open partition */
  108         u_int32_t xfer_block_wait;
  109         struct buf_queue_head buf_queue;
  110         int dkunit;
  111 #ifdef  DEVFS
  112         void    *ra_devfs_token;
  113         void    *rc_devfs_token;
  114         void    *a_devfs_token;
  115         void    *c_devfs_token;
  116         void    *ctl_devfs_token;
  117 #endif
  118 };
  119 
  120 static int cdunit(dev_t dev) { return CDUNIT(dev); }
  121 static dev_t cdsetunit(dev_t dev, int unit) { return CDSETUNIT(dev, unit); }
  122 
  123 static errval cd_open(dev_t dev, int flags, int fmt, struct proc *p,
  124                 struct scsi_link *sc_link);
  125 static errval cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
  126                 struct proc *p, struct scsi_link *sc_link);
  127 static errval cd_close(dev_t dev, int flag, int fmt, struct proc *p,
  128                 struct scsi_link *sc_link);
  129 static void cd_strategy(struct buf *bp, struct scsi_link *sc_link);
  130 
  131 SCSI_DEVICE_ENTRIES(cd)
  132 
  133 static struct scsi_device cd_switch =
  134 {
  135         NULL,                   /* use default error handler */
  136         cdstart,                /* we have a queue, which is started by this */
  137         NULL,                   /* we do not have an async handler */
  138         NULL,                   /* use default 'done' routine */
  139         "cd",                   /* we are to be refered to by this name */
  140         0,                      /* no device specific flags */
  141         {0, 0},
  142         0,                      /* Link flags */
  143         cdattach,
  144         "CD-ROM",
  145         cdopen,
  146         sizeof(struct scsi_data),
  147         T_READONLY,
  148         cdunit,
  149         cdsetunit,
  150         cd_open,
  151         cd_ioctl,
  152         cd_close,
  153         cd_strategy,
  154 };
  155 
  156 #define CD_STOP         0
  157 #define CD_START        1
  158 #define CD_EJECT        -2
  159 
  160 static __inline void
  161 cd_registerdev(int unit)
  162 {
  163         if(dk_ndrive < DK_NDRIVE) {
  164                 sprintf(dk_names[dk_ndrive], "cd%d", unit);
  165                 dk_wpms[dk_ndrive] = (150*1024/2);
  166                 SCSI_DATA(&cd_switch, unit)->dkunit = dk_ndrive++;
  167         } else {
  168                 SCSI_DATA(&cd_switch, unit)->dkunit = -1;
  169         }
  170 }
  171 
  172 /*
  173  * The routine called by the low level scsi routine when it discovers
  174  * A device suitable for this driver
  175  */
  176 static int
  177 cdattach(struct scsi_link *sc_link)
  178 {
  179         u_int32_t unit;
  180         struct cd_parms *dp;
  181         struct scsi_data *cd = sc_link->sd;
  182 
  183         unit = sc_link->dev_unit;
  184         dp = &(cd->params);
  185 
  186         bufq_init(&cd->buf_queue);
  187         if (sc_link->opennings > CDOUTSTANDING)
  188                 sc_link->opennings = CDOUTSTANDING;
  189         /*
  190          * Use the subdriver to request information regarding
  191          * the drive. We cannot use interrupts yet, so the
  192          * request must specify this.
  193          *
  194          * XXX dufault@hda.com:
  195          * Need to handle this better in the case of no record.  Rather than
  196          * a state driven sense handler I think we should make it so that
  197          * the command can get the sense back so that it can selectively log
  198          * errors.
  199          */
  200         if (sc_link->quirks & CD_Q_NO_TOUCH) {
  201                 dp->disksize = 0;
  202         } else {
  203                 cd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
  204         }
  205         if (dp->disksize) {
  206                 printf("cd present [%ld x %ld byte records]",
  207                     cd->params.disksize,
  208                     cd->params.blksize);
  209         } else {
  210                 printf("can't get the size");
  211         }
  212 
  213         cd->flags |= CDINIT;
  214         cd_registerdev(unit);
  215 #ifdef DEVFS
  216 #define CD_UID  UID_ROOT
  217 #define CD_GID  GID_OPERATOR
  218         cd->ra_devfs_token = 
  219                 devfs_add_devswf(&cd_cdevsw, unit * 8, DV_CHR, CD_UID, 
  220                                 CD_GID, 0640, "rcd%da", unit);
  221         cd->rc_devfs_token = 
  222                 devfs_add_devswf(&cd_cdevsw, (unit * 8 ) + RAW_PART, DV_CHR,
  223                                 CD_UID, CD_GID, 0640, "rcd%dc", unit);
  224         cd->a_devfs_token = 
  225                 devfs_add_devswf(&cd_bdevsw, unit * 8, DV_BLK, CD_UID, 
  226                                 CD_GID, 0640, "cd%da", unit);
  227         cd->c_devfs_token = 
  228                 devfs_add_devswf(&cd_bdevsw, (unit * 8 ) + RAW_PART, DV_BLK,
  229                                 CD_UID, CD_GID, 0640, "cd%dc", unit);
  230         cd->ctl_devfs_token =
  231                 devfs_add_devswf(&cd_cdevsw, (unit * 8) | SCSI_CONTROL_MASK,
  232                                  DV_CHR,
  233                                  UID_ROOT, GID_WHEEL, 0600, "rcd%d.ctl", unit);
  234 #endif
  235 
  236         return 0;
  237 }
  238 
  239 /*
  240  * open the device. Make sure the partition info is a up-to-date as can be.
  241  */
  242 static errval
  243 cd_open(dev_t dev, int flags, int fmt, struct proc *p,
  244         struct scsi_link *sc_link)
  245 {
  246         errval  errcode = 0;
  247         u_int32_t unit, part;
  248         struct scsi_data *cd;
  249 
  250         unit = CDUNIT(dev);
  251         part = PARTITION(dev);
  252 
  253         cd = sc_link->sd;
  254         /*
  255          * Make sure the device has been initialised
  256          */
  257         if ((cd == NULL) || (!(cd->flags & CDINIT)))
  258                 return (ENXIO);
  259 
  260         SC_DEBUG(sc_link, SDEV_DB1,
  261             ("cd_open: dev=0x%lx (unit %ld,partition %ld)\n",
  262                 dev, unit, part));
  263         /*
  264          * Check that it is still responding and ok.
  265          * if the media has been changed this will result in a
  266          * "unit attention" error which the error code will
  267          * disregard because the SDEV_OPEN flag is not yet set.
  268          * Makes sure that we know it if the media has been changed..
  269          */
  270         scsi_test_unit_ready(sc_link, SCSI_SILENT);
  271 
  272         /*
  273          * If it's been invalidated, and not everybody has closed it then
  274          * forbid re-entry.  (may have changed media)
  275          */
  276         if ((!(sc_link->flags & SDEV_MEDIA_LOADED))
  277             && (cd->openparts)) {
  278                 SC_DEBUG(sc_link, SDEV_DB2, ("unit attn, but openparts?\n"));
  279                 return (ENXIO);
  280         }
  281 
  282         /*
  283          * Start the drive, and take notice of error returns.
  284          */
  285         scsi_start_unit(sc_link, CD_START);
  286         SC_DEBUG(sc_link, SDEV_DB3, ("'start' attempted "));
  287         sc_link->flags |= SDEV_OPEN;    /* unit attn errors are now errors */
  288         if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
  289                 SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
  290                 errcode = ENXIO;
  291                 goto bad;
  292         }
  293         SC_DEBUG(sc_link, SDEV_DB3, ("Device present\n"));
  294         scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT);
  295         /*
  296          * Load the physical device parameters
  297          */
  298         if (cd_get_parms(unit, 0)) {
  299                 errcode = ENXIO;
  300                 goto bad;
  301         }
  302         SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
  303         /*
  304          * Make up some partition information
  305          */
  306         cd_getdisklabel(unit);
  307         SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated "));
  308         /*
  309          * Check the partition is legal
  310          */
  311         if(part != RAW_PART) {
  312                 /*
  313                  *  Check that the partition CAN exist
  314                  */
  315                 if (part >= cd->disklabel.d_npartitions) {
  316                         SC_DEBUG(sc_link, SDEV_DB3, ("partition %ld > %d\n", part
  317                                 ,cd->disklabel.d_npartitions));
  318                         errcode = ENXIO;
  319                         goto bad;
  320                 }
  321                 /*
  322                  *  and that it DOES exist
  323                  */
  324                 if (cd->disklabel.d_partitions[part].p_fstype == FS_UNUSED) {
  325                         SC_DEBUG(sc_link, SDEV_DB3,
  326                                         ("part %ld type UNUSED\n", part));
  327                         errcode = ENXIO;
  328                         goto bad;
  329                 }
  330         }
  331         cd->partflags[part] |= CDOPEN;
  332         cd->openparts |= (1 << part);
  333         SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
  334         sc_link->flags |= SDEV_MEDIA_LOADED;
  335         return 0;
  336  bad:
  337 
  338         /*
  339          *  if we would have been the only open
  340          * then leave things back as they were
  341          */
  342         if (!(cd->openparts)) {
  343                 sc_link->flags &= ~SDEV_OPEN;
  344                 scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
  345         }
  346         return (errcode);
  347 }
  348 
  349 /*
  350  * close the device.. only called if we are the LAST
  351  * occurence of an open device
  352  */
  353 static errval
  354 cd_close(dev_t dev, int flag, int fmt, struct proc *p,
  355          struct scsi_link *sc_link)
  356 {
  357         u_int8_t  unit, part;
  358         struct scsi_data *cd;
  359 
  360         unit = CDUNIT(dev);
  361         part = PARTITION(dev);
  362         cd = sc_link->sd;
  363 
  364         SC_DEBUG(sc_link, SDEV_DB2, ("cd%d: closing part %d\n", unit, part));
  365         cd->partflags[part] &= ~CDOPEN;
  366         cd->openparts &= ~(1 << part);
  367 
  368         /*
  369          * If we were the last open of the entire device, release it.
  370          */
  371         if (!(cd->openparts)) {
  372                 scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
  373                 sc_link->flags &= ~SDEV_OPEN;
  374         }
  375         return (0);
  376 }
  377 
  378 
  379 /*
  380  * Actually translate the requested transfer into one the physical driver can
  381  * understand.  The transfer is described by a buf and will include only one
  382  * physical transfer.
  383  */
  384 static void
  385 cd_strategy(struct buf *bp, struct scsi_link *sc_link)
  386 {
  387         u_int32_t opri;
  388         u_int32_t unit = CDUNIT((bp->b_dev));
  389         struct scsi_data *cd = sc_link->sd;
  390 
  391         cdstrats++;
  392         /*
  393          * If the device has been made invalid, error out
  394          * maybe the media changed
  395          */
  396         if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
  397                 bp->b_error = EIO;
  398                 goto bad;
  399         }
  400         /*
  401          * can't ever write to a CD
  402          */
  403         if ((bp->b_flags & B_READ) == 0) {
  404                 bp->b_error = EROFS;
  405                 goto bad;
  406         }
  407         /*
  408          * Decide which unit and partition we are talking about
  409          */
  410         if (PARTITION(bp->b_dev) != RAW_PART) {
  411                 /*
  412                  * do bounds checking, adjust transfer. if error, process.
  413                  * if end of partition, just return
  414                  */
  415                 if (bounds_check_with_label(bp, &cd->disklabel, 1) <= 0)
  416                         goto done;
  417                 /* otherwise, process transfer request */
  418         } else {
  419                 bp->b_pblkno = bp->b_blkno;
  420                 bp->b_resid = 0;
  421         }
  422         opri = SPLCD();
  423 
  424         /*
  425          * Use a bounce buffer if necessary
  426          */
  427 #ifdef BOUNCE_BUFFERS
  428         if (sc_link->flags & SDEV_BOUNCE)
  429                 vm_bounce_alloc(bp);
  430 #endif
  431 
  432         /*
  433          * Place it in the queue of disk activities for this disk
  434          */
  435         bufq_insert_tail(&cd->buf_queue, bp);
  436 
  437         /*
  438          * Tell the device to get going on the transfer if it's
  439          * not doing anything, otherwise just wait for completion
  440          */
  441         cdstart(unit, 0);
  442 
  443         splx(opri);
  444         return;
  445       bad:
  446         bp->b_flags |= B_ERROR;
  447       done:
  448 
  449         /*
  450          * Correctly set the buf to indicate a completed xfer
  451          */
  452         bp->b_resid = bp->b_bcount;
  453         biodone(bp);
  454         return;
  455 }
  456 
  457 /*
  458  * cdstart looks to see if there is a buf waiting for the device
  459  * and that the device is not already busy. If both are true,
  460  * It deques the buf and creates a scsi command to perform the
  461  * transfer in the buf. The transfer request will call scsi_done
  462  * on completion, which will in turn call this routine again
  463  * so that the next queued transfer is performed.
  464  * The bufs are queued by the strategy routine (cdstrategy)
  465  *
  466  * This routine is also called after other non-queued requests
  467  * have been made of the scsi driver, to ensure that the queue
  468  * continues to be drained.
  469  *
  470  * must be called at the correct (highish) spl level
  471  * cdstart() is called at SPLCD  from cdstrategy and scsi_done
  472  */
  473 static void
  474 cdstart(unit, flags)
  475         u_int32_t unit;
  476         u_int32_t flags;
  477 {
  478         register struct buf *bp = 0;
  479         struct scsi_rw_big cmd;
  480         u_int32_t blkno, nblk;
  481         struct partition *p;
  482         struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
  483         struct scsi_data *cd = sc_link->sd;
  484 
  485         SC_DEBUG(sc_link, SDEV_DB2, ("cdstart%ld ", unit));
  486         /*
  487          * See if there is a buf to do and we are not already
  488          * doing one
  489          */
  490         if (!sc_link->opennings) {
  491                 return;         /* no room for us, unit already underway */
  492         }
  493         if (sc_link->flags & SDEV_WAITING) {    /* is room, but a special waits */
  494                 return;         /* give the special that's waiting a chance to run */
  495         }
  496 
  497         bp = bufq_first(&cd->buf_queue);
  498         if (bp == NULL) {       /* yes, an assign */
  499                 return;
  500         }
  501         bufq_remove(&cd->buf_queue, bp);
  502 
  503         /*
  504          * Should reject all queued entries if SDEV_MEDIA_LOADED is not true.
  505          */
  506         if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
  507                 goto bad;       /* no I/O.. media changed or something */
  508         }
  509         /*
  510          * We have a buf, now we should make a command
  511          *
  512          * First, translate the block to absolute and put it in terms of the
  513          * logical blocksize of the device.  Really a bit silly until we have
  514          * real partitions, but.
  515          */
  516         blkno = bp->b_blkno / (cd->params.blksize / 512);
  517         if (PARTITION(bp->b_dev) != RAW_PART) {
  518                 p = cd->disklabel.d_partitions + PARTITION(bp->b_dev);
  519                 blkno += p->p_offset;
  520         }
  521         nblk = (bp->b_bcount + (cd->params.blksize - 1)) / (cd->params.blksize);
  522         /* what if something asks for 512 bytes not on a 2k boundary? *//*XXX */
  523 
  524         /*
  525          *  Fill out the scsi command
  526          */
  527         bzero(&cmd, sizeof(cmd));
  528         cmd.op_code = READ_BIG;
  529         cmd.addr_3 = (blkno & 0xff000000UL) >> 24;
  530         cmd.addr_2 = (blkno & 0xff0000) >> 16;
  531         cmd.addr_1 = (blkno & 0xff00) >> 8;
  532         cmd.addr_0 = blkno & 0xff;
  533         cmd.length2 = (nblk & 0xff00) >> 8;
  534         cmd.length1 = (nblk & 0xff);
  535 
  536         /*
  537          * Call the routine that chats with the adapter.
  538          * Note: we cannot sleep as we may be an interrupt
  539          */
  540         if (scsi_scsi_cmd(sc_link,
  541                 (struct scsi_generic *) &cmd,
  542                 sizeof(cmd),
  543                 (u_char *) bp->b_un.b_addr,
  544                 bp->b_bcount,
  545                 CDRETRIES,
  546                 30000,
  547                 bp,
  548                 flags | ((bp->b_flags & B_READ) ?
  549                     SCSI_DATA_IN : SCSI_DATA_OUT))
  550             != SUCCESSFULLY_QUEUED) {
  551               bad:
  552                 printf("cd%ld: oops not queued\n", unit);
  553                 bp->b_error = EIO;
  554                 bp->b_flags |= B_ERROR;
  555                 biodone(bp);
  556                 return;
  557         }
  558         cdqueues++;
  559         if(cd->dkunit >= 0) {
  560                 dk_xfer[cd->dkunit]++;
  561                 dk_seek[cd->dkunit]++; /* don't know */
  562                 dk_wds[cd->dkunit] += bp->b_bcount >> 6;
  563         }
  564 }
  565 
  566 /*
  567  * Perform special action on behalf of the user.
  568  * Knows about the internals of this device
  569  */
  570 static errval
  571 cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
  572          struct scsi_link *sc_link)
  573 {
  574         errval  error = 0;
  575         u_int8_t  unit, part;
  576         register struct scsi_data *cd;
  577 
  578         /*
  579          * Find the device that the user is talking about
  580          */
  581         unit = CDUNIT(dev);
  582         part = PARTITION(dev);
  583         cd = sc_link->sd;
  584         SC_DEBUG(sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd));
  585 
  586         /*
  587          * If the device is not valid.. abandon ship
  588          */
  589         if (!(sc_link->flags & SDEV_MEDIA_LOADED))
  590                 return (EIO);
  591         switch (cmd) {
  592 
  593         case DIOCSBAD:
  594                 error = EINVAL;
  595                 break;
  596 
  597         case DIOCGDINFO:
  598                 *(struct disklabel *) addr = cd->disklabel;
  599                 break;
  600 
  601         case DIOCGPART:
  602                 ((struct partinfo *) addr)->disklab = &cd->disklabel;
  603                 ((struct partinfo *) addr)->part =
  604                     &cd->disklabel.d_partitions[PARTITION(dev)];
  605                 break;
  606 
  607                 /*
  608                  * a bit silly, but someone might want to test something on a
  609                  * section of cdrom.
  610                  */
  611         case DIOCWDINFO:
  612         case DIOCSDINFO:
  613                 if ((flag & FWRITE) == 0)
  614                         error = EBADF;
  615                 else
  616                         error = setdisklabel(&cd->disklabel,
  617                             (struct disklabel *) addr, 0);
  618                 if (error == 0)
  619                         break;
  620 
  621         case DIOCWLABEL:
  622                 error = EBADF;
  623                 break;
  624 
  625         case CDIOCPLAYTRACKS:
  626                 {
  627                         struct ioc_play_track *args
  628                         = (struct ioc_play_track *) addr;
  629                         struct cd_mode_data data;
  630                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  631                         if (error)
  632                                 break;
  633                         data.page.audio.flags &= ~CD_PA_SOTC;
  634                         data.page.audio.flags |= CD_PA_IMMED;
  635                         error = cd_set_mode(unit, &data);
  636                         if (error)
  637                                 break;
  638                         if (sc_link->quirks & CD_Q_BCD_TRACKS) {
  639                                 args->start_track = bin2bcd(args->start_track);
  640                                 args->end_track = bin2bcd(args->end_track);
  641                         }
  642                         return (cd_play_tracks(unit
  643                                 ,args->start_track
  644                                 ,args->start_index
  645                                 ,args->end_track
  646                                 ,args->end_index
  647                             ));
  648                 }
  649                 break;
  650         case CDIOCPLAYMSF:
  651                 {
  652                         struct ioc_play_msf *args
  653                         = (struct ioc_play_msf *) addr;
  654                         struct cd_mode_data data;
  655                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  656                         if (error)
  657                                 break;
  658                         data.page.audio.flags &= ~CD_PA_SOTC;
  659                         data.page.audio.flags |= CD_PA_IMMED;
  660                         error = cd_set_mode(unit, &data);
  661                         if (error)
  662                                 break;
  663                         return (cd_play_msf(unit
  664                                 ,args->start_m
  665                                 ,args->start_s
  666                                 ,args->start_f
  667                                 ,args->end_m
  668                                 ,args->end_s
  669                                 ,args->end_f
  670                             ));
  671                 }
  672                 break;
  673         case CDIOCPLAYBLOCKS:
  674                 {
  675                         struct ioc_play_blocks *args
  676                         = (struct ioc_play_blocks *) addr;
  677                         struct cd_mode_data data;
  678                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  679                         if (error)
  680                                 break;
  681                         data.page.audio.flags &= ~CD_PA_SOTC;
  682                         data.page.audio.flags |= CD_PA_IMMED;
  683                         error = cd_set_mode(unit, &data);
  684                         if (error)
  685                                 break;
  686                         return (cd_play(unit, args->blk, args->len));
  687 
  688                 }
  689                 break;
  690         case CDIOCREADSUBCHANNEL:
  691                 {
  692                         struct ioc_read_subchannel *args
  693                         = (struct ioc_read_subchannel *) addr;
  694                         struct cd_sub_channel_info data;
  695                         u_int32_t len = args->data_len;
  696                         if (len > sizeof(data) ||
  697                             len < sizeof(struct cd_sub_channel_header)) {
  698                                 error = EINVAL;
  699                                 break;
  700                         }
  701                         if (sc_link->quirks & CD_Q_BCD_TRACKS)
  702                                 args->track = bin2bcd(args->track);
  703                         error = cd_read_subchannel(unit, args->address_format,
  704                                 args->data_format, args->track, &data, len);
  705                         if (error)
  706                                 break;
  707                         if (sc_link->quirks & CD_Q_BCD_TRACKS)
  708                                 data.what.track_info.track_number =
  709                                     bcd2bin(data.what.track_info.track_number);
  710                         len = min(len, ((data.header.data_len[0] << 8) +
  711                                 data.header.data_len[1] +
  712                                 sizeof(struct cd_sub_channel_header)));
  713                         if (copyout(&data, args->data, len) != 0) {
  714                                 error = EFAULT;
  715                         }
  716                 }
  717                 break;
  718         case CDIOREADTOCHEADER:
  719                 {
  720                         struct ioc_toc_header th;
  721                         error = cd_read_toc(unit, 0, 0,
  722                                         (struct cd_toc_entry *)&th, sizeof th);
  723                         if (error)
  724                                 break;
  725                         if (sc_link->quirks & CD_Q_BCD_TRACKS) {
  726                                 /* we are going to have to convert the BCD
  727                                  * encoding on the cd to what is expected
  728                                  */
  729                                 th.starting_track = bcd2bin(th.starting_track);
  730                                 th.ending_track = bcd2bin(th.ending_track);
  731                         }
  732                         NTOHS(th.len);
  733                         bcopy(&th, addr, sizeof th);
  734                 }
  735                 break;
  736         case CDIOREADTOCENTRYS:
  737                 {
  738                         struct {
  739                                 struct ioc_toc_header header;
  740                                 struct cd_toc_entry entries[100];
  741                         } data;
  742                         struct {
  743                                 struct ioc_toc_header header;
  744                                 struct cd_toc_entry entry;
  745                         } lead;
  746                         struct ioc_read_toc_entry *te =
  747                         (struct ioc_read_toc_entry *) addr;
  748                         struct ioc_toc_header *th;
  749                         u_int32_t len, readlen, idx, num;
  750                         u_int32_t starting_track = te->starting_track;
  751 
  752                         if (   te->data_len < sizeof(struct cd_toc_entry)
  753                             || (te->data_len % sizeof(struct cd_toc_entry)) != 0
  754                             || te->address_format != CD_MSF_FORMAT
  755                             && te->address_format != CD_LBA_FORMAT
  756                            ) {
  757                                 error = EINVAL;
  758                                 break;
  759                         }
  760 
  761                         th = &data.header;
  762                         error = cd_read_toc(unit, 0, 0,
  763                                         (struct cd_toc_entry *)th, sizeof (*th));
  764                         if (error)
  765                                 break;
  766 
  767                         if (sc_link->quirks & CD_Q_BCD_TRACKS) {
  768                                 /* we are going to have to convert the BCD
  769                                  * encoding on the cd to what is expected
  770                                  */
  771                                 th->starting_track =
  772                                     bcd2bin(th->starting_track);
  773                                 th->ending_track = bcd2bin(th->ending_track);
  774                         }
  775 
  776                         if (starting_track == 0)
  777                                 starting_track = th->starting_track;
  778                         else if (starting_track == LEADOUT)
  779                                 starting_track = th->ending_track + 1;
  780                         else if (starting_track < th->starting_track ||
  781                                  starting_track > th->ending_track + 1) {
  782                                 error = EINVAL;
  783                                 break;
  784                         }
  785 
  786                         /* calculate reading length without leadout entry */
  787                         readlen = (th->ending_track - starting_track + 1) *
  788                                   sizeof(struct cd_toc_entry);
  789 
  790                         /* and with leadout entry */
  791                         len = readlen + sizeof(struct cd_toc_entry);
  792                         if (te->data_len < len) {
  793                                 len = te->data_len;
  794                                 if (readlen > len)
  795                                         readlen = len;
  796                         }
  797                         if (len > sizeof(data.entries)) {
  798                                 error = EINVAL;
  799                                 break;
  800                         }
  801                         num = len / sizeof(struct cd_toc_entry);
  802 
  803                         if (readlen > 0) {
  804                                 error = cd_read_toc(unit, te->address_format,
  805                                         starting_track,
  806                                         (struct cd_toc_entry *)&data,
  807                                         readlen + sizeof (*th));
  808                                 if (error)
  809                                         break;
  810                         }
  811 
  812                         /* make leadout entry if needed */
  813                         idx = starting_track + num - 1;
  814                         if (sc_link->quirks & CD_Q_BCD_TRACKS)
  815                                 th->ending_track = bcd2bin(th->ending_track);
  816                         if (idx == th->ending_track + 1) {
  817                                 error = cd_read_toc(unit, te->address_format,
  818                                         LEADOUT,
  819                                         (struct cd_toc_entry *)&lead,
  820                                         sizeof(lead));
  821                                 if (error)
  822                                         break;
  823                                 data.entries[idx - starting_track] = lead.entry;
  824                         }
  825 
  826                         if (sc_link->quirks & CD_Q_BCD_TRACKS) {
  827                                 for (idx = 0; idx < num - 1; idx++) {
  828                                         data.entries[idx].track =
  829                                             bcd2bin(data.entries[idx].track);
  830                                 }
  831                         }
  832 
  833                         error = copyout(data.entries, te->data, len);
  834                 }
  835                 break;
  836         case CDIOREADTOCENTRY:
  837                 {
  838                         struct {
  839                                 struct ioc_toc_header header;
  840                                 struct cd_toc_entry entry;
  841                         } data;
  842                         struct ioc_read_toc_single_entry *te =
  843                         (struct ioc_read_toc_single_entry *) addr;
  844                         struct ioc_toc_header *th;
  845                         u_int32_t track;
  846 
  847                         if (te->address_format != CD_MSF_FORMAT
  848                             && te->address_format != CD_LBA_FORMAT) {
  849                                 error = EINVAL;
  850                                 break;
  851                         }
  852 
  853                         th = &data.header;
  854                         error = cd_read_toc(unit, 0, 0,
  855                                         (struct cd_toc_entry *)th, sizeof (*th));
  856                         if (error)
  857                                 break;
  858 
  859                         track = te->track;
  860                         if (track == 0)
  861                                 track = th->starting_track;
  862                         else if (track == LEADOUT)
  863                                 /* OK */;
  864                         else if (track < th->starting_track ||
  865                                  track > th->ending_track + 1) {
  866                                 error = EINVAL;
  867                                 break;
  868                         }
  869 
  870                         error = cd_read_toc(unit, te->address_format,
  871                                             track,
  872                                             (struct cd_toc_entry *)&data,
  873                                             sizeof data);
  874                         if (error)
  875                                 break;
  876 
  877                         bcopy(&data.entry, &te->entry,
  878                               sizeof(struct cd_toc_entry));
  879                 }
  880                 break;
  881         case CDIOCSETPATCH:
  882                 {
  883                         struct ioc_patch *arg = (struct ioc_patch *) addr;
  884                         struct cd_mode_data data;
  885                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  886                         if (error)
  887                                 break;
  888                         data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
  889                         data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
  890                         data.page.audio.port[2].channels = arg->patch[2];
  891                         data.page.audio.port[3].channels = arg->patch[3];
  892                         error = cd_set_mode(unit, &data);
  893                         if (error)
  894                                 break; /* eh? */
  895                 }
  896                 break;
  897         case CDIOCGETVOL:
  898                 {
  899                         struct ioc_vol *arg = (struct ioc_vol *) addr;
  900                         struct cd_mode_data data;
  901                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  902                         if (error)
  903                                 break;
  904                         arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
  905                         arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
  906                         arg->vol[2] = data.page.audio.port[2].volume;
  907                         arg->vol[3] = data.page.audio.port[3].volume;
  908                 }
  909                 break;
  910         case CDIOCSETVOL:
  911                 {
  912                         struct ioc_vol *arg = (struct ioc_vol *) addr;
  913                         struct cd_mode_data data;
  914                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  915                         if (error)
  916                                 break;
  917                         data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
  918                         data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
  919                         data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1;
  920                         data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
  921                         data.page.audio.port[2].volume = arg->vol[2];
  922                         data.page.audio.port[3].volume = arg->vol[3];
  923                         error = cd_set_mode(unit, &data);
  924                         if (error)
  925                                 break;
  926                 }
  927                 break;
  928         case CDIOCSETMONO:
  929                 {
  930                         struct cd_mode_data data;
  931                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  932                         if (error)
  933                                 break;
  934                         data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL;
  935                         data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL;
  936                         data.page.audio.port[2].channels = 0;
  937                         data.page.audio.port[3].channels = 0;
  938                         error = cd_set_mode(unit, &data);
  939                         if (error)
  940                                 break;
  941                 }
  942                 break;
  943         case CDIOCSETSTEREO:
  944                 {
  945                         struct cd_mode_data data;
  946                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  947                         if (error)
  948                                 break;
  949                         data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
  950                         data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
  951                         data.page.audio.port[2].channels = 0;
  952                         data.page.audio.port[3].channels = 0;
  953                         error = cd_set_mode(unit, &data);
  954                         if (error)
  955                                 break;
  956                 }
  957                 break;
  958         case CDIOCSETMUTE:
  959                 {
  960                         struct cd_mode_data data;
  961                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  962                         if (error)
  963                                 break;
  964                         data.page.audio.port[LEFT_PORT].channels = 0;
  965                         data.page.audio.port[RIGHT_PORT].channels = 0;
  966                         data.page.audio.port[2].channels = 0;
  967                         data.page.audio.port[3].channels = 0;
  968                         error = cd_set_mode(unit, &data);
  969                         if (error)
  970                                 break;
  971                 }
  972                 break;
  973         case CDIOCSETLEFT:
  974                 {
  975                         struct cd_mode_data data;
  976                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  977                         if (error)
  978                                 break;
  979                         data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
  980                         data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
  981                         data.page.audio.port[2].channels = 0;
  982                         data.page.audio.port[3].channels = 0;
  983                         error = cd_set_mode(unit, &data);
  984                         if (error)
  985                                 break;
  986                 }
  987                 break;
  988         case CDIOCSETRIGHT:
  989                 {
  990                         struct cd_mode_data data;
  991                         error = cd_get_mode(unit, &data, AUDIO_PAGE);
  992                         if (error)
  993                                 break;
  994                         data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
  995                         data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
  996                         data.page.audio.port[2].channels = 0;
  997                         data.page.audio.port[3].channels = 0;
  998                         error = cd_set_mode(unit, &data);
  999                         if (error)
 1000                                 break;
 1001                 }
 1002                 break;
 1003         case CDIOCRESUME:
 1004                 error = cd_pause(unit, 1);
 1005                 break;
 1006         case CDIOCPAUSE:
 1007                 error = cd_pause(unit, 0);
 1008                 break;
 1009         case CDIOCSTART:
 1010                 error = scsi_start_unit(sc_link, 0);
 1011                 break;
 1012         case CDIOCSTOP:
 1013                 error = scsi_stop_unit(sc_link, 0, 0);
 1014                 break;
 1015         case CDIOCEJECT:
 1016                 error = scsi_stop_unit(sc_link, 1, 0);
 1017                 break;
 1018         case CDIOCALLOW:
 1019                 error = scsi_prevent(sc_link, PR_ALLOW, 0);
 1020                 break;
 1021         case CDIOCPREVENT:
 1022                 error = scsi_prevent(sc_link, PR_PREVENT, 0);
 1023                 break;
 1024         case CDIOCSETDEBUG:
 1025                 sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
 1026                 break;
 1027         case CDIOCCLRDEBUG:
 1028                 sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
 1029                 break;
 1030         case CDIOCRESET:
 1031                 return (cd_reset(unit));
 1032                 break;
 1033         default:
 1034                 if(part == RAW_PART)
 1035                         error = scsi_do_ioctl(dev, cmd, addr, flag, p, sc_link);
 1036                 else
 1037                         error = ENOTTY;
 1038                 break;
 1039         }
 1040         return (error);
 1041 }
 1042 
 1043 /*
 1044  * Load the label information on the named device
 1045  * Actually fabricate a disklabel
 1046  *
 1047  * EVENTUALLY take information about different
 1048  * data tracks from the TOC and put it in the disklabel
 1049  */
 1050 static errval
 1051 cd_getdisklabel(unit)
 1052         u_int8_t  unit;
 1053 {
 1054         /*unsigned int n, m; */
 1055         struct scsi_data *cd;
 1056 
 1057         cd = SCSI_DATA(&cd_switch, unit);
 1058 
 1059         bzero(&cd->disklabel, sizeof(struct disklabel));
 1060         /*
 1061          * make partition 0 the whole disk
 1062          */
 1063         strncpy(cd->disklabel.d_typename, "scsi cd_rom", 16);
 1064         strncpy(cd->disklabel.d_packname, "fictitious", 16);
 1065         cd->disklabel.d_secsize = cd->params.blksize;   /* as long as it's not 0 */
 1066         cd->disklabel.d_nsectors = 100;
 1067         cd->disklabel.d_ntracks = 1;
 1068         cd->disklabel.d_ncylinders = (cd->params.disksize / 100) + 1;
 1069         cd->disklabel.d_secpercyl = 100;
 1070         cd->disklabel.d_secperunit = cd->params.disksize;
 1071         cd->disklabel.d_rpm = 300;
 1072         cd->disklabel.d_interleave = 1;
 1073         cd->disklabel.d_flags = D_REMOVABLE;
 1074 
 1075         /*
 1076          * remember that comparisons with the partition are done
 1077          * assuming the blocks are 512 bytes so fudge it.
 1078          */
 1079         cd->disklabel.d_npartitions = 1;
 1080         cd->disklabel.d_partitions[0].p_offset = 0;
 1081         cd->disklabel.d_partitions[0].p_size
 1082             = cd->params.disksize * (cd->params.blksize / 512);
 1083         cd->disklabel.d_partitions[0].p_fstype = 9;
 1084 
 1085         cd->disklabel.d_magic = DISKMAGIC;
 1086         cd->disklabel.d_magic2 = DISKMAGIC;
 1087         cd->disklabel.d_checksum = dkcksum(&(cd->disklabel));
 1088 
 1089         /*
 1090          * Signal to other users and routines that we now have a
 1091          * disklabel that represents the media (maybe)
 1092          */
 1093         return (ESUCCESS);
 1094 }
 1095 
 1096 /*
 1097  * Find out from the device what it's capacity is
 1098  */
 1099 static u_int32_t
 1100 cd_size(unit, flags)
 1101         int unit;
 1102         int flags;
 1103 {
 1104         struct scsi_read_cd_cap_data rdcap;
 1105         struct scsi_read_cd_capacity scsi_cmd;
 1106         u_int32_t size;
 1107         u_int32_t blksize;
 1108         struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
 1109         struct scsi_data *cd = sc_link->sd;
 1110 
 1111         /*
 1112          * make up a scsi command and ask the scsi driver to do
 1113          * it for you.
 1114          */
 1115         bzero(&scsi_cmd, sizeof(scsi_cmd));
 1116         scsi_cmd.op_code = READ_CD_CAPACITY;
 1117 
 1118         /*
 1119          * If the command works, interpret the result as a 4 byte
 1120          * number of blocks and a blocksize
 1121          */
 1122         if (scsi_scsi_cmd(sc_link,
 1123                 (struct scsi_generic *) &scsi_cmd,
 1124                 sizeof(scsi_cmd),
 1125                 (u_char *) & rdcap,
 1126                 sizeof(rdcap),
 1127                 CDRETRIES,
 1128                 20000,          /* might be a disk-changer */
 1129                 NULL,
 1130                 SCSI_DATA_IN | flags) != 0) {
 1131                 return (0);
 1132         } else {
 1133                 size = rdcap.addr_0 + 1;
 1134                 size += rdcap.addr_1 << 8;
 1135                 size += rdcap.addr_2 << 16;
 1136                 size += rdcap.addr_3 << 24;
 1137                 blksize = rdcap.length_0;
 1138                 blksize += rdcap.length_1 << 8;
 1139                 blksize += rdcap.length_2 << 16;
 1140                 blksize += rdcap.length_3 << 24;
 1141         }
 1142         if (blksize < 512)
 1143                 blksize = 2048; /* some drives lie ! */
 1144         if (size < 100)
 1145                 size = 400000;  /* ditto */
 1146         SC_DEBUG(sc_link, SDEV_DB3, ("cd%d: %ld %ld byte blocks\n"
 1147                 ,unit, size, blksize));
 1148         cd->params.disksize = size;
 1149         cd->params.blksize = blksize;
 1150         return (size);
 1151 }
 1152 
 1153 /*
 1154  * Get the requested page into the buffer given
 1155  */
 1156 static errval
 1157 cd_get_mode(unit, data, page)
 1158         u_int32_t unit;
 1159         struct cd_mode_data *data;
 1160         u_int32_t page;
 1161 {
 1162         struct scsi_mode_sense scsi_cmd;
 1163         errval  retval;
 1164 
 1165         bzero(&scsi_cmd, sizeof(scsi_cmd));
 1166         bzero(data, sizeof(*data));
 1167         scsi_cmd.op_code = MODE_SENSE;
 1168         scsi_cmd.page = page;
 1169         scsi_cmd.length = sizeof(*data) & 0xff;
 1170         retval = scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
 1171             (struct scsi_generic *) &scsi_cmd,
 1172             sizeof(scsi_cmd),
 1173             (u_char *) data,
 1174             sizeof(*data),
 1175             CDRETRIES,
 1176             20000,              /* should be immed */
 1177             NULL,
 1178             SCSI_DATA_IN);
 1179         return (retval);
 1180 }
 1181 
 1182 /*
 1183  * Get the requested page into the buffer given
 1184  */
 1185 static errval
 1186 cd_set_mode(unit, data)
 1187         u_int32_t unit;
 1188         struct cd_mode_data *data;
 1189 {
 1190         struct scsi_mode_select scsi_cmd;
 1191 
 1192         bzero(&scsi_cmd, sizeof(scsi_cmd));
 1193         scsi_cmd.op_code = MODE_SELECT;
 1194         scsi_cmd.byte2 |= SMS_PF;
 1195         scsi_cmd.length = sizeof(*data) & 0xff;
 1196         data->header.data_length = 0;
 1197         /*
 1198          * SONY drives do not allow a mode select with a medium_type
 1199          * value that has just been returned by a mode sense; use a
 1200          * medium_type of 0 (Default) instead.
 1201          */
 1202         data->header.medium_type = 0;
 1203         return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
 1204                 (struct scsi_generic *) &scsi_cmd,
 1205                 sizeof(scsi_cmd),
 1206                 (u_char *) data,
 1207                 sizeof(*data),
 1208                 CDRETRIES,
 1209                 20000,          /* should be immed */
 1210                 NULL,
 1211                 SCSI_DATA_OUT));
 1212 }
 1213 
 1214 /*
 1215  * Get scsi driver to send a "start playing" command
 1216  */
 1217 static errval
 1218 cd_play(unit, blk, len)
 1219         u_int32_t unit, blk, len;
 1220 {
 1221         struct scsi_play scsi_cmd;
 1222 
 1223         bzero(&scsi_cmd, sizeof(scsi_cmd));
 1224         scsi_cmd.op_code = PLAY;
 1225         scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
 1226         scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
 1227         scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
 1228         scsi_cmd.blk_addr[3] = blk & 0xff;
 1229         scsi_cmd.xfer_len[0] = (len >> 8) & 0xff;
 1230         scsi_cmd.xfer_len[1] = len & 0xff;
 1231         return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
 1232                 (struct scsi_generic *) &scsi_cmd,
 1233                 sizeof(scsi_cmd),
 1234                 0,
 1235                 0,
 1236                 CDRETRIES,
 1237                 200000,         /* should be immed */
 1238                 NULL,
 1239                 0));
 1240 }
 1241 
 1242 #ifdef notyet
 1243 /*
 1244  * Get scsi driver to send a "start playing" command
 1245  */
 1246 static errval
 1247 cd_play_big(unit, blk, len)
 1248         u_int32_t unit, blk, len;
 1249 {
 1250         struct scsi_play_big scsi_cmd;
 1251 
 1252         bzero(&scsi_cmd, sizeof(scsi_cmd));
 1253         scsi_cmd.op_code = PLAY_BIG;
 1254         scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
 1255         scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
 1256         scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
 1257         scsi_cmd.blk_addr[3] = blk & 0xff;
 1258         scsi_cmd.xfer_len[0] = (len >> 24) & 0xff;
 1259         scsi_cmd.xfer_len[1] = (len >> 16) & 0xff;
 1260         scsi_cmd.xfer_len[2] = (len >> 8) & 0xff;
 1261         scsi_cmd.xfer_len[3] = len & 0xff;
 1262         return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
 1263                 (struct scsi_generic *) &scsi_cmd,
 1264                 sizeof(scsi_cmd),
 1265                 0,
 1266                 0,
 1267                 CDRETRIES,
 1268                 20000,          /* should be immed */
 1269                 NULL,
 1270                 0));
 1271 }
 1272 #endif
 1273 
 1274 /*
 1275  * Get scsi driver to send a "start playing" command
 1276  */
 1277 static errval
 1278 cd_play_tracks(unit, strack, sindex, etrack, eindex)
 1279         u_int32_t unit, strack, sindex, etrack, eindex;
 1280 {
 1281         struct scsi_play_track scsi_cmd;
 1282 
 1283         bzero(&scsi_cmd, sizeof(scsi_cmd));
 1284         scsi_cmd.op_code = PLAY_TRACK;
 1285         scsi_cmd.start_track = strack;
 1286         scsi_cmd.start_index = sindex;
 1287         scsi_cmd.end_track = etrack;
 1288         scsi_cmd.end_index = eindex;
 1289         return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
 1290                 (struct scsi_generic *) &scsi_cmd,
 1291                 sizeof(scsi_cmd),
 1292                 0,
 1293                 0,
 1294                 CDRETRIES,
 1295                 20000,          /* should be immed */
 1296                 NULL,
 1297                 0));
 1298 }
 1299 
 1300 /*
 1301  * Get scsi driver to send a "play msf" command
 1302  */
 1303 static errval
 1304 cd_play_msf(unit, startm, starts, startf, endm, ends, endf)
 1305         u_int32_t unit, startm, starts, startf, endm, ends, endf;
 1306 {
 1307         struct scsi_play_msf scsi_cmd;
 1308 
 1309         bzero(&scsi_cmd, sizeof(scsi_cmd));
 1310         scsi_cmd.op_code = PLAY_MSF;
 1311         scsi_cmd.start_m = startm;
 1312         scsi_cmd.start_s = starts;
 1313         scsi_cmd.start_f = startf;
 1314         scsi_cmd.end_m = endm;
 1315         scsi_cmd.end_s = ends;
 1316         scsi_cmd.end_f = endf;
 1317 
 1318         return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
 1319                 (struct scsi_generic *) &scsi_cmd,
 1320                 sizeof(scsi_cmd),
 1321                 0,
 1322                 0,
 1323                 CDRETRIES,
 1324                 2000,
 1325                 NULL,
 1326                 0));
 1327 }
 1328 
 1329 /*
 1330  * Get scsi driver to send a "start up" command
 1331  */
 1332 static errval
 1333 cd_pause(unit, go)
 1334         u_int32_t unit, go;
 1335 {
 1336         struct scsi_pause scsi_cmd;
 1337 
 1338         bzero(&scsi_cmd, sizeof(scsi_cmd));
 1339         scsi_cmd.op_code = PAUSE;
 1340         scsi_cmd.resume = go;
 1341 
 1342         return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
 1343                 (struct scsi_generic *) &scsi_cmd,
 1344                 sizeof(scsi_cmd),
 1345                 0,
 1346                 0,
 1347                 CDRETRIES,
 1348                 2000,
 1349                 NULL,
 1350                 0));
 1351 }
 1352 
 1353 /*
 1354  * Get scsi driver to send a "RESET" command
 1355  */
 1356 static errval
 1357 cd_reset(unit)
 1358         u_int32_t unit;
 1359 {
 1360         return scsi_reset_target(SCSI_LINK(&cd_switch, unit));
 1361 }
 1362 
 1363 /*
 1364  * Read subchannel
 1365  */
 1366 static errval
 1367 cd_read_subchannel(unit, mode, format, track, data, len)
 1368         u_int32_t unit, mode, format;
 1369         int track;
 1370         struct cd_sub_channel_info *data;
 1371         u_int32_t len;
 1372 {
 1373         struct scsi_read_subchannel scsi_cmd;
 1374 
 1375         bzero(&scsi_cmd, sizeof(scsi_cmd));
 1376 
 1377         scsi_cmd.op_code = READ_SUBCHANNEL;
 1378         if (mode == CD_MSF_FORMAT)
 1379                 scsi_cmd.byte2 |= CD_MSF;
 1380         scsi_cmd.byte3 = SRS_SUBQ;
 1381         scsi_cmd.subchan_format = format;
 1382         scsi_cmd.track = track;
 1383         scsi_cmd.data_len[0] = (len) >> 8;
 1384         scsi_cmd.data_len[1] = (len) & 0xff;
 1385         return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
 1386                 (struct scsi_generic *) &scsi_cmd,
 1387                 sizeof(struct scsi_read_subchannel),
 1388                         (u_char *) data,
 1389                 len,
 1390                 CDRETRIES,
 1391                 5000,
 1392                 NULL,
 1393                 SCSI_DATA_IN));
 1394 }
 1395 
 1396 /*
 1397  * Read table of contents
 1398  */
 1399 static errval
 1400 cd_read_toc(unit, mode, start, data, len)
 1401         u_int32_t unit, mode, start;
 1402         struct cd_toc_entry *data;
 1403         u_int32_t len;
 1404 {
 1405         struct scsi_read_toc scsi_cmd;
 1406         u_int32_t ntoc;
 1407 
 1408         bzero(&scsi_cmd, sizeof(scsi_cmd));
 1409         /*if(len!=sizeof(struct ioc_toc_header))
 1410          * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
 1411          * else */
 1412         ntoc = len;
 1413 
 1414         scsi_cmd.op_code = READ_TOC;
 1415         if (mode == CD_MSF_FORMAT)
 1416                 scsi_cmd.byte2 |= CD_MSF;
 1417         scsi_cmd.from_track = start;
 1418         scsi_cmd.data_len[0] = (ntoc) >> 8;
 1419         scsi_cmd.data_len[1] = (ntoc) & 0xff;
 1420         return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
 1421                 (struct scsi_generic *) &scsi_cmd,
 1422                 sizeof(struct scsi_read_toc),
 1423                         (u_char *) data,
 1424                 len,
 1425                 CDRETRIES,
 1426                 5000,
 1427                 NULL,
 1428                 SCSI_DATA_IN));
 1429 }
 1430 
 1431 #define b2tol(a)        (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
 1432 
 1433 /*
 1434  * Get the scsi driver to send a full inquiry to the device and use the
 1435  * results to fill out the disk parameter structure.
 1436  */
 1437 static errval
 1438 cd_get_parms(unit, flags)
 1439         int unit;
 1440         int flags;
 1441 {
 1442         struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
 1443 
 1444         /*
 1445          * First check if we have it all loaded
 1446          */
 1447         if (sc_link->flags & SDEV_MEDIA_LOADED)
 1448                 return (0);
 1449         /*
 1450          * give a number of sectors so that sec * trks * cyls
 1451          * is <= disk_size
 1452          */
 1453         if (cd_size(unit, flags)) {
 1454                 sc_link->flags |= SDEV_MEDIA_LOADED;
 1455                 return (0);
 1456         } else {
 1457                 return (ENXIO);
 1458         }
 1459 }
 1460 
 1461 static cd_devsw_installed = 0;
 1462 
 1463 static void     cd_drvinit(void *unused)
 1464 {
 1465 
 1466         if( ! cd_devsw_installed ) {
 1467                 bdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &cd_bdevsw);
 1468                 cd_devsw_installed = 1;
 1469         }
 1470 }
 1471 
 1472 SYSINIT(cddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cd_drvinit,NULL)
 1473 
 1474 

Cache object: 67f3a9d80742171bc12c105ee85890ee


[ 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.