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/i386/isa/atapi-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  * Copyright (c) 1998 Søren Schmidt
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer,
   10  *    without modification, immediately at the beginning of the file.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * $FreeBSD$
   29  */
   30 
   31 #include "wdc.h"
   32 #include "acd.h"
   33 #include "opt_atapi.h"
   34 #include "opt_devfs.h"
   35 
   36 #if NACD > 0 && NWDC > 0 && defined(ATAPI)
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/kernel.h>
   41 #include <sys/proc.h>
   42 #include <sys/malloc.h>
   43 #include <sys/buf.h>
   44 #include <sys/disklabel.h>
   45 #include <sys/cdio.h>
   46 #include <sys/wormio.h>
   47 #include <sys/fcntl.h>
   48 #include <sys/conf.h>
   49 #include <sys/stat.h>
   50 #ifdef DEVFS
   51 #include <sys/devfsext.h>
   52 #endif
   53 #include <i386/isa/atapi.h>
   54 #include <i386/isa/atapi-cd.h>
   55 
   56 static d_open_t         acdopen;
   57 static d_close_t        acdclose;
   58 static d_write_t        acdwrite;
   59 static d_read_t         acdread;
   60 static d_ioctl_t        acdioctl;
   61 static d_strategy_t     acdstrategy;
   62 
   63 #define CDEV_MAJOR 69
   64 #define BDEV_MAJOR 19
   65 static struct cdevsw acd_cdevsw = {
   66     acdopen,    acdclose,       acdread,        acdwrite,       
   67     acdioctl,   nostop,         nullreset,      nodevtotty,
   68     seltrue,    nommap,         acdstrategy,    "acd",
   69     NULL,       -1,             nodump,         nopsize,
   70     D_DISK,     0,              -1
   71 };
   72 
   73 #define NUNIT   16              /* Max # of devices */
   74 
   75 #define F_BOPEN         0x0001  /* The block device is opened */
   76 #define F_MEDIA_CHANGED 0x0002  /* The media have changed since open */
   77 #define F_DEBUG         0x0004  /* Print debug info */
   78 #define F_LOCKED        0x0008  /* This unit is locked (or should be) */
   79 #define F_TRACK_PREP    0x0010  /* Track should be prep'ed */
   80 #define F_TRACK_PREPED  0x0020  /* Track has been prep'ed */
   81 #define F_DISK_PREPED   0x0040  /* Disk has been prep'ed */
   82 #define F_WRITTEN       0x0080  /* The medium has been written to */
   83 
   84 static struct acd *acdtab[NUNIT];
   85 static int acdnlun = 0;         /* Number of configured drives */
   86 
   87 #ifndef ATAPI_STATIC
   88 static
   89 #endif
   90 int acdattach(struct atapi *, int, struct atapi_params *, int);
   91 static struct acd *acd_init_lun(struct atapi *, int, struct atapi_params *,int);
   92 static void acd_start(struct acd *);
   93 static void acd_done(struct acd *, struct buf *, int, struct atapires);
   94 static int acd_read_toc(struct acd *);
   95 static int acd_request_wait(struct acd *, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, char *, int);
   96 static void acd_describe(struct acd *);
   97 static int acd_setchan(struct acd *, u_char, u_char, u_char, u_char);
   98 static int acd_eject(struct acd *, int);
   99 static void acd_select_slot(struct acd *);
  100 static int acd_open_disk(struct acd *, int);
  101 static int acd_open_track(struct acd *, struct wormio_prepare_track *);
  102 static int acd_close_track(struct acd *);
  103 static int acd_close_disk(struct acd *);
  104 static int acd_read_track_info(struct acd *cdp, int lba, struct acd_track_info *info);
  105 static int acd_blank_disk(struct acd *);
  106 static void atapi_dump(int ctrlr, int lun, char *label, void *data, int len);
  107 static void atapi_error(struct atapi *ata, int unit, struct atapires result);
  108 
  109 struct acd *
  110 acd_init_lun(struct atapi *ata, int unit, struct atapi_params *ap, int lun)
  111 {
  112     struct acd *ptr;
  113 
  114     if (!(ptr = malloc(sizeof(struct acd), M_TEMP, M_NOWAIT)))
  115         return NULL;
  116     bzero(ptr, sizeof(struct acd));
  117     bufq_init(&ptr->buf_queue);
  118     ptr->ata = ata;
  119     ptr->unit = unit;
  120     ptr->lun = lun;
  121     ptr->param = ap;
  122     ptr->flags = F_MEDIA_CHANGED;
  123     ptr->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED);
  124     ptr->block_size = 2048;
  125     ptr->refcnt = 0;
  126     ptr->slot = -1;
  127     ptr->changer_info = NULL;
  128 #ifdef DEVFS
  129     ptr->ra_devfs_token =
  130         devfs_add_devswf(&acd_cdevsw, dkmakeminor(lun, 0, 0),
  131         DV_CHR, UID_ROOT, GID_OPERATOR, 0640,
  132         "racd%da", lun);
  133     ptr->rc_devfs_token =
  134         devfs_add_devswf(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART),
  135         DV_CHR, UID_ROOT, GID_OPERATOR, 0640,
  136         "racd%dc", lun);
  137     ptr->a_devfs_token =
  138         devfs_add_devswf(&acd_cdevsw, dkmakeminor(lun, 0, 0),
  139         DV_BLK, UID_ROOT, GID_OPERATOR, 0640,
  140         "acd%da", lun);
  141     ptr->c_devfs_token =
  142         devfs_add_devswf(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART),
  143         DV_BLK, UID_ROOT, GID_OPERATOR, 0640,
  144         "acd%dc", lun);
  145 #endif
  146     return ptr;
  147 }
  148 
  149 #ifndef ATAPI_STATIC
  150 static
  151 #endif
  152 int
  153 acdattach(struct atapi *ata, int unit, struct atapi_params *ap, int debug)
  154 {
  155     struct acd *cdp;
  156     struct atapires result;
  157     struct changer *chp;
  158     int i, count;
  159 
  160     if (acdnlun >= NUNIT) {
  161         printf("acd: too many units\n");
  162         return 0;
  163     }
  164     if (!atapi_request_immediate) {
  165         printf("acd: configuration error, ATAPI code not present!\n");
  166         return 0;
  167     }
  168     if ((cdp = acd_init_lun(ata, unit, ap, acdnlun)) == NULL) {
  169         printf("acd: out of memory\n");
  170         return 0;
  171     }
  172     acdtab[acdnlun] = cdp;
  173 
  174     if (debug) {
  175         cdp->flags |= F_DEBUG;
  176         atapi_dump(cdp->ata->ctrlr, cdp->lun, "info", ap, sizeof(*ap));
  177     }
  178 
  179     /* Get drive capabilities, some drives needs this repeated */
  180     for (count = 0 ; count < 5 ; count++) {
  181         result = atapi_request_immediate(ata, unit,
  182                                          ATAPI_MODE_SENSE,
  183                                          0, ATAPI_CDROM_CAP_PAGE,
  184                                          0, 0, 0, 0, 
  185                                          sizeof(cdp->cap)>>8, sizeof(cdp->cap),
  186                                          0, 0, 0, 0, 0, 0, 0, 
  187                                          (char *)&cdp->cap, sizeof(cdp->cap));
  188         if (result.code == 0 || result.code == RES_UNDERRUN)
  189             break;
  190     }
  191 
  192     /* Some drives have shorter capabilities page. */
  193     if (result.code == RES_UNDERRUN)
  194         result.code = 0;
  195 
  196     if (result.code == 0) {
  197         cdp->cap.max_speed = ntohs(cdp->cap.max_speed);
  198         cdp->cap.max_vol_levels = ntohs(cdp->cap.max_vol_levels);
  199         cdp->cap.buf_size = ntohs(cdp->cap.buf_size);
  200         cdp->cap.cur_speed = ntohs(cdp->cap.cur_speed);
  201         acd_describe(cdp);
  202         if (cdp->flags & F_DEBUG)
  203             atapi_dump(cdp->ata->ctrlr, cdp->lun, "cap", &cdp->cap,
  204                        sizeof(cdp->cap));
  205     }
  206     /* If this is a changer device, allocate the neeeded lun's */
  207     if (cdp->cap.mech == MST_MECH_CHANGER) {
  208         chp = malloc(sizeof(struct changer), M_TEMP, M_NOWAIT);
  209         if (chp == NULL) {
  210             printf("acd: out of memory\n");
  211             return 0;
  212         }
  213         bzero(chp, sizeof(struct changer));
  214         result = atapi_request_immediate(ata, unit, ATAPI_MECH_STATUS,
  215                                          0, 0, 0, 0, 0, 0, 0,
  216                                          sizeof(struct changer)>>8,
  217                                          sizeof(struct changer),
  218                                          0, 0, 0, 0, 0, 0,
  219                                          (char *)chp, sizeof(struct changer));
  220         if (cdp->flags & F_DEBUG) {
  221             printf("result.code=%d curr=%02x slots=%d len=%d\n",
  222                 result.code, chp->current_slot, chp->slots,
  223                 htons(chp->table_length));
  224         }
  225         if (result.code == RES_UNDERRUN)
  226             result.code = 0;
  227 
  228         if (result.code == 0) {
  229             chp->table_length = htons(chp->table_length);
  230             for (i = 0; i < chp->slots && acdnlun < NUNIT; i++) {
  231                 if (i > 0) {
  232                     cdp = acd_init_lun(ata, unit, ap, acdnlun);
  233                     if (cdp == NULL) {
  234                         printf("acd: out of memory\n");
  235                         return 0;
  236                     }
  237                 }
  238                 cdp->slot = i;
  239                 cdp->changer_info = chp;
  240                 printf("acd%d: changer slot %d %s\n", acdnlun, i,
  241                        (chp->slot[i].present ? "disk present" : "no disk"));
  242                 acdtab[acdnlun++] = cdp;
  243             }
  244             if (acdnlun >= NUNIT) {
  245                 printf("acd: too many units\n");
  246                 return 0;
  247             }
  248         }
  249     } else
  250         acdnlun++;
  251     return 1;
  252 }
  253 
  254 void 
  255 acd_describe(struct acd *cdp)
  256 {
  257     int comma;
  258     char *mechanism;
  259 
  260     printf("acd%d: drive speed ", cdp->lun);
  261     if (cdp->cap.cur_speed != cdp->cap.max_speed)
  262         printf("%d - ", cdp->cap.cur_speed * 1000 / 1024);
  263     printf("%dKB/sec", cdp->cap.max_speed * 1000 / 1024);
  264     if (cdp->cap.buf_size)
  265         printf(", %dKB cache\n", cdp->cap.buf_size);
  266 
  267     printf("acd%d: supported read types:", cdp->lun);
  268     comma = 0;
  269     if (cdp->cap.read_cdr) {
  270         printf(" CD-R"); comma = 1;
  271     }
  272     if (cdp->cap.read_cdrw) {
  273         printf("%s CD-RW", comma ? "," : ""); comma = 1;
  274     }
  275     if (cdp->cap.cd_da) {
  276         printf("%s CD-DA", comma ? "," : ""); comma = 1;
  277     }
  278     if (cdp->cap.method2)
  279         printf("%s packet track", comma ? "," : "");
  280     if (cdp->cap.write_cdr || cdp->cap.write_cdrw) {
  281         printf("\nacd%d: supported write types:", cdp->lun);
  282         comma = 0;
  283         if (cdp->cap.write_cdr) {
  284             printf(" CD-R" ); comma = 1;
  285         }
  286         if (cdp->cap.write_cdrw) {
  287             printf("%s CD-RW", comma ? "," : ""); comma = 1;
  288         }
  289         if (cdp->cap.test_write) {
  290             printf("%s test write", comma ? "," : ""); comma = 1;
  291         }
  292     }
  293     if (cdp->cap.audio_play) {
  294         printf("\nacd%d: Audio: ", cdp->lun);
  295         if (cdp->cap.audio_play)
  296             printf("play");
  297         if (cdp->cap.max_vol_levels)
  298             printf(", %d volume levels", cdp->cap.max_vol_levels);
  299     }
  300     printf("\nacd%d: Mechanism: ", cdp->lun);
  301     switch (cdp->cap.mech) {
  302     case MST_MECH_CADDY:
  303         mechanism = "caddy"; break;
  304     case MST_MECH_TRAY:
  305         mechanism = "tray"; break;
  306     case MST_MECH_POPUP:
  307         mechanism = "popup"; break;
  308     case MST_MECH_CHANGER:
  309         mechanism = "changer"; break;
  310     case MST_MECH_CARTRIDGE:
  311         mechanism = "cartridge"; break;
  312     default:
  313         mechanism = 0; break;
  314     }
  315     if (mechanism)
  316         printf("%s%s", cdp->cap.eject ? "ejectable " : "", mechanism);
  317     else if (cdp->cap.eject)
  318         printf("ejectable");
  319 
  320     if (cdp->cap.mech != MST_MECH_CHANGER) {
  321         printf("\nacd%d: Medium: ", cdp->lun);
  322         switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
  323         case MST_CDROM:
  324             printf("CD-ROM "); break;
  325         case MST_CDR:
  326             printf("CD-R "); break;
  327         case MST_CDRW:
  328             printf("CD-RW "); break;
  329         case MST_DOOR_OPEN:
  330             printf("door open"); break;
  331         case MST_NO_DISC:
  332             printf("no/blank disc inside"); break;
  333         case MST_FMT_ERROR:
  334             printf("medium format error"); break;
  335         }
  336         if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH) < MST_TYPE_MASK_HIGH) {
  337             switch (cdp->cap.medium_type & MST_TYPE_MASK_LOW) {
  338             case MST_DATA_120:
  339                 printf("120mm data disc loaded"); break;
  340             case MST_AUDIO_120:
  341                 printf("120mm audio disc loaded"); break;
  342             case MST_COMB_120:
  343                 printf("120mm data/audio disc loaded"); break;
  344             case MST_PHOTO_120:
  345                 printf("120mm photo disc loaded"); break;
  346             case MST_DATA_80:
  347                 printf("80mm data disc loaded"); break;
  348             case MST_AUDIO_80:
  349                 printf("80mm audio disc loaded"); break;
  350             case MST_COMB_80:
  351                 printf("80mm data/audio disc loaded"); break;
  352             case MST_PHOTO_80:
  353                 printf("80mm photo disc loaded"); break;
  354             case MST_FMT_NONE:
  355                 switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
  356                 case MST_CDROM:
  357                     printf("unknown medium"); break;
  358                 case MST_CDR:
  359                 case MST_CDRW:
  360                     printf("blank medium"); break;
  361                 }
  362                 break;
  363             default:
  364                 printf("unknown type=0x%x", cdp->cap.medium_type); break;
  365             }
  366         }
  367     }
  368     if (cdp->cap.lock)
  369         printf(cdp->cap.locked ? ", locked" : ", unlocked");
  370     if (cdp->cap.prevent)
  371         printf(", lock protected");
  372     printf("\n");
  373 }
  374 
  375 static int
  376 acdopen(dev_t dev, int flags, int fmt, struct proc *p)
  377 {
  378     int lun = dkunit(dev);
  379     struct acd *cdp;
  380 
  381     if (lun >= acdnlun || !atapi_request_immediate)
  382         return ENXIO;
  383     cdp = acdtab[lun];
  384 
  385     if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) {
  386         /* Prevent user eject */
  387         acd_request_wait(cdp, ATAPI_PREVENT_ALLOW,
  388             0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0);
  389         cdp->flags |= F_LOCKED;
  390     }
  391     if (fmt == S_IFBLK)
  392         cdp->flags |= F_BOPEN;
  393     else
  394         ++cdp->refcnt;
  395 
  396     if (!(flags & O_NONBLOCK) && acd_read_toc(cdp) && !(flags & FWRITE))
  397         printf("acd%d: read_toc failed\n", lun);
  398     return 0;
  399 }
  400 
  401 int 
  402 acdclose(dev_t dev, int flags, int fmt, struct proc *p)
  403 {
  404     struct acd *cdp = acdtab[dkunit(dev)];
  405 
  406     if (fmt == S_IFBLK)
  407         cdp->flags &= ~F_BOPEN;
  408     else
  409         --cdp->refcnt;
  410 
  411     /* Are we the last open ?? */
  412     if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) {
  413         /* Yup, do we need to close any written tracks */
  414         if ((flags & FWRITE) != 0) {
  415             if ((cdp->flags & F_TRACK_PREPED) != 0) {
  416                 acd_close_track(cdp);
  417                 cdp->flags &= ~(F_TRACK_PREPED | F_TRACK_PREP);
  418             }
  419         }
  420         /* Allow the user eject */
  421         acd_request_wait(cdp, ATAPI_PREVENT_ALLOW,
  422                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  423     }
  424     cdp->flags &= ~F_LOCKED;
  425     return 0;
  426 }
  427 
  428 static int
  429 acdread(dev_t dev, struct uio *uio, int ioflag)
  430 {
  431     return physio(acdstrategy, NULL, dev, 1, minphys, uio);
  432 }
  433 
  434 static int
  435 acdwrite(dev_t dev, struct uio *uio, int ioflag)
  436 {
  437     return physio(acdstrategy, NULL, dev, 0, minphys, uio);
  438 }
  439 
  440 void 
  441 acdstrategy(struct buf *bp)
  442 {
  443     int lun = dkunit(bp->b_dev);
  444     struct acd *cdp = acdtab[lun];
  445     int x;
  446 
  447 #ifdef NOTYET
  448     /* allow write only on CD-R/RW media */   /* all for now SOS */
  449     if (!(bp->b_flags & B_READ) && !(writeable_media)) {
  450         bp->b_error = EROFS;
  451         bp->b_flags |= B_ERROR;
  452         biodone(bp);
  453         return;
  454     }
  455 #endif
  456 
  457     if (bp->b_bcount == 0) {
  458         bp->b_resid = 0;
  459         biodone(bp);
  460         return;
  461     }
  462     
  463     bp->b_pblkno = bp->b_blkno;
  464     bp->b_resid = bp->b_bcount;
  465 
  466     x = splbio();
  467     bufqdisksort(&cdp->buf_queue, bp);
  468     acd_start(cdp);
  469     splx(x);
  470 }
  471 
  472 static void 
  473 acd_start(struct acd *cdp)
  474 {
  475     struct buf *bp = bufq_first(&cdp->buf_queue);
  476     u_long lba, blocks;
  477     int cmd;
  478     int count;
  479 
  480     if (!bp)
  481         return;
  482 
  483     bufq_remove(&cdp->buf_queue, bp);
  484 
  485     /* Should reject all queued entries if media have changed. */
  486     if (cdp->flags & F_MEDIA_CHANGED) {
  487         bp->b_error = EIO;
  488         bp->b_flags |= B_ERROR;
  489         biodone(bp);
  490         return;
  491     }
  492     acd_select_slot(cdp);
  493 
  494     if ((bp->b_flags & B_READ) == B_WRITE) {
  495         if ((cdp->flags & F_TRACK_PREPED) == 0) {
  496             if ((cdp->flags & F_TRACK_PREP) == 0) {
  497                 printf("acd%d: sequence error\n", cdp->lun);
  498                 bp->b_error = EIO;
  499                 bp->b_flags |= B_ERROR;
  500                 biodone(bp);
  501                 return;
  502             } else {
  503                 if (acd_open_track(cdp, &cdp->preptrack) != 0) {
  504                     biodone(bp);
  505                     return;
  506                 }
  507                 cdp->flags |= F_TRACK_PREPED;
  508             }
  509         }
  510     }
  511 
  512     if (bp->b_flags & B_READ)
  513 #ifdef NOTYET
  514         lba = bp->b_offset / cdp->block_size;
  515 #else
  516         lba = bp->b_blkno / (cdp->block_size / DEV_BSIZE);
  517 #endif
  518     else 
  519         lba = cdp->next_writeable_lba + (bp->b_offset / cdp->block_size);
  520     blocks = (bp->b_bcount + (cdp->block_size - 1)) / cdp->block_size;
  521 
  522     if ((bp->b_flags & B_READ) == B_WRITE) {
  523         cmd = ATAPI_WRITE_BIG;
  524         count = -bp->b_bcount;
  525     } else {
  526         cmd = ATAPI_READ_BIG;
  527         count = bp->b_bcount;
  528     }
  529 
  530     atapi_request_callback(cdp->ata, cdp->unit, cmd, 0,
  531                            lba>>24, lba>>16, lba>>8, lba, 0, 
  532                            blocks>>8, blocks, 0, 0, 0, 0, 0, 0, 0, 
  533                            (u_char *)bp->b_data, count, 
  534                            (atapi_callback_t *)acd_done, cdp, bp);
  535 }
  536 
  537 static void 
  538 acd_done(struct acd *cdp, struct buf *bp, int resid, struct atapires result)
  539 {
  540     if (result.code) {
  541         atapi_error(cdp->ata, cdp->unit, result);
  542         bp->b_error = EIO;
  543         bp->b_flags |= B_ERROR;
  544     } else {
  545         bp->b_resid = resid;
  546         if ((bp->b_flags & B_READ) == B_WRITE)
  547             cdp->flags |= F_WRITTEN;
  548     }
  549     biodone(bp);
  550     acd_start(cdp);
  551 }
  552 
  553 static int 
  554 acd_request_wait(struct acd *cdp, u_char cmd, u_char a1, u_char a2,
  555     u_char a3, u_char a4, u_char a5, u_char a6, u_char a7, u_char a8,
  556     u_char a9, char *addr, int count)
  557 {
  558     struct atapires result;
  559 
  560     result = atapi_request_wait(cdp->ata, cdp->unit, cmd, a1, a2, a3, a4, a5,
  561                                 a6, a7, a8, a9, 0, 0, 0, 0, 0, 0, addr, count);
  562     if (result.code) {
  563         atapi_error(cdp->ata, cdp->unit, result);
  564         return EIO;
  565     }
  566     return 0;
  567 }
  568 
  569 static __inline void 
  570 lba2msf(int lba, u_char *m, u_char *s, u_char *f)
  571 {
  572     lba += 150;
  573     lba &= 0xffffff;
  574     *m = lba / (60 * 75);
  575     lba %= (60 * 75);
  576     *s = lba / 75;
  577     *f = lba % 75;
  578 }
  579 
  580 static __inline int 
  581 msf2lba(u_char m, u_char s, u_char f)
  582 {
  583     return (m * 60 + s) * 75 + f - 150;
  584 }
  585 
  586 int 
  587 acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
  588 {
  589     int lun = dkunit(dev);
  590     struct acd *cdp = acdtab[lun];
  591     int error = 0;
  592 
  593     if (cdp->flags & F_MEDIA_CHANGED)
  594         switch (cmd) {
  595         case CDIOCRESET:
  596             break;
  597         default:
  598             acd_read_toc(cdp);
  599             acd_request_wait(cdp, ATAPI_PREVENT_ALLOW,
  600                              0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0);
  601             cdp->flags |= F_LOCKED;
  602             break;
  603         }
  604     switch (cmd) {
  605 /*
  606     case CDIOCRESUME:
  607         bzero(cdb);
  608         cdb->cmd = ATAPI_PAUSE;
  609         cdb->b8 = 0x01;
  610         return atapi_cmd_wait(cdp->ata, cdp->unit, cdb, 0, 0, timout, 0);
  611 */
  612     case CDIOCRESUME:
  613         return acd_request_wait(cdp, ATAPI_PAUSE, 
  614                                 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
  615 
  616     case CDIOCPAUSE:
  617         return acd_request_wait(cdp, ATAPI_PAUSE, 
  618                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  619 
  620     case CDIOCSTART:
  621         return acd_request_wait(cdp, ATAPI_START_STOP,
  622                                 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0);
  623 
  624     case CDIOCSTOP:
  625         return acd_request_wait(cdp, ATAPI_START_STOP,
  626                                 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  627 
  628     case CDIOCALLOW:
  629         acd_select_slot(cdp);
  630         cdp->flags &= ~F_LOCKED;
  631         return acd_request_wait(cdp, ATAPI_PREVENT_ALLOW,
  632                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  633 
  634     case CDIOCPREVENT:
  635         acd_select_slot(cdp);
  636         cdp->flags |= F_LOCKED;
  637         return acd_request_wait(cdp, ATAPI_PREVENT_ALLOW,
  638                                 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0);
  639 
  640     case CDIOCRESET:
  641         if (p->p_cred->pc_ucred->cr_uid)
  642             return EPERM;
  643         return acd_request_wait(cdp, ATAPI_TEST_UNIT_READY,
  644                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  645 
  646     case CDIOCEJECT:
  647         if ((cdp->flags & F_BOPEN) && cdp->refcnt)
  648             return EBUSY;
  649         return acd_eject(cdp, 0);
  650 
  651     case CDIOCCLOSE:
  652         if ((cdp->flags & F_BOPEN) && cdp->refcnt)
  653             return 0;
  654         return acd_eject(cdp, 1);
  655 
  656     case CDIOREADTOCHEADER:
  657         if (!cdp->toc.hdr.ending_track)
  658             return EIO;
  659         bcopy(&cdp->toc.hdr, addr, sizeof(cdp->toc.hdr));
  660         break;
  661 
  662     case CDIOREADTOCENTRYS:
  663         {
  664             struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)addr;
  665             struct toc *toc = &cdp->toc;
  666             struct toc buf;
  667             u_long len;
  668             u_char starting_track = te->starting_track;
  669 
  670             if (!cdp->toc.hdr.ending_track)
  671                 return EIO;
  672 
  673             if (te->data_len < sizeof(toc->tab[0]) || 
  674                 (te->data_len % sizeof(toc->tab[0])) != 0 || 
  675                 te->address_format != CD_MSF_FORMAT &&
  676                 te->address_format != CD_LBA_FORMAT)
  677                 return EINVAL;
  678 
  679             if (!starting_track)
  680                 starting_track = toc->hdr.starting_track;
  681             else if (starting_track == 170) 
  682                 starting_track = toc->hdr.ending_track + 1;
  683             else if (starting_track < toc->hdr.starting_track ||
  684                      starting_track > toc->hdr.ending_track + 1)
  685                 return EINVAL;
  686 
  687             len = ((toc->hdr.ending_track + 1 - starting_track) + 1) *
  688                   sizeof(toc->tab[0]);
  689             if (te->data_len < len)
  690                 len = te->data_len;
  691             if (len > sizeof(toc->tab))
  692                 return EINVAL;
  693 
  694             if (te->address_format == CD_MSF_FORMAT) {
  695                 struct cd_toc_entry *entry;
  696 
  697                 buf = cdp->toc;
  698                 toc = &buf;
  699                 entry = toc->tab + (toc->hdr.ending_track + 1 -
  700                         toc->hdr.starting_track) + 1;
  701                 while (--entry >= toc->tab)
  702                     lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute,
  703                             &entry->addr.msf.second, &entry->addr.msf.frame);
  704             }
  705             return copyout(toc->tab + starting_track - toc->hdr.starting_track,
  706                            te->data, len);
  707         }
  708 
  709     case CDIOREADTOCENTRY:
  710         {
  711             struct ioc_read_toc_single_entry *te =
  712                 (struct ioc_read_toc_single_entry *)addr;
  713             struct toc *toc = &cdp->toc;
  714             struct toc buf;
  715             u_char track = te->track;
  716 
  717             if (!cdp->toc.hdr.ending_track)
  718                 return EIO;
  719 
  720             if (te->address_format != CD_MSF_FORMAT && 
  721                 te->address_format != CD_LBA_FORMAT)
  722                 return EINVAL;
  723 
  724             if (!track)
  725                 track = toc->hdr.starting_track;
  726             else if (track == 170)
  727                 track = toc->hdr.ending_track + 1;
  728             else if (track < toc->hdr.starting_track ||
  729                      track > toc->hdr.ending_track + 1)
  730                 return EINVAL;
  731 
  732             if (te->address_format == CD_MSF_FORMAT) {
  733                 struct cd_toc_entry *entry;
  734 
  735                 buf = cdp->toc;
  736                 toc = &buf;
  737                 entry = toc->tab + (track - toc->hdr.starting_track);
  738                 lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute,
  739                         &entry->addr.msf.second, &entry->addr.msf.frame);
  740             }
  741             bcopy(toc->tab + track - toc->hdr.starting_track,
  742                   &te->entry, sizeof(struct cd_toc_entry));
  743         }
  744         break;
  745 
  746     case CDIOCREADSUBCHANNEL:
  747         {
  748             struct ioc_read_subchannel *args =
  749                 (struct ioc_read_subchannel *)addr;
  750             struct cd_sub_channel_info data;
  751             u_long len = args->data_len;
  752             int abslba, rellba;
  753 
  754             if (len > sizeof(data) ||
  755                 len < sizeof(struct cd_sub_channel_header))
  756                 return EINVAL;
  757 
  758             if (acd_request_wait(cdp, ATAPI_READ_SUBCHANNEL,
  759                                  0, 0x40, 1, 0, 0, 0, 
  760                                  sizeof(cdp->subchan)>>8, sizeof(cdp->subchan),
  761                                  0,
  762                                  (char *)&cdp->subchan, 
  763                                  sizeof(cdp->subchan)) != 0)
  764                 return EIO;
  765             if (cdp->flags & F_DEBUG)
  766                 atapi_dump(cdp->ata->ctrlr, cdp->lun, "subchan", &cdp->subchan, 
  767                            sizeof(cdp->subchan));
  768 
  769             abslba = cdp->subchan.abslba;
  770             rellba = cdp->subchan.rellba;
  771             if (args->address_format == CD_MSF_FORMAT) {
  772                 lba2msf(ntohl(abslba),
  773                     &data.what.position.absaddr.msf.minute,
  774                     &data.what.position.absaddr.msf.second,
  775                     &data.what.position.absaddr.msf.frame);
  776                 lba2msf(ntohl(rellba),
  777                     &data.what.position.reladdr.msf.minute,
  778                     &data.what.position.reladdr.msf.second,
  779                     &data.what.position.reladdr.msf.frame);
  780             } else {
  781                 data.what.position.absaddr.lba = abslba;
  782                 data.what.position.reladdr.lba = rellba;
  783             }
  784             data.header.audio_status = cdp->subchan.audio_status;
  785             data.what.position.control = cdp->subchan.control & 0xf;
  786             data.what.position.addr_type = cdp->subchan.control >> 4;
  787             data.what.position.track_number = cdp->subchan.track;
  788             data.what.position.index_number = cdp->subchan.indx;
  789             return copyout(&data, args->data, len);
  790         }
  791 
  792     case CDIOCPLAYMSF:
  793         {
  794             struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
  795 
  796             return acd_request_wait(cdp, ATAPI_PLAY_MSF, 0, 0,
  797                                     args->start_m, args->start_s, args->start_f,
  798                                     args->end_m, args->end_s, args->end_f,
  799                                     0, 0, 0);
  800         }
  801 
  802     case CDIOCPLAYBLOCKS:
  803         {
  804             struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
  805 
  806             return acd_request_wait(cdp, ATAPI_PLAY_BIG, 0,
  807                                     args->blk>>24 & 0xff, args->blk>>16 & 0xff,
  808                                     args->blk>>8 & 0xff, args->blk & 0xff,
  809                                     args->len>>24 & 0xff, args->len>>16 & 0xff,
  810                                     args->len>>8 & 0xff, args->len & 0xff,
  811                                     0, 0);
  812         }
  813 
  814     case CDIOCPLAYTRACKS:
  815         {
  816             struct ioc_play_track *args = (struct ioc_play_track *)addr;
  817             u_long start, len;
  818             int t1, t2;
  819 
  820             if (!cdp->toc.hdr.ending_track)
  821                 return EIO;
  822 
  823             if (args->end_track < cdp->toc.hdr.ending_track + 1)
  824                 ++args->end_track;
  825             if (args->end_track > cdp->toc.hdr.ending_track + 1)
  826                 args->end_track = cdp->toc.hdr.ending_track + 1;
  827             t1 = args->start_track - cdp->toc.hdr.starting_track;
  828             t2 = args->end_track - cdp->toc.hdr.starting_track;
  829             if (t1 < 0 || t2 < 0)
  830                 return EINVAL;
  831             start = ntohl(cdp->toc.tab[t1].addr.lba);
  832             len = ntohl(cdp->toc.tab[t2].addr.lba) - start;
  833 
  834             return acd_request_wait(cdp, ATAPI_PLAY_BIG, 0,
  835                                     start>>24 & 0xff, start>>16 & 0xff,
  836                                     start>>8 & 0xff, start & 0xff,
  837                                     len>>24 & 0xff, len>>16 & 0xff,
  838                                     len>>8 & 0xff, len & 0xff, 0, 0);
  839         }
  840 
  841     case CDIOCREADAUDIO:
  842         {
  843             struct ioc_read_audio* args = (struct ioc_read_audio*) addr;
  844             int lba, frames, result = 0;
  845             u_char *buffer, *ubuf = args->buffer;
  846 
  847             if (!cdp->toc.hdr.ending_track)
  848                 return EIO;
  849                 
  850             if ((frames = args->nframes) < 0)
  851                 return EINVAL;
  852 
  853             if (args->address_format == CD_LBA_FORMAT)
  854                 lba = args->address.lba;
  855             else if (args->address_format == CD_MSF_FORMAT)
  856                 lba = msf2lba(args->address.msf.minute,
  857                              args->address.msf.second,
  858                              args->address.msf.frame);
  859             else
  860                 return EINVAL;
  861 #ifndef CD_BUFFER_BLOCKS
  862 #define CD_BUFFER_BLOCKS 8
  863 #endif
  864             if (!(buffer = malloc(CD_BUFFER_BLOCKS * 2352, M_TEMP, M_NOWAIT)))
  865                 return ENOMEM;
  866 
  867             while (frames > 0) {
  868                 u_char blocks;
  869                 int size;
  870 
  871                 blocks = (frames>CD_BUFFER_BLOCKS) ? CD_BUFFER_BLOCKS : frames;
  872                 size = blocks * 2352;
  873 
  874                 result = acd_request_wait(cdp, ATAPI_READ_CD, 4,
  875                                           lba>>24, (lba>>16)&0xff,
  876                                           (lba>>8)&0xff, lba&0xff, 0, 0,
  877                                           blocks, 0xf0, buffer, size);
  878                 if (result != 0)
  879                     break;
  880 
  881                 result = copyout(buffer, ubuf, size);
  882                 if (result != 0)
  883                     break;
  884                     
  885                 ubuf += size;
  886                 frames -= blocks;
  887                 lba += blocks;
  888             }
  889 
  890             free(buffer, M_TEMP);
  891             return result;
  892         }
  893 
  894     case CDIOCGETVOL:
  895         {
  896             struct ioc_vol *arg = (struct ioc_vol *)addr;
  897 
  898             error = acd_request_wait(cdp, ATAPI_MODE_SENSE, 0, CDROM_AUDIO_PAGE,
  899                                      0, 0, 0, 0, 
  900                                      sizeof(cdp->au)>>8, sizeof(cdp->au), 0,
  901                                      (char *)&cdp->au, sizeof(cdp->au));
  902             if (error)
  903                 return error;
  904             if (cdp->flags & F_DEBUG)
  905                 atapi_dump(cdp->ata->ctrlr, cdp->lun, "au", &cdp->au,
  906                            sizeof(cdp->au));
  907             if (cdp->au.page_code != CDROM_AUDIO_PAGE)
  908                 return EIO;
  909             arg->vol[0] = cdp->au.port[0].volume;
  910             arg->vol[1] = cdp->au.port[1].volume;
  911             arg->vol[2] = cdp->au.port[2].volume;
  912             arg->vol[3] = cdp->au.port[3].volume;
  913         }
  914         break;
  915 
  916     case CDIOCSETVOL:
  917         {
  918             struct ioc_vol *arg = (struct ioc_vol *)addr;
  919 
  920             error = acd_request_wait(cdp, ATAPI_MODE_SENSE, 0, CDROM_AUDIO_PAGE,
  921                                      0, 0, 0, 0, 
  922                                      sizeof(cdp->au)>>8, sizeof(cdp->au), 0,
  923                                      (char *)&cdp->au, sizeof(cdp->au));
  924             if (error)
  925                 return error;
  926             if (cdp->flags & F_DEBUG)
  927                 atapi_dump(cdp->ata->ctrlr, cdp->lun, "au", &cdp->au, 
  928                            sizeof(cdp->au));
  929             if (cdp->au.page_code != CDROM_AUDIO_PAGE)
  930                 return EIO;
  931 
  932             error = acd_request_wait(cdp, ATAPI_MODE_SENSE, 0, 
  933                                      CDROM_AUDIO_PAGE_MASK, 0, 0, 0, 0, 
  934                                      sizeof(cdp->aumask)>>8,sizeof(cdp->aumask),
  935                                      0,
  936                                      (char *)&cdp->aumask, sizeof(cdp->aumask));
  937             if (error)
  938                 return error;
  939             if (cdp->flags & F_DEBUG)
  940                 atapi_dump(cdp->ata->ctrlr, cdp->lun, "mask", &cdp->aumask, 
  941                            sizeof(cdp->aumask));
  942 
  943             cdp->au.data_length = 0;
  944             cdp->au.port[0].channels = CHANNEL_0;
  945             cdp->au.port[1].channels = CHANNEL_1;
  946             cdp->au.port[0].volume = arg->vol[0] & cdp->aumask.port[0].volume;
  947             cdp->au.port[1].volume = arg->vol[1] & cdp->aumask.port[1].volume;
  948             cdp->au.port[2].volume = arg->vol[2] & cdp->aumask.port[2].volume;
  949             cdp->au.port[3].volume = arg->vol[3] & cdp->aumask.port[3].volume;
  950             return acd_request_wait(cdp, ATAPI_MODE_SELECT, 0x10,
  951                                     0, 0, 0, 0, 0, 
  952                                     sizeof(cdp->au)>>8, sizeof(cdp->au),
  953                                     0, (char *)&cdp->au, -sizeof(cdp->au));
  954         }
  955 
  956     case CDIOCSETPATCH:
  957         {
  958             struct ioc_patch *arg = (struct ioc_patch *)addr;
  959 
  960             return acd_setchan(cdp, arg->patch[0], arg->patch[1],
  961                                arg->patch[2], arg->patch[3]);
  962         }
  963 
  964     case CDIOCSETMONO:
  965         return acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0, 0);
  966 
  967     case CDIOCSETSTEREO:
  968         return acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0);
  969 
  970     case CDIOCSETMUTE:
  971         return acd_setchan(cdp, 0, 0, 0, 0);
  972 
  973     case CDIOCSETLEFT:
  974         return acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0);
  975 
  976     case CDIOCSETRIGHT:
  977         return acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0);
  978 
  979     case CDRIOCNEXTWRITEABLEADDR:
  980         {
  981             struct acd_track_info track_info;
  982 
  983             if ((error = acd_read_track_info(cdp, 0xff, &track_info)))
  984                 break;
  985             if (!track_info.nwa_valid)
  986                 return EINVAL;
  987             cdp->next_writeable_lba = track_info.next_writeable_addr;
  988             *(int*)addr = track_info.next_writeable_addr;
  989         }
  990         break;
  991  
  992     case WORMIOCPREPDISK:
  993         {
  994             struct wormio_prepare_disk *w = (struct wormio_prepare_disk *)addr;
  995 
  996             if (w->dummy != 0 && w->dummy != 1)
  997                 error = EINVAL;
  998             else {
  999                 error = acd_open_disk(cdp, w->dummy);
 1000                 if (error == 0) {
 1001                     cdp->flags |= F_DISK_PREPED;
 1002                     cdp->dummy = w->dummy;
 1003                     cdp->speed = w->speed;
 1004                 }
 1005             }
 1006         }
 1007         break;
 1008 
 1009     case WORMIOCPREPTRACK:
 1010         {
 1011             struct wormio_prepare_track *w =(struct wormio_prepare_track *)addr;
 1012 
 1013             if (w->audio != 0 && w->audio != 1)
 1014                 error = EINVAL;
 1015             else if (w->audio == 0 && w->preemp)
 1016                 error = EINVAL;
 1017             else if ((cdp->flags & F_DISK_PREPED) == 0) {
 1018                 error = EINVAL;
 1019                 printf("acd%d: sequence error (PREP_TRACK)\n", cdp->lun);
 1020             } else {
 1021                 cdp->flags |= F_TRACK_PREP;
 1022                 cdp->preptrack = *w;
 1023             }
 1024         }
 1025         break;
 1026 
 1027     case WORMIOCFINISHTRACK:
 1028         if ((cdp->flags & F_TRACK_PREPED) != 0)
 1029             error = acd_close_track(cdp);
 1030         cdp->flags &= ~(F_TRACK_PREPED | F_TRACK_PREP);
 1031         break;
 1032 
 1033     case WORMIOCFIXATION:
 1034         {
 1035             struct wormio_fixation *w =
 1036             (struct wormio_fixation *)addr;
 1037 
 1038             if ((cdp->flags & F_WRITTEN) == 0)
 1039                 error = EINVAL;
 1040             else if (w->toc_type < 0 /* WORM_TOC_TYPE_AUDIO */ ||
 1041                 w->toc_type > 4 /* WORM_TOC_TYPE_CDI */ )
 1042                 error = EINVAL;
 1043             else if (w->onp != 0 && w->onp != 1)
 1044                 error = EINVAL;
 1045             else {
 1046                 /* no fixation needed if dummy write */
 1047                 if (cdp->dummy == 0)
 1048                     error = acd_close_disk(cdp);
 1049                 cdp->flags &=
 1050                     ~(F_WRITTEN|F_DISK_PREPED|F_TRACK_PREP|F_TRACK_PREPED);
 1051             }
 1052         }
 1053         break;
 1054 
 1055     case CDRIOCBLANK:
 1056         return acd_blank_disk(cdp);
 1057 
 1058     default:
 1059         return ENOTTY;
 1060     }
 1061     return error;
 1062 }
 1063 
 1064 static int 
 1065 acd_read_toc(struct acd *cdp)
 1066 {
 1067     int ntracks, len;
 1068     struct atapires result;
 1069 
 1070     bzero(&cdp->toc, sizeof(cdp->toc));
 1071     bzero(&cdp->info, sizeof(cdp->info));
 1072 
 1073     acd_select_slot(cdp);
 1074 
 1075     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_TEST_UNIT_READY,
 1076                                 0, 0, 0, 0, 0, 0, 0, 0,
 1077                                 0, 0, 0, 0, 0, 0, 0, 0, 0);
 1078 
 1079     if (result.code == RES_ERR &&
 1080         (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION) {
 1081         cdp->flags |= F_MEDIA_CHANGED;
 1082         cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED);
 1083         result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_TEST_UNIT_READY,
 1084                                     0, 0, 0, 0, 0, 0, 0, 0,
 1085                                     0, 0, 0, 0, 0, 0, 0, 0, 0);
 1086     }
 1087 
 1088     if (result.code) {
 1089         atapi_error(cdp->ata, cdp->unit, result);
 1090         return EIO;
 1091     }
 1092 
 1093     cdp->flags &= ~F_MEDIA_CHANGED;
 1094 
 1095     len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry);
 1096     if (acd_request_wait(cdp, ATAPI_READ_TOC, 0, 0, 0, 0, 0, 0,
 1097                          len>>8, len & 0xff, 0, (char *)&cdp->toc, len) != 0) {
 1098         bzero(&cdp->toc, sizeof(cdp->toc));
 1099         return 0;
 1100     }
 1101     ntracks = cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1;
 1102     if (ntracks <= 0 || ntracks > MAXTRK) {
 1103         bzero(&cdp->toc, sizeof(cdp->toc));
 1104         return 0;
 1105     }
 1106 
 1107     len = sizeof(struct ioc_toc_header) + ntracks * sizeof(struct cd_toc_entry);
 1108     if (acd_request_wait(cdp, ATAPI_READ_TOC, 0, 0, 0, 0, 0, 0,
 1109                          len>>8, len & 0xff, 0, (char *)&cdp->toc, len) & 0xff){
 1110         bzero(&cdp->toc, sizeof(cdp->toc));
 1111         return 0;
 1112     }
 1113 
 1114     cdp->toc.hdr.len = ntohs(cdp->toc.hdr.len);
 1115 
 1116     if (acd_request_wait(cdp, ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 1117                          (char *)&cdp->info, sizeof(cdp->info)) != 0)
 1118         bzero(&cdp->info, sizeof(cdp->info));
 1119 
 1120     cdp->toc.tab[ntracks].control = cdp->toc.tab[ntracks - 1].control;
 1121     cdp->toc.tab[ntracks].addr_type = cdp->toc.tab[ntracks - 1].addr_type;
 1122     cdp->toc.tab[ntracks].track = 170;
 1123     cdp->toc.tab[ntracks].addr.lba = cdp->info.volsize;
 1124 
 1125     cdp->info.volsize = ntohl(cdp->info.volsize);
 1126     cdp->info.blksize = ntohl(cdp->info.blksize);
 1127 
 1128     if (cdp->info.volsize && cdp->toc.hdr.ending_track
 1129         && (cdp->flags & F_DEBUG)) {
 1130         printf("acd%d: ", cdp->lun);
 1131         if (cdp->toc.tab[0].control & 4)
 1132             printf("%ldMB ", cdp->info.volsize / 512);
 1133         else
 1134             printf("%ld:%ld audio ", cdp->info.volsize / 75 / 60,
 1135                 cdp->info.volsize / 75 % 60);
 1136         printf("(%ld sectors (%ld bytes)), %d tracks\n", 
 1137             cdp->info.volsize, cdp->info.blksize,
 1138             cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1);
 1139     }
 1140     return 0;
 1141 }
 1142 
 1143 /*
 1144  * Set up the audio channel masks.
 1145  */
 1146 static int 
 1147 acd_setchan(struct acd *cdp, u_char c0, u_char c1, u_char c2, u_char c3)
 1148 {
 1149     int error;
 1150 
 1151     error = acd_request_wait(cdp, ATAPI_MODE_SENSE, 0, CDROM_AUDIO_PAGE,
 1152                              0, 0, 0, 0, 
 1153                              sizeof(cdp->au)>>8, sizeof(cdp->au), 0,
 1154                              (char *)&cdp->au, sizeof(cdp->au));
 1155     if (error)
 1156         return error;
 1157     if (cdp->flags & F_DEBUG)
 1158         atapi_dump(cdp->ata->ctrlr, cdp->lun, "au", &cdp->au, sizeof(cdp->au));
 1159     if (cdp->au.page_code != CDROM_AUDIO_PAGE)
 1160         return EIO;
 1161 
 1162     cdp->au.data_length = 0;
 1163     cdp->au.port[0].channels = c0;
 1164     cdp->au.port[1].channels = c1;
 1165     cdp->au.port[2].channels = c2;
 1166     cdp->au.port[3].channels = c3;
 1167     return acd_request_wait(cdp, ATAPI_MODE_SELECT, 0x10,
 1168                             0, 0, 0, 0, 0, 
 1169                             sizeof(cdp->au)>>8, sizeof(cdp->au), 0,
 1170                             (char *)&cdp->au, -sizeof(cdp->au));
 1171 }
 1172 
 1173 static int 
 1174 acd_eject(struct acd *cdp, int close)
 1175 {
 1176     struct atapires result;
 1177 
 1178     acd_select_slot(cdp);
 1179 
 1180     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_START_STOP, 1,
 1181                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 1182 
 1183     if (result.code == RES_ERR &&
 1184         ((result.error & AER_SKEY) == AER_SK_NOT_READY ||
 1185         (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION)) {
 1186         int err;
 1187 
 1188         if (!close)
 1189             return 0;
 1190         err = acd_request_wait(cdp, ATAPI_START_STOP, 0, 0, 0, 3,
 1191                                0, 0, 0, 0, 0, 0, 0);
 1192         if (err)
 1193             return err;
 1194 
 1195         acd_read_toc(cdp);
 1196 
 1197         acd_request_wait(cdp, ATAPI_PREVENT_ALLOW, 0, 0, 0, 1,
 1198                          0, 0, 0, 0, 0, 0, 0);
 1199         cdp->flags |= F_LOCKED;
 1200         return 0;
 1201     }
 1202     if (result.code) {
 1203         atapi_error(cdp->ata, cdp->unit, result);
 1204         return EIO;
 1205     }
 1206     if (close)
 1207         return 0;
 1208 
 1209     tsleep((caddr_t) &lbolt, PRIBIO, "acdej1", 0);
 1210     tsleep((caddr_t) &lbolt, PRIBIO, "acdej2", 0);
 1211 
 1212     acd_request_wait(cdp, ATAPI_PREVENT_ALLOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 1213     cdp->flags &= ~F_LOCKED;
 1214 
 1215     cdp->flags |= F_MEDIA_CHANGED;
 1216     cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED);
 1217     return acd_request_wait(cdp, ATAPI_START_STOP, 0, 0, 0, 2,
 1218                             0, 0, 0, 0, 0, 0, 0);
 1219 }
 1220 
 1221 static void
 1222 acd_select_slot(struct acd *cdp)
 1223 {
 1224     if (cdp->slot < 0 || cdp->changer_info->current_slot == cdp->slot)
 1225         return;
 1226 
 1227     /* Unlock (might not be needed but its cheaper than asking) */
 1228     acd_request_wait(cdp, ATAPI_PREVENT_ALLOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 1229 
 1230     /* Unload the current media from player */
 1231     acd_request_wait(cdp, ATAPI_LOAD_UNLOAD, 0, 0, 0, 2,
 1232                      0, 0, 0, cdp->changer_info->current_slot, 0, 0, 0);
 1233 
 1234     /* load the wanted slot */
 1235     acd_request_wait(cdp, ATAPI_LOAD_UNLOAD, 0, 0, 0, 3,
 1236                      0, 0, 0, cdp->slot, 0, 0, 0);
 1237 
 1238     cdp->changer_info->current_slot = cdp->slot;
 1239 
 1240     /* Lock the media if needed */
 1241     if (cdp->flags & F_LOCKED) {
 1242         acd_request_wait(cdp, ATAPI_PREVENT_ALLOW, 0, 0, 0, 1,
 1243                          0, 0, 0, 0, 0, 0, 0);
 1244     }
 1245 }
 1246 
 1247 static int
 1248 acd_open_disk(struct acd *cdp, int test)
 1249 {
 1250     cdp->next_writeable_lba = 0;
 1251     return 0;
 1252 }
 1253 
 1254 static int
 1255 acd_close_disk(struct acd *cdp)
 1256 {
 1257     return acd_request_wait(cdp, ATAPI_CLOSE_TRACK, 0x00,
 1258                             0x02, 0, 0, 0/*track*/, 0, 0, 0, 0, 0, 0);
 1259 }
 1260 
 1261 static int
 1262 acd_open_track(struct acd *cdp, struct wormio_prepare_track *ptp)
 1263 {
 1264     struct write_param param;
 1265     struct atapires result;
 1266 
 1267     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_MODE_SENSE,
 1268                                 0, 0x05, 0, 0, 0, 0, 
 1269                                 sizeof(param)>>8, sizeof(param),
 1270                                 0, 0, 0, 0, 0, 0, 0,
 1271                                 (char *)&param, sizeof(param));
 1272 
 1273     if (cdp->flags & F_DEBUG)
 1274         atapi_dump(cdp->ata->ctrlr, cdp->lun, "0x05", &param, sizeof(param));
 1275 
 1276     if (result.code == RES_UNDERRUN)
 1277         result.code = 0;
 1278 
 1279     if (result.code) {
 1280         atapi_error(cdp->ata, cdp->unit, result);
 1281         return EIO;
 1282     }
 1283     param.page_code = 0x05;
 1284     param.page_length = 0x32;
 1285     param.test_write = cdp->dummy ? 1 : 0;
 1286     param.write_type = CDR_WTYPE_TRACK;
 1287 
 1288     switch (ptp->audio) {
 1289 /*    switch (data_type) { */
 1290 
 1291     case 0:
 1292 /*    case CDR_DATA: */
 1293         cdp->block_size = 2048;
 1294         param.track_mode = CDR_TMODE_DATA;
 1295         param.data_block_type = CDR_DB_ROM_MODE1;
 1296         param.session_format = CDR_SESS_CDROM;
 1297         break;
 1298 
 1299     default:
 1300 /*    case CDR_AUDIO: */
 1301         cdp->block_size = 2352;
 1302         if (ptp->preemp)
 1303             param.track_mode = CDR_TMODE_AUDIO;
 1304         else
 1305             param.track_mode = 0;
 1306         param.data_block_type = CDR_DB_RAW;
 1307         param.session_format = CDR_SESS_CDROM;
 1308         break;
 1309 
 1310 /*
 1311     case CDR_MODE2:
 1312         param.track_mode = CDR_TMODE_DATA;
 1313         param.data_block_type = CDR_DB_ROM_MODE2;
 1314         param.session_format = CDR_SESS_CDROM;
 1315         break;
 1316 
 1317     case CDR_XA1:
 1318         param.track_mode = CDR_TMODE_DATA;
 1319         param.data_block_type = CDR_DB_XA_MODE1;
 1320         param.session_format = CDR_SESS_CDROM_XA;
 1321         break;
 1322 
 1323     case CDR_XA2:
 1324         param.track_mode = CDR_TMODE_DATA;
 1325         param.data_block_type = CDR_DB_XA_MODE2_F1;
 1326         param.session_format = CDR_SESS_CDROM_XA;
 1327         break;
 1328 
 1329     case CDR_CDI:
 1330         param.track_mode = CDR_TMODE_DATA;
 1331         param.data_block_type = CDR_DB_XA_MODE2_F1;
 1332         param.session_format = CDR_SESS_CDI;
 1333         break;
 1334 */
 1335     }
 1336 
 1337     param.multi_session = CDR_MSES_NONE;
 1338     param.fp = 0;
 1339     param.packet_size = 0;
 1340 
 1341     if (cdp->flags & F_DEBUG)
 1342         atapi_dump(cdp->ata->ctrlr, cdp->lun, "0x05", &param, sizeof(param));
 1343 
 1344     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_MODE_SELECT,
 1345                                 0x10, 0, 0, 0, 0, 0, 
 1346                                 sizeof(param)>>8, sizeof(param),
 1347                                 0, 0, 0, 0, 0, 0, 0,
 1348                                 (char *)&param, -sizeof(param));
 1349 
 1350     if (result.code == RES_UNDERRUN)
 1351         result.code = 0;
 1352 
 1353     if (result.code) {
 1354         atapi_error(cdp->ata, cdp->unit, result);
 1355         return EIO;
 1356     }
 1357     return 0;
 1358 }
 1359 
 1360 static int
 1361 acd_close_track(struct acd *cdp)
 1362 {
 1363     return acd_request_wait(cdp, ATAPI_SYNCHRONIZE_CACHE, 0,
 1364                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 1365 }
 1366 
 1367 static int
 1368 acd_read_track_info(struct acd *cdp, int lba, struct acd_track_info *info)
 1369 {
 1370     int error;
 1371 
 1372     error = acd_request_wait(cdp, ATAPI_READ_TRACK_INFO, 0x01,
 1373                              lba>>24, (lba>>16)&0xff,
 1374                              (lba>>8)&0xff, lba&0xff,
 1375                              0, 
 1376                              sizeof(*info)>>8, sizeof(*info), 0,
 1377                              (char *)info, sizeof(*info));
 1378     if (error)
 1379         return error;
 1380     info->track_start_addr = ntohl(info->track_start_addr);
 1381     info->next_writeable_addr = ntohl(info->next_writeable_addr);
 1382     info->free_blocks = ntohl(info->free_blocks);
 1383     info->fixed_packet_size = ntohl(info->fixed_packet_size);
 1384     info->track_length = ntohl(info->track_length);
 1385     return 0;
 1386 }
 1387 
 1388 static int
 1389 acd_blank_disk(struct acd *cdp)
 1390 {
 1391     int error;
 1392 
 1393     error = acd_request_wait(cdp, 0xa1, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 1394     cdp->flags |= F_MEDIA_CHANGED;
 1395     cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED);
 1396     return error;
 1397 }
 1398 
 1399 static void
 1400 atapi_error(struct atapi *ata, int unit, struct atapires result)
 1401 {
 1402     if (result.code != RES_ERR) {
 1403         printf("atapi%d:%d: ERROR %d, status=%b, error=%b\n", 
 1404                ata->ctrlr, unit, result.code, result.status, 
 1405                ARS_BITS, result.error, AER_BITS);
 1406         return;
 1407     }
 1408     switch (result.error & AER_SKEY) {
 1409     case AER_SK_NOT_READY:
 1410         if (ata->debug)
 1411             printf("atapi%d:%d: not ready\n", ata->ctrlr, unit);
 1412         break;
 1413 
 1414     case AER_SK_BLANK_CHECK:
 1415         if (ata->debug)
 1416             printf("atapi%d:%d: blank check\n", ata->ctrlr, unit);
 1417         break;
 1418 
 1419     case AER_SK_MEDIUM_ERROR:
 1420         if (ata->debug)
 1421             printf("atapi%d:%d: medium error\n", ata->ctrlr, unit);
 1422         break;
 1423 
 1424     case AER_SK_HARDWARE_ERROR:
 1425         if (ata->debug)
 1426             printf("atapi%d:%d: hardware error\n", ata->ctrlr, unit);
 1427         break;
 1428 
 1429     case AER_SK_ILLEGAL_REQUEST:
 1430         if (ata->debug)
 1431             printf("atapi%d:%d: illegal request\n", ata->ctrlr, unit);
 1432         break;
 1433 
 1434     case AER_SK_UNIT_ATTENTION:
 1435         if (ata->debug)
 1436             printf("atapi%d:%d: unit attention\n", ata->ctrlr, unit);
 1437         break;
 1438 
 1439     case AER_SK_DATA_PROTECT:
 1440         if (ata->debug)
 1441             printf("atapi%d:%d: reading protected data\n", ata->ctrlr, unit);
 1442         break;
 1443 
 1444     case AER_SK_ABORTED_COMMAND:
 1445         if (ata->debug)
 1446             printf("atapi%d:%d: command aborted\n", ata->ctrlr, unit);
 1447         break;
 1448 
 1449     case AER_SK_MISCOMPARE:
 1450         if (ata->debug)
 1451             printf("atapi%d:%d: data don't match medium\n", ata->ctrlr, unit);
 1452         break;
 1453 
 1454     default:
 1455         if (ata->debug)
 1456             printf("atapi%d:%d: unknown error, status=%b, error=%b\n", 
 1457                    ata->ctrlr, unit, result.status, ARS_BITS, 
 1458                    result.error, AER_BITS);
 1459     }
 1460 }
 1461 
 1462 static void 
 1463 atapi_dump(int ctrlr, int lun, char *label, void *data, int len)
 1464 {
 1465         u_char *p = data;
 1466 
 1467         printf ("atapi%d%d: %s %x", ctrlr, lun, label, *p++);
 1468         while (--len > 0) printf ("-%x", *p++);
 1469         printf ("\n");
 1470 }
 1471 
 1472 #ifdef ACD_MODULE
 1473 #include <sys/exec.h>
 1474 #include <sys/sysent.h>
 1475 #include <sys/lkm.h>
 1476 
 1477 MOD_DEV(acd, LM_DT_BLOCK, BDEV_MAJOR, &acd_bdevsw);
 1478 MOD_DEV(racd, LM_DT_CHAR, CDEV_MAJOR, &acd_cdevsw);
 1479 
 1480 int 
 1481 acd_load(struct lkm_table *lkmtp, int cmd)
 1482 {
 1483     struct atapi *ata;
 1484     int n, u;
 1485 
 1486     if (!atapi_start)
 1487         return EPROTONOSUPPORT;
 1488     n = 0;
 1489     for (ata = atapi_tab; ata < atapi_tab + 2; ++ata)
 1490         if (ata->port)
 1491             for (u = 0; u < 2; ++u)
 1492                 if (ata->params[u] && !ata->attached[u] &&
 1493                     acdattach(ata, u, ata->params[u],
 1494                     ata->debug) >= 0) {
 1495                     ata->attached[u] = 1;
 1496                     ++n;
 1497                 }
 1498     if (!n)
 1499         return ENXIO;
 1500     return 0;
 1501 }
 1502 
 1503 int 
 1504 acd_unload(struct lkm_table *lkmtp, int cmd)
 1505 {
 1506     struct acd **cdpp;
 1507 
 1508     for (cdpp = acdtab; cdpp < acdtab + acdnlun; ++cdpp)
 1509         if (((*cdpp)->flags & F_BOPEN) || (*cdpp)->refcnt)
 1510             return EBUSY;
 1511     for (cdpp = acdtab; cdpp < acdtab + acdnlun; ++t) {
 1512         (*cdpp)->ata->attached[(*cdpp)->unit] = 0;
 1513         free(*cdpp, M_TEMP);
 1514     }
 1515     acdnlun = 0;
 1516     bzero(acdtab, sizeof(acdtab));
 1517     return 0;
 1518 }
 1519 
 1520 int 
 1521 acd_mod(struct lkm_table *lkmtp, int cmd, int ver)
 1522 {
 1523     int err = 0;
 1524 
 1525     if (ver != LKM_VERSION)
 1526         return EINVAL;
 1527 
 1528     if (cmd == LKM_E_LOAD)
 1529         err = acd_load(lkmtp, cmd);
 1530     else if (cmd == LKM_E_UNLOAD)
 1531         err = acd_unload(lkmtp, cmd);
 1532     if (err)
 1533         return err;
 1534 
 1535     lkmtp->private.lkm_dev = &MOD_PRIVATE(racd);
 1536     err = lkmdispatch(lkmtp, cmd);
 1537     if (err)
 1538         return err;
 1539 
 1540     lkmtp->private.lkm_dev = &MOD_PRIVATE(acd);
 1541     return lkmdispatch(lkmtp, cmd);
 1542 }
 1543 
 1544 #endif /* ACD_MODULE */
 1545 
 1546 static acd_devsw_installed = 0;
 1547 
 1548 static void 
 1549 acd_drvinit(void *unused)
 1550 {
 1551     if (!acd_devsw_installed) {
 1552         cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &acd_cdevsw);
 1553         acd_devsw_installed = 1;
 1554     }
 1555 }
 1556 
 1557 SYSINIT(acddev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, acd_drvinit, NULL)
 1558 #endif /* NACD && NWDC && ATAPI */

Cache object: b4758df9d3600de6309e490ae33ccb22


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