File:  [DragonFly] / src / sys / dev / disk / ata / atapi-cd.c
Revision 1.16: download - view: text, annotated - select for diffs
Thu May 13 23:49:14 2004 UTC (10 years, 6 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*-
    2:  * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
    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/dev/ata/atapi-cd.c,v 1.48.2.20 2002/11/25 05:30:31 njl Exp $
   29:  * $DragonFly: src/sys/dev/disk/ata/atapi-cd.c,v 1.16 2004/05/13 23:49:14 dillon Exp $
   30:  */
   31: 
   32: #include "opt_ata.h"
   33: #include <sys/param.h>
   34: #include <sys/systm.h>
   35: #include <sys/ata.h>
   36: #include <sys/kernel.h>
   37: #include <sys/malloc.h>
   38: #include <sys/proc.h>
   39: #include <sys/buf.h>
   40: #include <sys/bus.h>
   41: #include <sys/disklabel.h>
   42: #include <sys/devicestat.h>
   43: #include <sys/cdio.h>
   44: #include <sys/cdrio.h>
   45: #include <sys/dvdio.h>
   46: #include <sys/fcntl.h>
   47: #include <sys/conf.h>
   48: #include <sys/ctype.h>
   49: #include <machine/bus.h>
   50: #include <sys/buf2.h>
   51: #include "ata-all.h"
   52: #include "atapi-all.h"
   53: #include "atapi-cd.h"
   54: 
   55: /* device structures */
   56: static d_open_t		acdopen;
   57: static d_close_t	acdclose;
   58: static d_ioctl_t	acdioctl;
   59: static d_strategy_t	acdstrategy;
   60: 
   61: static struct cdevsw acd_cdevsw = {
   62: 	/* name */	"acd",
   63: 	/* maj */	117,
   64: 	/* flags */	D_DISK | D_TRACKCLOSE,
   65: 	/* port */      NULL,
   66: 	/* clone */	NULL,
   67: 
   68: 	/* open */	acdopen,
   69: 	/* close */	acdclose,
   70: 	/* read */	physread,
   71: 	/* write */	physwrite,
   72: 	/* ioctl */	acdioctl,
   73: 	/* poll */	nopoll,
   74: 	/* mmap */	nommap,
   75: 	/* strategy */	acdstrategy,
   76: 	/* dump */	nodump,
   77: 	/* psize */	nopsize
   78: };
   79: 
   80: /* prototypes */
   81: static struct acd_softc *acd_init_lun(struct ata_device *);
   82: static void acd_make_dev(struct acd_softc *);
   83: static void acd_set_ioparm(struct acd_softc *);
   84: static void acd_describe(struct acd_softc *);
   85: static void lba2msf(u_int32_t, u_int8_t *, u_int8_t *, u_int8_t *);
   86: static u_int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t);
   87: static int acd_done(struct atapi_request *);
   88: static void acd_read_toc(struct acd_softc *);
   89: static int acd_play(struct acd_softc *, int, int);
   90: static int acd_setchan(struct acd_softc *, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
   91: static void acd_select_slot(struct acd_softc *);
   92: static int acd_init_writer(struct acd_softc *, int);
   93: static int acd_fixate(struct acd_softc *, int);
   94: static int acd_init_track(struct acd_softc *, struct cdr_track *);
   95: static int acd_flush(struct acd_softc *);
   96: static int acd_read_track_info(struct acd_softc *, int32_t, struct acd_track_info *);
   97: static int acd_get_progress(struct acd_softc *, int *);
   98: static int acd_send_cue(struct acd_softc *, struct cdr_cuesheet *);
   99: static int acd_report_key(struct acd_softc *, struct dvd_authinfo *);
  100: static int acd_send_key(struct acd_softc *, struct dvd_authinfo *);
  101: static int acd_read_structure(struct acd_softc *, struct dvd_struct *);
  102: static int acd_eject(struct acd_softc *, int);
  103: static int acd_blank(struct acd_softc *, int);
  104: static int acd_prevent_allow(struct acd_softc *, int);
  105: static int acd_start_stop(struct acd_softc *, int);
  106: static int acd_pause_resume(struct acd_softc *, int);
  107: static int acd_mode_sense(struct acd_softc *, int, caddr_t, int);
  108: static int acd_mode_select(struct acd_softc *, caddr_t, int);
  109: static int acd_set_speed(struct acd_softc *, int, int);
  110: static void acd_get_cap(struct acd_softc *);
  111: 
  112: /* internal vars */
  113: static u_int32_t acd_lun_map = 0;
  114: static MALLOC_DEFINE(M_ACD, "ACD driver", "ATAPI CD driver buffers");
  115: 
  116: int
  117: acdattach(struct ata_device *atadev)
  118: {
  119:     struct acd_softc *cdp;
  120:     struct changer *chp;
  121: 
  122:     if ((cdp = acd_init_lun(atadev)) == NULL) {
  123: 	ata_prtdev(atadev, "acd: out of memory\n");
  124: 	return 0;
  125:     }
  126: 
  127:     ata_set_name(atadev, "acd", cdp->lun);
  128:     acd_get_cap(cdp);
  129: 
  130:     /* if this is a changer device, allocate the neeeded lun's */
  131:     if (cdp->cap.mech == MST_MECH_CHANGER) {
  132: 	int8_t ccb[16] = { ATAPI_MECH_STATUS, 0, 0, 0, 0, 0, 0, 0, 
  133: 			   sizeof(struct changer)>>8, sizeof(struct changer),
  134: 			   0, 0, 0, 0, 0, 0 };
  135: 
  136: 	chp = malloc(sizeof(struct changer), M_ACD, M_WAITOK | M_ZERO);
  137: 	if (!atapi_queue_cmd(cdp->device, ccb, (caddr_t)chp, 
  138: 			     sizeof(struct changer),
  139: 			     ATPR_F_READ, 60, NULL, NULL)) {
  140: 	    struct acd_softc *tmpcdp = cdp;
  141: 	    struct acd_softc **cdparr;
  142: 	    char *name;
  143: 	    int count;
  144: 
  145: 	    chp->table_length = htons(chp->table_length);
  146: 	    cdparr = malloc(sizeof(struct acd_softc) * chp->slots,
  147: 				  M_ACD, M_WAITOK);
  148: 	    for (count = 0; count < chp->slots; count++) {
  149: 		if (count > 0) {
  150: 		    tmpcdp = acd_init_lun(atadev);
  151: 		    if (!tmpcdp) {
  152: 			ata_prtdev(atadev, "out of memory\n");
  153: 			break;
  154: 		    }
  155: 		}
  156: 		cdparr[count] = tmpcdp;
  157: 		tmpcdp->driver = cdparr;
  158: 		tmpcdp->slot = count;
  159: 		tmpcdp->changer_info = chp;
  160: 		acd_make_dev(tmpcdp);
  161: 		devstat_add_entry(tmpcdp->stats, "acd", tmpcdp->lun, DEV_BSIZE,
  162: 				  DEVSTAT_NO_ORDERED_TAGS,
  163: 				  DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE,
  164: 				  DEVSTAT_PRIORITY_CD);
  165: 	    }
  166: 	    name = malloc(strlen(atadev->name) + 2, M_ACD, M_WAITOK);
  167: 	    strcpy(name, atadev->name);
  168: 	    strcat(name, "-");
  169: 	    ata_free_name(atadev);
  170: 	    ata_set_name(atadev, name, cdp->lun + cdp->changer_info->slots - 1);
  171: 	    free(name, M_ACD);
  172: 	}
  173:     }
  174:     else {
  175: 	acd_make_dev(cdp);
  176: 	devstat_add_entry(cdp->stats, "acd", cdp->lun, DEV_BSIZE,
  177: 			  DEVSTAT_NO_ORDERED_TAGS,
  178: 			  DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE,
  179: 			  DEVSTAT_PRIORITY_CD);
  180:     }
  181:     acd_describe(cdp);
  182:     atadev->driver = cdp;
  183:     return 1;
  184: }
  185: 
  186: void
  187: acddetach(struct ata_device *atadev)
  188: {   
  189:     struct acd_softc *cdp = atadev->driver;
  190:     struct acd_devlist *entry;
  191:     struct buf *bp;
  192:     int subdev;
  193:     
  194:     if (cdp->changer_info) {
  195: 	for (subdev = 0; subdev < cdp->changer_info->slots; subdev++) {
  196: 	    if (cdp->driver[subdev] == cdp)
  197: 		continue;
  198: 	    while ((bp = bufq_first(&cdp->driver[subdev]->queue))) {
  199: 		bufq_remove(&cdp->driver[subdev]->queue, bp);
  200: 		bp->b_flags |= B_ERROR;
  201: 		bp->b_error = ENXIO;
  202: 		biodone(bp);
  203: 	    }
  204: 	    destroy_dev(cdp->driver[subdev]->dev);
  205: 	    while ((entry = TAILQ_FIRST(&cdp->driver[subdev]->dev_list))) {
  206: 		destroy_dev(entry->dev);
  207: 		TAILQ_REMOVE(&cdp->driver[subdev]->dev_list, entry, chain);
  208: 		free(entry, M_ACD);
  209: 	    }
  210: 	    devstat_remove_entry(cdp->driver[subdev]->stats);
  211: 	    free(cdp->driver[subdev]->stats, M_ACD);
  212: 	    ata_free_lun(&acd_lun_map, cdp->driver[subdev]->lun);
  213: 	    free(cdp->driver[subdev], M_ACD);
  214: 	}
  215: 	free(cdp->driver, M_ACD);
  216: 	free(cdp->changer_info, M_ACD);
  217:     }
  218:     while ((bp = bufq_first(&cdp->queue))) {
  219: 	bp->b_flags |= B_ERROR;
  220: 	bp->b_error = ENXIO;
  221: 	biodone(bp);
  222:     }
  223:     while ((entry = TAILQ_FIRST(&cdp->dev_list))) {
  224: 	destroy_dev(entry->dev);
  225: 	TAILQ_REMOVE(&cdp->dev_list, entry, chain);
  226: 	free(entry, M_ACD);
  227:     }
  228:     destroy_dev(cdp->dev);
  229:     devstat_remove_entry(cdp->stats);
  230:     free(cdp->stats, M_ACD);
  231:     ata_free_name(atadev);
  232:     ata_free_lun(&acd_lun_map, cdp->lun);
  233:     free(cdp, M_ACD);
  234:     atadev->driver = NULL;
  235: }
  236: 
  237: static struct acd_softc *
  238: acd_init_lun(struct ata_device *atadev)
  239: {
  240:     struct acd_softc *cdp;
  241: 
  242:     cdp = malloc(sizeof(struct acd_softc), M_ACD, M_WAITOK | M_ZERO);
  243:     TAILQ_INIT(&cdp->dev_list);
  244:     bufq_init(&cdp->queue);
  245:     cdp->device = atadev;
  246:     cdp->lun = ata_get_lun(&acd_lun_map);
  247:     cdp->block_size = 2048;
  248:     cdp->slot = -1;
  249:     cdp->changer_info = NULL;
  250:     cdp->stats = malloc(sizeof(struct devstat), M_ACD, M_WAITOK | M_ZERO);
  251:     return cdp;
  252: }
  253: 
  254: static void
  255: acd_make_dev(struct acd_softc *cdp)
  256: {
  257:     dev_t dev;
  258: 
  259:     dev = make_dev(&acd_cdevsw, dkmakeminor(cdp->lun, 0, 0),
  260: 		   UID_ROOT, GID_OPERATOR, 0644, "acd%d", cdp->lun);
  261:     dev->si_drv1 = cdp;
  262:     cdp->dev = dev;
  263:     cdp->device->flags |= ATA_D_MEDIA_CHANGED;
  264:     acd_set_ioparm(cdp);
  265: }
  266: 
  267: static void
  268: acd_set_ioparm(struct acd_softc *cdp)
  269: {
  270:      cdp->dev->si_iosize_max = ((256*DEV_BSIZE)/cdp->block_size)*cdp->block_size;
  271:      cdp->dev->si_bsize_phys = cdp->block_size;
  272: }
  273: 
  274: static void 
  275: acd_describe(struct acd_softc *cdp)
  276: {
  277:     int comma = 0;
  278:     char *mechanism;
  279: 
  280:     if (bootverbose) {
  281: 	ata_prtdev(cdp->device, "<%.40s/%.8s> %s drive at ata%d as %s\n",
  282: 		   cdp->device->param->model, cdp->device->param->revision,
  283: 		   (cdp->cap.write_dvdr) ? "DVD-R" : 
  284: 		    (cdp->cap.write_dvdram) ? "DVD-RAM" : 
  285: 		     (cdp->cap.write_cdrw) ? "CD-RW" :
  286: 		      (cdp->cap.write_cdr) ? "CD-R" : 
  287: 		       (cdp->cap.read_dvdrom) ? "DVD-ROM" : "CDROM",
  288: 		   device_get_unit(cdp->device->channel->dev),
  289: 		   (cdp->device->unit == ATA_MASTER) ? "master" : "slave");
  290: 
  291: 	ata_prtdev(cdp->device, "%s", "");
  292: 	if (cdp->cap.cur_read_speed) {
  293: 	    printf("read %dKB/s", cdp->cap.cur_read_speed * 1000 / 1024);
  294: 	    if (cdp->cap.max_read_speed) 
  295: 		printf(" (%dKB/s)", cdp->cap.max_read_speed * 1000 / 1024);
  296: 	    if ((cdp->cap.cur_write_speed) &&
  297: 		(cdp->cap.write_cdr || cdp->cap.write_cdrw || 
  298: 		 cdp->cap.write_dvdr || cdp->cap.write_dvdram)) {
  299: 		printf(" write %dKB/s", cdp->cap.cur_write_speed * 1000 / 1024);
  300: 		if (cdp->cap.max_write_speed)
  301: 		    printf(" (%dKB/s)", cdp->cap.max_write_speed * 1000 / 1024);
  302: 	    }
  303: 	    comma = 1;
  304: 	}
  305: 	if (cdp->cap.buf_size) {
  306: 	    printf("%s %dKB buffer", comma ? "," : "", cdp->cap.buf_size);
  307: 	    comma = 1;
  308: 	}
  309: 	printf("%s %s\n", comma ? "," : "", ata_mode2str(cdp->device->mode));
  310: 
  311: 	ata_prtdev(cdp->device, "Reads:");
  312: 	comma = 0;
  313: 	if (cdp->cap.read_cdr) {
  314: 	    printf(" CD-R"); comma = 1;
  315: 	}
  316: 	if (cdp->cap.read_cdrw) {
  317: 	    printf("%s CD-RW", comma ? "," : ""); comma = 1;
  318: 	}
  319: 	if (cdp->cap.cd_da) {
  320: 	    if (cdp->cap.cd_da_stream)
  321: 		printf("%s CD-DA stream", comma ? "," : "");
  322: 	    else
  323: 		printf("%s CD-DA", comma ? "," : "");
  324: 	    comma = 1;
  325: 	}
  326: 	if (cdp->cap.read_dvdrom) {
  327: 	    printf("%s DVD-ROM", comma ? "," : ""); comma = 1;
  328: 	}
  329: 	if (cdp->cap.read_dvdr) {
  330: 	    printf("%s DVD-R", comma ? "," : ""); comma = 1;
  331: 	}
  332: 	if (cdp->cap.read_dvdram) {
  333: 	    printf("%s DVD-RAM", comma ? "," : ""); comma = 1;
  334: 	}
  335: 	if (cdp->cap.read_packet)
  336: 	    printf("%s packet", comma ? "," : "");
  337: 
  338: 	printf("\n");
  339: 	ata_prtdev(cdp->device, "Writes:");
  340: 	if (cdp->cap.write_cdr || cdp->cap.write_cdrw || 
  341: 	    cdp->cap.write_dvdr || cdp->cap.write_dvdram) {
  342: 	    comma = 0;
  343: 	    if (cdp->cap.write_cdr) {
  344: 		printf(" CD-R" ); comma = 1;
  345: 	    }
  346: 	    if (cdp->cap.write_cdrw) {
  347: 		printf("%s CD-RW", comma ? "," : ""); comma = 1;
  348: 	    }
  349: 	    if (cdp->cap.write_dvdr) {
  350: 		printf("%s DVD-R", comma ? "," : ""); comma = 1;
  351: 	    }
  352: 	    if (cdp->cap.write_dvdram) {
  353: 		printf("%s DVD-RAM", comma ? "," : ""); comma = 1; 
  354: 	    }
  355: 	    if (cdp->cap.test_write) {
  356: 		printf("%s test write", comma ? "," : ""); comma = 1;
  357: 	    }
  358: 	    if (cdp->cap.burnproof)
  359: 		printf("%s burnproof", comma ? "," : "");
  360: 	}
  361: 	printf("\n");
  362: 	if (cdp->cap.audio_play) {
  363: 	    ata_prtdev(cdp->device, "Audio: ");
  364: 	    if (cdp->cap.audio_play)
  365: 		printf("play");
  366: 	    if (cdp->cap.max_vol_levels)
  367: 		printf(", %d volume levels", cdp->cap.max_vol_levels);
  368: 	    printf("\n");
  369: 	}
  370: 	ata_prtdev(cdp->device, "Mechanism: ");
  371: 	switch (cdp->cap.mech) {
  372: 	case MST_MECH_CADDY:
  373: 	    mechanism = "caddy"; break;
  374: 	case MST_MECH_TRAY:
  375: 	    mechanism = "tray"; break;
  376: 	case MST_MECH_POPUP:
  377: 	    mechanism = "popup"; break;
  378: 	case MST_MECH_CHANGER:
  379: 	    mechanism = "changer"; break;
  380: 	case MST_MECH_CARTRIDGE:
  381: 	    mechanism = "cartridge"; break;
  382: 	default:
  383: 	    mechanism = 0; break;
  384: 	}
  385: 	if (mechanism)
  386: 	    printf("%s%s", cdp->cap.eject ? "ejectable " : "", mechanism);
  387: 	else if (cdp->cap.eject)
  388: 	    printf("ejectable");
  389: 
  390: 	if (cdp->cap.lock)
  391: 	    printf(cdp->cap.locked ? ", locked" : ", unlocked");
  392: 	if (cdp->cap.prevent)
  393: 	    printf(", lock protected");
  394: 	printf("\n");
  395: 
  396: 	if (cdp->cap.mech != MST_MECH_CHANGER) {
  397: 	    ata_prtdev(cdp->device, "Medium: ");
  398: 	    switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
  399: 	    case MST_CDROM:
  400: 		printf("CD-ROM "); break;
  401: 	    case MST_CDR:
  402: 		printf("CD-R "); break;
  403: 	    case MST_CDRW:
  404: 		printf("CD-RW "); break;
  405: 	    case MST_DOOR_OPEN:
  406: 		printf("door open"); break;
  407: 	    case MST_NO_DISC:
  408: 		printf("no/blank disc"); break;
  409: 	    case MST_FMT_ERROR:
  410: 		printf("medium format error"); break;
  411: 	    }
  412: 	    if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH)<MST_TYPE_MASK_HIGH){
  413: 		switch (cdp->cap.medium_type & MST_TYPE_MASK_LOW) {
  414: 		case MST_DATA_120:
  415: 		    printf("120mm data disc"); break;
  416: 		case MST_AUDIO_120:
  417: 		    printf("120mm audio disc"); break;
  418: 		case MST_COMB_120:
  419: 		    printf("120mm data/audio disc"); break;
  420: 		case MST_PHOTO_120:
  421: 		    printf("120mm photo disc"); break;
  422: 		case MST_DATA_80:
  423: 		    printf("80mm data disc"); break;
  424: 		case MST_AUDIO_80:
  425: 		    printf("80mm audio disc"); break;
  426: 		case MST_COMB_80:
  427: 		    printf("80mm data/audio disc"); break;
  428: 		case MST_PHOTO_80:
  429: 		    printf("80mm photo disc"); break;
  430: 		case MST_FMT_NONE:
  431: 		    switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) {
  432: 		    case MST_CDROM:
  433: 			printf("unknown"); break;
  434: 		    case MST_CDR:
  435: 		    case MST_CDRW:
  436: 			printf("blank"); break;
  437: 		    }
  438: 		    break;
  439: 		default:
  440: 		    printf("unknown (0x%x)", cdp->cap.medium_type); break;
  441: 		}
  442: 	    }
  443: 	    printf("\n");
  444: 	}
  445:     }
  446:     else {
  447: 	ata_prtdev(cdp->device, "%s ",
  448: 		   (cdp->cap.write_dvdr) ? "DVD-R" : 
  449: 		    (cdp->cap.write_dvdram) ? "DVD-RAM" : 
  450: 		     (cdp->cap.write_cdrw) ? "CD-RW" :
  451: 		      (cdp->cap.write_cdr) ? "CD-R" : 
  452: 		       (cdp->cap.read_dvdrom) ? "DVD-ROM" : "CDROM");
  453: 
  454: 	if (cdp->changer_info)
  455: 	    printf("with %d CD changer ", cdp->changer_info->slots);
  456: 
  457: 	printf("<%.40s> at ata%d-%s %s\n", cdp->device->param->model,
  458: 	       device_get_unit(cdp->device->channel->dev),
  459: 	       (cdp->device->unit == ATA_MASTER) ? "master" : "slave",
  460: 	       ata_mode2str(cdp->device->mode) );
  461:     }
  462: }
  463: 
  464: static __inline void 
  465: lba2msf(u_int32_t lba, u_int8_t *m, u_int8_t *s, u_int8_t *f)
  466: {
  467:     lba += 150;
  468:     lba &= 0xffffff;
  469:     *m = lba / (60 * 75);
  470:     lba %= (60 * 75);
  471:     *s = lba / 75;
  472:     *f = lba % 75;
  473: }
  474: 
  475: static __inline u_int32_t 
  476: msf2lba(u_int8_t m, u_int8_t s, u_int8_t f)
  477: {
  478:     return (m * 60 + s) * 75 + f - 150;
  479: }
  480: 
  481: static int
  482: acdopen(dev_t dev, int flags, int fmt, struct thread *td)
  483: {
  484:     struct acd_softc *cdp = dev->si_drv1;
  485:     int timeout = 60;
  486:     
  487:     if (!cdp)
  488: 	return ENXIO;
  489: 
  490:     if (flags & FWRITE) {
  491: 	if (count_dev(dev) > 1)
  492: 	    return EBUSY;
  493:     }
  494: 
  495:     /* wait if drive is not finished loading the medium */
  496:     while (timeout--) {
  497: 	struct atapi_reqsense *sense = cdp->device->result;
  498: 
  499: 	if (!atapi_test_ready(cdp->device))
  500: 	    break;
  501: 	if (sense->sense_key == 2  && sense->asc == 4 && sense->ascq == 1)
  502: 	    tsleep(&timeout, 0, "acdld", hz / 2);
  503: 	else
  504: 	    break;
  505:     }
  506: 
  507:     if (count_dev(dev) == 1) {
  508: 	if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
  509: 	    acd_select_slot(cdp);
  510: 	    tsleep(&cdp->changer_info, 0, "acdopn", 0);
  511: 	}
  512: 	acd_prevent_allow(cdp, 1);
  513: 	cdp->flags |= F_LOCKED;
  514: 	acd_read_toc(cdp);
  515:     }
  516:     return 0;
  517: }
  518: 
  519: static int 
  520: acdclose(dev_t dev, int flags, int fmt, struct thread *td)
  521: {
  522:     struct acd_softc *cdp = dev->si_drv1;
  523:     
  524:     if (!cdp)
  525: 	return ENXIO;
  526: 
  527:     if (count_dev(dev) == 1) {
  528: 	if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
  529: 	    acd_select_slot(cdp);
  530: 	    tsleep(&cdp->changer_info, 0, "acdclo", 0);
  531: 	}
  532: 	acd_prevent_allow(cdp, 0);
  533: 	cdp->flags &= ~F_LOCKED;
  534:     }
  535:     return 0;
  536: }
  537: 
  538: static int 
  539: acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
  540: {
  541:     struct acd_softc *cdp = dev->si_drv1;
  542:     int error = 0;
  543: 
  544:     if (!cdp)
  545: 	return ENXIO;
  546: 
  547:     if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
  548: 	acd_select_slot(cdp);
  549: 	tsleep(&cdp->changer_info, 0, "acdctl", 0);
  550:     }
  551:     if (cdp->device->flags & ATA_D_MEDIA_CHANGED)
  552: 	switch (cmd) {
  553: 	case CDIOCRESET:
  554: 	    atapi_test_ready(cdp->device);
  555: 	    break;
  556: 	   
  557: 	default:
  558: 	    acd_read_toc(cdp);
  559: 	    acd_prevent_allow(cdp, 1);
  560: 	    cdp->flags |= F_LOCKED;
  561: 	    break;
  562: 	}
  563:     switch (cmd) {
  564: 
  565:     case CDIOCRESUME:
  566: 	error = acd_pause_resume(cdp, 1);
  567: 	break;
  568: 
  569:     case CDIOCPAUSE:
  570: 	error = acd_pause_resume(cdp, 0);
  571: 	break;
  572: 
  573:     case CDIOCSTART:
  574: 	error = acd_start_stop(cdp, 1);
  575: 	break;
  576: 
  577:     case CDIOCSTOP:
  578: 	error = acd_start_stop(cdp, 0);
  579: 	break;
  580: 
  581:     case CDIOCALLOW:
  582: 	error = acd_prevent_allow(cdp, 0);
  583: 	cdp->flags &= ~F_LOCKED;
  584: 	break;
  585: 
  586:     case CDIOCPREVENT:
  587: 	error = acd_prevent_allow(cdp, 1);
  588: 	cdp->flags |= F_LOCKED;
  589: 	break;
  590: 
  591:     case CDIOCRESET:
  592: 	error = suser(td);	/* note: if no proc EPERM will be returned */
  593: 	if (error)
  594: 	    break;
  595: 	error = atapi_test_ready(cdp->device);
  596: 	break;
  597: 
  598:     case CDIOCEJECT:
  599: 	if (count_dev(dev) > 1) {
  600: 	    error = EBUSY;
  601: 	    break;
  602: 	}
  603: 	error = acd_eject(cdp, 0);
  604: 	break;
  605: 
  606:     case CDIOCCLOSE:
  607: 	if (count_dev(dev) > 1)
  608: 	    break;
  609: 	error = acd_eject(cdp, 1);
  610: 	break;
  611: 
  612:     case CDIOREADTOCHEADER:
  613: 	if (!cdp->toc.hdr.ending_track) {
  614: 	    error = EIO;
  615: 	    break;
  616: 	}
  617: 	bcopy(&cdp->toc.hdr, addr, sizeof(cdp->toc.hdr));
  618: 	break;
  619: 
  620:     case CDIOREADTOCENTRYS:
  621: 	{
  622: 	    struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)addr;
  623: 	    struct toc *toc = &cdp->toc;
  624: 	    int starting_track = te->starting_track;
  625: 	    int len;
  626: 
  627: 	    if (!toc->hdr.ending_track) {
  628: 		error = EIO;
  629: 		break;
  630: 	    }
  631: 
  632: 	    if (te->data_len < sizeof(toc->tab[0]) || 
  633: 		(te->data_len % sizeof(toc->tab[0])) != 0 || 
  634: 		(te->address_format != CD_MSF_FORMAT &&
  635: 		te->address_format != CD_LBA_FORMAT)) {
  636: 		error = EINVAL;
  637: 		break;
  638: 	    }
  639: 
  640: 	    if (!starting_track)
  641: 		starting_track = toc->hdr.starting_track;
  642: 	    else if (starting_track == 170) 
  643: 		starting_track = toc->hdr.ending_track + 1;
  644: 	    else if (starting_track < toc->hdr.starting_track ||
  645: 		     starting_track > toc->hdr.ending_track + 1) {
  646: 		error = EINVAL;
  647: 		break;
  648: 	    }
  649: 
  650: 	    len = ((toc->hdr.ending_track + 1 - starting_track) + 1) *
  651: 		  sizeof(toc->tab[0]);
  652: 	    if (te->data_len < len)
  653: 		len = te->data_len;
  654: 	    if (len > sizeof(toc->tab)) {
  655: 		error = EINVAL;
  656: 		break;
  657: 	    }
  658: 
  659: 	    if (te->address_format == CD_MSF_FORMAT) {
  660: 		struct cd_toc_entry *entry;
  661: 
  662: 		toc = malloc(sizeof(struct toc), M_ACD, M_WAITOK | M_ZERO);
  663: 		bcopy(&cdp->toc, toc, sizeof(struct toc));
  664: 		entry = toc->tab + (toc->hdr.ending_track + 1 -
  665: 			toc->hdr.starting_track) + 1;
  666: 		while (--entry >= toc->tab)
  667: 		    lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute,
  668: 			    &entry->addr.msf.second, &entry->addr.msf.frame);
  669: 	    }
  670: 	    error = copyout(toc->tab + starting_track - toc->hdr.starting_track,
  671: 			    te->data, len);
  672: 	    if (te->address_format == CD_MSF_FORMAT)
  673: 		free(toc, M_ACD);
  674: 	    break;
  675: 	}
  676:     case CDIOREADTOCENTRY:
  677: 	{
  678: 	    struct ioc_read_toc_single_entry *te =
  679: 		(struct ioc_read_toc_single_entry *)addr;
  680: 	    struct toc *toc = &cdp->toc;
  681: 	    u_char track = te->track;
  682: 
  683: 	    if (!toc->hdr.ending_track) {
  684: 		error = EIO;
  685: 		break;
  686: 	    }
  687: 
  688: 	    if (te->address_format != CD_MSF_FORMAT && 
  689: 		te->address_format != CD_LBA_FORMAT) {
  690: 		error = EINVAL;
  691: 		break;
  692: 	    }
  693: 
  694: 	    if (!track)
  695: 		track = toc->hdr.starting_track;
  696: 	    else if (track == 170)
  697: 		track = toc->hdr.ending_track + 1;
  698: 	    else if (track < toc->hdr.starting_track ||
  699: 		     track > toc->hdr.ending_track + 1) {
  700: 		error = EINVAL;
  701: 		break;
  702: 	    }
  703: 
  704: 	    if (te->address_format == CD_MSF_FORMAT) {
  705: 		struct cd_toc_entry *entry;
  706: 
  707: 		toc = malloc(sizeof(struct toc), M_ACD, M_WAITOK | M_ZERO);
  708: 		bcopy(&cdp->toc, toc, sizeof(struct toc));
  709: 
  710: 		entry = toc->tab + (track - toc->hdr.starting_track);
  711: 		lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute,
  712: 			&entry->addr.msf.second, &entry->addr.msf.frame);
  713: 	    }
  714: 	    bcopy(toc->tab + track - toc->hdr.starting_track,
  715: 		  &te->entry, sizeof(struct cd_toc_entry));
  716: 	    if (te->address_format == CD_MSF_FORMAT)
  717: 		free(toc, M_ACD);
  718: 	}
  719: 	break;
  720: 
  721:     case CDIOCREADSUBCHANNEL:
  722: 	{
  723: 	    struct ioc_read_subchannel *args =
  724: 		(struct ioc_read_subchannel *)addr;
  725: 	    u_int8_t format;
  726: 	    int8_t ccb[16] = { ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, 0, 0,
  727: 			       sizeof(cdp->subchan)>>8, sizeof(cdp->subchan),
  728: 			       0, 0, 0, 0, 0, 0, 0 };
  729: 
  730: 	    if (args->data_len > sizeof(struct cd_sub_channel_info) ||
  731: 		args->data_len < sizeof(struct cd_sub_channel_header)) {
  732: 		error = EINVAL;
  733: 		break;
  734: 	    }
  735: 
  736: 	    format=args->data_format;
  737: 	    if ((format != CD_CURRENT_POSITION) &&
  738: 		(format != CD_MEDIA_CATALOG) && (format != CD_TRACK_INFO)) {
  739: 		error = EINVAL;
  740: 		break;
  741: 	    }
  742: 
  743: 	    ccb[1] = args->address_format & CD_MSF_FORMAT;
  744: 
  745: 	    if ((error = atapi_queue_cmd(cdp->device,ccb,(caddr_t)&cdp->subchan,
  746: 					 sizeof(cdp->subchan), ATPR_F_READ, 10,
  747: 					 NULL, NULL)))
  748: 		break;
  749: 
  750: 	    if ((format == CD_MEDIA_CATALOG) || (format == CD_TRACK_INFO)) {
  751: 		if (cdp->subchan.header.audio_status == 0x11) {
  752: 		    error = EINVAL;
  753: 		    break;
  754: 		}
  755: 
  756: 		ccb[3] = format;
  757: 		if (format == CD_TRACK_INFO)
  758: 		    ccb[6] = args->track;
  759: 
  760: 		if ((error = atapi_queue_cmd(cdp->device, ccb,
  761: 					     (caddr_t)&cdp->subchan, 
  762: 					     sizeof(cdp->subchan), ATPR_F_READ,
  763: 					     10, NULL, NULL))) {
  764: 		    break;
  765: 		}
  766: 	    }
  767: 	    error = copyout(&cdp->subchan, args->data, args->data_len);
  768: 	    break;
  769: 	}
  770: 
  771:     case CDIOCPLAYMSF:
  772: 	{
  773: 	    struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
  774: 
  775: 	    error = 
  776: 		acd_play(cdp, 
  777: 			 msf2lba(args->start_m, args->start_s, args->start_f),
  778: 			 msf2lba(args->end_m, args->end_s, args->end_f));
  779: 	    break;
  780: 	}
  781: 
  782:     case CDIOCPLAYBLOCKS:
  783: 	{
  784: 	    struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
  785: 
  786: 	    error = acd_play(cdp, args->blk, args->blk + args->len);
  787: 	    break;
  788: 	}
  789: 
  790:     case CDIOCPLAYTRACKS:
  791: 	{
  792: 	    struct ioc_play_track *args = (struct ioc_play_track *)addr;
  793: 	    int t1, t2;
  794: 
  795: 	    if (!cdp->toc.hdr.ending_track) {
  796: 		error = EIO;
  797: 		break;
  798: 	    }
  799: 	    if (args->end_track < cdp->toc.hdr.ending_track + 1)
  800: 		++args->end_track;
  801: 	    if (args->end_track > cdp->toc.hdr.ending_track + 1)
  802: 		args->end_track = cdp->toc.hdr.ending_track + 1;
  803: 	    t1 = args->start_track - cdp->toc.hdr.starting_track;
  804: 	    t2 = args->end_track - cdp->toc.hdr.starting_track;
  805: 	    if (t1 < 0 || t2 < 0 ||
  806: 		t1 > (cdp->toc.hdr.ending_track-cdp->toc.hdr.starting_track)) {
  807: 		error = EINVAL;
  808: 		break;
  809: 	    }
  810: 	    error = acd_play(cdp, ntohl(cdp->toc.tab[t1].addr.lba),
  811: 			     ntohl(cdp->toc.tab[t2].addr.lba));
  812: 	    break;
  813: 	}
  814: 
  815:     case CDIOCREADAUDIO:
  816: 	{
  817: 	    struct ioc_read_audio *args = (struct ioc_read_audio *)addr;
  818: 	    int32_t lba;
  819: 	    caddr_t buffer, ubuf = args->buffer;
  820: 	    int8_t ccb[16];
  821: 	    int frames;
  822: 
  823: 	    if (!cdp->toc.hdr.ending_track) {
  824: 		error = EIO;
  825: 		break;
  826: 	    }
  827: 		
  828: 	    if ((frames = args->nframes) < 0) {
  829: 		error = EINVAL;
  830: 		break;
  831: 	    }
  832: 
  833: 	    if (args->address_format == CD_LBA_FORMAT)
  834: 		lba = args->address.lba;
  835: 	    else if (args->address_format == CD_MSF_FORMAT)
  836: 		lba = msf2lba(args->address.msf.minute,
  837: 			     args->address.msf.second,
  838: 			     args->address.msf.frame);
  839: 	    else {
  840: 		error = EINVAL;
  841: 		break;
  842: 	    }
  843: 
  844: #ifndef CD_BUFFER_BLOCKS
  845: #define CD_BUFFER_BLOCKS 13
  846: #endif
  847: 	    if (!(buffer = malloc(CD_BUFFER_BLOCKS * 2352, M_ACD, M_WAITOK))){
  848: 		error = ENOMEM;
  849: 		break;
  850: 	    }
  851: 	    bzero(ccb, sizeof(ccb));
  852: 	    while (frames > 0) {
  853: 		int8_t blocks;
  854: 		int size;
  855: 
  856: 		blocks = (frames>CD_BUFFER_BLOCKS) ? CD_BUFFER_BLOCKS : frames;
  857: 		size = blocks * 2352;
  858: 
  859: 		ccb[0] = ATAPI_READ_CD;
  860: 		ccb[1] = 4;
  861: 		ccb[2] = lba>>24;
  862: 		ccb[3] = lba>>16;
  863: 		ccb[4] = lba>>8;
  864: 		ccb[5] = lba;
  865: 		ccb[8] = blocks;
  866: 		ccb[9] = 0xf0;
  867: 		if ((error = atapi_queue_cmd(cdp->device, ccb, buffer, size, 
  868: 					     ATPR_F_READ, 30, NULL,NULL)))
  869: 		    break;
  870: 
  871: 		if ((error = copyout(buffer, ubuf, size)))
  872: 		    break;
  873: 		    
  874: 		ubuf += size;
  875: 		frames -= blocks;
  876: 		lba += blocks;
  877: 	    }
  878: 	    free(buffer, M_ACD);
  879: 	    if (args->address_format == CD_LBA_FORMAT)
  880: 		args->address.lba = lba;
  881: 	    else if (args->address_format == CD_MSF_FORMAT)
  882: 		lba2msf(lba, &args->address.msf.minute,
  883: 			     &args->address.msf.second,
  884: 			     &args->address.msf.frame);
  885: 	    break;
  886: 	}
  887: 
  888:     case CDIOCGETVOL:
  889: 	{
  890: 	    struct ioc_vol *arg = (struct ioc_vol *)addr;
  891: 
  892: 	    if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE,
  893: 					(caddr_t)&cdp->au, sizeof(cdp->au))))
  894: 		break;
  895: 
  896: 	    if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) {
  897: 		error = EIO;
  898: 		break;
  899: 	    }
  900: 	    arg->vol[0] = cdp->au.port[0].volume;
  901: 	    arg->vol[1] = cdp->au.port[1].volume;
  902: 	    arg->vol[2] = cdp->au.port[2].volume;
  903: 	    arg->vol[3] = cdp->au.port[3].volume;
  904: 	    break;
  905: 	}
  906: 
  907:     case CDIOCSETVOL:
  908: 	{
  909: 	    struct ioc_vol *arg = (struct ioc_vol *)addr;
  910: 
  911: 	    if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE,
  912: 					(caddr_t)&cdp->au, sizeof(cdp->au))))
  913: 		break;
  914: 	    if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) {
  915: 		error = EIO;
  916: 		break;
  917: 	    }
  918: 	    if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE_MASK,
  919: 					(caddr_t)&cdp->aumask,
  920: 					sizeof(cdp->aumask))))
  921: 		break;
  922: 	    cdp->au.data_length = 0;
  923: 	    cdp->au.port[0].channels = CHANNEL_0;
  924: 	    cdp->au.port[1].channels = CHANNEL_1;
  925: 	    cdp->au.port[0].volume = arg->vol[0] & cdp->aumask.port[0].volume;
  926: 	    cdp->au.port[1].volume = arg->vol[1] & cdp->aumask.port[1].volume;
  927: 	    cdp->au.port[2].volume = arg->vol[2] & cdp->aumask.port[2].volume;
  928: 	    cdp->au.port[3].volume = arg->vol[3] & cdp->aumask.port[3].volume;
  929: 	    error =  acd_mode_select(cdp, (caddr_t)&cdp->au, sizeof(cdp->au));
  930: 	    break;
  931: 	}
  932:     case CDIOCSETPATCH:
  933: 	{
  934: 	    struct ioc_patch *arg = (struct ioc_patch *)addr;
  935: 
  936: 	    error = acd_setchan(cdp, arg->patch[0], arg->patch[1],
  937: 				arg->patch[2], arg->patch[3]);
  938: 	    break;
  939: 	}
  940: 
  941:     case CDIOCSETMONO:
  942: 	error = acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0,0);
  943: 	break;
  944: 
  945:     case CDIOCSETSTEREO:
  946: 	error = acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0);
  947: 	break;
  948: 
  949:     case CDIOCSETMUTE:
  950: 	error = acd_setchan(cdp, 0, 0, 0, 0);
  951: 	break;
  952: 
  953:     case CDIOCSETLEFT:
  954: 	error = acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0);
  955: 	break;
  956: 
  957:     case CDIOCSETRIGHT:
  958: 	error = acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0);
  959: 	break;
  960: 
  961:     case CDRIOCBLANK:
  962: 	error = acd_blank(cdp, (*(int *)addr));
  963: 	break;
  964: 
  965:     case CDRIOCNEXTWRITEABLEADDR:
  966: 	{
  967: 	    struct acd_track_info track_info;
  968: 
  969: 	    if ((error = acd_read_track_info(cdp, 0xff, &track_info)))
  970: 		break;
  971: 
  972: 	    if (!track_info.nwa_valid) {
  973: 		error = EINVAL;
  974: 		break;
  975: 	    }
  976: 	    *(int*)addr = track_info.next_writeable_addr;
  977: 	}
  978: 	break;
  979:  
  980:     case CDRIOCINITWRITER:
  981: 	error = acd_init_writer(cdp, (*(int *)addr));
  982: 	break;
  983: 
  984:     case CDRIOCINITTRACK:
  985: 	error = acd_init_track(cdp, (struct cdr_track *)addr);
  986: 	break;
  987: 
  988:     case CDRIOCFLUSH:
  989: 	error = acd_flush(cdp);
  990: 	break;
  991: 
  992:     case CDRIOCFIXATE:
  993: 	error = acd_fixate(cdp, (*(int *)addr));
  994: 	break;
  995: 
  996:     case CDRIOCREADSPEED:
  997: 	{
  998: 	    int speed = *(int *)addr;
  999: 
 1000: 	    /* Preserve old behavior: units in multiples of CDROM speed */
 1001: 	    if (speed < 177)
 1002: 		speed *= 177;
 1003: 	    error = acd_set_speed(cdp, speed, CDR_MAX_SPEED);
 1004: 	}
 1005: 	break;
 1006: 
 1007:     case CDRIOCWRITESPEED:
 1008:     	{
 1009: 	    int speed = *(int *)addr;
 1010: 
 1011: 	    if (speed < 177)
 1012: 		speed *= 177;
 1013: 	    error = acd_set_speed(cdp, CDR_MAX_SPEED, speed);
 1014: 	}
 1015: 	break;
 1016: 
 1017:     case CDRIOCGETBLOCKSIZE:
 1018: 	*(int *)addr = cdp->block_size;
 1019: 	break;
 1020: 
 1021:     case CDRIOCSETBLOCKSIZE:
 1022: 	cdp->block_size = *(int *)addr;
 1023: 	acd_set_ioparm(cdp);
 1024: 	break;
 1025: 
 1026:     case CDRIOCGETPROGRESS:
 1027: 	error = acd_get_progress(cdp, (int *)addr);
 1028: 	break;
 1029: 
 1030:     case CDRIOCSENDCUE:
 1031: 	error = acd_send_cue(cdp, (struct cdr_cuesheet *)addr);
 1032: 	break;
 1033: 
 1034:     case DVDIOCREPORTKEY:
 1035: 	if (!cdp->cap.read_dvdrom)
 1036: 	    error = EINVAL;
 1037: 	else
 1038: 	    error = acd_report_key(cdp, (struct dvd_authinfo *)addr);
 1039: 	break;
 1040: 
 1041:     case DVDIOCSENDKEY:
 1042: 	if (!cdp->cap.read_dvdrom)
 1043: 	    error = EINVAL;
 1044: 	else
 1045: 	    error = acd_send_key(cdp, (struct dvd_authinfo *)addr);
 1046: 	break;
 1047: 
 1048:     case DVDIOCREADSTRUCTURE:
 1049: 	if (!cdp->cap.read_dvdrom)
 1050: 	    error = EINVAL;
 1051: 	else
 1052: 	    error = acd_read_structure(cdp, (struct dvd_struct *)addr);
 1053: 	break;
 1054: 
 1055:     case DIOCGDINFO:
 1056: 	*(struct disklabel *)addr = cdp->disklabel;
 1057: 	break;
 1058: 
 1059:     case DIOCWDINFO:
 1060:     case DIOCSDINFO:
 1061: 	if ((flags & FWRITE) == 0)
 1062: 	    error = EBADF;
 1063: 	else
 1064: 	    error = setdisklabel(&cdp->disklabel, (struct disklabel *)addr, 0);
 1065: 	break;
 1066: 
 1067:     case DIOCWLABEL:
 1068: 	error = EBADF;
 1069: 	break;
 1070: 
 1071:     case DIOCGPART:
 1072: 	((struct partinfo *)addr)->disklab = &cdp->disklabel;
 1073: 	((struct partinfo *)addr)->part = &cdp->disklabel.d_partitions[0];
 1074: 	break;
 1075: 
 1076:     default:
 1077: 	error = ENOTTY;
 1078:     }
 1079:     return error;
 1080: }
 1081: 
 1082: static void 
 1083: acdstrategy(struct buf *bp)
 1084: {
 1085:     struct acd_softc *cdp = bp->b_dev->si_drv1;
 1086:     int s;
 1087: 
 1088:     if (cdp->device->flags & ATA_D_DETACHING) {
 1089: 	bp->b_flags |= B_ERROR;
 1090: 	bp->b_error = ENXIO;
 1091: 	biodone(bp);
 1092: 	return;
 1093:     }
 1094: 
 1095:     /* if it's a null transfer, return immediatly. */
 1096:     if (bp->b_bcount == 0) {
 1097: 	bp->b_resid = 0;
 1098: 	biodone(bp);
 1099: 	return;
 1100:     }
 1101:     
 1102:     bp->b_pblkno = bp->b_blkno;
 1103:     bp->b_resid = bp->b_bcount;
 1104: 
 1105:     s = splbio();
 1106:     bufqdisksort(&cdp->queue, bp);
 1107:     splx(s);
 1108:     ata_start(cdp->device->channel);
 1109: }
 1110: 
 1111: void 
 1112: acd_start(struct ata_device *atadev)
 1113: {
 1114:     struct acd_softc *cdp = atadev->driver;
 1115:     struct buf *bp = bufq_first(&cdp->queue);
 1116:     u_int32_t lba, lastlba, count;
 1117:     int8_t ccb[16];
 1118:     int track, blocksize;
 1119: 
 1120:     if (cdp->changer_info) {
 1121: 	int i;
 1122: 
 1123: 	cdp = cdp->driver[cdp->changer_info->current_slot];
 1124: 	bp = bufq_first(&cdp->queue);
 1125: 
 1126: 	/* check for work pending on any other slot */
 1127: 	for (i = 0; i < cdp->changer_info->slots; i++) {
 1128: 	    if (i == cdp->changer_info->current_slot)
 1129: 		continue;
 1130: 	    if (bufq_first(&(cdp->driver[i]->queue))) {
 1131: 		if (!bp || time_second > (cdp->timestamp + 10)) {
 1132: 		    acd_select_slot(cdp->driver[i]);
 1133: 		    return;
 1134: 		}
 1135: 	    }
 1136: 	}
 1137:     }
 1138:     if (!bp)
 1139: 	return;
 1140:     bufq_remove(&cdp->queue, bp);
 1141: 
 1142:     /* reject all queued entries if media changed */
 1143:     if (cdp->device->flags & ATA_D_MEDIA_CHANGED) {
 1144: 	bp->b_flags |= B_ERROR;
 1145: 	bp->b_error = EIO;
 1146: 	biodone(bp);
 1147: 	return;
 1148:     }
 1149: 
 1150:     bzero(ccb, sizeof(ccb));
 1151: 
 1152:     track = (bp->b_dev->si_udev & 0x00ff0000) >> 16;
 1153: 
 1154:     if (track) {
 1155: 	blocksize = (cdp->toc.tab[track - 1].control & 4) ? 2048 : 2352;
 1156: 	lastlba = ntohl(cdp->toc.tab[track].addr.lba);
 1157: 	if (bp->b_flags & B_PHYS)
 1158: 	    lba = bp->b_offset / blocksize;
 1159: 	else
 1160: 	    lba = bp->b_blkno / (blocksize / DEV_BSIZE);
 1161: 	lba += ntohl(cdp->toc.tab[track - 1].addr.lba);
 1162:     }
 1163:     else {
 1164: 	blocksize = cdp->block_size;
 1165: 	lastlba = cdp->disk_size;
 1166: 	if (bp->b_flags & B_PHYS)
 1167: 	    lba = bp->b_offset / blocksize;
 1168: 	else
 1169: 	    lba = bp->b_blkno / (blocksize / DEV_BSIZE);
 1170:     }
 1171: 
 1172:     if (bp->b_bcount % blocksize != 0) {
 1173: 	bp->b_flags |= B_ERROR;
 1174: 	bp->b_error = EINVAL;
 1175: 	biodone(bp);
 1176: 	return;
 1177:     }
 1178:     count = bp->b_bcount / blocksize;
 1179: 
 1180:     if (bp->b_flags & B_READ) {
 1181: 	/* if transfer goes beyond range adjust it to be within limits */
 1182: 	if (lba + count > lastlba) {
 1183: 	    /* if we are entirely beyond EOM return EOF */
 1184: 	    if (lastlba <= lba) {
 1185: 		bp->b_resid = bp->b_bcount;
 1186: 		biodone(bp);
 1187: 		return;
 1188: 	    }
 1189: 	    count = lastlba - lba;
 1190: 	}
 1191: 	switch (blocksize) {
 1192: 	case 2048:
 1193: 	    ccb[0] = ATAPI_READ_BIG;
 1194: 	    break;
 1195: 
 1196: 	case 2352: 
 1197: 	    ccb[0] = ATAPI_READ_CD;
 1198: 	    ccb[9] = 0xf8;
 1199: 	    break;
 1200: 
 1201: 	default:
 1202: 	    ccb[0] = ATAPI_READ_CD;
 1203: 	    ccb[9] = 0x10;
 1204: 	}
 1205:     }
 1206:     else 
 1207: 	ccb[0] = ATAPI_WRITE_BIG;
 1208:     
 1209:     ccb[1] = 0;
 1210:     ccb[2] = lba>>24;
 1211:     ccb[3] = lba>>16;
 1212:     ccb[4] = lba>>8;
 1213:     ccb[5] = lba;
 1214:     ccb[6] = count>>16;
 1215:     ccb[7] = count>>8;
 1216:     ccb[8] = count;
 1217: 
 1218:     devstat_start_transaction(cdp->stats);
 1219:     bp->b_caller1 = cdp;
 1220:     atapi_queue_cmd(cdp->device, ccb, bp->b_data, count * blocksize,
 1221: 		    bp->b_flags & B_READ ? ATPR_F_READ : 0, 
 1222: 		    (ccb[0] == ATAPI_WRITE_BIG) ? 60 : 30, acd_done, bp);
 1223: }
 1224: 
 1225: static int 
 1226: acd_done(struct atapi_request *request)
 1227: {
 1228:     struct buf *bp = request->driver;
 1229:     struct acd_softc *cdp = bp->b_caller1;
 1230:     
 1231:     if (request->error) {
 1232: 	bp->b_error = request->error;
 1233: 	bp->b_flags |= B_ERROR;
 1234:     }	
 1235:     else
 1236: 	bp->b_resid = bp->b_bcount - request->donecount;
 1237:     devstat_end_transaction_buf(cdp->stats, bp);
 1238:     biodone(bp);
 1239:     return 0;
 1240: }
 1241: 
 1242: static void 
 1243: acd_read_toc(struct acd_softc *cdp)
 1244: {
 1245:     struct acd_devlist *entry;
 1246:     int track, ntracks, len;
 1247:     u_int32_t sizes[2];
 1248:     int8_t ccb[16];
 1249: 
 1250:     bzero(&cdp->toc, sizeof(cdp->toc));
 1251:     bzero(ccb, sizeof(ccb));
 1252: 
 1253:     if (atapi_test_ready(cdp->device) != 0)
 1254: 	return;
 1255: 
 1256:     cdp->device->flags &= ~ATA_D_MEDIA_CHANGED;
 1257: 
 1258:     len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry);
 1259:     ccb[0] = ATAPI_READ_TOC;
 1260:     ccb[7] = len>>8;
 1261:     ccb[8] = len;
 1262:     if (atapi_queue_cmd(cdp->device, ccb, (caddr_t)&cdp->toc, len,
 1263: 			ATPR_F_READ | ATPR_F_QUIET, 30, NULL, NULL)) {
 1264: 	bzero(&cdp->toc, sizeof(cdp->toc));
 1265: 	return;
 1266:     }
 1267:     ntracks = cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1;
 1268:     if (ntracks <= 0 || ntracks > MAXTRK) {
 1269: 	bzero(&cdp->toc, sizeof(cdp->toc));
 1270: 	return;
 1271:     }
 1272: 
 1273:     len = sizeof(struct ioc_toc_header)+(ntracks+1)*sizeof(struct cd_toc_entry);
 1274:     bzero(ccb, sizeof(ccb));
 1275:     ccb[0] = ATAPI_READ_TOC;
 1276:     ccb[7] = len>>8;
 1277:     ccb[8] = len;
 1278:     if (atapi_queue_cmd(cdp->device, ccb, (caddr_t)&cdp->toc, len,
 1279: 			ATPR_F_READ | ATPR_F_QUIET, 30, NULL, NULL)) {
 1280: 	bzero(&cdp->toc, sizeof(cdp->toc));
 1281: 	return;
 1282:     }
 1283:     cdp->toc.hdr.len = ntohs(cdp->toc.hdr.len);
 1284: 
 1285:     cdp->block_size = (cdp->toc.tab[0].control & 4) ? 2048 : 2352;
 1286:     acd_set_ioparm(cdp);
 1287:     bzero(ccb, sizeof(ccb));
 1288:     ccb[0] = ATAPI_READ_CAPACITY;
 1289:     if (atapi_queue_cmd(cdp->device, ccb, (caddr_t)sizes, sizeof(sizes),
 1290: 			ATPR_F_READ | ATPR_F_QUIET, 30, NULL, NULL)) {
 1291: 	bzero(&cdp->toc, sizeof(cdp->toc));
 1292: 	return;
 1293:     }
 1294:     cdp->disk_size = ntohl(sizes[0]) + 1;
 1295: 
 1296:     bzero(&cdp->disklabel, sizeof(struct disklabel));
 1297:     strncpy(cdp->disklabel.d_typename, "	       ", 
 1298: 	    sizeof(cdp->disklabel.d_typename));
 1299:     strncpy(cdp->disklabel.d_typename, cdp->device->name, 
 1300: 	    min(strlen(cdp->device->name),sizeof(cdp->disklabel.d_typename)-1));
 1301:     strncpy(cdp->disklabel.d_packname, "unknown	       ", 
 1302: 	    sizeof(cdp->disklabel.d_packname));
 1303:     cdp->disklabel.d_secsize = cdp->block_size;
 1304:     cdp->disklabel.d_nsectors = 100;
 1305:     cdp->disklabel.d_ntracks = 1;
 1306:     cdp->disklabel.d_ncylinders = (cdp->disk_size / 100) + 1;
 1307:     cdp->disklabel.d_secpercyl = 100;
 1308:     cdp->disklabel.d_secperunit = cdp->disk_size;
 1309:     cdp->disklabel.d_rpm = 300;
 1310:     cdp->disklabel.d_interleave = 1;
 1311:     cdp->disklabel.d_flags = D_REMOVABLE;
 1312:     cdp->disklabel.d_npartitions = 1;
 1313:     cdp->disklabel.d_partitions[0].p_offset = 0;
 1314:     cdp->disklabel.d_partitions[0].p_size = cdp->disk_size;
 1315:     cdp->disklabel.d_partitions[0].p_fstype = FS_BSDFFS;
 1316:     cdp->disklabel.d_magic = DISKMAGIC;
 1317:     cdp->disklabel.d_magic2 = DISKMAGIC;
 1318:     cdp->disklabel.d_checksum = dkcksum(&cdp->disklabel);
 1319: 
 1320:     while ((entry = TAILQ_FIRST(&cdp->dev_list))) {
 1321: 	destroy_dev(entry->dev);
 1322: 	TAILQ_REMOVE(&cdp->dev_list, entry, chain);
 1323: 	free(entry, M_ACD);
 1324:     }
 1325:     for (track = 1; track <= ntracks; track ++) {
 1326: 	char name[16];
 1327: 
 1328: 	sprintf(name, "acd%dt%d", cdp->lun, track);
 1329: 	entry = malloc(sizeof(struct acd_devlist), M_ACD, M_WAITOK | M_ZERO);
 1330: 	entry->dev = make_dev(&acd_cdevsw, (cdp->lun << 3) | (track << 16),
 1331: 			      0, 0, 0644, name, NULL);
 1332: 	entry->dev->si_drv1 = cdp->dev->si_drv1;
 1333: 	TAILQ_INSERT_TAIL(&cdp->dev_list, entry, chain);
 1334:     }
 1335: 
 1336: #ifdef ACD_DEBUG
 1337:     if (cdp->disk_size && cdp->toc.hdr.ending_track) {
 1338: 	ata_prtdev(cdp->device, "(%d sectors (%d bytes)), %d tracks ", 
 1339: 		   cdp->disk_size, cdp->block_size,
 1340: 		   cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1);
 1341: 	if (cdp->toc.tab[0].control & 4)
 1342: 	    printf("%dMB\n", cdp->disk_size / 512);
 1343: 	else
 1344: 	    printf("%d:%d audio\n",
 1345: 		   cdp->disk_size / 75 / 60, cdp->disk_size / 75 % 60);
 1346:     }
 1347: #endif
 1348: }
 1349: 
 1350: static int
 1351: acd_play(struct acd_softc *cdp, int start, int end)
 1352: {
 1353:     int8_t ccb[16];
 1354: 
 1355:     bzero(ccb, sizeof(ccb));
 1356:     ccb[0] = ATAPI_PLAY_MSF;
 1357:     lba2msf(start, &ccb[3], &ccb[4], &ccb[5]);
 1358:     lba2msf(end, &ccb[6], &ccb[7], &ccb[8]);
 1359:     return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 10, NULL, NULL);
 1360: }
 1361: 
 1362: static int 
 1363: acd_setchan(struct acd_softc *cdp,
 1364: 	    u_int8_t c0, u_int8_t c1, u_int8_t c2, u_int8_t c3)
 1365: {
 1366:     int error;
 1367: 
 1368:     if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, (caddr_t)&cdp->au, 
 1369: 				sizeof(cdp->au))))
 1370: 	return error;
 1371:     if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE)
 1372: 	return EIO;
 1373:     cdp->au.data_length = 0;
 1374:     cdp->au.port[0].channels = c0;
 1375:     cdp->au.port[1].channels = c1;
 1376:     cdp->au.port[2].channels = c2;
 1377:     cdp->au.port[3].channels = c3;
 1378:     return acd_mode_select(cdp, (caddr_t)&cdp->au, sizeof(cdp->au));
 1379: }
 1380: 
 1381: static int 
 1382: acd_select_done1(struct atapi_request *request)
 1383: {
 1384:     struct acd_softc *cdp = request->driver;
 1385: 
 1386:     cdp->changer_info->current_slot = cdp->slot;
 1387:     cdp->driver[cdp->changer_info->current_slot]->timestamp = time_second;
 1388:     wakeup(&cdp->changer_info);
 1389:     return 0;
 1390: }
 1391: 
 1392: static int 
 1393: acd_select_done(struct atapi_request *request)
 1394: {
 1395:     struct acd_softc *cdp = request->driver;
 1396:     int8_t ccb[16] = { ATAPI_LOAD_UNLOAD, 0, 0, 0, 3, 0, 0, 0, 
 1397: 		       cdp->slot, 0, 0, 0, 0, 0, 0, 0 };
 1398: 
 1399:     /* load the wanted slot */
 1400:     atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_AT_HEAD, 30, 
 1401: 		    acd_select_done1, cdp);
 1402:     return 0;
 1403: }
 1404: 
 1405: static void 
 1406: acd_select_slot(struct acd_softc *cdp)
 1407: {
 1408:     int8_t ccb[16] = { ATAPI_LOAD_UNLOAD, 0, 0, 0, 2, 0, 0, 0, 
 1409: 		       cdp->changer_info->current_slot, 0, 0, 0, 0, 0, 0, 0 };
 1410: 
 1411:     /* unload the current media from player */
 1412:     atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_AT_HEAD, 30, 
 1413: 		    acd_select_done, cdp);
 1414: }
 1415: 
 1416: static int
 1417: acd_init_writer(struct acd_softc *cdp, int test_write)
 1418: {
 1419:     int8_t ccb[16];
 1420: 
 1421:     bzero(ccb, sizeof(ccb));
 1422:     ccb[0] = ATAPI_REZERO;
 1423:     atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_QUIET, 60, NULL, NULL);
 1424:     ccb[0] = ATAPI_SEND_OPC_INFO;
 1425:     ccb[1] = 0x01;
 1426:     atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_QUIET, 30, NULL, NULL);
 1427:     return 0;
 1428: }
 1429: 
 1430: static int
 1431: acd_fixate(struct acd_softc *cdp, int multisession)
 1432: {
 1433:     int8_t ccb[16] = { ATAPI_CLOSE_TRACK, 0x01, 0x02, 0, 0, 0, 0, 0, 
 1434: 		       0, 0, 0, 0, 0, 0, 0, 0 };
 1435:     int timeout = 5*60*2;
 1436:     int error;
 1437:     struct write_param param;
 1438: 
 1439:     if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
 1440: 				(caddr_t)&param, sizeof(param))))
 1441: 	return error;
 1442: 
 1443:     param.data_length = 0;
 1444:     if (multisession)
 1445: 	param.session_type = CDR_SESS_MULTI;
 1446:     else
 1447: 	param.session_type = CDR_SESS_NONE;
 1448: 
 1449:     if ((error = acd_mode_select(cdp, (caddr_t)&param, param.page_length + 10)))
 1450: 	return error;
 1451:   
 1452:     error = atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
 1453:     if (error)
 1454: 	return error;
 1455: 
 1456:     /* some drives just return ready, wait for the expected fixate time */
 1457:     if ((error = atapi_test_ready(cdp->device)) != EBUSY) {
 1458: 	timeout = timeout / (cdp->cap.cur_write_speed / 177);
 1459: 	tsleep(&error, 0, "acdfix", timeout * hz / 2);
 1460: 	return atapi_test_ready(cdp->device);
 1461:     }
 1462: 
 1463:     while (timeout-- > 0) {
 1464: 	if ((error = atapi_test_ready(cdp->device)) != EBUSY)
 1465: 	    return error;
 1466: 	tsleep(&error, 0, "acdcld", hz/2);
 1467:     }
 1468:     return EIO;
 1469: }
 1470: 
 1471: static int
 1472: acd_init_track(struct acd_softc *cdp, struct cdr_track *track)
 1473: {
 1474:     struct write_param param;
 1475:     int error;
 1476: 
 1477:     if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
 1478: 				(caddr_t)&param, sizeof(param))))
 1479: 	return error;
 1480: 
 1481:     param.data_length = 0;
 1482:     param.page_code = ATAPI_CDROM_WRITE_PARAMETERS_PAGE;
 1483:     param.page_length = 0x32;
 1484:     param.test_write = track->test_write ? 1 : 0;
 1485:     param.write_type = CDR_WTYPE_TRACK;
 1486:     param.session_type = CDR_SESS_NONE;
 1487:     param.fp = 0;
 1488:     param.packet_size = 0;
 1489: 
 1490:     if (cdp->cap.burnproof) 
 1491: 	param.burnproof = 1;
 1492: 
 1493:     switch (track->datablock_type) {
 1494: 
 1495:     case CDR_DB_RAW:
 1496: 	if (track->preemp)
 1497: 	    param.track_mode = CDR_TMODE_AUDIO_PREEMP;
 1498: 	else
 1499: 	    param.track_mode = CDR_TMODE_AUDIO;
 1500: 	cdp->block_size = 2352;
 1501: 	param.datablock_type = CDR_DB_RAW;
 1502: 	param.session_format = CDR_SESS_CDROM;
 1503: 	break;
 1504: 
 1505:     case CDR_DB_ROM_MODE1:
 1506: 	cdp->block_size = 2048;
 1507: 	param.track_mode = CDR_TMODE_DATA;
 1508: 	param.datablock_type = CDR_DB_ROM_MODE1;
 1509: 	param.session_format = CDR_SESS_CDROM;
 1510: 	break;
 1511: 
 1512:     case CDR_DB_ROM_MODE2:
 1513: 	cdp->block_size = 2336;
 1514: 	param.track_mode = CDR_TMODE_DATA;
 1515: 	param.datablock_type = CDR_DB_ROM_MODE2;
 1516: 	param.session_format = CDR_SESS_CDROM;
 1517: 	break;
 1518: 
 1519:     case CDR_DB_XA_MODE1:
 1520: 	cdp->block_size = 2048;
 1521: 	param.track_mode = CDR_TMODE_DATA;
 1522: 	param.datablock_type = CDR_DB_XA_MODE1;
 1523: 	param.session_format = CDR_SESS_CDROM_XA;
 1524: 	break;
 1525: 
 1526:     case CDR_DB_XA_MODE2_F1:
 1527: 	cdp->block_size = 2056;
 1528: 	param.track_mode = CDR_TMODE_DATA;
 1529: 	param.datablock_type = CDR_DB_XA_MODE2_F1;
 1530: 	param.session_format = CDR_SESS_CDROM_XA;
 1531: 	break;
 1532: 
 1533:     case CDR_DB_XA_MODE2_F2:
 1534: 	cdp->block_size = 2324;
 1535: 	param.track_mode = CDR_TMODE_DATA;
 1536: 	param.datablock_type = CDR_DB_XA_MODE2_F2;
 1537: 	param.session_format = CDR_SESS_CDROM_XA;
 1538: 	break;
 1539: 
 1540:     case CDR_DB_XA_MODE2_MIX:
 1541: 	cdp->block_size = 2332;
 1542: 	param.track_mode = CDR_TMODE_DATA;
 1543: 	param.datablock_type = CDR_DB_XA_MODE2_MIX;
 1544: 	param.session_format = CDR_SESS_CDROM_XA;
 1545: 	break;
 1546:     }
 1547:     acd_set_ioparm(cdp);
 1548:     return acd_mode_select(cdp, (caddr_t)&param, param.page_length + 10);
 1549: }
 1550: 
 1551: static int
 1552: acd_flush(struct acd_softc *cdp)
 1553: {
 1554:     int8_t ccb[16] = { ATAPI_SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0, 0,
 1555: 		       0, 0, 0, 0, 0, 0, 0, 0 };
 1556: 
 1557:     return atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_QUIET, 60,
 1558: 			   NULL, NULL);
 1559: }
 1560: 
 1561: static int
 1562: acd_read_track_info(struct acd_softc *cdp,
 1563: 		    int32_t lba, struct acd_track_info *info)
 1564: {
 1565:     int8_t ccb[16] = { ATAPI_READ_TRACK_INFO, 1,
 1566: 		     lba>>24, lba>>16, lba>>8, lba,
 1567: 		     0,
 1568: 		     sizeof(*info)>>8, sizeof(*info),
 1569: 		     0, 0, 0, 0, 0, 0, 0 };
 1570:     int error;
 1571: 
 1572:     if ((error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)info, sizeof(*info),
 1573: 				 ATPR_F_READ, 30, NULL, NULL)))
 1574: 	return error;
 1575:     info->track_start_addr = ntohl(info->track_start_addr);
 1576:     info->next_writeable_addr = ntohl(info->next_writeable_addr);
 1577:     info->free_blocks = ntohl(info->free_blocks);
 1578:     info->fixed_packet_size = ntohl(info->fixed_packet_size);
 1579:     info->track_length = ntohl(info->track_length);
 1580:     return 0;
 1581: }
 1582: 
 1583: static int
 1584: acd_get_progress(struct acd_softc *cdp, int *finished)
 1585: {
 1586:     int8_t ccb[16] = { ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0,  
 1587: 		       0, 0, 0, 0, 0, 0, 0, 0 };
 1588:     struct atapi_reqsense *sense = cdp->device->result;
 1589:     char tmp[8];
 1590: 
 1591:     if (atapi_test_ready(cdp->device) != EBUSY) {
 1592: 	if (atapi_queue_cmd(cdp->device, ccb, tmp, sizeof(tmp),
 1593: 			    ATPR_F_READ, 30, NULL, NULL) != EBUSY) {
 1594: 	    *finished = 100;
 1595: 	    return 0;
 1596: 	}
 1597:     }
 1598:     if (sense->sksv)
 1599: 	*finished = 
 1600: 	    ((sense->sk_specific2 | (sense->sk_specific1 << 8)) * 100) / 65535;
 1601:     else
 1602: 	*finished = 0;
 1603:     return 0;
 1604: }
 1605: 
 1606: static int
 1607: acd_send_cue(struct acd_softc *cdp, struct cdr_cuesheet *cuesheet)
 1608: {
 1609:     struct write_param param;
 1610:     int8_t ccb[16] = { ATAPI_SEND_CUE_SHEET, 0, 0, 0, 0, 0, 
 1611: 		       cuesheet->len>>16, cuesheet->len>>8, cuesheet->len,
 1612: 		       0, 0, 0, 0, 0, 0, 0 };
 1613:     int8_t *buffer;
 1614:     int32_t error;
 1615: #ifdef ACD_DEBUG
 1616:     int i;
 1617: #endif
 1618: 
 1619:     if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE,
 1620: 				(caddr_t)&param, sizeof(param))))
 1621: 	return error;
 1622:     param.data_length = 0;
 1623:     param.page_code = ATAPI_CDROM_WRITE_PARAMETERS_PAGE;
 1624:     param.page_length = 0x32;
 1625:     param.test_write = cuesheet->test_write ? 1 : 0;
 1626:     param.write_type = CDR_WTYPE_SESSION;
 1627:     param.session_type = cuesheet->session_type;
 1628:     param.fp = 0;
 1629:     param.packet_size = 0;
 1630:     param.track_mode = CDR_TMODE_AUDIO;
 1631:     param.datablock_type = CDR_DB_RAW;
 1632:     param.session_format = cuesheet->session_format;
 1633:     if (cdp->cap.burnproof) 
 1634: 	param.burnproof = 1;
 1635:     if ((error = acd_mode_select(cdp, (caddr_t)&param, param.page_length + 10)))
 1636: 	return error;
 1637: 
 1638:     buffer = malloc(cuesheet->len, M_ACD, M_WAITOK);
 1639:     if (!buffer)
 1640: 	return ENOMEM;
 1641:     if ((error = copyin(cuesheet->entries, buffer, cuesheet->len)))
 1642: 	return error;
 1643: #ifdef ACD_DEBUG
 1644:     printf("acd: cuesheet lenght = %d\n", cuesheet->len);
 1645:     for (i=0; i<cuesheet->len; i++)
 1646: 	if (i%8)
 1647: 	    printf(" %02x", buffer[i]);
 1648: 	else
 1649: 	    printf("\n%02x", buffer[i]);
 1650:     printf("\n");
 1651: #endif
 1652:     error = atapi_queue_cmd(cdp->device, ccb, buffer, cuesheet->len, 0,
 1653: 			    30, NULL, NULL);
 1654:     free(buffer, M_ACD);
 1655:     return error;
 1656: }
 1657: 
 1658: static int
 1659: acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
 1660: {
 1661:     struct dvd_miscauth *d;
 1662:     u_int32_t lba = 0;
 1663:     int16_t length;
 1664:     int8_t ccb[16];
 1665:     int error;
 1666: 
 1667:     /* this is common even for ai->format == DVD_INVALIDATE_AGID */
 1668:     bzero(ccb, sizeof(ccb));
 1669:     ccb[0] = ATAPI_REPORT_KEY;
 1670:     ccb[2] = (lba >> 24) & 0xff;
 1671:     ccb[3] = (lba >> 16) & 0xff;
 1672:     ccb[4] = (lba >> 8) & 0xff;
 1673:     ccb[5] = lba & 0xff;
 1674:     ccb[10] = (ai->agid << 6) | ai->format;
 1675: 
 1676:     switch (ai->format) {
 1677:     case DVD_REPORT_AGID:
 1678:     case DVD_REPORT_ASF:
 1679:     case DVD_REPORT_RPC:
 1680: 	length = 8;
 1681: 	break;
 1682:     case DVD_REPORT_KEY1:
 1683: 	length = 12;
 1684: 	break;
 1685:     case DVD_REPORT_TITLE_KEY:
 1686: 	length = 12;
 1687: 	lba = ai->lba;
 1688: 	break;
 1689:     case DVD_REPORT_CHALLENGE:
 1690: 	length = 16;
 1691: 	break;
 1692:     case DVD_INVALIDATE_AGID:
 1693: 	return(atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 10, NULL, NULL));
 1694:     default:
 1695: 	return EINVAL;
 1696:     }
 1697: 
 1698:     ccb[8] = (length >> 8) & 0xff;
 1699:     ccb[9] = length & 0xff;
 1700: 
 1701:     d = malloc(length, M_ACD, M_WAITOK | M_ZERO);
 1702:     d->length = htons(length - 2);
 1703: 
 1704:     error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)d, length,
 1705: 			    ATPR_F_READ, 10, NULL, NULL);
 1706:     if (error) {
 1707:         free(d, M_ACD);
 1708: 	return(error);
 1709:     }
 1710: 
 1711:     switch (ai->format) {
 1712:     case DVD_REPORT_AGID:
 1713: 	ai->agid = d->data[3] >> 6;
 1714: 	break;
 1715:     
 1716:     case DVD_REPORT_CHALLENGE:
 1717: 	bcopy(&d->data[0], &ai->keychal[0], 10);
 1718: 	break;
 1719:     
 1720:     case DVD_REPORT_KEY1:
 1721: 	bcopy(&d->data[0], &ai->keychal[0], 5);
 1722: 	break;
 1723:     
 1724:     case DVD_REPORT_TITLE_KEY:
 1725: 	ai->cpm = (d->data[0] >> 7);
 1726: 	ai->cp_sec = (d->data[0] >> 6) & 0x1;
 1727: 	ai->cgms = (d->data[0] >> 4) & 0x3;
 1728: 	bcopy(&d->data[1], &ai->keychal[0], 5);
 1729: 	break;
 1730:     
 1731:     case DVD_REPORT_ASF:
 1732: 	ai->asf = d->data[3] & 1;
 1733: 	break;
 1734:     
 1735:     case DVD_REPORT_RPC:
 1736: 	ai->reg_type = (d->data[0] >> 6);
 1737: 	ai->vend_rsts = (d->data[0] >> 3) & 0x7;
 1738: 	ai->user_rsts = d->data[0] & 0x7;
 1739: 	ai->region = d->data[1];
 1740: 	ai->rpc_scheme = d->data[2];
 1741: 	break;
 1742:     
 1743:     case DVD_INVALIDATE_AGID:
 1744: 	/* not reached */
 1745: 	break;
 1746: 
 1747:     default:
 1748: 	error = EINVAL;
 1749:     }
 1750:     free(d, M_ACD);
 1751:     return error;
 1752: }
 1753: 
 1754: static int
 1755: acd_send_key(struct acd_softc *cdp, struct dvd_authinfo *ai)
 1756: {
 1757:     struct dvd_miscauth *d;
 1758:     int16_t length;
 1759:     int8_t ccb[16];
 1760:     int error;
 1761: 
 1762:     switch (ai->format) {
 1763:     case DVD_SEND_CHALLENGE:
 1764: 	length = 16;
 1765: 	d = malloc(length, M_ACD, M_WAITOK | M_ZERO);
 1766: 	bcopy(ai->keychal, &d->data[0], 10);
 1767: 	break;
 1768: 
 1769:     case DVD_SEND_KEY2:
 1770: 	length = 12;
 1771: 	d = malloc(length, M_ACD, M_WAITOK | M_ZERO);
 1772: 	bcopy(&ai->keychal[0], &d->data[0], 5);
 1773: 	break;
 1774:     
 1775:     case DVD_SEND_RPC:
 1776: 	length = 8;
 1777: 	d = malloc(length, M_ACD, M_WAITOK | M_ZERO);
 1778: 	d->data[0] = ai->region;
 1779: 	break;
 1780: 
 1781:     default:
 1782: 	return EINVAL;
 1783:     }
 1784: 
 1785:     bzero(ccb, sizeof(ccb));
 1786:     ccb[0] = ATAPI_SEND_KEY;
 1787:     ccb[8] = (length >> 8) & 0xff;
 1788:     ccb[9] = length & 0xff;
 1789:     ccb[10] = (ai->agid << 6) | ai->format;
 1790:     d->length = htons(length - 2);
 1791:     error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)d, length, 0,
 1792: 			    10, NULL, NULL);
 1793:     free(d, M_ACD);
 1794:     return error;
 1795: }
 1796: 
 1797: static int
 1798: acd_read_structure(struct acd_softc *cdp, struct dvd_struct *s)
 1799: {
 1800:     struct dvd_miscauth *d;
 1801:     u_int16_t length;
 1802:     int8_t ccb[16];
 1803:     int error = 0;
 1804: 
 1805:     switch(s->format) {
 1806:     case DVD_STRUCT_PHYSICAL:
 1807: 	length = 21;
 1808: 	break;
 1809: 
 1810:     case DVD_STRUCT_COPYRIGHT:
 1811: 	length = 8;
 1812: 	break;
 1813: 
 1814:     case DVD_STRUCT_DISCKEY:
 1815: 	length = 2052;
 1816: 	break;
 1817: 
 1818:     case DVD_STRUCT_BCA:
 1819: 	length = 192;
 1820: 	break;
 1821: 
 1822:     case DVD_STRUCT_MANUFACT:
 1823: 	length = 2052;
 1824: 	break;
 1825: 
 1826:     case DVD_STRUCT_DDS:
 1827:     case DVD_STRUCT_PRERECORDED:
 1828:     case DVD_STRUCT_UNIQUEID:
 1829:     case DVD_STRUCT_LIST:
 1830:     case DVD_STRUCT_CMI:
 1831:     case DVD_STRUCT_RMD_LAST:
 1832:     case DVD_STRUCT_RMD_RMA:
 1833:     case DVD_STRUCT_DCB:
 1834: 	return ENOSYS;
 1835: 
 1836:     default:
 1837: 	return EINVAL;
 1838:     }
 1839: 
 1840:     d = malloc(length, M_ACD, M_WAITOK | M_ZERO);
 1841:     d->length = htons(length - 2);
 1842: 	
 1843:     bzero(ccb, sizeof(ccb));
 1844:     ccb[0] = ATAPI_READ_STRUCTURE;
 1845:     ccb[6] = s->layer_num;
 1846:     ccb[7] = s->format;
 1847:     ccb[8] = (length >> 8) & 0xff;
 1848:     ccb[9] = length & 0xff;
 1849:     ccb[10] = s->agid << 6;
 1850:     error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)d, length, ATPR_F_READ,
 1851: 			    30, NULL, NULL);
 1852:     if (error) {
 1853: 	free(d, M_ACD);
 1854: 	return error;
 1855:     }
 1856: 
 1857:     switch (s->format) {
 1858:     case DVD_STRUCT_PHYSICAL: {
 1859: 	struct dvd_layer *layer = (struct dvd_layer *)&s->data[0];
 1860: 
 1861: 	layer->book_type = d->data[0] >> 4;
 1862: 	layer->book_version = d->data[0] & 0xf;
 1863: 	layer->disc_size = d->data[1] >> 4;
 1864: 	layer->max_rate = d->data[1] & 0xf;
 1865: 	layer->nlayers = (d->data[2] >> 5) & 3;
 1866: 	layer->track_path = (d->data[2] >> 4) & 1;
 1867: 	layer->layer_type = d->data[2] & 0xf;
 1868: 	layer->linear_density = d->data[3] >> 4;
 1869: 	layer->track_density = d->data[3] & 0xf;
 1870: 	layer->start_sector = d->data[5] << 16 | d->data[6] << 8 | d->data[7];
 1871: 	layer->end_sector = d->data[9] << 16 | d->data[10] << 8 | d->data[11];
 1872: 	layer->end_sector_l0 = d->data[13] << 16 | d->data[14] << 8|d->data[15];
 1873: 	layer->bca = d->data[16] >> 7;
 1874: 	break;
 1875:     }
 1876: 
 1877:     case DVD_STRUCT_COPYRIGHT:
 1878: 	s->cpst = d->data[0];
 1879: 	s->rmi = d->data[0];
 1880: 	break;
 1881: 
 1882:     case DVD_STRUCT_DISCKEY:
 1883: 	bcopy(&d->data[0], &s->data[0], 2048);
 1884: 	break;
 1885: 
 1886:     case DVD_STRUCT_BCA:
 1887: 	s->length = ntohs(d->length);
 1888: 	bcopy(&d->data[0], &s->data[0], s->length);
 1889: 	break;
 1890: 
 1891:     case DVD_STRUCT_MANUFACT:
 1892: 	s->length = ntohs(d->length);
 1893: 	bcopy(&d->data[0], &s->data[0], s->length);
 1894: 	break;
 1895: 		
 1896:     default:
 1897: 	error = EINVAL;
 1898:     }
 1899:     free(d, M_ACD);
 1900:     return error;
 1901: }
 1902: 
 1903: static int 
 1904: acd_eject(struct acd_softc *cdp, int close)
 1905: {
 1906:     int error;
 1907: 
 1908:     if ((error = acd_start_stop(cdp, 0)) == EBUSY) {
 1909: 	if (!close)
 1910: 	    return 0;
 1911: 	if ((error = acd_start_stop(cdp, 3)))
 1912: 	    return error;
 1913: 	acd_read_toc(cdp);
 1914: 	acd_prevent_allow(cdp, 1);
 1915: 	cdp->flags |= F_LOCKED;
 1916: 	return 0;
 1917:     }
 1918:     if (error)
 1919: 	return error;
 1920:     if (close)
 1921: 	return 0;
 1922:     acd_prevent_allow(cdp, 0);
 1923:     cdp->flags &= ~F_LOCKED;
 1924:     cdp->device->flags |= ATA_D_MEDIA_CHANGED;
 1925:     return acd_start_stop(cdp, 2);
 1926: }
 1927: 
 1928: static int
 1929: acd_blank(struct acd_softc *cdp, int blanktype)
 1930: {
 1931:     int8_t ccb[16] = { ATAPI_BLANK, 0x10 | (blanktype & 0x7), 0, 0, 0, 0, 0, 0, 
 1932: 		       0, 0, 0, 0, 0, 0, 0, 0 };
 1933: 
 1934:     cdp->device->flags |= ATA_D_MEDIA_CHANGED;
 1935:     return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
 1936: }
 1937: 
 1938: static int
 1939: acd_prevent_allow(struct acd_softc *cdp, int lock)
 1940: {
 1941:     int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
 1942: 		       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 1943: 
 1944:     return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
 1945: }
 1946: 
 1947: static int
 1948: acd_start_stop(struct acd_softc *cdp, int start)
 1949: {
 1950:     int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
 1951: 		       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 1952: 
 1953:     return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
 1954: }
 1955: 
 1956: static int
 1957: acd_pause_resume(struct acd_softc *cdp, int pause)
 1958: {
 1959:     int8_t ccb[16] = { ATAPI_PAUSE, 0, 0, 0, 0, 0, 0, 0, pause,
 1960: 		       0, 0, 0, 0, 0, 0, 0 };
 1961: 
 1962:     return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
 1963: }
 1964: 
 1965: static int
 1966: acd_mode_sense(struct acd_softc *cdp, int page, caddr_t pagebuf, int pagesize)
 1967: {
 1968:     int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, page, 0, 0, 0, 0,
 1969: 		       pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 };
 1970:     int error;
 1971: 
 1972:     error = atapi_queue_cmd(cdp->device, ccb, pagebuf, pagesize, ATPR_F_READ,
 1973: 			    10, NULL, NULL);
 1974: #ifdef ACD_DEBUG
 1975:     atapi_dump("acd: mode sense ", pagebuf, pagesize);
 1976: #endif
 1977:     return error;
 1978: }
 1979: 
 1980: static int
 1981: acd_mode_select(struct acd_softc *cdp, caddr_t pagebuf, int pagesize)
 1982: {
 1983:     int8_t ccb[16] = { ATAPI_MODE_SELECT_BIG, 0x10, 0, 0, 0, 0, 0,
 1984: 		     pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 };
 1985: 
 1986: #ifdef ACD_DEBUG
 1987:     ata_prtdev(cdp->device,
 1988: 	       "modeselect pagesize=%d\n", pagesize);
 1989:     atapi_dump("mode select ", pagebuf, pagesize);
 1990: #endif
 1991:     return atapi_queue_cmd(cdp->device, ccb, pagebuf, pagesize, 0,
 1992: 			   30, NULL, NULL);
 1993: }
 1994: 
 1995: static int
 1996: acd_set_speed(struct acd_softc *cdp, int rdspeed, int wrspeed)
 1997: {
 1998:     int8_t ccb[16] = { ATAPI_SET_SPEED, 0, rdspeed >> 8, rdspeed, 
 1999: 		       wrspeed >> 8, wrspeed, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 2000:     int error;
 2001: 
 2002:     error = atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
 2003:     if (!error)
 2004: 	acd_get_cap(cdp);
 2005:     return error;
 2006: }
 2007: 
 2008: static void
 2009: acd_get_cap(struct acd_softc *cdp)
 2010: {
 2011:     int retry = 5;
 2012: 
 2013:     /* get drive capabilities, some drives needs this repeated */
 2014:     while (retry-- && acd_mode_sense(cdp, ATAPI_CDROM_CAP_PAGE,
 2015: 				     (caddr_t)&cdp->cap, sizeof(cdp->cap)))
 2016: 
 2017:     cdp->cap.max_read_speed = ntohs(cdp->cap.max_read_speed);
 2018:     cdp->cap.cur_read_speed = ntohs(cdp->cap.cur_read_speed);
 2019:     cdp->cap.max_write_speed = ntohs(cdp->cap.max_write_speed);
 2020:     cdp->cap.cur_write_speed = max(ntohs(cdp->cap.cur_write_speed), 177);
 2021:     cdp->cap.max_vol_levels = ntohs(cdp->cap.max_vol_levels);
 2022:     cdp->cap.buf_size = ntohs(cdp->cap.buf_size);
 2023: }