summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/atapiscsi/atapiscsi.c5
-rw-r--r--sys/scsi/atapi_all.h77
-rw-r--r--sys/scsi/atapi_base.c292
-rw-r--r--sys/scsi/atapi_cd.h122
-rw-r--r--sys/scsi/cd.c632
-rw-r--r--sys/scsi/cd.h213
-rw-r--r--sys/scsi/cd_atapi.c188
-rw-r--r--sys/scsi/cd_scsi.c232
-rw-r--r--sys/scsi/cdvar.h76
-rw-r--r--sys/scsi/files.scsi5
-rw-r--r--sys/scsi/scsi_cd.h214
-rw-r--r--sys/scsi/scsiconf.c41
-rw-r--r--sys/scsi/scsiconf.h25
-rw-r--r--sys/sys/cdio.h21
14 files changed, 1684 insertions, 459 deletions
diff --git a/sys/dev/atapiscsi/atapiscsi.c b/sys/dev/atapiscsi/atapiscsi.c
index 36f73e8dce4..ab34d658bb1 100644
--- a/sys/dev/atapiscsi/atapiscsi.c
+++ b/sys/dev/atapiscsi/atapiscsi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atapiscsi.c,v 1.2 1999/07/19 00:32:44 csapuntz Exp $ */
+/* $OpenBSD: atapiscsi.c,v 1.3 1999/07/20 06:21:58 csapuntz Exp $ */
/*
* This code is derived from code with the copyright below.
@@ -197,6 +197,7 @@ atapiscsi_attach(parent, self, aux)
as->sc_adapterlink.adapter = &atapiscsi_switch;
as->sc_adapterlink.device = &atapiscsi_dev;
as->sc_adapterlink.openings = 1;
+ as->sc_adapterlink.flags = SDEV_ATAPI;
as->sc_wdc->channels[as->sc_channel]->ch_as = as;
for (drive = 0; drive < 2 ; drive++ ) {
@@ -782,7 +783,7 @@ again:
sc_xfer->error = XS_SHORTSENSE;
ATAPI_TO_SCSI_SENSE(&sc_xfer->sense, chp->ch_error);
if ((sc_xfer->sc_link->quirks &
- SDEV_NOSENSE) == 0) {
+ ADEV_NOSENSE) == 0) {
/*
* let the driver issue a
* 'request sense'
diff --git a/sys/scsi/atapi_all.h b/sys/scsi/atapi_all.h
new file mode 100644
index 00000000000..713aabbcf08
--- /dev/null
+++ b/sys/scsi/atapi_all.h
@@ -0,0 +1,77 @@
+/* $OpenBSD: atapi_all.h,v 1.1 1999/07/20 06:21:59 csapuntz Exp $ */
+/* $NetBSD: atapi_all.h,v 1.3 1998/02/13 08:28:16 enami Exp $ */
+
+/*
+ * Copyright (c) 1996 Manuel Bouyer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Manuel Bouyer.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+struct scsi_link;
+
+#define ATAPI_MODE_SELECT 0x55
+struct atapi_mode_select {
+ u_int8_t opcode;
+ u_int8_t byte2;
+#define AMS_SP 0x01 /* save pages */
+#define AMS_PF 0x10 /* must be set in byte2 */
+ u_int8_t reserved1[5];
+ u_int8_t length[2];
+ u_int8_t reserved2[3];
+};
+
+#define ATAPI_MODE_SENSE 0x5a
+struct atapi_mode_sense {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t page;
+ u_int8_t reserved1[4];
+ u_int8_t length[2];
+ u_int8_t reserved2[3];
+};
+
+struct atapi_mode_header {
+ u_int8_t length[2];
+ u_int8_t medium;
+#define MDT_UNKNOWN 0x00
+#define MDT_DATA_120 0x01
+#define MDT_AUDIO_120 0x02
+#define MDT_COMB_120 0x03
+#define MDT_PHOTO_120 0x04
+#define MDT_DATA_80 0x05
+#define MDT_AUDIO_80 0x06
+#define MDT_COMB_80 0x07
+#define MDT_PHOTO_80 0x08
+#define MDT_NO_DISC 0x70
+#define MDT_DOOR_OPEN 0x71
+#define MDT_FMT_ERROR 0x72
+ u_int8_t reserved[5];
+};
+
+int atapi_mode_select __P((struct scsi_link *,
+ struct atapi_mode_header *, int, int, int, int));
+int atapi_mode_sense __P((struct scsi_link *, int,
+ struct atapi_mode_header *, int, int, int, int));
diff --git a/sys/scsi/atapi_base.c b/sys/scsi/atapi_base.c
new file mode 100644
index 00000000000..351e98c7059
--- /dev/null
+++ b/sys/scsi/atapi_base.c
@@ -0,0 +1,292 @@
+/* $OpenBSD: atapi_base.c,v 1.1 1999/07/20 06:21:59 csapuntz Exp $ */
+/* $NetBSD: atapi_base.c,v 1.12 1999/06/25 18:58:54 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/buf.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/atapi_all.h>
+#include <scsi/scsiconf.h>
+
+#ifndef __OpenBSD__
+/*
+ * Look at the returned sense and act on the error, determining
+ * the unix error number to pass back. (0 = report no error)
+ *
+ * THIS IS THE DEFAULT ERROR HANDLER
+ */
+int
+atapi_interpret_sense(xs)
+ struct scsipi_xfer *xs;
+{
+ int key, error;
+ struct scsipi_link *sc_link = xs->sc_link;
+ char *msg = NULL;
+
+ /*
+ * If the device has it's own error handler, call it first.
+ * If it returns a legit error value, return that, otherwise
+ * it wants us to continue with normal error processing.
+ */
+ if (sc_link->device->err_handler) {
+ SC_DEBUG(sc_link, SDEV_DB2,
+ ("calling private err_handler()\n"));
+ error = (*sc_link->device->err_handler) (xs);
+ if (error != SCSIRET_CONTINUE)
+ return (error); /* error >= 0 better ? */
+ }
+ /*
+ * otherwise use the default, call the generic sense handler if we have
+ * more than the sense key
+ */
+ if (xs->error == XS_SENSE)
+ return (scsipi_interpret_sense(xs));
+
+ key = (xs->sense.atapi_sense & 0xf0) >> 4;
+ switch (key) {
+ case SKEY_RECOVERED_ERROR:
+ msg = "soft error (corrected)";
+ case SKEY_NO_SENSE:
+ if (xs->resid == xs->datalen)
+ xs->resid = 0; /* not short read */
+ error = 0;
+ break;
+ case SKEY_NOT_READY:
+ if ((sc_link->flags & SDEV_REMOVABLE) != 0)
+ sc_link->flags &= ~SDEV_MEDIA_LOADED;
+ if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0)
+ return (0);
+ if ((xs->flags & SCSI_SILENT) != 0)
+ return (EIO);
+ msg = "not ready";
+ error = EIO;
+ break;
+ case SKEY_MEDIUM_ERROR: /* MEDIUM ERROR */
+ msg = "medium error";
+ error = EIO;
+ break;
+ case SKEY_HARDWARE_ERROR:
+ msg = "non-media hardware failure";
+ error = EIO;
+ break;
+ case SKEY_ILLEGAL_REQUEST:
+ if ((xs->flags & SCSI_IGNORE_ILLEGAL_REQUEST) != 0)
+ return (0);
+ if ((xs->flags & SCSI_SILENT) != 0)
+ return (EIO);
+ msg = "illegal request";
+ error = EINVAL;
+ break;
+ case SKEY_UNIT_ATTENTION:
+ if ((sc_link->flags & SDEV_REMOVABLE) != 0)
+ sc_link->flags &= ~SDEV_MEDIA_LOADED;
+ if ((xs->flags & SCSI_IGNORE_MEDIA_CHANGE) != 0 ||
+ /* XXX Should reupload any transient state. */
+ (sc_link->flags & SDEV_REMOVABLE) == 0)
+ return (ERESTART);
+ if ((xs->flags & SCSI_SILENT) != 0)
+ return (EIO);
+ msg = "unit attention";
+ error = EIO;
+ break;
+ case SKEY_WRITE_PROTECT:
+ msg = "readonly device";
+ error = EROFS;
+ break;
+ case SKEY_ABORTED_COMMAND:
+ msg = "command aborted";
+ error = ERESTART;
+ break;
+ default:
+ error = EIO;
+ break;
+ }
+
+ if (!key) {
+ if (xs->sense.atapi_sense & 0x01) {
+ /* Illegal length indication */
+ msg = "ATA illegal length indication";
+ error = EIO;
+ }
+ if (xs->sense.atapi_sense & 0x02) { /* vol overflow */
+ msg = "ATA volume overflow";
+ error = ENOSPC;
+ }
+ if (xs->sense.atapi_sense & 0x04) { /* Aborted command */
+ msg = "ATA command aborted";
+ error = ERESTART;
+ }
+ }
+ if (msg) {
+ sc_link->sc_print_addr(sc_link);
+ printf("%s\n", msg);
+ } else {
+ if (error) {
+ sc_link->sc_print_addr(sc_link);
+ printf("unknown error code %d\n",
+ xs->sense.atapi_sense);
+ }
+ }
+
+ return (error);
+
+}
+
+/*
+ * Utility routines often used in SCSI stuff
+ */
+
+
+/*
+ * Print out the scsi_link structure's address info.
+ */
+void
+atapi_print_addr(sc_link)
+ struct scsipi_link *sc_link;
+{
+
+ printf("%s(%s:%d:%d): ",
+ sc_link->device_softc ?
+ ((struct device *)sc_link->device_softc)->dv_xname : "probe",
+ ((struct device *)sc_link->adapter_softc)->dv_xname,
+ sc_link->scsipi_atapi.channel, sc_link->scsipi_atapi.drive);
+}
+
+/*
+ * ask the atapi driver to perform a command for us.
+ * tell it where to read/write the data, and how
+ * long the data is supposed to be. If we have a buf
+ * to associate with the transfer, we need that too.
+ */
+int
+atapi_scsipi_cmd(sc_link, scsipi_cmd, cmdlen, data_addr, datalen,
+ retries, timeout, bp, flags)
+ struct scsipi_link *sc_link;
+ struct scsipi_generic *scsipi_cmd;
+ int cmdlen;
+ u_char *data_addr;
+ int datalen;
+ int retries;
+ int timeout;
+ struct buf *bp;
+ int flags;
+{
+ struct scsipi_xfer *xs;
+ int error, s;
+
+ SC_DEBUG(sc_link, SDEV_DB2, ("atapi_cmd\n"));
+
+#ifdef DIAGNOSTIC
+ if (bp != 0 && (flags & SCSI_NOSLEEP) == 0)
+ panic("atapi_scsipi_cmd: buffer without nosleep");
+#endif
+
+ if ((xs = scsipi_make_xs(sc_link, scsipi_cmd, cmdlen, data_addr,
+ datalen, retries, timeout, bp, flags)) == NULL)
+ return (ENOMEM);
+
+ xs->cmdlen = (sc_link->scsipi_atapi.cap & ACAP_LEN) ? 16 : 12;
+
+ if ((error = scsipi_execute_xs(xs)) == EJUSTRETURN)
+ return (0);
+
+ /*
+ * we have finished with the xfer stuct, free it and
+ * check if anyone else needs to be started up.
+ */
+ s = splbio();
+ scsipi_free_xs(xs, flags);
+ splx(s);
+ return (error);
+}
+
+#endif
+
+int
+atapi_mode_select(l, data, len, flags, retries, timeout)
+ struct scsi_link *l;
+ struct atapi_mode_header *data;
+ int len, flags, retries, timeout;
+{
+ struct atapi_mode_select scsi_cmd;
+ int error;
+
+ bzero(&scsi_cmd, sizeof(scsi_cmd));
+ scsi_cmd.opcode = ATAPI_MODE_SELECT;
+ scsi_cmd.byte2 = AMS_PF;
+ _lto2b(len, scsi_cmd.length);
+
+ /* length is reserved when doing mode select; zero it */
+ _lto2l(0, data->length);
+
+ error = scsi_scsi_cmd(l, (struct scsi_generic *)&scsi_cmd,
+ sizeof(scsi_cmd), (void *)data, len, retries, timeout, NULL,
+ flags | SCSI_DATA_OUT);
+ SC_DEBUG(l, SDEV_DB2, ("atapi_mode_select: error=%d\n", error));
+ return (error);
+}
+
+int
+atapi_mode_sense(l, page, data, len, flags, retries, timeout)
+ struct scsi_link *l;
+ int page, len, flags, retries, timeout;
+ struct atapi_mode_header *data;
+{
+ struct atapi_mode_sense scsi_cmd;
+ int error;
+
+ bzero(&scsi_cmd, sizeof(scsi_cmd));
+ scsi_cmd.opcode = ATAPI_MODE_SENSE;
+ scsi_cmd.page = page;
+ _lto2b(len, scsi_cmd.length);
+
+ error = scsi_scsi_cmd(l, (struct scsi_generic *)&scsi_cmd,
+ sizeof(scsi_cmd), (void *)data, len, retries, timeout, NULL,
+ flags | SCSI_DATA_IN);
+ SC_DEBUG(l, SDEV_DB2, ("atapi_mode_sense: error=%d\n", error));
+ return (error);
+}
diff --git a/sys/scsi/atapi_cd.h b/sys/scsi/atapi_cd.h
new file mode 100644
index 00000000000..3c5ebd839bb
--- /dev/null
+++ b/sys/scsi/atapi_cd.h
@@ -0,0 +1,122 @@
+/* $OpenBSD: atapi_cd.h,v 1.1 1999/07/20 06:21:59 csapuntz Exp $ */
+/* $NetBSD: atapi_cd.h,v 1.9 1998/07/13 16:50:56 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1996 Manuel Bouyer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Manuel Bouyer.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define ATAPI_LOAD_UNLOAD 0xa6
+struct atapi_load_unload {
+ u_int8_t opcode;
+ u_int8_t unused1[3];
+ u_int8_t options;
+ u_int8_t unused2[3];
+ u_int8_t slot;
+ u_int8_t unused3[3];
+};
+
+struct atapi_cdrom_page {
+ u_int8_t page;
+ u_int8_t length;
+ u_int8_t reserved;
+ u_int8_t inact_mult;
+ u_int8_t spm[2];
+ u_int8_t fps[2];
+};
+
+struct atapi_cap_page {
+ /* Capabilities page */
+ u_int8_t page_code;
+ u_int8_t param_len;
+ u_int8_t reserved1[2];
+
+ u_int8_t cap1;
+#define AUDIO_PLAY 0x01 /* audio play supported */
+#define AV_COMPOSITE /* composite audio/video supported */
+#define DA_PORT1 /* digital audio on port 1 */
+#define DA_PORT2 /* digital audio on port 2 */
+#define M2F1 /* mode 2 form 1 (XA) read */
+#define M2F2 /* mode 2 form 2 format */
+#define CD_MULTISESSION /* multi-session photo-CD */
+ u_int8_t cap2;
+#define CD_DA 0x01 /* audio-CD read supported */
+#define CD_DA_STREAM 0x02 /* CD-DA streaming */
+#define RW_SUB 0x04 /* combined R-W subchannels */
+#define RW_SUB_CORR 0x08 /* R-W subchannel data corrected */
+#define C2_ERRP 0x10 /* C2 error pointers supported */
+#define ISRC 0x20 /* can return the ISRC */
+#define UPC 0x40 /* can return the catalog number UPC */
+ u_int8_t m_status;
+#define CANLOCK 0x01 /* could be locked */
+#define LOCK_STATE 0x02 /* current lock state */
+#define PREVENT_JUMP 0x04 /* prevent jumper installed */
+#define CANEJECT 0x08 /* can eject */
+#define MECH_MASK 0xe0 /* loading mechanism type */
+#define MECH_CADDY 0x00
+#define MECH_TRAY 0x20
+#define MECH_POPUP 0x40
+#define MECH_CHANGER_INDIV 0x80
+#define MECH_CHANGER_CARTRIDGE 0xa0
+ u_int8_t cap3;
+#define SEPARATE_VOL 0x01 /* independent volume of channels */
+#define SEPARATE_MUTE 0x02 /* independent mute of channels */
+#define SUPP_DISK_PRESENT 0x04 /* changer can report contents of slots */
+#define SSS 0x08 /* software slot selection */
+ u_int8_t max_speed[2]; /* max raw data rate in bytes/1000 */
+ u_int8_t max_vol_levels[2]; /* number of discrete volume levels */
+ u_int8_t buf_size[2]; /* internal buffer size in bytes/1024 */
+ u_int8_t cur_speed[2]; /* current data rate in bytes/1000 */
+ /* Digital drive output format description (optional?) */
+ u_int8_t reserved2;
+ u_int8_t dig_output; /* Digital drive output format description */
+ u_int8_t reserved3[2];
+};
+
+#define ATAPI_CDROM_PAGE 0x0d
+#define ATAPI_AUDIO_PAGE 0x0e
+#define ATAPI_AUDIO_PAGE_MASK 0x4e
+#define ATAPI_CAP_PAGE 0x2a
+
+union atapi_cd_pages {
+ u_int8_t page_code;
+ struct atapi_cdrom_page cdrom;
+ struct atapi_cap_page cap;
+ struct cd_audio_page audio;
+};
+
+struct atapi_cd_mode_data {
+ struct atapi_mode_header header;
+ union atapi_cd_pages pages;
+};
+
+#define AUDIOPAGESIZE \
+ (sizeof(struct atapi_mode_header) + sizeof(struct cd_audio_page))
+#define CDROMPAGESIZE \
+ (sizeof(struct atapi_mode_header) + sizeof(struct atapi_cdrom_page))
+#define CAPPAGESIZE \
+ (sizeof(struct atapi_mode_header) + sizeof(struct atapi_cap_page))
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c
index 2f81a7050a6..e136dd57dba 100644
--- a/sys/scsi/cd.c
+++ b/sys/scsi/cd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cd.c,v 1.36 1999/04/01 01:46:51 millert Exp $ */
+/* $OpenBSD: cd.c,v 1.37 1999/07/20 06:21:59 csapuntz Exp $ */
/* $NetBSD: cd.c,v 1.100 1997/04/02 02:29:30 mycroft Exp $ */
/*
@@ -65,47 +65,38 @@
#include <sys/cdio.h>
#include <sys/proc.h>
#include <sys/conf.h>
+#include <sys/scsiio.h>
#include <scsi/scsi_all.h>
+#include <scsi/cd.h>
#include <scsi/scsi_cd.h>
#include <scsi/scsi_disk.h> /* rw_big and start_stop come from there */
#include <scsi/scsiconf.h>
+
#include <ufs/ffs/fs.h> /* for BBSIZE and SBSIZE */
+#include "cdvar.h"
+
#define CDOUTSTANDING 4
-#define CDRETRIES 1
#define CDUNIT(z) DISKUNIT(z)
#define CDPART(z) DISKPART(z)
#define MAKECDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part)
-#define CDLABELDEV(dev) (MAKECDDEV(major(dev), CDUNIT(dev), RAW_PART))
-
-struct cd_softc {
- struct device sc_dev;
- struct disk sc_dk;
+#define MAXTRACK 99
+#define CD_BLOCK_OFFSET 150
+#define CD_FRAMES 75
+#define CD_SECS 60
- int flags;
-#define CDF_LOCKED 0x01
-#define CDF_WANTED 0x02
-#define CDF_WLABEL 0x04 /* label is writable */
-#define CDF_LABELLING 0x08 /* writing label */
-#define CDF_ANCIENT 0x10 /* disk is ancient; for minphys */
-#ifdef CDDA
-#define CDF_CDDAMODE 0x08
-#endif
- struct scsi_link *sc_link; /* contains our targ, lun, etc. */
- struct cd_parms {
- int blksize;
- u_long disksize; /* total number sectors */
- } params;
-#ifdef CDDA
- struct cd_parms orig_params; /* filled in when CD-DA mode starts */
-#endif
- struct buf buf_queue;
+struct cd_toc {
+ struct ioc_toc_header header;
+ struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */
+ /* leadout */
};
+#define CDLABELDEV(dev) (MAKECDDEV(major(dev), CDUNIT(dev), RAW_PART))
+
int cdmatch __P((struct device *, void *, void *));
void cdattach __P((struct device *, struct device *, void *));
int cdlock __P((struct cd_softc *));
@@ -115,18 +106,20 @@ void cdminphys __P((struct buf *));
void cdgetdisklabel __P((dev_t, struct cd_softc *, struct disklabel *,
struct cpu_disklabel *, int));
void cddone __P((struct scsi_xfer *));
-int cd_get_mode __P((struct cd_softc *, struct cd_mode_data *, int));
-int cd_set_mode __P((struct cd_softc *, struct cd_mode_data *));
-int cd_play_big __P((struct cd_softc *, int, int ));
-int cd_play_tracks __P((struct cd_softc *, int, int, int, int ));
-int cd_play_msf __P((struct cd_softc *, int, int, int, int, int, int ));
+u_long cd_size __P((struct cd_softc *, int));
+void lba2msf __P((u_long, u_char *, u_char *, u_char *));
+u_long msf2lba __P((u_char, u_char, u_char));
+int cd_play __P((struct cd_softc *, int, int));
+int cd_play_tracks __P((struct cd_softc *, int, int, int, int));
+int cd_play_msf __P((struct cd_softc *, int, int, int, int, int, int));
int cd_pause __P((struct cd_softc *, int));
int cd_reset __P((struct cd_softc *));
int cd_read_subchannel __P((struct cd_softc *, int, int, int,
struct cd_sub_channel_info *, int ));
-int cd_read_toc __P((struct cd_softc *, int, int, struct cd_toc_entry *,
- int ));
+int cd_read_toc __P((struct cd_softc *, int, int, void *,
+ int, int ));
int cd_get_parms __P((struct cd_softc *, int));
+int cd_load_toc __P((struct cd_softc *, struct cd_toc *));
struct cfattach cd_ca = {
sizeof(struct cd_softc), cdmatch, cdattach
@@ -148,12 +141,19 @@ struct scsi_device cd_switch = {
struct scsi_inquiry_pattern cd_patterns[] = {
{T_CDROM, T_REMOV,
"", "", ""},
+ {T_WORM, T_REMOV,
+ "", "", ""},
+ {T_DIRECT, T_REMOV,
+ "NEC CD-ROM DRIVE:260", "", ""},
#if 0
{T_CDROM, T_REMOV, /* more luns */
"PIONEER ", "CD-ROM DRM-600 ", ""},
#endif
};
+extern struct cd_ops cd_atapibus_ops;
+extern struct cd_ops cd_scsibus_ops;
+
int
cdmatch(parent, match, aux)
struct device *parent;
@@ -204,9 +204,16 @@ cdattach(parent, self, aux)
/*
* Note if this device is ancient. This is used in cdminphys().
*/
- if ((sa->sa_inqbuf->version & SID_ANSII) == 0)
+ if (!(sc_link->flags & SDEV_ATAPI) &&
+ (sa->sa_inqbuf->version & SID_ANSII) == 0)
cd->flags |= CDF_ANCIENT;
+ if (sc_link->flags & SDEV_ATAPI) {
+ cd->sc_ops = &cd_atapibus_ops;
+ } else {
+ cd->sc_ops = &cd_scsibus_ops;
+ }
+
printf("\n");
}
@@ -603,7 +610,8 @@ cdstart(v)
* Fill out the scsi command. If the transfer will
* fit in a "small" cdb, use it.
*/
- if (((blkno & 0x1fffff) == blkno) &&
+ if (!(sc_link->flags & SDEV_ATAPI) &&
+ ((blkno & 0x1fffff) == blkno) &&
((nblks & 0xff) == nblks)) {
/*
* We can fit in a small cdb.
@@ -704,6 +712,34 @@ cdwrite(dev, uio, ioflag)
}
/*
+ * conversion between minute-seconde-frame and logical block adress
+ * adresses format
+ */
+void
+lba2msf (lba, m, s, f)
+ u_long lba;
+ u_char *m, *s, *f;
+{
+ u_long tmp;
+
+ tmp = lba + CD_BLOCK_OFFSET; /* offset of first logical frame */
+ tmp &= 0xffffff; /* negative lbas use only 24 bits */
+ *m = tmp / (CD_SECS * CD_FRAMES);
+ tmp %= (CD_SECS * CD_FRAMES);
+ *s = tmp / CD_FRAMES;
+ *f = tmp % CD_FRAMES;
+}
+
+u_long
+msf2lba (m, s, f)
+ u_char m, s, f;
+{
+
+ return ((((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET);
+}
+
+
+/*
* Perform special action on behalf of the user.
* Knows about the internals of this device
*/
@@ -716,6 +752,7 @@ cdioctl(dev, cmd, addr, flag, p)
struct proc *p;
{
struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(dev)];
+ int part = CDPART(dev);
int error;
SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%lx ", cmd));
@@ -723,8 +760,40 @@ cdioctl(dev, cmd, addr, flag, p)
/*
* If the device is not valid.. abandon ship
*/
- if ((cd->sc_link->flags & SDEV_MEDIA_LOADED) == 0)
- return EIO;
+ if ((cd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
+ switch (cmd) {
+ case DIOCWLABEL:
+ case DIOCLOCK:
+ case DIOCEJECT:
+ case SCIOCIDENTIFY:
+ case SCIOCCOMMAND:
+ case SCIOCDEBUG:
+ case CDIOCLOADUNLOAD:
+ case SCIOCRESET:
+ case CDIOCGETVOL:
+ case CDIOCSETVOL:
+ case CDIOCSETMONO:
+ case CDIOCSETSTEREO:
+ case CDIOCSETMUTE:
+ case CDIOCSETLEFT:
+ case CDIOCSETRIGHT:
+ case CDIOCCLOSE:
+ case CDIOCEJECT:
+ case CDIOCALLOW:
+ case CDIOCPREVENT:
+ case CDIOCSETDEBUG:
+ case CDIOCCLRDEBUG:
+ case CDIOCRESET:
+ if (part == RAW_PART)
+ break;
+ /* FALLTHROUGH */
+ default:
+ if ((cd->sc_link->flags & SDEV_OPEN) == 0)
+ return (ENODEV);
+ else
+ return (EIO);
+ }
+ }
switch (cmd) {
case DIOCGDINFO:
@@ -762,40 +831,26 @@ cdioctl(dev, cmd, addr, flag, p)
case CDIOCPLAYTRACKS: {
struct ioc_play_track *args = (struct ioc_play_track *)addr;
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- data.page.audio.flags &= ~CD_PA_SOTC;
- data.page.audio.flags |= CD_PA_IMMED;
- if ((error = cd_set_mode(cd, &data)) != 0)
- return error;
- return cd_play_tracks(cd, args->start_track,
- args->start_index, args->end_track,
- args->end_index);
+
+ if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd, 0)) != 0)
+ return (error);
+ return (cd_play_tracks(cd, args->start_track,
+ args->start_index, args->end_track, args->end_index));
}
case CDIOCPLAYMSF: {
struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- data.page.audio.flags &= ~CD_PA_SOTC;
- data.page.audio.flags |= CD_PA_IMMED;
- if ((error = cd_set_mode(cd, &data)) != 0)
- return error;
- return cd_play_msf(cd, args->start_m, args->start_s,
- args->start_f, args->end_m, args->end_s,
- args->end_f);
+
+ if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd, 0)) != 0)
+ return (error);
+ return (cd_play_msf(cd, args->start_m, args->start_s,
+ args->start_f, args->end_m, args->end_s, args->end_f));
}
case CDIOCPLAYBLOCKS: {
struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- data.page.audio.flags &= ~CD_PA_SOTC;
- data.page.audio.flags |= CD_PA_IMMED;
- if ((error = cd_set_mode(cd, &data)) != 0)
- return error;
- return cd_play_big(cd, args->blk, args->len);
+
+ if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd, 0)) != 0)
+ return (error);
+ return (cd_play(cd, args->blk, args->len));
}
case CDIOCREADSUBCHANNEL: {
struct ioc_read_subchannel *args
@@ -816,135 +871,147 @@ cdioctl(dev, cmd, addr, flag, p)
}
case CDIOREADTOCHEADER: {
struct ioc_toc_header th;
- if ((error = cd_read_toc(cd, 0, 0,
- (struct cd_toc_entry *) &th,
- sizeof(th))) != 0)
- return error;
- th.len = ntohs(th.len);
+
+ if ((error = cd_read_toc(cd, 0, 0, &th, sizeof(th), 0)) != 0)
+ return (error);
+ if (cd->sc_link->quirks & ADEV_LITTLETOC) {
+#if BYTE_ORDER == BIG_ENDIAN
+ bswap((u_int8_t *)&th.len, sizeof(th.len));
+#endif
+ } else
+ th.len = ntohs(th.len);
bcopy(&th, addr, sizeof(th));
- return 0;
+ return (0);
}
- case CDIOREADTOCENTRYS: {
- struct cd_toc {
- struct ioc_toc_header header;
- struct cd_toc_entry entries[100];
- } * data;
+ case CDIOREADTOCENTRYS: {
+ struct cd_toc *toc;
struct ioc_read_toc_entry *te =
- (struct ioc_read_toc_entry *)addr;
+ (struct ioc_read_toc_entry *)addr;
struct ioc_toc_header *th;
+ struct cd_toc_entry *cte;
int len = te->data_len;
+ int ntracks;
int res;
- if (len > sizeof(data->entries) ||
- len < sizeof(struct cd_toc_entry))
- return EINVAL;
-
- MALLOC (data, struct cd_toc *, sizeof (struct cd_toc),
+ MALLOC (toc, struct cd_toc *, sizeof (struct cd_toc),
M_DEVBUF, M_WAITOK);
- th = &data->header;
+ th = &toc->header;
- error = cd_read_toc(cd, te->address_format,
- te->starting_track,
- (struct cd_toc_entry *)data,
- len + sizeof(struct ioc_toc_header));
+ if (len > sizeof(toc->entries) ||
+ len < sizeof(struct cd_toc_entry)) {
+ FREE(toc, M_DEVBUF);
+ return (EINVAL);
+ }
+ error = cd_read_toc(cd, te->address_format, te->starting_track,
+ toc, len + sizeof(struct ioc_toc_header), 0);
if (error) {
- FREE(data, M_DEVBUF);
- return error;
+ FREE(toc, M_DEVBUF);
+ return (error);
}
- len = min(len, ntohs(th->len) - (sizeof(th->starting_track) +
- sizeof(th->ending_track)));
- res = copyout(data->entries, te->data, len);
- FREE(data, M_DEVBUF);
+ if (te->address_format == CD_LBA_FORMAT)
+ for (ntracks =
+ th->ending_track - th->starting_track + 1;
+ ntracks >= 0; ntracks--) {
+ cte = &toc->entries[ntracks];
+ cte->addr_type = CD_LBA_FORMAT;
+ if (cd->sc_link->quirks & ADEV_LITTLETOC) {
+#if BYTE_ORDER == BIG_ENDIAN
+ bswap((u_int8_t*)&cte->addr,
+ sizeof(cte->addr));
+#endif
+ } else
+ cte->addr.lba = ntohl(cte->addr.lba);
+ }
+ if (cd->sc_link->quirks & ADEV_LITTLETOC) {
+#if BYTE_ORDER == BIG_ENDIAN
+ bswap((u_int8_t*)&th->len, sizeof(th->len));
+#endif
+ } else
+ th->len = ntohs(th->len);
+ len = min(len, th->len - (sizeof(th->starting_track) +
+ sizeof(th->ending_track)));
+
+ res = copyout(toc->entries, te->data, len);
+ FREE(toc, M_DEVBUF);
+
return (res);
}
+ case CDIOREADMSADDR: {
+ struct cd_toc *toc;
+ int sessno = *(int*)addr;
+ struct cd_toc_entry *cte;
+
+ if (sessno != 0)
+ return (EINVAL);
+
+ MALLOC (toc, struct cd_toc *, sizeof (struct cd_toc),
+ M_DEVBUF, M_WAITOK);
+
+ error = cd_read_toc(cd, 0, 0, toc,
+ sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry),
+ 0x40 /* control word for "get MS info" */);
+
+ if (error) {
+ FREE(toc, M_DEVBUF);
+ return (error);
+ }
+
+ cte = &toc->entries[0];
+ if (cd->sc_link->quirks & ADEV_LITTLETOC) {
+#if BYTE_ORDER == BIG_ENDIAN
+ bswap((u_int8_t*)&cte->addr, sizeof(cte->addr));
+#endif
+ } else
+ cte->addr.lba = ntohl(cte->addr.lba);
+ if (cd->sc_link->quirks & ADEV_LITTLETOC) {
+#if BYTE_ORDER == BIG_ENDIAN
+ bswap((u_int8_t*)&toc->header.len, sizeof(toc->header.len));
+#endif
+ } else
+ toc->header.len = ntohs(toc->header.len);
+
+ *(int*)addr = (toc->header.len >= 10 && cte->track > 1) ?
+ cte->addr.lba : 0;
+ FREE(toc, M_DEVBUF);
+ return 0;
+ }
case CDIOCSETPATCH: {
struct ioc_patch *arg = (struct ioc_patch *)addr;
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
- data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
- data.page.audio.port[2].channels = arg->patch[2];
- data.page.audio.port[3].channels = arg->patch[3];
- return cd_set_mode(cd, &data);
+
+ return ((*cd->sc_ops->cdo_setchan)(cd, arg->patch[0],
+ arg->patch[1], arg->patch[2], arg->patch[3], 0));
}
case CDIOCGETVOL: {
struct ioc_vol *arg = (struct ioc_vol *)addr;
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
- arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
- arg->vol[2] = data.page.audio.port[2].volume;
- arg->vol[3] = data.page.audio.port[3].volume;
- return 0;
+
+ return ((*cd->sc_ops->cdo_getvol)(cd, arg, 0));
}
case CDIOCSETVOL: {
struct ioc_vol *arg = (struct ioc_vol *)addr;
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
- data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
- data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1;
- data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
- data.page.audio.port[2].volume = arg->vol[2];
- data.page.audio.port[3].volume = arg->vol[3];
- return cd_set_mode(cd, &data);
- }
- case CDIOCSETMONO: {
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- data.page.audio.port[LEFT_PORT].channels =
- LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8;
- data.page.audio.port[RIGHT_PORT].channels =
- LEFT_CHANNEL | RIGHT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- return cd_set_mode(cd, &data);
- }
- case CDIOCSETSTEREO: {
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- return cd_set_mode(cd, &data);
- }
- case CDIOCSETMUTE: {
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- data.page.audio.port[LEFT_PORT].channels = 0;
- data.page.audio.port[RIGHT_PORT].channels = 0;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- return cd_set_mode(cd, &data);
- }
- case CDIOCSETLEFT: {
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- return cd_set_mode(cd, &data);
- }
- case CDIOCSETRIGHT: {
- struct cd_mode_data data;
- if ((error = cd_get_mode(cd, &data, AUDIO_PAGE)) != 0)
- return error;
- data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- return cd_set_mode(cd, &data);
+
+ return ((*cd->sc_ops->cdo_setvol)(cd, arg, 0));
}
+
+ case CDIOCSETMONO:
+ return ((*cd->sc_ops->cdo_setchan)(cd, BOTH_CHANNEL,
+ BOTH_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
+
+ case CDIOCSETSTEREO:
+ return ((*cd->sc_ops->cdo_setchan)(cd, LEFT_CHANNEL,
+ RIGHT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
+
+ case CDIOCSETMUTE:
+ return ((*cd->sc_ops->cdo_setchan)(cd, MUTE_CHANNEL,
+ MUTE_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
+
+ case CDIOCSETLEFT:
+ return ((*cd->sc_ops->cdo_setchan)(cd, LEFT_CHANNEL,
+ LEFT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
+
+ case CDIOCSETRIGHT:
+ return ((*cd->sc_ops->cdo_setchan)(cd, RIGHT_CHANNEL,
+ RIGHT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
case CDIOCRESUME:
return cd_pause(cd, 1);
case CDIOCPAUSE:
@@ -953,6 +1020,10 @@ cdioctl(dev, cmd, addr, flag, p)
return scsi_start(cd->sc_link, SSS_START, 0);
case CDIOCSTOP:
return scsi_start(cd->sc_link, SSS_STOP, 0);
+ case CDIOCCLOSE:
+ return (scsi_start(cd->sc_link, SSS_START|SSS_LOEJ,
+ SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE));
+
case MTIOCTOP:
if (((struct mtop *)addr)->mt_op != MTOFFL)
return EIO;
@@ -974,13 +1045,11 @@ cdioctl(dev, cmd, addr, flag, p)
case CDIOCCLRDEBUG:
cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
return 0;
- case CDIOCRESET:
- return cd_reset(cd);
#ifdef CDDA
case CDIOCSETCDDA: {
int onoff = *(int *)addr;
/* select CD-DA mode */
- struct cd_mode_data data;
+ struct scsi_cd_mode_data data;
if (CDPART(dev) != RAW_PART)
return ENOTTY;
@@ -1037,6 +1106,16 @@ cdioctl(dev, cmd, addr, flag, p)
}
#endif
+ case CDIOCRESET:
+ case SCIOCRESET:
+ return (cd_reset(cd));
+ case CDIOCLOADUNLOAD: {
+ struct ioc_load_unload *args = (struct ioc_load_unload *)addr;
+
+ return ((*cd->sc_ops->cdo_load_unload)(cd, args->options,
+ args->slot));
+ }
+
default:
if (CDPART(dev) != RAW_PART)
return ENOTTY;
@@ -1112,62 +1191,77 @@ cdgetdisklabel(dev, cd, lp, clp, spoofonly)
}
/*
- * Get the requested page into the buffer given
+ * Find out from the device what it's capacity is
*/
-int
-cd_get_mode(cd, data, page)
+u_long
+cd_size(cd, flags)
struct cd_softc *cd;
- struct cd_mode_data *data;
- int page;
+ int flags;
{
- struct scsi_mode_sense scsi_cmd;
+ struct scsi_read_cd_cap_data rdcap;
+ struct scsi_read_cd_capacity scsi_cmd;
+ int blksize;
+ u_long size;
+ if (cd->sc_link->quirks & ADEV_NOCAPACITY) {
+ /*
+ * the drive doesn't support the READ_CD_CAPACITY command
+ * use a fake size
+ */
+ cd->params.blksize = 2048;
+ cd->params.disksize = 400000;
+ return (400000);
+ }
+
+ /*
+ * make up a scsi command and ask the scsi driver to do
+ * it for you.
+ */
bzero(&scsi_cmd, sizeof(scsi_cmd));
- bzero(data, sizeof(*data));
- scsi_cmd.opcode = MODE_SENSE;
- scsi_cmd.page = page;
- scsi_cmd.length = sizeof(*data) & 0xff;
- return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
- sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
- NULL, SCSI_DATA_IN);
-}
+ scsi_cmd.opcode = READ_CD_CAPACITY;
-/*
- * Get the requested page into the buffer given
- */
-int
-cd_set_mode(cd, data)
- struct cd_softc *cd;
- struct cd_mode_data *data;
-{
- struct scsi_mode_select scsi_cmd;
+ /*
+ * If the command works, interpret the result as a 4 byte
+ * number of blocks and a blocksize
+ */
+ if (scsi_scsi_cmd(cd->sc_link,
+ (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
+ (u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 20000, NULL,
+ flags | SCSI_DATA_IN) != 0)
+ return (0);
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.opcode = MODE_SELECT;
- scsi_cmd.byte2 |= SMS_PF;
- scsi_cmd.length = sizeof(*data) & 0xff;
- data->header.data_length = 0;
- return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
- sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
- NULL, SCSI_DATA_OUT);
+ blksize = _4btol(rdcap.length);
+ if ((blksize < 512) || ((blksize & 511) != 0))
+ blksize = 2048; /* some drives lie ! */
+ cd->params.blksize = blksize;
+
+ size = _4btol(rdcap.addr) + 1;
+ if (size < 100)
+ size = 400000; /* ditto */
+ cd->params.disksize = size;
+
+ SC_DEBUG(cd->sc_link, SDEV_DB2, ("cd_size: %d %ld\n", blksize, size));
+ return (size);
}
+
/*
* Get scsi driver to send a "start playing" command
*/
int
-cd_play_big(cd, blkno, nblks)
+cd_play(cd, blkno, nblks)
struct cd_softc *cd;
int blkno, nblks;
{
- struct scsi_play_big scsi_cmd;
+ struct scsi_play scsi_cmd;
bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.opcode = PLAY_BIG;
+ scsi_cmd.opcode = PLAY;
_lto4b(blkno, scsi_cmd.blk_addr);
- _lto4b(nblks, scsi_cmd.xfer_len);
- return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
- sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
+ _lto2b(nblks, scsi_cmd.xfer_len);
+ return (scsi_scsi_cmd(cd->sc_link,
+ (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
+ 0, 0, CDRETRIES, 200000, NULL, 0));
}
/*
@@ -1178,16 +1272,31 @@ cd_play_tracks(cd, strack, sindex, etrack, eindex)
struct cd_softc *cd;
int strack, sindex, etrack, eindex;
{
- struct scsi_play_track scsi_cmd;
+ struct cd_toc toc;
+ int error;
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.opcode = PLAY_TRACK;
- scsi_cmd.start_track = strack;
- scsi_cmd.start_index = sindex;
- scsi_cmd.end_track = etrack;
- scsi_cmd.end_index = eindex;
- return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
- sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
+ if (!etrack)
+ return (EIO);
+ if (strack > etrack)
+ return (EINVAL);
+
+ if ((error = cd_load_toc(cd, &toc)) != 0)
+ return (error);
+
+ if (++etrack > (toc.header.ending_track+1))
+ etrack = toc.header.ending_track+1;
+
+ strack -= toc.header.starting_track;
+ etrack -= toc.header.starting_track;
+ if (strack < 0)
+ return (EINVAL);
+
+ return (cd_play_msf(cd, toc.entries[strack].addr.msf.minute,
+ toc.entries[strack].addr.msf.second,
+ toc.entries[strack].addr.msf.frame,
+ toc.entries[etrack].addr.msf.minute,
+ toc.entries[etrack].addr.msf.second,
+ toc.entries[etrack].addr.msf.frame));
}
/*
@@ -1208,8 +1317,9 @@ cd_play_msf(cd, startm, starts, startf, endm, ends, endf)
scsi_cmd.end_m = endm;
scsi_cmd.end_s = ends;
scsi_cmd.end_f = endf;
- return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
- sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
+ return (scsi_scsi_cmd(cd->sc_link,
+ (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
+ 0, 0, CDRETRIES, 2000, NULL, 0));
}
/*
@@ -1269,29 +1379,51 @@ cd_read_subchannel(cd, mode, format, track, data, len)
* Read table of contents
*/
int
-cd_read_toc(cd, mode, start, data, len)
+cd_read_toc(cd, mode, start, data, len, control)
struct cd_softc *cd;
- int mode, start, len;
- struct cd_toc_entry *data;
+ int mode, start, len, control;
+ void *data;
{
struct scsi_read_toc scsi_cmd;
int ntoc;
bzero(&scsi_cmd, sizeof(scsi_cmd));
- /*if (len!=sizeof(struct ioc_toc_header))
- * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
- * else */
+#if 0
+ if (len!=sizeof(struct ioc_toc_header))
+ ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
+ else
+#endif
ntoc = len;
scsi_cmd.opcode = READ_TOC;
if (mode == CD_MSF_FORMAT)
scsi_cmd.byte2 |= CD_MSF;
scsi_cmd.from_track = start;
_lto2b(ntoc, scsi_cmd.data_len);
+ scsi_cmd.control = control;
return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
sizeof(struct scsi_read_toc), (u_char *)data, len, CDRETRIES,
5000, NULL, SCSI_DATA_IN);
}
+int
+cd_load_toc(cd, toc)
+ struct cd_softc *cd;
+ struct cd_toc *toc;
+{
+ int ntracks, len, error;
+
+ if ((error = cd_read_toc(cd, 0, 0, toc, sizeof(toc->header), 0)) != 0)
+ return (error);
+
+ ntracks = toc->header.ending_track - toc->header.starting_track + 1;
+ len = (ntracks + 1) * sizeof(struct cd_toc_entry) +
+ sizeof(toc->header);
+ if ((error = cd_read_toc(cd, CD_MSF_FORMAT, 0, toc, len, 0)) != 0)
+ return (error);
+ return (0);
+}
+
+
/*
* Get the scsi driver to send a full inquiry to the device and use the
* results to fill out the disk parameter structure.
@@ -1301,49 +1433,13 @@ cd_get_parms(cd, flags)
struct cd_softc *cd;
int flags;
{
- struct scsi_read_cd_cap_data rdcap;
- struct scsi_read_cd_capacity scsi_cmd;
- int blksize;
- u_long size;
-
/*
- * make up a scsi command and ask the scsi driver to do
- * it for you.
+ * give a number of sectors so that sec * trks * cyls
+ * is <= disk_size
*/
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.opcode = READ_CD_CAPACITY;
-
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks and a blocksize
- */
- if (scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
- sizeof(scsi_cmd), (u_char *)&rdcap, sizeof(rdcap), CDRETRIES,
- 20000, NULL, flags | SCSI_DATA_IN) != 0) {
- /*
- * Some CD-R devices and such will fail READ_CD_CAPACITY
- * when blank media is loaded. We still want to be able
- * to open them, however.
- *
- * scsi_scsi_cmd() will log failure of the command; just use
- * the defaults.
- */
- cd->params.blksize = 2048;
- cd->params.disksize = 400000;
- return 0;
- }
-
- blksize = _4btol(rdcap.length);
- if (blksize < 512 || blksize > 2048)
- blksize = 2048; /* some drives lie ! */
- cd->params.blksize = blksize;
-
- size = _4btol(rdcap.addr) + 1;
- if (size < 100)
- size = 400000; /* ditto */
- cd->params.disksize = size;
-
- return 0;
+ if (cd_size(cd, flags) == 0)
+ return (ENXIO);
+ return (0);
}
int
diff --git a/sys/scsi/cd.h b/sys/scsi/cd.h
new file mode 100644
index 00000000000..6260ab7cd64
--- /dev/null
+++ b/sys/scsi/cd.h
@@ -0,0 +1,213 @@
+/* $OpenBSD: cd.h,v 1.1 1999/07/20 06:21:59 csapuntz Exp $ */
+/* $NetBSD: scsi_cd.h,v 1.6 1996/03/19 03:06:39 mycroft Exp $ */
+
+/*
+ * Written by Julian Elischer (julian@tfs.com)
+ * for TRW Financial Systems.
+ *
+ * TRW Financial Systems, in accordance with their agreement with Carnegie
+ * Mellon University, makes this software available to CMU to distribute
+ * or use in any manner that they see fit as long as this message is kept with
+ * the software. For this reason TFS also grants any other persons or
+ * organisations permission to use or modify this software.
+ *
+ * TFS supplies this software to be publicly redistributed
+ * on the understanding that TFS is not responsible for the correct
+ * functioning of this software in any circumstances.
+ *
+ * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ */
+#ifndef _SCSI_CD_H
+#define _SCSI_CD_H 1
+
+/*
+ * Define two bits always in the same place in byte 2 (flag byte)
+ */
+#define CD_RELADDR 0x01
+#define CD_MSF 0x02
+
+/*
+ * SCSI command format
+ */
+
+struct scsi_read_capacity_cd {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t addr[4];
+ u_int8_t unused[3];
+ u_int8_t control;
+};
+
+struct scsi_pause {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t unused[6];
+ u_int8_t resume;
+ u_int8_t control;
+};
+#define PA_PAUSE 1
+#define PA_RESUME 0
+
+struct scsi_play_msf {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t unused;
+ u_int8_t start_m;
+ u_int8_t start_s;
+ u_int8_t start_f;
+ u_int8_t end_m;
+ u_int8_t end_s;
+ u_int8_t end_f;
+ u_int8_t control;
+};
+
+struct scsi_play_track {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t unused[2];
+ u_int8_t start_track;
+ u_int8_t start_index;
+ u_int8_t unused1;
+ u_int8_t end_track;
+ u_int8_t end_index;
+ u_int8_t control;
+};
+
+struct scsi_play {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t blk_addr[4];
+ u_int8_t unused;
+ u_int8_t xfer_len[2];
+ u_int8_t control;
+};
+
+struct scsi_play_big {
+ u_int8_t opcode;
+ u_int8_t byte2; /* same as above */
+ u_int8_t blk_addr[4];
+ u_int8_t xfer_len[4];
+ u_int8_t unused;
+ u_int8_t control;
+};
+
+struct scsi_play_rel_big {
+ u_int8_t opcode;
+ u_int8_t byte2; /* same as above */
+ u_int8_t blk_addr[4];
+ u_int8_t xfer_len[4];
+ u_int8_t track;
+ u_int8_t control;
+};
+
+struct scsi_read_header {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t blk_addr[4];
+ u_int8_t unused;
+ u_int8_t data_len[2];
+ u_int8_t control;
+};
+
+struct scsi_read_subchannel {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t byte3;
+#define SRS_SUBQ 0x40
+ u_int8_t subchan_format;
+ u_int8_t unused[2];
+ u_int8_t track;
+ u_int8_t data_len[2];
+ u_int8_t control;
+};
+
+struct scsi_read_toc {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t unused[4];
+ u_int8_t from_track;
+ u_int8_t data_len[2];
+ u_int8_t control;
+};
+;
+
+struct scsi_read_cd_capacity {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t addr[4];
+ u_int8_t unused[3];
+ u_int8_t control;
+};
+
+/*
+ * Opcodes
+ */
+
+#define READ_CD_CAPACITY 0x25 /* slightly different from disk */
+#define READ_SUBCHANNEL 0x42 /* cdrom read Subchannel */
+#define READ_TOC 0x43 /* cdrom read TOC */
+#define READ_HEADER 0x44 /* cdrom read header */
+#define PLAY 0x45 /* cdrom play 'play audio' mode */
+#define PLAY_MSF 0x47 /* cdrom play Min,Sec,Frames mode */
+#define PLAY_TRACK 0x48 /* cdrom play track/index mode */
+#define PLAY_TRACK_REL 0x49 /* cdrom play track/index mode */
+#define PAUSE 0x4b /* cdrom pause in 'play audio' mode */
+#define PLAY_BIG 0xa5 /* cdrom pause in 'play audio' mode */
+#define PLAY_TRACK_REL_BIG 0xa9 /* cdrom play track/index mode */
+
+
+struct scsi_read_cd_cap_data {
+ u_int8_t addr[4];
+ u_int8_t length[4];
+};
+
+struct cd_audio_page {
+ u_int8_t page_code;
+#define CD_PAGE_CODE 0x3F
+#define AUDIO_PAGE 0x0e
+#define CD_PAGE_PS 0x80
+ u_int8_t param_len;
+ u_int8_t flags;
+#define CD_PA_SOTC 0x02
+#define CD_PA_IMMED 0x04
+ u_int8_t unused[2];
+ u_int8_t format_lba;
+#define CD_PA_FORMAT_LBA 0x0F
+#define CD_PA_APR_VALID 0x80
+ u_int8_t lb_per_sec[2];
+ struct port_control {
+ u_int8_t channels;
+#define CHANNEL 0x0F
+#define CHANNEL_0 1
+#define CHANNEL_1 2
+#define CHANNEL_2 4
+#define CHANNEL_3 8
+#define LEFT_CHANNEL CHANNEL_0
+#define RIGHT_CHANNEL CHANNEL_1
+#define MUTE_CHANNEL 0x0
+#define BOTH_CHANNEL LEFT_CHANNEL | RIGHT_CHANNEL
+ u_int8_t volume;
+ } port[4];
+#define LEFT_PORT 0
+#define RIGHT_PORT 1
+};
+
+#ifdef CDDA
+/*
+ * There are 2352 bytes in a CD digital audio frame. One frame is 1/75 of a
+ * second, at 44.1kHz sample rate, 16 bits/sample, 2 channels.
+ *
+ * The frame data have the two channels interleaved, with the left
+ * channel first. Samples are little endian 16-bit signed values.
+ */
+#define CD_DA_BLKSIZ 2352 /* # bytes in CD-DA frame */
+#ifndef CD_NORMAL_DENSITY_CODE
+#define CD_NORMAL_DENSITY_CODE 0x00 /* from Toshiba CD-ROM specs */
+#endif
+#ifndef CD_DA_DENSITY_CODE
+#define CD_DA_DENSITY_CODE 0x82 /* from Toshiba CD-ROM specs */
+#endif
+#endif /* CDDA */
+
+#endif /*_SCSI_CD_H*/
+
diff --git a/sys/scsi/cd_atapi.c b/sys/scsi/cd_atapi.c
new file mode 100644
index 00000000000..389f2c44e0f
--- /dev/null
+++ b/sys/scsi/cd_atapi.c
@@ -0,0 +1,188 @@
+/* $OpenBSD: cd_atapi.c,v 1.1 1999/07/20 06:21:59 csapuntz Exp $ */
+/* $NetBSD: cd_atapi.c,v 1.10 1998/08/31 22:28:06 cgd Exp $ */
+
+/*
+ * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Originally written by Julian Elischer (julian@tfs.com)
+ * for TRW Financial Systems for use under the MACH(2.5) operating system.
+ *
+ * TRW Financial Systems, in accordance with their agreement with Carnegie
+ * Mellon University, makes this software available to CMU to distribute
+ * or use in any manner that they see fit as long as this message is kept with
+ * the software. For this reason TFS also grants any other persons or
+ * organisations permission to use or modify this software.
+ *
+ * TFS supplies this software to be publicly redistributed
+ * on the understanding that TFS is not responsible for the correct
+ * functioning of this software in any circumstances.
+ *
+ * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ */
+#ifndef __OpenBSD__
+#include "rnd.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/file.h>
+#include <sys/device.h>
+#include <sys/disk.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#if NRND > 0
+#include <sys/rnd.h>
+#endif
+
+#include <sys/cdio.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/cd.h>
+#include <scsi/atapi_all.h>
+#include <scsi/atapi_cd.h>
+#include <scsi/cdvar.h>
+#include <scsi/scsiconf.h>
+
+
+static int cd_atapibus_setchan __P((struct cd_softc *, int, int, int, int, int));
+static int cd_atapibus_getvol __P((struct cd_softc *, struct ioc_vol *, int));
+static int cd_atapibus_setvol __P((struct cd_softc *, const struct ioc_vol *,
+ int));
+static int cd_atapibus_set_pa_immed __P((struct cd_softc *, int));
+static int cd_atapibus_load_unload __P((struct cd_softc *, int, int));
+
+const struct cd_ops cd_atapibus_ops = {
+ cd_atapibus_setchan,
+ cd_atapibus_getvol,
+ cd_atapibus_setvol,
+ cd_atapibus_set_pa_immed,
+ cd_atapibus_load_unload,
+};
+
+static int
+cd_atapibus_setchan(cd, p0, p1, p2, p3, flags)
+ struct cd_softc *cd;
+ int p0, p1, p2, p3, flags;
+{
+ struct atapi_cd_mode_data data;
+ int error;
+
+ if ((error = atapi_mode_sense(cd->sc_link, ATAPI_AUDIO_PAGE,
+ (struct atapi_mode_header *)&data, AUDIOPAGESIZE, flags,
+ CDRETRIES, 20000)) != 0)
+ return (error);
+ data.pages.audio.port[LEFT_PORT].channels = p0;
+ data.pages.audio.port[RIGHT_PORT].channels = p1;
+ data.pages.audio.port[2].channels = p2;
+ data.pages.audio.port[3].channels = p3;
+ return (atapi_mode_select(cd->sc_link,
+ (struct atapi_mode_header *)&data, AUDIOPAGESIZE, flags,
+ CDRETRIES, 20000));
+}
+
+static int
+cd_atapibus_getvol(cd, arg, flags)
+ struct cd_softc *cd;
+ struct ioc_vol *arg;
+ int flags;
+{
+ struct atapi_cd_mode_data data;
+ int error;
+
+ if ((error = atapi_mode_sense(cd->sc_link, ATAPI_AUDIO_PAGE,
+ (struct atapi_mode_header *)&data, AUDIOPAGESIZE, flags,
+ CDRETRIES, 20000)) != 0)
+ return (error);
+ arg->vol[0] = data.pages.audio.port[0].volume;
+ arg->vol[1] = data.pages.audio.port[1].volume;
+ arg->vol[2] = data.pages.audio.port[2].volume;
+ arg->vol[3] = data.pages.audio.port[3].volume;
+ return (0);
+}
+
+static int
+cd_atapibus_setvol(cd, arg, flags)
+ struct cd_softc *cd;
+ const struct ioc_vol *arg;
+ int flags;
+{
+ struct atapi_cd_mode_data data, mask;
+ int error;
+
+ if ((error = atapi_mode_sense(cd->sc_link, ATAPI_AUDIO_PAGE,
+ (struct atapi_mode_header *)&data, AUDIOPAGESIZE, flags,
+ CDRETRIES, 20000)) != 0)
+ return (error);
+ if ((error = atapi_mode_sense(cd->sc_link, ATAPI_AUDIO_PAGE_MASK,
+ (struct atapi_mode_header *)&mask, AUDIOPAGESIZE, flags,
+ CDRETRIES, 20000)) != 0)
+ return (error);
+
+ data.pages.audio.port[0].volume = arg->vol[0] &
+ mask.pages.audio.port[0].volume;
+ data.pages.audio.port[1].volume = arg->vol[1] &
+ mask.pages.audio.port[1].volume;
+ data.pages.audio.port[2].volume = arg->vol[2] &
+ mask.pages.audio.port[2].volume;
+ data.pages.audio.port[3].volume = arg->vol[3] &
+ mask.pages.audio.port[3].volume;
+
+ return (atapi_mode_select(cd->sc_link,
+ (struct atapi_mode_header *)&data, AUDIOPAGESIZE,
+ flags, CDRETRIES, 20000));
+}
+
+static int
+cd_atapibus_set_pa_immed(cd, flags)
+ struct cd_softc *cd;
+ int flags;
+{
+
+ /* Noop. */
+ return (0);
+}
+
+static int
+cd_atapibus_load_unload(cd, options, slot)
+ struct cd_softc *cd;
+ int options, slot;
+{
+ struct atapi_load_unload atapi_cmd;
+
+ bzero(&atapi_cmd, sizeof(atapi_cmd));
+ atapi_cmd.opcode = ATAPI_LOAD_UNLOAD;
+ atapi_cmd.options = options; /* ioctl uses ATAPI values */
+ atapi_cmd.slot = slot;
+ return (scsi_scsi_cmd(cd->sc_link,
+ (struct scsi_generic *)&atapi_cmd, sizeof(atapi_cmd),
+ 0, 0, CDRETRIES, 200000, NULL, 0));
+}
diff --git a/sys/scsi/cd_scsi.c b/sys/scsi/cd_scsi.c
new file mode 100644
index 00000000000..c458c2070e2
--- /dev/null
+++ b/sys/scsi/cd_scsi.c
@@ -0,0 +1,232 @@
+/* $OpenBSD: cd_scsi.c,v 1.1 1999/07/20 06:21:59 csapuntz Exp $ */
+/* $NetBSD: cd_scsi.c,v 1.14 1998/08/31 22:28:06 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Originally written by Julian Elischer (julian@tfs.com)
+ * for TRW Financial Systems for use under the MACH(2.5) operating system.
+ *
+ * TRW Financial Systems, in accordance with their agreement with Carnegie
+ * Mellon University, makes this software available to CMU to distribute
+ * or use in any manner that they see fit as long as this message is kept with
+ * the software. For this reason TFS also grants any other persons or
+ * organisations permission to use or modify this software.
+ *
+ * TFS supplies this software to be publicly redistributed
+ * on the understanding that TFS is not responsible for the correct
+ * functioning of this software in any circumstances.
+ *
+ * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ */
+
+#ifndef __OpenBSD__
+#include "rnd.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/file.h>
+#include <sys/device.h>
+#include <sys/disk.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#if NRND > 0
+#include <sys/rnd.h>
+#endif
+
+#include <sys/cdio.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/cd.h>
+#include <scsi/scsi_cd.h>
+#include <scsi/scsiconf.h>
+#include <scsi/cdvar.h>
+
+int cd_scsibus_get_mode __P((struct cd_softc *,
+ struct scsi_cd_mode_data *, int, int, int));
+int cd_scsibus_set_mode __P((struct cd_softc *,
+ struct scsi_cd_mode_data *, int, int));
+
+int cd_scsibus_setchan __P((struct cd_softc *, int, int, int, int, int));
+int cd_scsibus_getvol __P((struct cd_softc *, struct ioc_vol *, int));
+int cd_scsibus_setvol __P((struct cd_softc *, const struct ioc_vol *,
+ int));
+int cd_scsibus_set_pa_immed __P((struct cd_softc *, int));
+int cd_scsibus_load_unload __P((struct cd_softc *, int, int));
+
+const struct cd_ops cd_scsibus_ops = {
+ cd_scsibus_setchan,
+ cd_scsibus_getvol,
+ cd_scsibus_setvol,
+ cd_scsibus_set_pa_immed,
+ cd_scsibus_load_unload,
+};
+
+/*
+ * Get the requested page into the buffer given
+ */
+int
+cd_scsibus_get_mode(cd, data, page, len, flags)
+ struct cd_softc *cd;
+ struct scsi_cd_mode_data *data;
+ int page, len, flags;
+{
+ struct scsi_mode_sense scsi_cmd;
+
+ bzero(&scsi_cmd, sizeof(scsi_cmd));
+ bzero(data, sizeof(*data));
+ scsi_cmd.opcode = MODE_SENSE;
+ scsi_cmd.page = page;
+ scsi_cmd.length = len & 0xff;
+ return (scsi_scsi_cmd(cd->sc_link,
+ (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
+ (u_char *)data, sizeof(*data), CDRETRIES, 20000, NULL,
+ SCSI_DATA_IN));
+}
+
+/*
+ * Get the requested page into the buffer given
+ */
+int
+cd_scsibus_set_mode(cd, data, len, flags)
+ struct cd_softc *cd;
+ struct scsi_cd_mode_data *data;
+ int len, flags;
+{
+ struct scsi_mode_select scsi_cmd;
+
+ bzero(&scsi_cmd, sizeof(scsi_cmd));
+ scsi_cmd.opcode = MODE_SELECT;
+ scsi_cmd.byte2 |= SMS_PF;
+ scsi_cmd.length = len & 0xff;
+ data->header.data_length = 0;
+ return (scsi_scsi_cmd(cd->sc_link,
+ (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
+ (u_char *)data, sizeof(*data), CDRETRIES, 20000, NULL,
+ SCSI_DATA_OUT));
+}
+
+int
+cd_scsibus_set_pa_immed(cd, flags)
+ struct cd_softc *cd;
+ int flags;
+{
+ struct scsi_cd_mode_data data;
+ int error;
+
+ if ((error = cd_scsibus_get_mode(cd, &data, AUDIO_PAGE,
+ AUDIOPAGESIZE, flags)) != 0)
+ return (error);
+ data.page.audio.flags &= ~CD_PA_SOTC;
+ data.page.audio.flags |= CD_PA_IMMED;
+ return (cd_scsibus_set_mode(cd, &data, AUDIOPAGESIZE, flags));
+}
+
+int
+cd_scsibus_setchan(cd, p0, p1, p2, p3, flags)
+ struct cd_softc *cd;
+ int p0, p1, p2, p3;
+ int flags;
+{
+ struct scsi_cd_mode_data data;
+ int error;
+
+ if ((error = cd_scsibus_get_mode(cd, &data, AUDIO_PAGE,
+ AUDIOPAGESIZE, flags)) != 0)
+ return (error);
+ data.page.audio.port[LEFT_PORT].channels = p0;
+ data.page.audio.port[RIGHT_PORT].channels = p1;
+ data.page.audio.port[2].channels = p2;
+ data.page.audio.port[3].channels = p3;
+ return (cd_scsibus_set_mode(cd, &data, AUDIOPAGESIZE, flags));
+}
+
+int
+cd_scsibus_getvol(cd, arg, flags)
+ struct cd_softc *cd;
+ struct ioc_vol *arg;
+ int flags;
+{
+
+ struct scsi_cd_mode_data data;
+ int error;
+
+ if ((error = cd_scsibus_get_mode(cd, &data, AUDIO_PAGE,
+ AUDIOPAGESIZE, flags)) != 0)
+ return (error);
+ arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
+ arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
+ arg->vol[2] = data.page.audio.port[2].volume;
+ arg->vol[3] = data.page.audio.port[3].volume;
+ return (0);
+}
+
+int
+cd_scsibus_setvol(cd, arg, flags)
+ struct cd_softc *cd;
+ const struct ioc_vol *arg;
+ int flags;
+{
+ struct scsi_cd_mode_data data;
+ int error;
+
+ if ((error = cd_scsibus_get_mode(cd, &data, AUDIO_PAGE,
+ AUDIOPAGESIZE, flags)) != 0)
+ return (error);
+ data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
+ data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
+ data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1;
+ data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
+ data.page.audio.port[2].volume = arg->vol[2];
+ data.page.audio.port[3].volume = arg->vol[3];
+ return (cd_scsibus_set_mode(cd, &data, AUDIOPAGESIZE, flags));
+}
+
+int
+cd_scsibus_load_unload(cd, options, slot)
+ struct cd_softc *cd;
+ int options, slot;
+{
+ /*
+ * Not supported on SCSI CDs that we know of (but we'll leave
+ * the hook here Just In Case).
+ */
+ return (ENODEV);
+}
diff --git a/sys/scsi/cdvar.h b/sys/scsi/cdvar.h
new file mode 100644
index 00000000000..e2e075d887a
--- /dev/null
+++ b/sys/scsi/cdvar.h
@@ -0,0 +1,76 @@
+/* $OpenBSD: cdvar.h,v 1.1 1999/07/20 06:21:59 csapuntz Exp $ */
+/* $NetBSD: cdvar.h,v 1.10 1999/02/02 13:02:49 bouyer Exp $ */
+
+/*
+ * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define CDRETRIES 4
+
+struct cd_ops;
+
+struct cd_softc {
+ struct device sc_dev;
+ struct disk sc_dk;
+
+ int flags;
+#define CDF_LOCKED 0x01
+#define CDF_WANTED 0x02
+#define CDF_WLABEL 0x04 /* label is writable */
+#define CDF_LABELLING 0x08 /* writing label */
+#define CDF_ANCIENT 0x10 /* disk is ancient; for minphys */
+#ifdef CDDA
+#define CDF_CDDA 0x20
+#endif
+ struct scsi_link *sc_link; /* contains our targ, lun, etc. */
+ struct cd_parms {
+ int blksize;
+ u_long disksize; /* total number sectors */
+ } params;
+#ifdef CDDA
+ struct cd_parms orig_params; /* filled in when CD-DA mode starts */
+#endif
+ struct buf buf_queue;
+ char name[16]; /* product name, for default disklabel */
+ const struct cd_ops *sc_ops; /* our bus-dependent ops vector */
+
+#if NRND > 0
+ rndsource_element_t rnd_source;
+#endif
+};
+
+struct cd_ops {
+ int (*cdo_setchan) __P((struct cd_softc *, int, int, int, int,
+ int));
+ int (*cdo_getvol) __P((struct cd_softc *, struct ioc_vol *, int));
+ int (*cdo_setvol) __P((struct cd_softc *, const struct ioc_vol *,
+ int));
+ int (*cdo_set_pa_immed) __P((struct cd_softc *, int));
+ int (*cdo_load_unload) __P((struct cd_softc *, int, int));
+};
+
diff --git a/sys/scsi/files.scsi b/sys/scsi/files.scsi
index f5e11bc3120..ec69940f0b4 100644
--- a/sys/scsi/files.scsi
+++ b/sys/scsi/files.scsi
@@ -1,4 +1,4 @@
-# $OpenBSD: files.scsi,v 1.5 1996/10/31 01:09:21 niklas Exp $
+# $OpenBSD: files.scsi,v 1.6 1999/07/20 06:21:59 csapuntz Exp $
# $NetBSD: files.scsi,v 1.4 1996/05/16 04:01:08 mycroft Exp $
#
# Config.new file and device description for machine-independent SCSI code.
@@ -8,6 +8,7 @@
file scsi/scsi_base.c scsi
file scsi/scsi_ioctl.c scsi
file scsi/scsiconf.c scsi
+file scsi/atapi_base.c scsi
device scsibus {target = -1, lun = -1}
attach scsibus at scsi
@@ -15,6 +16,8 @@ attach scsibus at scsi
device cd: disk
attach cd at scsibus
file scsi/cd.c cd needs-flag
+file scsi/cd_scsi.c
+file scsi/cd_atapi.c
device ch: disk
attach ch at scsibus
diff --git a/sys/scsi/scsi_cd.h b/sys/scsi/scsi_cd.h
index b4269c2db62..0821f8b8c6a 100644
--- a/sys/scsi/scsi_cd.h
+++ b/sys/scsi/scsi_cd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsi_cd.h,v 1.4 1996/10/31 01:09:21 niklas Exp $ */
+/* $OpenBSD: scsi_cd.h,v 1.5 1999/07/20 06:21:59 csapuntz Exp $ */
/* $NetBSD: scsi_cd.h,v 1.6 1996/03/19 03:06:39 mycroft Exp $ */
/*
@@ -20,176 +20,34 @@
#ifndef _SCSI_SCSI_CD_H
#define _SCSI_SCSI_CD_H 1
-/*
- * Define two bits always in the same place in byte 2 (flag byte)
- */
-#define CD_RELADDR 0x01
-#define CD_MSF 0x02
-
-/*
- * SCSI command format
- */
-
-struct scsi_read_capacity_cd {
- u_int8_t opcode;
- u_int8_t byte2;
- u_int8_t addr[4];
- u_int8_t unused[3];
- u_int8_t control;
-};
-
-struct scsi_pause {
- u_int8_t opcode;
- u_int8_t byte2;
- u_int8_t unused[6];
- u_int8_t resume;
- u_int8_t control;
-};
-#define PA_PAUSE 1
-#define PA_RESUME 0
-
-struct scsi_play_msf {
- u_int8_t opcode;
- u_int8_t byte2;
- u_int8_t unused;
- u_int8_t start_m;
- u_int8_t start_s;
- u_int8_t start_f;
- u_int8_t end_m;
- u_int8_t end_s;
- u_int8_t end_f;
- u_int8_t control;
-};
-
-struct scsi_play_track {
- u_int8_t opcode;
- u_int8_t byte2;
- u_int8_t unused[2];
- u_int8_t start_track;
- u_int8_t start_index;
- u_int8_t unused1;
- u_int8_t end_track;
- u_int8_t end_index;
- u_int8_t control;
-};
-
-struct scsi_play {
- u_int8_t opcode;
- u_int8_t byte2;
- u_int8_t blk_addr[4];
- u_int8_t unused;
- u_int8_t xfer_len[2];
- u_int8_t control;
-};
-
-struct scsi_play_big {
- u_int8_t opcode;
- u_int8_t byte2; /* same as above */
- u_int8_t blk_addr[4];
- u_int8_t xfer_len[4];
- u_int8_t unused;
- u_int8_t control;
-};
-
-struct scsi_play_rel_big {
- u_int8_t opcode;
- u_int8_t byte2; /* same as above */
- u_int8_t blk_addr[4];
- u_int8_t xfer_len[4];
- u_int8_t track;
- u_int8_t control;
-};
-
-struct scsi_read_header {
- u_int8_t opcode;
- u_int8_t byte2;
- u_int8_t blk_addr[4];
- u_int8_t unused;
- u_int8_t data_len[2];
- u_int8_t control;
-};
-
-struct scsi_read_subchannel {
- u_int8_t opcode;
- u_int8_t byte2;
- u_int8_t byte3;
-#define SRS_SUBQ 0x40
- u_int8_t subchan_format;
- u_int8_t unused[2];
- u_int8_t track;
- u_int8_t data_len[2];
- u_int8_t control;
-};
-
-struct scsi_read_toc {
- u_int8_t opcode;
- u_int8_t byte2;
- u_int8_t unused[4];
- u_int8_t from_track;
- u_int8_t data_len[2];
- u_int8_t control;
-};
-;
-
-struct scsi_read_cd_capacity {
- u_int8_t opcode;
- u_int8_t byte2;
- u_int8_t addr[4];
- u_int8_t unused[3];
- u_int8_t control;
-};
-
-/*
- * Opcodes
- */
-
-#define READ_CD_CAPACITY 0x25 /* slightly different from disk */
-#define READ_SUBCHANNEL 0x42 /* cdrom read Subchannel */
-#define READ_TOC 0x43 /* cdrom read TOC */
-#define READ_HEADER 0x44 /* cdrom read header */
-#define PLAY 0x45 /* cdrom play 'play audio' mode */
-#define PLAY_MSF 0x47 /* cdrom play Min,Sec,Frames mode */
-#define PLAY_TRACK 0x48 /* cdrom play track/index mode */
-#define PLAY_TRACK_REL 0x49 /* cdrom play track/index mode */
-#define PAUSE 0x4b /* cdrom pause in 'play audio' mode */
-#define PLAY_BIG 0xa5 /* cdrom pause in 'play audio' mode */
-#define PLAY_TRACK_REL_BIG 0xa9 /* cdrom play track/index mode */
-
-
-struct scsi_read_cd_cap_data {
- u_int8_t addr[4];
- u_int8_t length[4];
-};
-
-union cd_pages {
- struct audio_page {
- u_int8_t page_code;
-#define CD_PAGE_CODE 0x3F
-#define AUDIO_PAGE 0x0e
-#define CD_PAGE_PS 0x80
- u_int8_t param_len;
- u_int8_t flags;
-#define CD_PA_SOTC 0x02
-#define CD_PA_IMMED 0x04
- u_int8_t unused[2];
- u_int8_t format_lba;
-#define CD_PA_FORMAT_LBA 0x0F
-#define CD_PA_APR_VALID 0x80
- u_int8_t lb_per_sec[2];
- struct port_control {
- u_int8_t channels;
-#define CHANNEL 0x0F
-#define CHANNEL_0 1
-#define CHANNEL_1 2
-#define CHANNEL_2 4
-#define CHANNEL_3 8
-#define LEFT_CHANNEL CHANNEL_0
-#define RIGHT_CHANNEL CHANNEL_1
- u_int8_t volume;
- } port[4];
-#define LEFT_PORT 0
-#define RIGHT_PORT 1
- } audio;
+struct scsi_cd_write_params_page {
+ u_int8_t page_code;
+ u_int8_t page_len;
+ u_int8_t write_type;
+#define WRITE_TYPE_DUMMY 0x10 /* do not actually write blocks */
+#define WRITE_TYPE_MASK 0x0f /* session write type */
+ u_int8_t track_mode;
+#define TRACK_MODE_MULTI_SESS 0xc0 /* multisession write type */
+#define TRACK_MODE_FP 0x20 /* fixed packet (if in packet mode) */
+#define TRACK_MODE_COPY 0x10 /* 1st higher gen of copy prot track */
+#define TRACK_MODE_PREEPMPASIS 0x01 /* audio w/ preemphasis (audio) */
+#define TRACK_MODE_INCREMENTAL 0x01 /* incremental data track (data) */
+#define TRACK_MODE_ALLOW_COPY 0x02 /* digital copy is permitted */
+#define TRACK_MODE_DATA 0x04 /* this is a data track */
+#define TRACK_MODE_4CHAN 0x08 /* four channel audio */
+ u_int8_t dbtype;
+#define DBTYPE_MASK 0x0f /* data block type */
+ u_int8_t reserved1[2];
+ u_int8_t host_appl_code;
+#define HOST_APPL_CODE_MASK 0x3f /* host application code of disk */
+ u_int8_t session_format;
+ u_int8_t reserved2;
+ u_int8_t packet_size[4];
+ u_int8_t audio_pause_len[2];
+ u_int8_t media_cat_number[16];
+ u_int8_t isrc[14];
+ u_int8_t sub_header[4];
+ u_int8_t vendir_unique[4];
};
#ifdef CDDA
@@ -209,10 +67,20 @@ union cd_pages {
#endif
#endif /* CDDA */
-struct cd_mode_data {
+union scsi_cd_pages {
+ struct scsi_cd_write_params_page write_params;
+ struct cd_audio_page audio;
+};
+
+struct scsi_cd_mode_data {
struct scsi_mode_header header;
struct scsi_blk_desc blk_desc;
- union cd_pages page;
+ union scsi_cd_pages page;
};
+
+#define AUDIOPAGESIZE \
+ (sizeof(struct scsi_mode_header) + sizeof(struct scsi_blk_desc) \
+ + sizeof(struct cd_audio_page))
+
#endif /*_SCSI_SCSI_CD_H*/
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c
index 4bd2de8fd7a..7ef064ad45c 100644
--- a/sys/scsi/scsiconf.c
+++ b/sys/scsi/scsiconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsiconf.c,v 1.42 1999/02/24 07:36:02 downsj Exp $ */
+/* $OpenBSD: scsiconf.c,v 1.43 1999/07/20 06:21:59 csapuntz Exp $ */
/* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */
/*
@@ -305,7 +305,7 @@ scsi_strvis(dst, src, len)
struct scsi_quirk_inquiry_pattern {
struct scsi_inquiry_pattern pattern;
- u_int8_t quirks;
+ u_int16_t quirks;
};
struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = {
@@ -512,8 +512,45 @@ struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = {
"ULTIMA ", "AT3 1.60 ", ""}, SDEV_NOLUNS},
{{T_SCANNER, T_FIXED,
"UMAX ", "SuperVista S-12 ", "V1.9"}, SDEV_NOLUNS},
+
+ /* ATAPI device quirks */
+ {{T_CDROM, T_REMOV,
+ "ALPS ELECTRIC CO.,LTD. DC544C", "", "SW03D"}, ADEV_NOTUR},
+ {{T_CDROM, T_REMOV,
+ "BCD-16X 1997-04-25", "", "VER 2.2"}, SDEV_NOSTARTUNIT},
+ {{T_CDROM, T_REMOV,
+ "BCD-24X 1997-06-27", "", "VER 2.0"}, SDEV_NOSTARTUNIT},
+ {{T_CDROM, T_REMOV,
+ "CR-2801TE", "", "1.07"}, ADEV_NOSENSE},
+ {{T_CDROM, T_REMOV,
+ "CREATIVECD3630E", "", "AC101"}, ADEV_NOSENSE},
+ {{T_CDROM, T_REMOV,
+ "FX320S", "", "q01"}, ADEV_NOSENSE},
+ {{T_CDROM, T_REMOV,
+ "GCD-R580B", "", "1.00"}, ADEV_LITTLETOC},
+ {{T_CDROM, T_REMOV,
+ "MATSHITA CR-574", "", "1.02"}, ADEV_NOCAPACITY},
+ {{T_CDROM, T_REMOV,
+ "MATSHITA CR-574", "", "1.06"}, ADEV_NOCAPACITY},
+ {{T_CDROM, T_REMOV,
+ "Memorex CRW-2642", "", "1.0g"}, ADEV_NOSENSE},
+ {{T_CDROM, T_REMOV,
+ "NEC CD-ROM DRIVE:273", "", "4.21"}, ADEV_NOTUR},
+ {{T_CDROM, T_REMOV,
+ "SANYO CRD-256P", "", "1.02"}, ADEV_NOCAPACITY},
+ {{T_CDROM, T_REMOV,
+ "SANYO CRD-254P", "", "1.02"}, ADEV_NOCAPACITY},
+ {{T_CDROM, T_REMOV,
+ "SANYO CRD-S54P", "", "1.08"}, ADEV_NOCAPACITY},
+ {{T_CDROM, T_REMOV,
+ "CD-ROM CDR-S1", "", "1.70"}, ADEV_NOCAPACITY}, /* Sanyo */
+ {{T_CDROM, T_REMOV,
+ "CD-ROM CDR-N16", "", "1.25"}, ADEV_NOCAPACITY}, /* Sanyo */
+ {{T_CDROM, T_REMOV,
+ "UJDCD8730", "", "1.14"}, ADEV_NODOORLOCK}, /* Acer */
};
+
/*
* Print out autoconfiguration information for a subdevice.
*
diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h
index ffe8a2dce71..6a0520f6c35 100644
--- a/sys/scsi/scsiconf.h
+++ b/sys/scsi/scsiconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsiconf.h,v 1.17 1999/07/18 22:49:41 csapuntz Exp $ */
+/* $OpenBSD: scsiconf.h,v 1.18 1999/07/20 06:21:59 csapuntz Exp $ */
/* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */
/*
@@ -150,15 +150,20 @@ struct scsi_link {
#define SDEV_OPEN 0x0008 /* at least 1 open session */
#define SDEV_DBX 0x00f0 /* debuging flags (scsi_debug.h) */
#define SDEV_EJECTING 0x0100 /* eject on device close */
- u_int8_t quirks; /* per-device oddities */
-#define SDEV_AUTOSAVE 0x01 /* do implicit SAVEDATAPOINTER on disconnect */
-#define SDEV_NOSYNCWIDE 0x02 /* does not grok SDTR or WDTR */
-#define SDEV_NOLUNS 0x04 /* does not grok LUNs */
-#define SDEV_FORCELUNS 0x08 /* prehistoric drive/ctlr groks LUNs */
-#define SDEV_NOMODESENSE 0x10 /* removable media/optical drives */
-#define SDEV_NOSTARTUNIT 0x20 /* do not issue start unit requests in sd.c */
-#define SDEV_NOTAGS 0x40 /* lies about having tagged queueing */
-#define SDEV_NOSENSE 0x80 /* No request sense - ATAPI */
+#define SDEV_ATAPI 0x0200 /* device is ATAPI */
+ u_int16_t quirks; /* per-device oddities */
+#define SDEV_AUTOSAVE 0x0001 /* do implicit SAVEDATAPOINTER on disconnect */
+#define SDEV_NOSYNCWIDE 0x0002 /* does not grok SDTR or WDTR */
+#define SDEV_NOLUNS 0x0004 /* does not grok LUNs */
+#define SDEV_FORCELUNS 0x0008 /* prehistoric drive/ctlr groks LUNs */
+#define SDEV_NOMODESENSE 0x0010 /* removable media/optical drives */
+#define SDEV_NOSTARTUNIT 0x0020 /* do not issue start unit requests in sd.c */
+#define SDEV_NOTAGS 0x0040 /* lies about having tagged queueing */
+#define ADEV_NOSENSE 0x0080 /* No request sense - ATAPI */
+#define ADEV_LITTLETOC 0x0100 /* little-endian TOC - ATAPI */
+#define ADEV_NOCAPACITY 0x0200
+#define ADEV_NOTUR 0x0400
+#define ADEV_NODOORLOCK 0x0800
u_int8_t inquiry_flags; /* copy of flags from probe INQUIRY */
struct scsi_device *device; /* device entry points etc. */
diff --git a/sys/sys/cdio.h b/sys/sys/cdio.h
index b1b1223cfdb..2bd5ac9d5fc 100644
--- a/sys/sys/cdio.h
+++ b/sys/sys/cdio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cdio.h,v 1.6 1998/08/21 22:08:12 deraadt Exp $ */
+/* $OpenBSD: cdio.h,v 1.7 1999/07/20 06:21:59 csapuntz Exp $ */
/* $NetBSD: cdio.h,v 1.11 1996/02/19 18:29:04 scottr Exp $ */
#ifndef _SYS_CDIO_H_
@@ -13,7 +13,7 @@ union msf_lba {
u_char second;
u_char frame;
} msf;
- int lba;
+ u_int32_t lba;
u_char addr[4];
};
@@ -129,6 +129,7 @@ struct cd_sub_channel_track_info {
struct cd_sub_channel_info {
struct cd_sub_channel_header header;
union {
+ struct cd_sub_channel_q_data q_data;
struct cd_sub_channel_position_data position;
struct cd_sub_channel_media_catalog media_catalog;
struct cd_sub_channel_track_info track_info;
@@ -181,8 +182,12 @@ struct ioc_read_toc_entry {
u_short data_len;
struct cd_toc_entry *data;
};
+#define CDIOREADTOCENTRIES _IOWR('c', 5, struct ioc_read_toc_entry)
#define CDIOREADTOCENTRYS _IOWR('c', 5, struct ioc_read_toc_entry)
+/* read LBA start of a given session; 0=last, others not yet supported */
+#define CDIOREADMSADDR _IOWR('c', 6, int)
+
struct ioc_patch {
u_char patch[4]; /* one for each channel */
};
@@ -208,7 +213,8 @@ struct ioc_vol {
#define CDIOCEJECT _IO('c', 24)
#define CDIOCALLOW _IO('c', 25)
#define CDIOCPREVENT _IO('c', 26)
-#define CDIOCSETCDDA _IOW('c', 27, int) /* (re)set CDDA reading mode */
+#define CDIOCCLOSE _IO('c', 27)
+#define CDIOCSETCDDA _IOW('c', 28, int) /* (re)set CDDA reading mode */
struct ioc_play_msf {
u_char start_m;
@@ -220,4 +226,13 @@ struct ioc_play_msf {
};
#define CDIOCPLAYMSF _IOW('c', 25, struct ioc_play_msf)
+struct ioc_load_unload {
+ u_char options;
+#define CD_LU_ABORT 0x1 /* NOTE: These are the same as the ATAPI */
+#define CD_LU_UNLOAD 0x2 /* op values for the LOAD_UNLOAD command */
+#define CD_LU_LOAD 0x3
+ u_char slot;
+};
+#define CDIOCLOADUNLOAD _IOW('c', 26, struct ioc_load_unload)
+
#endif /* !_SYS_CDIO_H_ */