diff options
Diffstat (limited to 'sys/dev/ata/atapi-cd.c')
| -rw-r--r-- | sys/dev/ata/atapi-cd.c | 1437 |
1 files changed, 741 insertions, 696 deletions
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index ab7a43f5f3acc..4cf3f2092b919 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -30,6 +30,7 @@ #include "ata.h" #include "atapicd.h" +#include "apm.h" #if NATA > 0 && NATAPICD > 0 @@ -47,6 +48,9 @@ #include <sys/conf.h> #include <sys/stat.h> #include <pci/pcivar.h> +#if NAPM > 0 +#include <machine/apm_bios.h> +#endif #include <dev/ata/ata-all.h> #include <dev/ata/atapi-all.h> #include <dev/ata/atapi-cd.h> @@ -78,44 +82,37 @@ static struct cdevsw acd_cdevsw = { /* bmaj */ 31 }; +/* misc defines */ #define NUNIT 16 /* max # of devices */ -#define F_BOPEN 0x0001 /* the block device is opened */ -#define F_MEDIA_CHANGED 0x0002 /* The media have changed since open */ -#define F_LOCKED 0x0004 /* this unit is locked (or should be) */ -#define F_TRACK_PREP 0x0008 /* track should be prep'ed */ -#define F_TRACK_PREPED 0x0010 /* track has been prep'ed */ -#define F_DISK_PREPED 0x0020 /* disk has been prep'ed */ -#define F_WRITTEN 0x0040 /* the medium has been written to */ - -static struct acd_softc *acdtab[NUNIT]; -static int32_t acdnlun = 0; /* number of configured drives */ - +/* prototypes */ int32_t acdattach(struct atapi_softc *); static struct acd_softc *acd_init_lun(struct atapi_softc *, int, struct devstat *); +static void acd_describe(struct acd_softc *); +static void lba2msf(int32_t, u_int8_t *, u_int8_t *, u_int8_t *); +static int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t); static void acd_start(struct acd_softc *); static void acd_done(struct atapi_request *); -static int32_t acd_test_unit_ready (struct acd_softc *); -static int32_t acd_lock_device (struct acd_softc *, int32_t); -static int32_t acd_start_device (struct acd_softc *, int32_t); -static int32_t acd_pause_device (struct acd_softc *, int32_t); -static int32_t acd_mode_sense (struct acd_softc *, u_int8_t, void *, int32_t); -static int32_t acd_mode_select (struct acd_softc *, void *, int32_t); static int32_t acd_read_toc(struct acd_softc *); -static void acd_describe(struct acd_softc *); static int32_t acd_setchan(struct acd_softc *, u_int8_t, u_int8_t, u_int8_t, u_int8_t); -static int32_t acd_eject(struct acd_softc *, int); static void acd_select_slot(struct acd_softc *); static int32_t acd_open_disk(struct acd_softc *, int); static int32_t acd_open_track(struct acd_softc *, struct wormio_prepare_track *); static int32_t acd_close_track(struct acd_softc *); static int32_t acd_close_disk(struct acd_softc *); static int32_t acd_read_track_info(struct acd_softc *, int, struct acd_track_info*); -static int32_t acd_blank_disk(struct acd_softc *); -static void lba2msf(int32_t, u_int8_t *, u_int8_t *, u_int8_t *); -static int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t); +static int32_t acd_eject(struct acd_softc *, int); +static int32_t acd_blank(struct acd_softc *); +static int32_t acd_prevent_allow(struct acd_softc *, int32_t); +static int32_t acd_start_stop(struct acd_softc *, int32_t); +static int32_t acd_pause_resume(struct acd_softc *, int32_t); +static int32_t acd_mode_sense(struct acd_softc *, u_int8_t, void *, int32_t); +static int32_t acd_mode_select(struct acd_softc *, void *, int32_t); static void acd_drvinit(void *); +/* internal vars */ +static int32_t acdnlun = 0; /* number of configured drives */ + int acdattach(struct atapi_softc *atp) { @@ -124,88 +121,89 @@ acdattach(struct atapi_softc *atp) int32_t error, count; if (acdnlun >= NUNIT) { - printf("acd: too many units\n"); - return -1; + printf("acd: too many units\n"); + return -1; } if ((cdp = acd_init_lun(atp, acdnlun, NULL)) == NULL) { - printf("acd: out of memory\n"); - return -1; + printf("acd: out of memory\n"); + return -1; } /* get drive capabilities, some drives needs this repeated */ for (count = 0 ; count < 5 ; count++) { if (!(error = acd_mode_sense(cdp, ATAPI_CDROM_CAP_PAGE, &cdp->cap, sizeof(cdp->cap)))) - break; + break; } if (error) { free(cdp, M_TEMP); return -1; } - cdp->cap.max_speed = ntohs(cdp->cap.max_speed); + cdp->cap.max_read_speed = ntohs(cdp->cap.max_read_speed); + cdp->cap.cur_read_speed = ntohs(cdp->cap.cur_read_speed); + cdp->cap.max_write_speed = ntohs(cdp->cap.max_write_speed); + cdp->cap.cur_write_speed = ntohs(cdp->cap.cur_write_speed); cdp->cap.max_vol_levels = ntohs(cdp->cap.max_vol_levels); cdp->cap.buf_size = ntohs(cdp->cap.buf_size); - cdp->cap.cur_speed = ntohs(cdp->cap.cur_speed); acd_describe(cdp); /* if this is a changer device, allocate the neeeded lun's */ if (cdp->cap.mech == MST_MECH_CHANGER) { int8_t ccb[16] = { ATAPI_MECH_STATUS, - 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, sizeof(struct changer)>>8, sizeof(struct changer), - 0, 0, 0, 0, 0, 0 }; - - chp = malloc(sizeof(struct changer), M_TEMP, M_NOWAIT); - if (chp == NULL) { - printf("acd: out of memory\n"); - return 0; - } - bzero(chp, sizeof(struct changer)); - error = atapi_queue_cmd(cdp->atp, ccb, chp, sizeof(struct changer), - A_READ, 60, NULL, NULL, NULL); + 0, 0, 0, 0, 0, 0 }; + chp = malloc(sizeof(struct changer), M_TEMP, M_NOWAIT); + if (chp == NULL) { + printf("acd: out of memory\n"); + return 0; + } + bzero(chp, sizeof(struct changer)); + error = atapi_immed_cmd(cdp->atp, ccb, chp, sizeof(struct changer), + A_READ, 60); #ifdef ACD_DEBUG - printf("error=%02x curr=%02x slots=%d len=%d\n", - error, chp->current_slot, chp->slots, htons(chp->table_length)); + printf("error=%02x curr=%02x slots=%d len=%d\n", + error, chp->current_slot, chp->slots, htons(chp->table_length)); #endif - if (!error) { - struct acd_softc *tmpcdp = cdp; + if (!error) { + struct acd_softc *tmpcdp = cdp; int32_t count; int8_t string[16]; - chp->table_length = htons(chp->table_length); - for (count = 0; count < chp->slots && acdnlun < NUNIT; count++) { - if (count > 0) { - tmpcdp = acd_init_lun(atp, acdnlun, cdp->stats); + chp->table_length = htons(chp->table_length); + for (count = 0; count < chp->slots && acdnlun < NUNIT; count++) { + if (count > 0) { + tmpcdp = acd_init_lun(atp, acdnlun, cdp->stats); if (!tmpcdp) { - printf("acd: out of memory\n"); - return -1; - } - } - tmpcdp->slot = count; - tmpcdp->changer_info = chp; - printf("acd%d: changer slot %d %s\n", acdnlun, count, + printf("acd: out of memory\n"); + return -1; + } + } + tmpcdp->slot = count; + tmpcdp->changer_info = chp; + printf("acd%d: changer slot %d %s\n", acdnlun, count, (chp->slot[count].present ? "CD present" : "empty")); - acdtab[acdnlun++] = tmpcdp; - } - if (acdnlun >= NUNIT) { - printf("acd: too many units\n"); - return 0; - } + acdnlun++; + } + if (acdnlun >= NUNIT) { + printf("acd: too many units\n"); + return 0; + } sprintf(string, "acd%d-", cdp->lun); - devstat_add_entry(cdp->stats, string, tmpcdp->lun, DEV_BSIZE, - DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE, + devstat_add_entry(cdp->stats, string, tmpcdp->lun, DEV_BSIZE, + DEVSTAT_NO_ORDERED_TAGS, + DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE, 0x178); - } + } } else { - acdtab[acdnlun++] = cdp; - devstat_add_entry(cdp->stats, "acd", cdp->lun, DEV_BSIZE, - DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE, + devstat_add_entry(cdp->stats, "acd", cdp->lun, DEV_BSIZE, + DEVSTAT_NO_ORDERED_TAGS, + DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE, 0x178); + acdnlun++; } return 0; } @@ -214,35 +212,40 @@ static struct acd_softc * acd_init_lun(struct atapi_softc *atp, int32_t lun, struct devstat *stats) { struct acd_softc *acd; + dev_t dev; if (!(acd = malloc(sizeof(struct acd_softc), M_TEMP, M_NOWAIT))) - return NULL; + return NULL; bzero(acd, sizeof(struct acd_softc)); bufq_init(&acd->buf_queue); acd->atp = atp; acd->lun = lun; - acd->flags = F_MEDIA_CHANGED; acd->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED); acd->block_size = 2048; acd->refcnt = 0; acd->slot = -1; acd->changer_info = NULL; + acd->atp->flags |= ATAPI_F_MEDIA_CHANGED; if (stats == NULL) { - if (!(acd->stats = malloc(sizeof(struct devstat), + if (!(acd->stats = malloc(sizeof(struct devstat), M_TEMP, M_NOWAIT))) - return NULL; + return NULL; bzero(acd->stats, sizeof(struct devstat)); } else acd->stats = stats; - make_dev(&acd_cdevsw, dkmakeminor(lun, 0, 0), - UID_ROOT, GID_OPERATOR, 0644, "racd%da", lun); - make_dev(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART), - UID_ROOT, GID_OPERATOR, 0644, "racd%dc", lun); - make_dev(&acd_cdevsw, dkmakeminor(lun, 0, 0), - UID_ROOT, GID_OPERATOR, 0644, "acd%da", lun); - make_dev(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART), - UID_ROOT, GID_OPERATOR, 0644, "acd%dc", lun); + dev = make_dev(&acd_cdevsw, dkmakeminor(lun, 0, 0), + UID_ROOT, GID_OPERATOR, 0644, "racd%da", lun); + dev->si_drv1 = acd; + dev = make_dev(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART), + UID_ROOT, GID_OPERATOR, 0644, "racd%dc", lun); + dev->si_drv1 = acd; + dev = make_dev(&acd_cdevsw, dkmakeminor(lun, 0, 0), + UID_ROOT, GID_OPERATOR, 0644, "acd%da", lun); + dev->si_drv1 = acd; + dev = make_dev(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART), + UID_ROOT, GID_OPERATOR, 0644, "acd%dc", lun); + dev->si_drv1 = acd; return acd; } @@ -257,125 +260,149 @@ acd_describe(struct acd_softc *cdp) bpack(cdp->atp->atapi_parm->model, model_buf, sizeof(model_buf)); bpack(cdp->atp->atapi_parm->revision, revision_buf, sizeof(revision_buf)); printf("acd%d: <%s/%s> CDROM drive at ata%d as %s\n", - cdp->lun, model_buf, revision_buf, - cdp->atp->controller->lun, - (cdp->atp->unit == ATA_MASTER) ? "master" : "slave "); + cdp->lun, model_buf, revision_buf, + cdp->atp->controller->lun, + (cdp->atp->unit == ATA_MASTER) ? "master" : "slave "); - printf("acd%d: drive speed ", cdp->lun); - if (cdp->cap.cur_speed != cdp->cap.max_speed) - printf("%d - ", cdp->cap.cur_speed * 1000 / 1024); - printf("%dKB/sec", cdp->cap.max_speed * 1000 / 1024); + if (cdp->cap.cur_read_speed) { + printf("acd%d: ", cdp->lun); + printf("read %dKB/s", cdp->cap.cur_read_speed * 1000 / 1024); + if (cdp->cap.max_read_speed) + printf(" (%dKB/s)", cdp->cap.max_read_speed * 1000 / 1024); + if ((cdp->cap.cur_write_speed) && + (cdp->cap.write_cdr || cdp->cap.write_cdrw || + cdp->cap.write_dvdr || cdp->cap.write_dvdram)) { + printf(" write %dKB/s", cdp->cap.cur_write_speed * 1000 / 1024); + if (cdp->cap.max_write_speed) + printf(" (%dKB/s)", cdp->cap.max_write_speed * 1000 / 1024); + } + } if (cdp->cap.buf_size) - printf(", %dKB cache", cdp->cap.buf_size); - if (cdp->atp->flags & ATAPI_F_DMA_ENABLED) - printf(", DMA"); - printf("\n"); + printf(", %dKB buffer", cdp->cap.buf_size); + printf(", %s\n", ata_mode2str(cdp->atp->controller->mode[ + (cdp->atp->unit == ATA_MASTER) ? 0 : 1])); printf("acd%d: supported read types:", cdp->lun); comma = 0; if (cdp->cap.read_cdr) { - printf(" CD-R"); comma = 1; + printf(" CD-R"); comma = 1; } if (cdp->cap.read_cdrw) { - printf("%s CD-RW", comma ? "," : ""); comma = 1; + printf("%s CD-RW", comma ? "," : ""); comma = 1; } if (cdp->cap.cd_da) { - printf("%s CD-DA", comma ? "," : ""); comma = 1; + printf("%s CD-DA", comma ? "," : ""); comma = 1; + } + if (cdp->cap.read_dvdrom) { + printf("%s DVD-ROM", comma ? "," : ""); comma = 1; + } + if (cdp->cap.read_dvdr) { + printf("%s DVD-R", comma ? "," : ""); comma = 1; } - if (cdp->cap.method2) - printf("%s packet track", comma ? "," : ""); - if (cdp->cap.write_cdr || cdp->cap.write_cdrw) { - printf("\nacd%d: supported write types:", cdp->lun); - comma = 0; - if (cdp->cap.write_cdr) { - printf(" CD-R" ); comma = 1; + if (cdp->cap.read_dvdram) { + printf("%s DVD-RAM", comma ? "," : ""); comma = 1; + } + if (cdp->cap.read_packet) + printf("%s packet", comma ? "," : ""); + + if (cdp->cap.write_cdr || cdp->cap.write_cdrw || + cdp->cap.write_dvdr || cdp->cap.write_dvdram) { + printf("\nacd%d: supported write types:", cdp->lun); + comma = 0; + if (cdp->cap.write_cdr) { + printf(" CD-R" ); comma = 1; } - if (cdp->cap.write_cdrw) { - printf("%s CD-RW", comma ? "," : ""); comma = 1; + if (cdp->cap.write_cdrw) { + printf("%s CD-RW", comma ? "," : ""); comma = 1; } - if (cdp->cap.test_write) { - printf("%s test write", comma ? "," : ""); comma = 1; + if (cdp->cap.write_dvdr) { + printf("%s DVD-R", comma ? "," : ""); comma = 1; } + if (cdp->cap.write_dvdram) { + printf("%s DVD-RAM", comma ? "," : ""); comma = 1; + } + if (cdp->cap.test_write) + printf("%s test write", comma ? "," : ""); } if (cdp->cap.audio_play) { - printf("\nacd%d: Audio: ", cdp->lun); - if (cdp->cap.audio_play) - printf("play"); - if (cdp->cap.max_vol_levels) - printf(", %d volume levels", cdp->cap.max_vol_levels); + printf("\nacd%d: Audio: ", cdp->lun); + if (cdp->cap.audio_play) + printf("play"); + if (cdp->cap.max_vol_levels) + printf(", %d volume levels", cdp->cap.max_vol_levels); } printf("\nacd%d: Mechanism: ", cdp->lun); switch (cdp->cap.mech) { case MST_MECH_CADDY: - mechanism = "caddy"; break; + mechanism = "caddy"; break; case MST_MECH_TRAY: - mechanism = "tray"; break; + mechanism = "tray"; break; case MST_MECH_POPUP: - mechanism = "popup"; break; + mechanism = "popup"; break; case MST_MECH_CHANGER: - mechanism = "changer"; break; + mechanism = "changer"; break; case MST_MECH_CARTRIDGE: - mechanism = "cartridge"; break; + mechanism = "cartridge"; break; default: - mechanism = 0; break; + mechanism = 0; break; } if (mechanism) - printf("%s%s", cdp->cap.eject ? "ejectable " : "", mechanism); + printf("%s%s", cdp->cap.eject ? "ejectable " : "", mechanism); else if (cdp->cap.eject) - printf("ejectable"); + printf("ejectable"); if (cdp->cap.mech != MST_MECH_CHANGER) { - printf("\nacd%d: Medium: ", cdp->lun); - switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) { - case MST_CDROM: - printf("CD-ROM "); break; - case MST_CDR: - printf("CD-R "); break; - case MST_CDRW: - printf("CD-RW "); break; - case MST_DOOR_OPEN: - printf("door open"); break; - case MST_NO_DISC: - printf("no/blank disc inside"); break; - case MST_FMT_ERROR: - printf("medium format error"); break; + printf("\nacd%d: Medium: ", cdp->lun); + switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) { + case MST_CDROM: + printf("CD-ROM "); break; + case MST_CDR: + printf("CD-R "); break; + case MST_CDRW: + printf("CD-RW "); break; + case MST_DOOR_OPEN: + printf("door open"); break; + case MST_NO_DISC: + printf("no/blank disc inside"); break; + case MST_FMT_ERROR: + printf("medium format error"); break; } - if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH) < MST_TYPE_MASK_HIGH) { - switch (cdp->cap.medium_type & MST_TYPE_MASK_LOW) { - case MST_DATA_120: - printf("120mm data disc loaded"); break; - case MST_AUDIO_120: - printf("120mm audio disc loaded"); break; - case MST_COMB_120: - printf("120mm data/audio disc loaded"); break; - case MST_PHOTO_120: - printf("120mm photo disc loaded"); break; - case MST_DATA_80: - printf("80mm data disc loaded"); break; - case MST_AUDIO_80: - printf("80mm audio disc loaded"); break; - case MST_COMB_80: - printf("80mm data/audio disc loaded"); break; - case MST_PHOTO_80: - printf("80mm photo disc loaded"); break; - case MST_FMT_NONE: - switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) { - case MST_CDROM: + if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH) < MST_TYPE_MASK_HIGH) { + switch (cdp->cap.medium_type & MST_TYPE_MASK_LOW) { + case MST_DATA_120: + printf("120mm data disc loaded"); break; + case MST_AUDIO_120: + printf("120mm audio disc loaded"); break; + case MST_COMB_120: + printf("120mm data/audio disc loaded"); break; + case MST_PHOTO_120: + printf("120mm photo disc loaded"); break; + case MST_DATA_80: + printf("80mm data disc loaded"); break; + case MST_AUDIO_80: + printf("80mm audio disc loaded"); break; + case MST_COMB_80: + printf("80mm data/audio disc loaded"); break; + case MST_PHOTO_80: + printf("80mm photo disc loaded"); break; + case MST_FMT_NONE: + switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) { + case MST_CDROM: printf("unknown medium"); break; - case MST_CDR: - case MST_CDRW: - printf("blank medium"); break; - } - break; - default: - printf("unknown type=0x%x", cdp->cap.medium_type); break; - } + case MST_CDR: + case MST_CDRW: + printf("blank medium"); break; + } + break; + default: + printf("unknown type=0x%x", cdp->cap.medium_type); break; + } } } if (cdp->cap.lock) - printf(cdp->cap.locked ? ", locked" : ", unlocked"); + printf(cdp->cap.locked ? ", locked" : ", unlocked"); if (cdp->cap.prevent) - printf(", lock protected"); + printf(", lock protected"); printf("\n"); } @@ -399,333 +426,329 @@ msf2lba(u_int8_t m, u_int8_t s, u_int8_t f) static int acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { - int32_t lun = dkunit(dev); - struct acd_softc *cdp; + struct acd_softc *cdp = dev->si_drv1; - if (lun >= acdnlun || !(cdp = acdtab[lun])) - return ENXIO; + if (cdp->flags & F_WRITING) + return EBUSY; + + if (flags & FWRITE) { + if ((cdp->flags & F_BOPEN) || cdp->refcnt) + return EBUSY; + else + cdp->flags |= F_WRITING; + } - dev->si_bsize_phys = 2048; + dev->si_bsize_phys = 2048; /* XXX SOS */ if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) { - acd_lock_device(cdp, 1); /* prevent user eject */ - cdp->flags |= F_LOCKED; + acd_prevent_allow(cdp, 1); /* prevent user eject */ + cdp->flags |= F_LOCKED; + if (!(flags & O_NONBLOCK) && acd_read_toc(cdp) && !(flags & FWRITE)) + printf("acd%d: read_toc failed\n", cdp->lun); } if (fmt == S_IFBLK) - cdp->flags |= F_BOPEN; + cdp->flags |= F_BOPEN; else - cdp->refcnt++; - - if (!(flags & O_NONBLOCK) && acd_read_toc(cdp) && !(flags & FWRITE)) - printf("acd%d: read_toc failed\n", lun); + cdp->refcnt++; return 0; } static int acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { - int32_t lun = dkunit(dev); - struct acd_softc *cdp; + struct acd_softc *cdp = dev->si_drv1; - if (lun >= acdnlun || !(cdp = acdtab[lun])) - return ENXIO; - if (fmt == S_IFBLK) - cdp->flags &= ~F_BOPEN; + cdp->flags &= ~F_BOPEN; else - cdp->refcnt--; + cdp->refcnt--; /* are we the last open ?? */ if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) { /* yup, do we need to close any written tracks */ - if ((flags & FWRITE) != 0) { - if ((cdp->flags & F_TRACK_PREPED) != 0) { - acd_close_track(cdp); - cdp->flags &= ~(F_TRACK_PREPED | F_TRACK_PREP); - } - } - acd_lock_device(cdp, 0); /* allow the user eject */ + if ((flags & FWRITE) != 0) { + if ((cdp->flags & F_TRACK_PREPED) != 0) { + acd_close_track(cdp); + cdp->flags &= ~(F_TRACK_PREPED | F_TRACK_PREP); + } + } + acd_prevent_allow(cdp, 0); /* allow the user eject */ } - cdp->flags &= ~F_LOCKED; + cdp->flags &= ~(F_LOCKED | F_WRITING); return 0; } static int acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) { - int32_t lun = dkunit(dev); - struct acd_softc *cdp = acdtab[lun]; + struct acd_softc *cdp = dev->si_drv1; int32_t error = 0; - if (cdp->flags & F_MEDIA_CHANGED) - switch (cmd) { - case CDIOCRESET: - acd_test_unit_ready(cdp); + if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED) + switch (cmd) { + case CDIOCRESET: + atapi_test_ready(cdp->atp); break; - - default: - acd_read_toc(cdp); - acd_lock_device(cdp, 1); - cdp->flags |= F_LOCKED; - break; - } + + default: + acd_read_toc(cdp); + acd_prevent_allow(cdp, 1); + cdp->flags |= F_LOCKED; + break; + } switch (cmd) { case CDIOCRESUME: - error = acd_pause_device(cdp, 1); + error = acd_pause_resume(cdp, 1); break; case CDIOCPAUSE: - error = acd_pause_device(cdp, 0); + error = acd_pause_resume(cdp, 0); break; case CDIOCSTART: - error = acd_start_device(cdp, 1); + error = acd_start_stop(cdp, 1); break; case CDIOCSTOP: - error = acd_start_device(cdp, 0); + error = acd_start_stop(cdp, 0); break; case CDIOCALLOW: - acd_select_slot(cdp); - cdp->flags &= ~F_LOCKED; - error = acd_lock_device(cdp, 0); + acd_select_slot(cdp); + cdp->flags &= ~F_LOCKED; + error = acd_prevent_allow(cdp, 0); break; case CDIOCPREVENT: - acd_select_slot(cdp); - cdp->flags |= F_LOCKED; - error = acd_lock_device(cdp, 1); + acd_select_slot(cdp); + cdp->flags |= F_LOCKED; + error = acd_prevent_allow(cdp, 1); break; case CDIOCRESET: - error = suser(p); - if (error) - break; - error = acd_test_unit_ready(cdp); + error = suser(p); + if (error) + break; + error = atapi_error(cdp->atp, atapi_test_ready(cdp->atp)); break; case CDIOCEJECT: - if ((cdp->flags & F_BOPEN) && cdp->refcnt) { - error = EBUSY; + if ((cdp->flags & F_BOPEN) && cdp->refcnt) { + error = EBUSY; break; } - error = acd_eject(cdp, 0); + error = acd_eject(cdp, 0); break; case CDIOCCLOSE: - if ((cdp->flags & F_BOPEN) && cdp->refcnt) - break; - error = acd_eject(cdp, 1); + if ((cdp->flags & F_BOPEN) && cdp->refcnt) + break; + error = acd_eject(cdp, 1); break; case CDIOREADTOCHEADER: - if (!cdp->toc.hdr.ending_track) { - error = EIO; + if (!cdp->toc.hdr.ending_track) { + error = EIO; break; } - bcopy(&cdp->toc.hdr, addr, sizeof(cdp->toc.hdr)); - break; + bcopy(&cdp->toc.hdr, addr, sizeof(cdp->toc.hdr)); + break; case CDIOREADTOCENTRYS: { - struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)addr; - struct toc *toc = &cdp->toc; - struct toc buf; - u_int32_t len; - u_int8_t starting_track = te->starting_track; + struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)addr; + struct toc *toc = &cdp->toc; + struct toc buf; + u_int32_t len; + u_int8_t starting_track = te->starting_track; - if (!cdp->toc.hdr.ending_track) { - error = EIO; + if (!cdp->toc.hdr.ending_track) { + error = EIO; break; } - if (te->data_len < sizeof(toc->tab[0]) || + if (te->data_len < sizeof(toc->tab[0]) || (te->data_len % sizeof(toc->tab[0])) != 0 || (te->address_format != CD_MSF_FORMAT && te->address_format != CD_LBA_FORMAT)) { - error = EINVAL; + error = EINVAL; break; } - if (!starting_track) - starting_track = toc->hdr.starting_track; - else if (starting_track == 170) - starting_track = toc->hdr.ending_track + 1; - else if (starting_track < toc->hdr.starting_track || - starting_track > toc->hdr.ending_track + 1) { - error = EINVAL; + if (!starting_track) + starting_track = toc->hdr.starting_track; + else if (starting_track == 170) + starting_track = toc->hdr.ending_track + 1; + else if (starting_track < toc->hdr.starting_track || + starting_track > toc->hdr.ending_track + 1) { + error = EINVAL; break; } - len = ((toc->hdr.ending_track + 1 - starting_track) + 1) * + len = ((toc->hdr.ending_track + 1 - starting_track) + 1) * sizeof(toc->tab[0]); - if (te->data_len < len) - len = te->data_len; - if (len > sizeof(toc->tab)) { - error = EINVAL; + if (te->data_len < len) + len = te->data_len; + if (len > sizeof(toc->tab)) { + error = EINVAL; break; } - if (te->address_format == CD_MSF_FORMAT) { - struct cd_toc_entry *entry; + if (te->address_format == CD_MSF_FORMAT) { + struct cd_toc_entry *entry; - buf = cdp->toc; - toc = &buf; - entry = toc->tab + (toc->hdr.ending_track + 1 - - toc->hdr.starting_track) + 1; - while (--entry >= toc->tab) - lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute, - &entry->addr.msf.second, &entry->addr.msf.frame); - } - error = copyout(toc->tab + starting_track - toc->hdr.starting_track, - te->data, len); + buf = cdp->toc; + toc = &buf; + entry = toc->tab + (toc->hdr.ending_track + 1 - + toc->hdr.starting_track) + 1; + while (--entry >= toc->tab) + lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute, + &entry->addr.msf.second, &entry->addr.msf.frame); + } + error = copyout(toc->tab + starting_track - toc->hdr.starting_track, + te->data, len); break; - } + } case CDIOREADTOCENTRY: { - struct ioc_read_toc_single_entry *te = - (struct ioc_read_toc_single_entry *)addr; - struct toc *toc = &cdp->toc; - struct toc buf; - u_int8_t track = te->track; + struct ioc_read_toc_single_entry *te = + (struct ioc_read_toc_single_entry *)addr; + struct toc *toc = &cdp->toc; + struct toc buf; + u_int8_t track = te->track; - if (!cdp->toc.hdr.ending_track) { - error = EIO; + if (!cdp->toc.hdr.ending_track) { + error = EIO; break; } - if (te->address_format != CD_MSF_FORMAT && + if (te->address_format != CD_MSF_FORMAT && te->address_format != CD_LBA_FORMAT) { - error = EINVAL; + error = EINVAL; break; } - if (!track) - track = toc->hdr.starting_track; - else if (track == 170) - track = toc->hdr.ending_track + 1; - else if (track < toc->hdr.starting_track || - track > toc->hdr.ending_track + 1) { - error = EINVAL; + if (!track) + track = toc->hdr.starting_track; + else if (track == 170) + track = toc->hdr.ending_track + 1; + else if (track < toc->hdr.starting_track || + track > toc->hdr.ending_track + 1) { + error = EINVAL; break; } - if (te->address_format == CD_MSF_FORMAT) { - struct cd_toc_entry *entry; + if (te->address_format == CD_MSF_FORMAT) { + struct cd_toc_entry *entry; - buf = cdp->toc; - toc = &buf; - entry = toc->tab + (track - toc->hdr.starting_track); - lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute, - &entry->addr.msf.second, &entry->addr.msf.frame); - } - bcopy(toc->tab + track - toc->hdr.starting_track, - &te->entry, sizeof(struct cd_toc_entry)); - } + buf = cdp->toc; + toc = &buf; + entry = toc->tab + (track - toc->hdr.starting_track); + lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute, + &entry->addr.msf.second, &entry->addr.msf.frame); + } + bcopy(toc->tab + track - toc->hdr.starting_track, + &te->entry, sizeof(struct cd_toc_entry)); + } break; case CDIOCREADSUBCHANNEL: { - struct ioc_read_subchannel *args = - (struct ioc_read_subchannel *)addr; - struct cd_sub_channel_info data; - u_int32_t len = args->data_len; - int32_t abslba, rellba; + struct ioc_read_subchannel *args = + (struct ioc_read_subchannel *)addr; + struct cd_sub_channel_info data; + u_int32_t len = args->data_len; + int32_t abslba, rellba; int8_t ccb[16] = { ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, 0, 0, sizeof(cdp->subchan)>>8, sizeof(cdp->subchan), 0, 0, 0, 0, 0, 0, 0 }; - if (len > sizeof(data) || - len < sizeof(struct cd_sub_channel_header)) { - error = EINVAL; + if (len > sizeof(data) || + len < sizeof(struct cd_sub_channel_header)) { + error = EINVAL; break; } - if ((error = atapi_queue_cmd(cdp->atp, ccb, &cdp->subchan, - sizeof(cdp->subchan), A_READ, 10, - NULL, NULL, NULL))) - break; - -#ifdef ACD_DEBUG - atapi_dump("acd: subchan", &cdp->subchan, sizeof(cdp->subchan)); -#endif - - abslba = cdp->subchan.abslba; - rellba = cdp->subchan.rellba; - if (args->address_format == CD_MSF_FORMAT) { - lba2msf(ntohl(abslba), - &data.what.position.absaddr.msf.minute, - &data.what.position.absaddr.msf.second, - &data.what.position.absaddr.msf.frame); - lba2msf(ntohl(rellba), - &data.what.position.reladdr.msf.minute, - &data.what.position.reladdr.msf.second, - &data.what.position.reladdr.msf.frame); - } else { - data.what.position.absaddr.lba = abslba; - data.what.position.reladdr.lba = rellba; - } - data.header.audio_status = cdp->subchan.audio_status; - data.what.position.control = cdp->subchan.control & 0xf; - data.what.position.addr_type = cdp->subchan.control >> 4; - data.what.position.track_number = cdp->subchan.track; - data.what.position.index_number = cdp->subchan.indx; - error = copyout(&data, args->data, len); + if ((error = atapi_immed_cmd(cdp->atp, ccb, &cdp->subchan, + sizeof(cdp->subchan), A_READ, 10))) { + error = atapi_error(cdp->atp, error); + break; + } + abslba = cdp->subchan.abslba; + rellba = cdp->subchan.rellba; + if (args->address_format == CD_MSF_FORMAT) { + lba2msf(ntohl(abslba), + &data.what.position.absaddr.msf.minute, + &data.what.position.absaddr.msf.second, + &data.what.position.absaddr.msf.frame); + lba2msf(ntohl(rellba), + &data.what.position.reladdr.msf.minute, + &data.what.position.reladdr.msf.second, + &data.what.position.reladdr.msf.frame); + } else { + data.what.position.absaddr.lba = abslba; + data.what.position.reladdr.lba = rellba; + } + data.header.audio_status = cdp->subchan.audio_status; + data.what.position.control = cdp->subchan.control & 0xf; + data.what.position.addr_type = cdp->subchan.control >> 4; + data.what.position.track_number = cdp->subchan.track; + data.what.position.index_number = cdp->subchan.indx; + error = copyout(&data, args->data, len); break; - } + } case CDIOCPLAYMSF: { - struct ioc_play_msf *args = (struct ioc_play_msf *)addr; - int8_t ccb[16] = { ATAPI_PLAY_MSF, 0, 0, + struct ioc_play_msf *args = (struct ioc_play_msf *)addr; + int8_t ccb[16] = { ATAPI_PLAY_MSF, 0, 0, args->start_m, args->start_s, args->start_f, args->end_m, args->end_s, args->end_f, - 0, 0, 0, 0, 0, 0, 0 }; + 0, 0, 0, 0, 0, 0, 0 }; - error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, - NULL, NULL,NULL); + error = atapi_error(cdp->atp, + atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10)); break; - } + } case CDIOCPLAYBLOCKS: { - struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr; + struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr; int8_t ccb[16] = { ATAPI_PLAY_BIG, 0, - args->blk>>24, args->blk>>16, args->blk>>8, + args->blk>>24, args->blk>>16, args->blk>>8, args->blk, args->len>>24, args->len>>16, args->len>>8, args->len, - 0, 0, 0, 0, 0, 0 }; + 0, 0, 0, 0, 0, 0 }; - error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, - NULL, NULL, NULL); + error = atapi_error(cdp->atp, + atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10)); break; - } + } case CDIOCPLAYTRACKS: { - struct ioc_play_track *args = (struct ioc_play_track *)addr; - u_int32_t start, len; - int32_t t1, t2; + struct ioc_play_track *args = (struct ioc_play_track *)addr; + u_int32_t start, len; + int32_t t1, t2; int8_t ccb[16]; - if (!cdp->toc.hdr.ending_track) { - error = EIO; + if (!cdp->toc.hdr.ending_track) { + error = EIO; break; } - if (args->end_track < cdp->toc.hdr.ending_track + 1) - ++args->end_track; - if (args->end_track > cdp->toc.hdr.ending_track + 1) - args->end_track = cdp->toc.hdr.ending_track + 1; - t1 = args->start_track - cdp->toc.hdr.starting_track; - t2 = args->end_track - cdp->toc.hdr.starting_track; - if (t1 < 0 || t2 < 0) { - error = EINVAL; + if (args->end_track < cdp->toc.hdr.ending_track + 1) + ++args->end_track; + if (args->end_track > cdp->toc.hdr.ending_track + 1) + args->end_track = cdp->toc.hdr.ending_track + 1; + t1 = args->start_track - cdp->toc.hdr.starting_track; + t2 = args->end_track - cdp->toc.hdr.starting_track; + if (t1 < 0 || t2 < 0) { + error = EINVAL; break; } - start = ntohl(cdp->toc.tab[t1].addr.lba); - len = ntohl(cdp->toc.tab[t2].addr.lba) - start; + start = ntohl(cdp->toc.tab[t1].addr.lba); + len = ntohl(cdp->toc.tab[t2].addr.lba) - start; bzero(ccb, sizeof(ccb)); ccb[0] = ATAPI_PLAY_BIG; @@ -738,10 +761,10 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) ccb[8] = len>>8; ccb[9] = len; - error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, - NULL, NULL, NULL); + error = atapi_error(cdp->atp, + atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10)); break; - } + } case CDIOCREADAUDIO: { @@ -763,7 +786,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) if (args->address_format == CD_LBA_FORMAT) lba = args->address.lba; else if (args->address_format == CD_MSF_FORMAT) - lba = msf2lba(args->address.msf.minute, + lba = msf2lba(args->address.msf.minute, args->address.msf.second, args->address.msf.frame); else { @@ -774,18 +797,18 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) #ifndef CD_BUFFER_BLOCKS #define CD_BUFFER_BLOCKS 13 #endif - if (!(buffer = malloc(CD_BUFFER_BLOCKS * 2352, + if (!(buffer = malloc(CD_BUFFER_BLOCKS * 2352, M_TEMP,M_NOWAIT))) { - error = ENOMEM; + error = ENOMEM; break; } bzero(ccb, sizeof(ccb)); - while (frames > 0) { - int32_t size; - u_int8_t blocks; + while (frames > 0) { + int32_t size; + u_int8_t blocks; - blocks = (frames>CD_BUFFER_BLOCKS) ? CD_BUFFER_BLOCKS : frames; - size = blocks * 2352; + blocks = (frames>CD_BUFFER_BLOCKS) ? CD_BUFFER_BLOCKS : frames; + size = blocks * 2352; ccb[0] = ATAPI_READ_CD; ccb[1] = 4; @@ -795,97 +818,97 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) ccb[5] = lba; ccb[8] = blocks; ccb[9] = 0xf0; - if ((error = atapi_queue_cmd(cdp->atp, ccb, buffer, size, + if ((error = atapi_queue_cmd(cdp->atp, ccb, buffer, size, A_READ, 30, NULL, NULL, NULL))) - break; + break; - if ((error = copyout(buffer, ubuf, size))) - break; - - ubuf += size; - frames -= blocks; - lba += blocks; - } - free(buffer, M_TEMP); + if ((error = copyout(buffer, ubuf, size))) + break; + + ubuf += size; + frames -= blocks; + lba += blocks; + } + free(buffer, M_TEMP); if (args->address_format == CD_LBA_FORMAT) args->address.lba = lba; else if (args->address_format == CD_MSF_FORMAT) - lba2msf(lba, &args->address.msf.minute, + lba2msf(lba, &args->address.msf.minute, &args->address.msf.second, &args->address.msf.frame); - break; - } + break; + } case CDIOCGETVOL: { - struct ioc_vol *arg = (struct ioc_vol *)addr; + struct ioc_vol *arg = (struct ioc_vol *)addr; if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, - &cdp->au, sizeof(cdp->au)))) - break; + &cdp->au, sizeof(cdp->au)))) + break; - if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) { - error = EIO; + if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) { + error = EIO; break; } - arg->vol[0] = cdp->au.port[0].volume; - arg->vol[1] = cdp->au.port[1].volume; - arg->vol[2] = cdp->au.port[2].volume; - arg->vol[3] = cdp->au.port[3].volume; - break; - } + arg->vol[0] = cdp->au.port[0].volume; + arg->vol[1] = cdp->au.port[1].volume; + arg->vol[2] = cdp->au.port[2].volume; + arg->vol[3] = cdp->au.port[3].volume; + break; + } case CDIOCSETVOL: { - struct ioc_vol *arg = (struct ioc_vol *)addr; + struct ioc_vol *arg = (struct ioc_vol *)addr; if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, - &cdp->au, sizeof(cdp->au)))) - break; - if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) { - error = EIO; + &cdp->au, sizeof(cdp->au)))) + break; + if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) { + error = EIO; break; } if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE_MASK, - &cdp->aumask, sizeof(cdp->aumask)))) - break; - cdp->au.data_length = 0; - cdp->au.port[0].channels = CHANNEL_0; - cdp->au.port[1].channels = CHANNEL_1; - cdp->au.port[0].volume = arg->vol[0] & cdp->aumask.port[0].volume; - cdp->au.port[1].volume = arg->vol[1] & cdp->aumask.port[1].volume; - cdp->au.port[2].volume = arg->vol[2] & cdp->aumask.port[2].volume; - cdp->au.port[3].volume = arg->vol[3] & cdp->aumask.port[3].volume; + &cdp->aumask, sizeof(cdp->aumask)))) + break; + cdp->au.data_length = 0; + cdp->au.port[0].channels = CHANNEL_0; + cdp->au.port[1].channels = CHANNEL_1; + cdp->au.port[0].volume = arg->vol[0] & cdp->aumask.port[0].volume; + cdp->au.port[1].volume = arg->vol[1] & cdp->aumask.port[1].volume; + cdp->au.port[2].volume = arg->vol[2] & cdp->aumask.port[2].volume; + cdp->au.port[3].volume = arg->vol[3] & cdp->aumask.port[3].volume; error = acd_mode_select(cdp, &cdp->au, sizeof(cdp->au)); break; - } + } case CDIOCSETPATCH: { - struct ioc_patch *arg = (struct ioc_patch *)addr; + struct ioc_patch *arg = (struct ioc_patch *)addr; - error = acd_setchan(cdp, arg->patch[0], arg->patch[1], - arg->patch[2], arg->patch[3]); + error = acd_setchan(cdp, arg->patch[0], arg->patch[1], + arg->patch[2], arg->patch[3]); break; - } + } case CDIOCSETMONO: - error = acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0,0); + error = acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0,0); break; case CDIOCSETSTEREO: - error = acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0); + error = acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0); break; case CDIOCSETMUTE: - error = acd_setchan(cdp, 0, 0, 0, 0); + error = acd_setchan(cdp, 0, 0, 0, 0); break; case CDIOCSETLEFT: - error = acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0); + error = acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0); break; case CDIOCSETRIGHT: - error = acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0); + error = acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0); break; case CDRIOCNEXTWRITEABLEADDR: @@ -899,79 +922,79 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) error = EINVAL; break; } - cdp->next_writeable_lba = track_info.next_writeable_addr; + cdp->next_writeable_addr = track_info.next_writeable_addr; *(int*)addr = track_info.next_writeable_addr; } break; case WORMIOCPREPDISK: - { - struct wormio_prepare_disk *w = (struct wormio_prepare_disk *)addr; + { + struct wormio_prepare_disk *w = (struct wormio_prepare_disk *)addr; - if (w->dummy != 0 && w->dummy != 1) - error = EINVAL; - else { - error = acd_open_disk(cdp, w->dummy); - if (error == 0) { - cdp->flags |= F_DISK_PREPED; - cdp->dummy = w->dummy; - cdp->speed = w->speed; - } - } - break; - } + if (w->dummy != 0 && w->dummy != 1) + error = EINVAL; + else { + error = acd_open_disk(cdp, w->dummy); + if (error == 0) { + cdp->flags |= F_DISK_PREPED; + cdp->dummy = w->dummy; + cdp->speed = w->speed; + } + } + break; + } case WORMIOCPREPTRACK: - { - struct wormio_prepare_track *w =(struct wormio_prepare_track *)addr; + { + struct wormio_prepare_track *w =(struct wormio_prepare_track *)addr; - if (w->audio != 0 && w->audio != 1) - error = EINVAL; - else if (w->audio == 0 && w->preemp) - error = EINVAL; - else if ((cdp->flags & F_DISK_PREPED) == 0) { - error = EINVAL; - printf("acd%d: sequence error (PREP_TRACK)\n", cdp->lun); - } else { - cdp->flags |= F_TRACK_PREP; - cdp->preptrack = *w; - } - break; - } + if (w->audio != 0 && w->audio != 1) + error = EINVAL; + else if (w->audio == 0 && w->preemp) + error = EINVAL; + else if ((cdp->flags & F_DISK_PREPED) == 0) { + error = EINVAL; + printf("acd%d: sequence error (PREP_TRACK)\n", cdp->lun); + } else { + cdp->flags |= F_TRACK_PREP; + cdp->preptrack = *w; + } + break; + } case WORMIOCFINISHTRACK: - if ((cdp->flags & F_TRACK_PREPED) != 0) - error = acd_close_track(cdp); - cdp->flags &= ~(F_TRACK_PREPED | F_TRACK_PREP); - break; + if ((cdp->flags & F_TRACK_PREPED) != 0) + error = acd_close_track(cdp); + cdp->flags &= ~(F_TRACK_PREPED | F_TRACK_PREP); + break; case WORMIOCFIXATION: - { - struct wormio_fixation *w = (struct wormio_fixation *)addr; + { + struct wormio_fixation *w = (struct wormio_fixation *)addr; - if ((cdp->flags & F_WRITTEN) == 0) - error = EINVAL; - else if (w->toc_type < 0 /* WORM_TOC_TYPE_AUDIO */ || - w->toc_type > 4 /* WORM_TOC_TYPE_CDI */ ) - error = EINVAL; - else if (w->onp != 0 && w->onp != 1) - error = EINVAL; - else { - /* no fixation needed if dummy write */ - if (cdp->dummy == 0) - error = acd_close_disk(cdp); - cdp->flags &= - ~(F_WRITTEN|F_DISK_PREPED|F_TRACK_PREP|F_TRACK_PREPED); - } - break; - } + if ((cdp->flags & F_WRITTEN) == 0) + error = EINVAL; + else if (w->toc_type < 0 /* WORM_TOC_TYPE_AUDIO */ || + w->toc_type > 4 /* WORM_TOC_TYPE_CDI */ ) + error = EINVAL; + else if (w->onp != 0 && w->onp != 1) + error = EINVAL; + else { + /* no fixation needed if dummy write */ + if (cdp->dummy == 0) + error = acd_close_disk(cdp); + cdp->flags &= + ~(F_WRITTEN|F_DISK_PREPED|F_TRACK_PREP|F_TRACK_PREPED); + } + break; + } case CDRIOCBLANK: - error = acd_blank_disk(cdp); + error = acd_blank(cdp); break; default: - error = ENOTTY; + error = ENOTTY; } return error; } @@ -979,24 +1002,23 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) static void acdstrategy(struct buf *bp) { - int32_t lun = dkunit(bp->b_dev); - struct acd_softc *cdp = acdtab[lun]; - int32_t x; + struct acd_softc *cdp = bp->b_dev->si_drv1; + int32_t s; #ifdef NOTYET /* allow write only on CD-R/RW media */ /* all for now SOS */ if (!(bp->b_flags & B_READ) && !(writeable_media)) { - bp->b_error = EROFS; - bp->b_flags |= B_ERROR; - biodone(bp); - return; + bp->b_error = EROFS; + bp->b_flags |= B_ERROR; + biodone(bp); + return; } #endif if (bp->b_bcount == 0) { - bp->b_resid = 0; - biodone(bp); - return; + bp->b_resid = 0; + biodone(bp); + return; } /* check for valid blocksize SOS */ @@ -1004,10 +1026,10 @@ acdstrategy(struct buf *bp) bp->b_pblkno = bp->b_blkno; bp->b_resid = bp->b_bcount; - x = splbio(); + s = splbio(); bufqdisksort(&cdp->buf_queue, bp); acd_start(cdp); - splx(x); + splx(s); } static void @@ -1018,42 +1040,43 @@ acd_start(struct acd_softc *cdp) int8_t ccb[16]; if (!bp) - return; + return; bufq_remove(&cdp->buf_queue, bp); - /* should reject all queued entries if media have changed. */ - if (cdp->flags & F_MEDIA_CHANGED) { - bp->b_error = EIO; - bp->b_flags |= B_ERROR; - biodone(bp); - return; + /* reject all queued entries if media changed */ + if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED) { + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + biodone(bp); + return; } + acd_select_slot(cdp); if ((bp->b_flags & B_READ) == B_WRITE) { - if ((cdp->flags & F_TRACK_PREPED) == 0) { - if ((cdp->flags & F_TRACK_PREP) == 0) { - printf("acd%d: sequence error\n", cdp->lun); - bp->b_error = EIO; - bp->b_flags |= B_ERROR; - biodone(bp); - return; - } else { - if (acd_open_track(cdp, &cdp->preptrack) != 0) { - biodone(bp); - return; - } - cdp->flags |= F_TRACK_PREPED; - } - } + if ((cdp->flags & F_TRACK_PREPED) == 0) { + if ((cdp->flags & F_TRACK_PREP) == 0) { + printf("acd%d: sequence error\n", cdp->lun); + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + biodone(bp); + return; + } else { + if (acd_open_track(cdp, &cdp->preptrack) != 0) { + biodone(bp); + return; + } + cdp->flags |= F_TRACK_PREPED; + } + } } bzero(ccb, sizeof(ccb)); if (bp->b_flags & B_READ) { - lba = bp->b_blkno / (cdp->block_size / DEV_BSIZE); + lba = bp->b_blkno / (cdp->block_size / DEV_BSIZE); ccb[0] = ATAPI_READ_BIG; } else { - lba = cdp->next_writeable_lba + (bp->b_offset / cdp->block_size); + lba = cdp->next_writeable_addr + (bp->b_offset / cdp->block_size); ccb[0] = ATAPI_WRITE_BIG; } count = (bp->b_bcount + (cdp->block_size - 1)) / cdp->block_size; @@ -1072,7 +1095,7 @@ acd_start(struct acd_softc *cdp) devstat_start_transaction(cdp->stats); atapi_queue_cmd(cdp->atp, ccb, bp->b_data, bp->b_bcount, - (bp->b_flags&B_READ)?A_READ : 0, 30, acd_done, cdp, bp); + (bp->b_flags&B_READ)?A_READ : 0, 30, acd_done, cdp, bp); } static void @@ -1080,89 +1103,35 @@ acd_done(struct atapi_request *request) { struct buf *bp = request->bp; struct acd_softc *cdp = request->driver; + int32_t error = request->result; - devstat_end_transaction(cdp->stats, request->donecount, - DEVSTAT_TAG_NONE, - (bp->b_flags&B_READ) ? DEVSTAT_READ:DEVSTAT_WRITE); - if (request->result) { - bp->b_error = atapi_error(request->device, request->result); - bp->b_flags |= B_ERROR; - } + if ((error & ATAPI_SK_MASK) == ATAPI_SK_UNIT_ATTENTION) { + struct toc buf = cdp->toc; + + acd_read_toc(cdp); + if (memcmp(&buf, &cdp->toc, sizeof(struct toc))) + cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED; + else { + error = atapi_immed_cmd(cdp->atp, request->ccb, request->data, + request->bytecount, request->flags, 30); + if (cdp->flags & F_LOCKED) + acd_prevent_allow(cdp, 1); + } + } + if (error) { + bp->b_error = atapi_error(request->device, error); + bp->b_flags |= B_ERROR; + } else { - bp->b_resid = request->bytecount; - if ((bp->b_flags & B_READ) == B_WRITE) - cdp->flags |= F_WRITTEN; + bp->b_resid = request->bytecount; + if ((bp->b_flags & B_READ) == B_WRITE) + cdp->flags |= F_WRITTEN; } + devstat_end_transaction_buf(&cdp->stats, bp); biodone(bp); acd_start(cdp); } -static int32_t -acd_test_unit_ready(struct acd_softc *cdp) -{ - int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); -} - -static int32_t -acd_lock_device(struct acd_softc *cdp, int32_t lock) -{ - int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); -} - -static int32_t -acd_start_device(struct acd_softc *cdp, int32_t start) -{ - int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); -} - -static int32_t -acd_pause_device(struct acd_softc *cdp, int32_t pause) -{ - int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, 0, 0, 0, 0, pause, - 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); -} - -static int32_t -acd_mode_sense(struct acd_softc *cdp, u_int8_t page, - void *pagebuf, int32_t pagesize) -{ - int32_t error; - int8_t ccb[16] = { ATAPI_MODE_SENSE, 0, page, 0, 0, 0, 0, - pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 }; - - error = atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, A_READ, 30, - NULL, NULL, NULL); -#ifdef ACD_DEBUG - atapi_dump("acd: mode sense ", pagebuf, pagesize); -#endif - return error; -} - -static int32_t -acd_mode_select(struct acd_softc *cdp, void *pagebuf, int32_t pagesize) -{ - int8_t ccb[16] = { ATAPI_MODE_SELECT, 0x10, 0, 0, 0, 0, 0, - pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 }; - -#ifdef ACD_DEBUG - printf("acd: modeselect pagesize=%d\n", pagesize); - atapi_dump("acd: mode select ", pagebuf, pagesize); -#endif - return atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, 0, 30, - NULL, NULL, NULL); -} - static int32_t acd_read_toc(struct acd_softc *cdp) { @@ -1175,71 +1144,64 @@ acd_read_toc(struct acd_softc *cdp) acd_select_slot(cdp); - error = acd_test_unit_ready(cdp); - if (error == EAGAIN) { - cdp->flags |= F_MEDIA_CHANGED; - cdp->flags &= ~(F_WRITTEN | F_TRACK_PREP | F_TRACK_PREPED); - error = acd_test_unit_ready(cdp); + error = atapi_test_ready(cdp->atp); + if ((error & ATAPI_SK_MASK) == ATAPI_SK_UNIT_ATTENTION) { + cdp->flags &= ~(F_WRITTEN | F_TRACK_PREP | F_TRACK_PREPED); + cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED; + error = atapi_test_ready(cdp->atp); } if (error) - return error; + return atapi_error(cdp->atp, error); - cdp->flags &= ~F_MEDIA_CHANGED; + cdp->atp->flags &= ~ATAPI_F_MEDIA_CHANGED; len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry); ccb[0] = ATAPI_READ_TOC; ccb[7] = len>>8; ccb[8] = len; - if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, 30, - NULL, NULL, NULL)){ - bzero(&cdp->toc, sizeof(cdp->toc)); - return 0; + if (atapi_immed_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, 30)) { + bzero(&cdp->toc, sizeof(cdp->toc)); + return 0; } ntracks = cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1; if (ntracks <= 0 || ntracks > MAXTRK) { - bzero(&cdp->toc, sizeof(cdp->toc)); - return 0; + bzero(&cdp->toc, sizeof(cdp->toc)); + return 0; } - len = sizeof(struct ioc_toc_header) + ntracks * sizeof(struct cd_toc_entry); + len = sizeof(struct ioc_toc_header)+(ntracks+1)*sizeof(struct cd_toc_entry); bzero(ccb, sizeof(ccb)); ccb[0] = ATAPI_READ_TOC; ccb[7] = len>>8; ccb[8] = len; - if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, 30, - NULL, NULL, NULL)){ - bzero(&cdp->toc, sizeof(cdp->toc)); - return 0; + if (atapi_immed_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, 30)) { + bzero(&cdp->toc, sizeof(cdp->toc)); + return 0; } cdp->toc.hdr.len = ntohs(cdp->toc.hdr.len); bzero(ccb, sizeof(ccb)); ccb[0] = ATAPI_READ_CAPACITY; - if (atapi_queue_cmd(cdp->atp, ccb, &cdp->info, sizeof(cdp->info), - A_READ, 30, NULL, NULL, NULL)) - bzero(&cdp->info, sizeof(cdp->info)); - - cdp->toc.tab[ntracks].control = cdp->toc.tab[ntracks - 1].control; - cdp->toc.tab[ntracks].addr_type = cdp->toc.tab[ntracks - 1].addr_type; - cdp->toc.tab[ntracks].track = 170; - cdp->toc.tab[ntracks].addr.lba = cdp->info.volsize; + if (atapi_immed_cmd(cdp->atp, ccb, &cdp->info, sizeof(cdp->info), + A_READ, 30)) + bzero(&cdp->info, sizeof(cdp->info)); cdp->info.volsize = ntohl(cdp->info.volsize); cdp->info.blksize = ntohl(cdp->info.blksize); #ifdef ACD_DEBUG if (cdp->info.volsize && cdp->toc.hdr.ending_track) { - printf("acd%d: ", cdp->lun); - if (cdp->toc.tab[0].control & 4) - printf("%dMB ", cdp->info.volsize / 512); - else - printf("%d:%d audio ", cdp->info.volsize / 75 / 60, - cdp->info.volsize / 75 % 60); - printf("(%d sectors (%d bytes)), %d tracks\n", + printf("acd%d: ", cdp->lun); + if (cdp->toc.tab[0].control & 4) + printf("%dMB ", cdp->info.volsize / 512); + else + printf("%d:%d audio ", cdp->info.volsize / 75 / 60, + cdp->info.volsize / 75 % 60); + printf("(%d sectors (%d bytes)), %d tracks\n", cdp->info.volsize, cdp->info.blksize, - cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1); + cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1); } #endif return 0; @@ -1253,9 +1215,9 @@ acd_setchan(struct acd_softc *cdp, if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, &cdp->au, sizeof(cdp->au)))) - return error; + return error; if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) - return EIO; + return EIO; cdp->au.data_length = 0; cdp->au.port[0].channels = c0; cdp->au.port[1].channels = c1; @@ -1264,84 +1226,59 @@ acd_setchan(struct acd_softc *cdp, return acd_mode_select(cdp, &cdp->au, sizeof(cdp->au)); } -static int32_t -acd_eject(struct acd_softc *cdp, int32_t close) -{ - int32_t error; - - acd_select_slot(cdp); - - error = acd_start_device(cdp, 0); - - if (error == EBUSY || error == EAGAIN) { - if (!close) - return 0; - if ((error = acd_start_device(cdp, 3))) - return error; - acd_read_toc(cdp); - acd_lock_device(cdp, 1); - cdp->flags |= F_LOCKED; - return 0; - } - if (error) - return error; - if (close) - return 0; - - tsleep((caddr_t) &lbolt, PRIBIO, "acdej1", 0); - tsleep((caddr_t) &lbolt, PRIBIO, "acdej2", 0); - acd_lock_device(cdp, 0); - cdp->flags &= ~F_LOCKED; - cdp->flags |= F_MEDIA_CHANGED; - cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED); - return acd_start_device(cdp, 2); -} - static void acd_select_slot(struct acd_softc *cdp) { int8_t ccb[16]; if (cdp->slot < 0 || cdp->changer_info->current_slot == cdp->slot) - return; + return; /* unlock (might not be needed but its cheaper than asking) */ - acd_lock_device(cdp, 0); + acd_prevent_allow(cdp, 0); bzero(ccb, sizeof(ccb)); /* unload the current media from player */ ccb[0] = ATAPI_LOAD_UNLOAD; + ccb[1] = 0x01; ccb[4] = 2; ccb[8] = cdp->changer_info->current_slot; - atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); + atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10); + atapi_wait_ready(cdp->atp, 30); /* load the wanted slot */ ccb[0] = ATAPI_LOAD_UNLOAD; + ccb[1] = 0x01; ccb[4] = 3; ccb[8] = cdp->slot; - atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); + atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10); + atapi_wait_ready(cdp->atp, 30); cdp->changer_info->current_slot = cdp->slot; /* lock the media if needed */ if (cdp->flags & F_LOCKED) - acd_lock_device(cdp, 1); + acd_prevent_allow(cdp, 1); } static int32_t acd_open_disk(struct acd_softc *cdp, int32_t test) { - cdp->next_writeable_lba = 0; + cdp->next_writeable_addr = 0; return 0; } static int32_t acd_close_disk(struct acd_softc *cdp) { - int8_t ccb[16] = { ATAPI_CLOSE_TRACK, 0, 0x02, 0, 0, 0, 0, 0, + int8_t ccb[16] = { ATAPI_CLOSE_TRACK, 0x01, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int32_t error; - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 600, NULL, NULL, NULL); + error = atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10); + if (error) + return atapi_error(cdp->atp, error); + return atapi_error(cdp->atp, atapi_wait_ready(cdp->atp, 10*60)); } static int32_t @@ -1352,7 +1289,7 @@ acd_open_track(struct acd_softc *cdp, struct wormio_prepare_track *ptp) if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE, ¶m, sizeof(param)))) - return error; + return error; param.page_code = 0x05; param.page_length = 0x32; param.test_write = cdp->dummy ? 1 : 0; @@ -1364,51 +1301,55 @@ acd_open_track(struct acd_softc *cdp, struct wormio_prepare_track *ptp) case 0: /* case CDR_DATA: */ cdp->block_size = 2048; - param.track_mode = CDR_TMODE_DATA; - param.data_block_type = CDR_DB_ROM_MODE1; - param.session_format = CDR_SESS_CDROM; + param.track_mode = CDR_TMODE_DATA; + param.data_block_type = CDR_DB_ROM_MODE1; + param.session_format = CDR_SESS_CDROM; break; default: /* case CDR_AUDIO: */ cdp->block_size = 2352; if (ptp->preemp) - param.track_mode = CDR_TMODE_AUDIO; + param.track_mode = CDR_TMODE_AUDIO; else - param.track_mode = 0; - param.data_block_type = CDR_DB_RAW; - param.session_format = CDR_SESS_CDROM; + param.track_mode = 0; + param.data_block_type = CDR_DB_RAW; + param.session_format = CDR_SESS_CDROM; break; /* case CDR_MODE2: - param.track_mode = CDR_TMODE_DATA; - param.data_block_type = CDR_DB_ROM_MODE2; - param.session_format = CDR_SESS_CDROM; + param.track_mode = CDR_TMODE_DATA; + param.data_block_type = CDR_DB_ROM_MODE2; + param.session_format = CDR_SESS_CDROM; break; case CDR_XA1: - param.track_mode = CDR_TMODE_DATA; - param.data_block_type = CDR_DB_XA_MODE1; - param.session_format = CDR_SESS_CDROM_XA; + param.track_mode = CDR_TMODE_DATA; + param.data_block_type = CDR_DB_XA_MODE1; + param.session_format = CDR_SESS_CDROM_XA; break; case CDR_XA2: - param.track_mode = CDR_TMODE_DATA; - param.data_block_type = CDR_DB_XA_MODE2_F1; - param.session_format = CDR_SESS_CDROM_XA; + param.track_mode = CDR_TMODE_DATA; + param.data_block_type = CDR_DB_XA_MODE2_F1; + param.session_format = CDR_SESS_CDROM_XA; break; case CDR_CDI: - param.track_mode = CDR_TMODE_DATA; - param.data_block_type = CDR_DB_XA_MODE2_F1; - param.session_format = CDR_SESS_CDI; + param.track_mode = CDR_TMODE_DATA; + param.data_block_type = CDR_DB_XA_MODE2_F1; + param.session_format = CDR_SESS_CDI; break; } */ } +#if 0 + param.multi_session = CDR_MSES_MULTI; +#else param.multi_session = CDR_MSES_NONE; +#endif param.fp = 0; param.packet_size = 0; return acd_mode_select(cdp, ¶m, sizeof(param)); @@ -1417,26 +1358,41 @@ acd_open_track(struct acd_softc *cdp, struct wormio_prepare_track *ptp) static int32_t acd_close_track(struct acd_softc *cdp) { - int8_t ccb[16] = { ATAPI_SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0}; + int8_t ccb1[16] = { ATAPI_SYNCHRONIZE_CACHE, 0x02, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; + int8_t ccb2[16] = { ATAPI_CLOSE_TRACK, 0x01, 0x01, 0, 0, 0xff, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; + int32_t error; + + error = atapi_immed_cmd(cdp->atp, ccb1, NULL, 0, 0, 10); + if (error) + return atapi_error(cdp->atp, error); + + error = atapi_error(cdp->atp, atapi_wait_ready(cdp->atp, 5*60)); + if (error) + return atapi_error(cdp->atp, error); + + error = atapi_immed_cmd(cdp->atp, ccb2, NULL, 0, 0, 10); + if (error) + return atapi_error(cdp->atp, error); - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 600, NULL, NULL, NULL); + return atapi_error(cdp->atp, atapi_wait_ready(cdp->atp, 5*60)); } static int32_t acd_read_track_info(struct acd_softc *cdp, int32_t lba, struct acd_track_info *info) { - int32_t error; int8_t ccb[16] = { ATAPI_READ_TRACK_INFO, 1, lba>>24, lba>>16, lba>>8, lba, 0, - sizeof(*info)>>8, sizeof(*info), - 0, 0, 0, 0, 0, 0, 0 }; + sizeof(*info)>>8, sizeof(*info), + 0, 0, 0, 0, 0, 0, 0 }; + int32_t error; - if ((error = atapi_queue_cmd(cdp->atp, ccb, info, sizeof(*info), - A_READ, 30, NULL, NULL, NULL))) - return error; + if ((error = atapi_immed_cmd(cdp->atp, ccb, info, sizeof(*info), + A_READ, 30))) + return atapi_error(cdp->atp, error); info->track_start_addr = ntohl(info->track_start_addr); info->next_writeable_addr = ntohl(info->next_writeable_addr); info->free_blocks = ntohl(info->free_blocks); @@ -1445,17 +1401,105 @@ acd_read_track_info(struct acd_softc *cdp, return 0; } -static int32_t -acd_blank_disk(struct acd_softc *cdp) +static int32_t +acd_eject(struct acd_softc *cdp, int32_t close) { int32_t error; + + acd_select_slot(cdp); + error = acd_start_stop(cdp, 0); + if (((cdp->atp->controller->error&ATAPI_SK_MASK)==ATAPI_SK_NOT_READY) || + ((cdp->atp->controller->error&ATAPI_SK_MASK)==ATAPI_SK_UNIT_ATTENTION)){ + if (!close) + return 0; + if ((error = acd_start_stop(cdp, 3))) + return error; + acd_read_toc(cdp); + acd_prevent_allow(cdp, 1); + cdp->flags |= F_LOCKED; + return 0; + } + if (error) + return error; + if (close) + return 0; + + tsleep((caddr_t) &lbolt, PRIBIO, "acdej1", 0); + tsleep((caddr_t) &lbolt, PRIBIO, "acdej2", 0); + acd_prevent_allow(cdp, 0); + cdp->flags &= ~F_LOCKED; + cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED); + cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED; + return acd_start_stop(cdp, 2); +} + +static int32_t +acd_blank(struct acd_softc *cdp) +{ int8_t ccb[16] = { ATAPI_BLANK, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int32_t error; - error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 60*60, NULL, NULL, NULL); - cdp->flags |= F_MEDIA_CHANGED; + error = atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 60*60); cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED); - return error; + cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED; + return atapi_error(cdp->atp, error); +} + +static int32_t +acd_prevent_allow(struct acd_softc *cdp, int32_t lock) +{ + int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + return atapi_error(cdp->atp, atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0,30)); +} + +static int32_t +acd_start_stop(struct acd_softc *cdp, int32_t start) +{ + int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + return atapi_error(cdp->atp, atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0,30)); +} + +static int32_t +acd_pause_resume(struct acd_softc *cdp, int32_t pause) +{ + int8_t ccb[16] = { ATAPI_PAUSE, 0, 0, 0, 0, 0, 0, 0, pause, + 0, 0, 0, 0, 0, 0, 0 }; + + return atapi_error(cdp->atp, atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0,30)); +} + +static int32_t +acd_mode_sense(struct acd_softc *cdp, u_int8_t page, + void *pagebuf, int32_t pagesize) +{ + int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, page, 0, 0, 0, 0, + pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 }; + int32_t error; + + error = atapi_immed_cmd(cdp->atp, ccb, pagebuf, pagesize, A_READ, 10); +#ifdef ACD_DEBUG + atapi_dump("acd: mode sense ", pagebuf, pagesize); +#endif + return atapi_error(cdp->atp, error); +} + +static int32_t +acd_mode_select(struct acd_softc *cdp, void *pagebuf, int32_t pagesize) +{ + int8_t ccb[16] = { ATAPI_MODE_SELECT_BIG, 0x10, 0, 0, 0, 0, 0, + pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 }; + +#ifdef ACD_DEBUG + printf("acd: modeselect pagesize=%d\n", pagesize); + atapi_dump("acd: mode select ", pagebuf, pagesize); +#endif + return atapi_error(cdp->atp, atapi_immed_cmd(cdp->atp, ccb, + pagebuf, pagesize, 0, 30)); } static void @@ -1464,11 +1508,12 @@ acd_drvinit(void *unused) static int32_t acd_devsw_installed = 0; if (!acd_devsw_installed) { - if (!acd_cdevsw.d_maxio) - acd_cdevsw.d_maxio = 254 * DEV_BSIZE; - cdevsw_add(&acd_cdevsw); - acd_devsw_installed = 1; + if (!acd_cdevsw.d_maxio) + acd_cdevsw.d_maxio = 254 * DEV_BSIZE; + cdevsw_add(&acd_cdevsw); + acd_devsw_installed = 1; } } + SYSINIT(acddev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, acd_drvinit, NULL) #endif /* NATA && NATAPICD */ |
