/*	$NetBSD: mcdreg.h,v 1.9 2000/06/08 18:22:16 cgd Exp $	*/

/*
 * Copyright 1993 by Holger Veit (data part)
 * Copyright 1993 by Brian Moore (audio part)
 * 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 software was developed by Holger Veit and Brian Moore
 *      for use with "386BSD" and similar operating systems.
 *    "Similar operating systems" includes mainly non-profit oriented
 *    systems for research and education, including but not restricted to
 *    "NetBSD", "FreeBSD", "Mach" (by CMU).
 * 4. Neither the name of the developer(s) nor the name "386BSD"
 *    may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``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 DEVELOPER(S) 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.
 *
 * This file contains definitions for some cdrom control commands
 * and status codes. This info was "inherited" from the DOS MTMCDE.SYS
 * driver, and is thus not complete (and may even be wrong). Some day
 * the manufacturer or anyone else might provide better documentation,
 * so this file (and the driver) will then have a better quality.
 */

#if __GNUC__ >= 2
#pragma pack(1)
#endif

typedef unsigned char	bcd_t;
#define	M_msf(msf)	msf[0]
#define	S_msf(msf)	msf[1]
#define	F_msf(msf)	msf[2]

#define	MCD_COMMAND	0
#define	MCD_STATUS	0
#define	MCD_RDATA	0
#define	MCD_RESET	1
#define	MCD_XFER	1
#define	MCD_CTL2	2 /* XXX Is this right? */
#define	MCD_CONFIG	3
#define MCD_NPORT	4

#define	MCD_MASK_DMA	0x07	/* bits 2-0 = DMA channel */
#define	MCD_MASK_IRQ	0x70	/* bits 6-4 = INT number */
				/* 001 = int 2,9 */
				/* 010 = int 3 */
				/* 011 = int 5 */
				/* 100 = int 10 */
				/* 101 = int 11 */

/* Status bits */
#define	MCD_ST_DOOROPEN		0x80
#define	MCD_ST_DSKIN		0x40
#define	MCD_ST_DSKCHNG		0x20
#define	MCD_ST_SPINNING		0x10
#define	MCD_ST_AUDIODISK	0x08	/* audio disk is in */
#define	MCD_ST_READERR		0x04
#define	MCD_ST_AUDIOBSY		0x02	/* audio disk is playing */
#define	MCD_ST_CMDCHECK		0x01	/* command error */

/* Xfer bits */
#define	MCD_XF_STATUSUNAVAIL	0x04
#define	MCD_XF_DATAUNAVAIL	0x02

/* Modes */
#define	MCD_MD_TESTMODE		0x80	/* 0 = DATALENGTH is valid */
#define	MCD_MD_DATALENGTH	0x40	/* 1 = read ECC data also */
#define	MCD_MD_ECCMODE		0x20	/* 1 = disable secondary ECC */
#define	MCD_MD_SPINDOWN		0x08	/* 1 = spin down */
#define	MCD_MD_READTOC		0x04	/* 1 = read TOC on GETQCHN */
#define	MCD_MD_PLAYAUDIO	0x01	/* 1 = play audio through headphones */

#define	MCD_MD_RAW		(MCD_MD_PLAYAUDIO|MCD_MD_ECCMODE|MCD_MD_DATALENGTH)
#define	MCD_MD_COOKED		(MCD_MD_PLAYAUDIO)
#define	MCD_MD_TOC		(MCD_MD_PLAYAUDIO|MCD_MD_READTOC)
#define	MCD_MD_SLEEP		(MCD_MD_PLAYAUDIO|MCD_MD_SPINDOWN)

#define	MCD_BLKSIZE_RAW		sizeof(struct mcd_rawsector)
#define	MCD_BLKSIZE_COOKED	2048

/* Lock states */
#define	MCD_LK_UNLOCK		0x00
#define	MCD_LK_LOCK		0x01
#define	MCD_LK_TEST		0x02

/* Config commands */
#define	MCD_CF_IRQENABLE	0x10
#define	MCD_CF_DMATIMEOUT	0x08
#define	MCD_CF_READUPC		0x04
#define	MCD_CF_DMAENABLE	0x02
#define	MCD_CF_BLOCKSIZE	0x01

/* UPC subcommands */
#define	MCD_UPC_DISABLE		0x00
#define	MCD_UPC_ENABLE		0x01

/* commands known by the controller */
#define	MCD_CMDRESET		0x00
#define	MCD_CMDGETVOLINFO	0x10	/* gets mcd_volinfo */
#define	MCD_CMDGETDISKINFO	0x11	/* gets mcd_disk */
#define	MCD_CMDGETQCHN		0x20	/* gets mcd_qchninfo */
#define	MCD_CMDGETSENSE		0x30	/* gets sense info */
#define	MCD_CMDGETSTAT		0x40	/* gets a byte of status */
#define	MCD_CMDSETMODE		0x50	/* set transmission mode, needs byte */
#define	MCD_CMDSTOPAUDIO	0x70
#define	MCD_CMDSTOPAUDIOTIME	0x80
#define	MCD_CMDGETVOLUME	0x8E	/* gets mcd_volume */
#define	MCD_CMDCONFIGDRIVE	0x90
#define	MCD_CMDSETDRIVEMODE	0xa0	/* set drive mode */
#define	MCD_CMDSETVOLUME	0xae	/* sets mcd_volume */
#define	MCD_CMDREAD1		0xb0	/* read n sectors */
#define	MCD_CMDREADSINGLESPEED	0xc0	/* read (single speed) */
#define	MCD_CMDREADDOUBLESPEED	0xc1	/* read (double speed) */
#define	MCD_CMDGETDRIVEMODE	0xc2	/* get drive mode */
#define	MCD_CMDREAD3		0xc3	/* ? */
#define	MCD_CMDSETINTERLEAVE	0xc8	/* set interleave for read */
#define	MCD_CMDCONTINFO		0xdc	/* get controller info */
#define	MCD_CMDSTOP		0xf0	/* stop everything */
#define	MCD_CMDEJECTDISK	0xf6
#define	MCD_CMDCLOSETRAY	0xf8
#define	MCD_CMDSETLOCK		0xfe	/* needs byte */

union mcd_qchninfo {
	struct {
		u_char	control:4;
		u_char	addr_type:4;
		u_char	trk_no;
		u_char	idx_no;
		bcd_t	track_size[3];
		u_char	:8;
		bcd_t	absolute_pos[3];
	} toc;
	struct {
		u_char	control:4;
		u_char	addr_type:4;
		u_char	trk_no;
		u_char	idx_no;
		bcd_t	relative_pos[3];
		u_char	:8;
		bcd_t	absolute_pos[3];
	} current;
	struct {
		u_char	control:4;
		u_char	addr_type:4;
		u_char	upccode[7];
		u_char	junk[2];
	} upc;
};

struct mcd_volinfo {
	bcd_t	trk_low;
	bcd_t	trk_high;
	bcd_t	vol_msf[3];
	bcd_t	trk1_msf[3];
};

struct mcd_result {
	u_char	length;
	union {
		struct {
			u_char	data[1];
		} raw;
		struct {
			u_char	code;
			u_char	version;
		} continfo;
		union mcd_qchninfo qchninfo;
		struct mcd_volinfo volinfo;
	} data;
};

struct mcd_command {
	u_char	opcode;
	u_char	length;
	union {
		struct {
			u_char	data[1];
		} raw;
		struct {
			bcd_t	start_msf[3];
			bcd_t	reserved[3];
		} seek;
		struct {
			bcd_t	start_msf[3];
			bcd_t	length[3];
		} read;
		struct {
			bcd_t	start_msf[3];
			bcd_t	end_msf[3];
		} play;
		struct {
			u_char	mode;
		} datamode;
		struct {
			u_char	time;
		} hold;
		struct {
			u_char	mode;
		} drivemode;
		struct {
			u_char	mode;
		} lockmode;
		struct {
			u_char	subcommand;
			u_char	data1, data2;
		} config;
	} data;
};

struct mcd_mbox {
	struct mcd_command cmd;
	struct mcd_result res;
};

struct mcd_volume {
	u_char	v0l;
	u_char	v0rs;
	u_char	v0r;
	u_char	v0ls;
};

struct mcd_rawsector {
	u_char	sync1[12];
	u_char	header[4];
	u_char	subheader1[4];
	u_char	subheader2[4];
	u_char	data[MCD_BLKSIZE_COOKED];
	u_char	ecc_bits[280];
};

#if __GNUC__ >= 2
#pragma pack()
#endif
