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

Cache object: 6f7b1bfe011c02e45575c20b187c4d45


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