diff options
-rw-r--r-- | sys/dev/atapiscsi/atapiscsi.c | 5 | ||||
-rw-r--r-- | sys/scsi/atapi_all.h | 77 | ||||
-rw-r--r-- | sys/scsi/atapi_base.c | 292 | ||||
-rw-r--r-- | sys/scsi/atapi_cd.h | 122 | ||||
-rw-r--r-- | sys/scsi/cd.c | 632 | ||||
-rw-r--r-- | sys/scsi/cd.h | 213 | ||||
-rw-r--r-- | sys/scsi/cd_atapi.c | 188 | ||||
-rw-r--r-- | sys/scsi/cd_scsi.c | 232 | ||||
-rw-r--r-- | sys/scsi/cdvar.h | 76 | ||||
-rw-r--r-- | sys/scsi/files.scsi | 5 | ||||
-rw-r--r-- | sys/scsi/scsi_cd.h | 214 | ||||
-rw-r--r-- | sys/scsi/scsiconf.c | 41 | ||||
-rw-r--r-- | sys/scsi/scsiconf.h | 25 | ||||
-rw-r--r-- | sys/sys/cdio.h | 21 |
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_ */ |