xref: /netbsd-src/sys/dev/mscp/mscp.h (revision d8a3d8c395e61151e8c549c3f810eeab442223dd)
1*d8a3d8c3Sabs /*	$NetBSD: mscp.h,v 1.9 2012/07/10 22:30:23 abs Exp $	*/
26c8c62c5Sragge 
36c8c62c5Sragge /*
46c8c62c5Sragge  * Copyright (c) 1988 Regents of the University of California.
56c8c62c5Sragge  * All rights reserved.
66c8c62c5Sragge  *
76c8c62c5Sragge  * This code is derived from software contributed to Berkeley by
86c8c62c5Sragge  * Chris Torek.
96c8c62c5Sragge  *
106c8c62c5Sragge  * Redistribution and use in source and binary forms, with or without
116c8c62c5Sragge  * modification, are permitted provided that the following conditions
126c8c62c5Sragge  * are met:
136c8c62c5Sragge  * 1. Redistributions of source code must retain the above copyright
146c8c62c5Sragge  *    notice, this list of conditions and the following disclaimer.
156c8c62c5Sragge  * 2. Redistributions in binary form must reproduce the above copyright
166c8c62c5Sragge  *    notice, this list of conditions and the following disclaimer in the
176c8c62c5Sragge  *    documentation and/or other materials provided with the distribution.
18aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
196c8c62c5Sragge  *    may be used to endorse or promote products derived from this software
206c8c62c5Sragge  *    without specific prior written permission.
216c8c62c5Sragge  *
226c8c62c5Sragge  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
236c8c62c5Sragge  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
246c8c62c5Sragge  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
256c8c62c5Sragge  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
266c8c62c5Sragge  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
276c8c62c5Sragge  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
286c8c62c5Sragge  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
296c8c62c5Sragge  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
306c8c62c5Sragge  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
316c8c62c5Sragge  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
326c8c62c5Sragge  * SUCH DAMAGE.
336c8c62c5Sragge  *
346c8c62c5Sragge  *	@(#)mscp.h	7.5 (Berkeley) 6/28/90
356c8c62c5Sragge  */
366c8c62c5Sragge 
376c8c62c5Sragge /*
386c8c62c5Sragge  * Definitions for the Mass Storage Control Protocol
396c8c62c5Sragge  * I WISH I KNEW WHAT MORE OF THESE WERE.  IT SURE WOULD BE NICE
406c8c62c5Sragge  * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
416c8c62c5Sragge  */
426c8c62c5Sragge 
43*d8a3d8c3Sabs #define MSCP_MAX_UNIT	4095
44*d8a3d8c3Sabs 
456c8c62c5Sragge /*
466c8c62c5Sragge  * Control message opcodes
476c8c62c5Sragge  */
486c8c62c5Sragge #define M_OP_ABORT	0x01	/* Abort command */
496c8c62c5Sragge #define M_OP_GETCMDST	0x02	/* Get command status command */
506c8c62c5Sragge #define M_OP_GETUNITST	0x03	/* Get unit status command */
516c8c62c5Sragge #define M_OP_SETCTLRC	0x04	/* Set controller characteristics command */
526c8c62c5Sragge #define M_OP_SEREX	0x07	/* Serious exception end message */
536c8c62c5Sragge #define M_OP_AVAILABLE	0x08	/* Available command */
546c8c62c5Sragge #define M_OP_ONLINE	0x09	/* Online command */
556c8c62c5Sragge #define M_OP_SETUNITC	0x0a	/* Set unit characteristics command */
566c8c62c5Sragge #define M_OP_DTACCPATH	0x0b	/* Determine access paths command */
576c8c62c5Sragge #define M_OP_ACCESS	0x10	/* Access command */
586c8c62c5Sragge #define M_OP_COMPCD	0x11	/* Compare controller data command */
596c8c62c5Sragge #define M_OP_ERASE	0x12	/* Erase command */
606c8c62c5Sragge #define M_OP_FLUSH	0x13	/* Flush command */
616c8c62c5Sragge #define M_OP_REPLACE	0x14	/* Replace command */
626c8c62c5Sragge #define M_OP_COMPHD	0x20	/* Compare host data command */
636c8c62c5Sragge #define M_OP_READ	0x21	/* Read command */
646c8c62c5Sragge #define M_OP_WRITE	0x22	/* Write command */
656c8c62c5Sragge #define M_OP_WRITM	0x24	/* Write mark command */
666c8c62c5Sragge #define M_OP_POS	0x25	/* Positioning command */
676c8c62c5Sragge #define M_OP_AVAILATTN	0x40	/* Available attention message */
686c8c62c5Sragge #define M_OP_DUPUNIT	0x41	/* Duplicate unit number attention message */
696c8c62c5Sragge #define M_OP_ACCPATH	0x42	/* Access path attention message */
706c8c62c5Sragge #define M_OP_END	0x80	/* End message flag */
716c8c62c5Sragge 
726c8c62c5Sragge 
736c8c62c5Sragge /*
746c8c62c5Sragge  * Generic command modifiers
756c8c62c5Sragge  */
766c8c62c5Sragge #define M_MD_EXPRS	0x8000	/* Express request */
776c8c62c5Sragge #define M_MD_COMP	0x4000	/* Compare */
786c8c62c5Sragge #define M_MD_CLSEX	0x2000	/* Clear serious exception */
796c8c62c5Sragge #define M_MD_ERROR	0x1000	/* Force error */
806c8c62c5Sragge #define M_MD_SCCHH	0x0800	/* Suppress caching (high speed) */
816c8c62c5Sragge #define M_MD_SCCHL	0x0400	/* Suppress caching (low speed) */
826c8c62c5Sragge #define M_MD_SECOR	0x0200	/* Suppress error correction */
836c8c62c5Sragge #define M_MD_SEREC	0x0100	/* Suppress error recovery */
846c8c62c5Sragge #define M_MD_SSHDW	0x0080	/* Suppress shadowing */
856c8c62c5Sragge #define M_MD_WBKNV	0x0040	/* Write back (non-volatile) */
866c8c62c5Sragge #define M_MD_WBKVL	0x0020	/* Write back (volatile) */
876c8c62c5Sragge #define M_MD_WRSEQ	0x0010	/* Write shadow set one unit at a time */
886c8c62c5Sragge 
896c8c62c5Sragge /*
906c8c62c5Sragge  * tape command modifiers
916c8c62c5Sragge  */
926c8c62c5Sragge #define M_MD_IMMEDIATE	0x0040	/* Immediate completion */
936c8c62c5Sragge #define M_MD_UNLOAD	0x0010	/* Unload tape */
946c8c62c5Sragge #define M_MD_REVERSE	0x0008	/* Reverse action */
956c8c62c5Sragge #define M_MD_OBJCOUNT	0x0004	/* Object count */
966c8c62c5Sragge #define M_MD_REWIND	0x0002	/* Rewind */
976c8c62c5Sragge 
986c8c62c5Sragge /*
996c8c62c5Sragge  * AVAILABLE command modifiers
1006c8c62c5Sragge  */
1016c8c62c5Sragge #define M_AVM_ALLCD	0x0002	/* All class drivers */
1026c8c62c5Sragge #define M_AVM_SPINDOWN	0x0001	/* Spin down */
1036c8c62c5Sragge 
1046c8c62c5Sragge /*
1056c8c62c5Sragge  * FLUSH command modifiers
1066c8c62c5Sragge  */
1076c8c62c5Sragge #define M_FLM_FLUSHENU	0x0001	/* Flush entire unit */
1086c8c62c5Sragge #define M_FLM_VOLATILE	0x0002	/* Volatile only */
1096c8c62c5Sragge 
1106c8c62c5Sragge /*
1116c8c62c5Sragge  * GET UNIT STATUS command modifiers
1126c8c62c5Sragge  */
1136c8c62c5Sragge #define M_GUM_NEXTUNIT	0x0001	/* Next unit */
1146c8c62c5Sragge 
1156c8c62c5Sragge /*
1166c8c62c5Sragge  * ONLINE command modifiers
1176c8c62c5Sragge  */
1186c8c62c5Sragge #define M_OLM_RIP	0x0001	/* Allow self destruction */
1196c8c62c5Sragge #define M_OLM_IGNMF	0x0002	/* Ignore media format error */
1206c8c62c5Sragge 
1216c8c62c5Sragge /*
1226c8c62c5Sragge  * ONLINE and SET UNIT CHARACTERISTICS command modifiers
1236c8c62c5Sragge  */
1246c8c62c5Sragge #define M_OSM_ALTERHI	0x0020	/* Alter host identifier */
1256c8c62c5Sragge #define M_OSM_SHADOWSP	0x0010	/* Shadow unit specified */
1266c8c62c5Sragge #define M_OSM_CLEARWBL	0x0008	/* Clear write-back data lost */
1276c8c62c5Sragge #define M_OSM_SETWRPROT 0x0004	/* Set write protect */
1286c8c62c5Sragge 
1296c8c62c5Sragge /*
1306c8c62c5Sragge  * REPLACE command modifiers
1316c8c62c5Sragge  */
1326c8c62c5Sragge #define M_RPM_PRIMARY	0x0001	/* Primary replacement block */
1336c8c62c5Sragge 
1346c8c62c5Sragge /*
1356c8c62c5Sragge  * End message flags
1366c8c62c5Sragge  */
1376c8c62c5Sragge #define M_EF_BBLKR	0x80	/* Bad block reported */
1386c8c62c5Sragge #define M_EF_BBLKU	0x40	/* Bad block unreported */
1396c8c62c5Sragge #define M_EF_ERLOG	0x20	/* Error log generated */
1406c8c62c5Sragge #define M_EF_SEREX	0x10	/* Serious exception */
1416c8c62c5Sragge #define M_EF_EOT	0x08	/* at end-of-tape */
1426c8c62c5Sragge #define M_EF_POSLOST	0x04	/* position lost */
1436c8c62c5Sragge 
1446c8c62c5Sragge /*
1456c8c62c5Sragge  * Controller flags
1466c8c62c5Sragge  */
1476c8c62c5Sragge #define M_CF_ATTN	0x80	/* Enable attention messages */
1486c8c62c5Sragge #define M_CF_MISC	0x40	/* Enable miscellaneous error log messages */
1496c8c62c5Sragge #define M_CF_OTHER	0x20	/* Enable other host's error log messages */
1506c8c62c5Sragge #define M_CF_THIS	0x10	/* Enable this host's error log messages */
1516c8c62c5Sragge #define M_CF_MLTHS	0x04	/* Multi-host */
1526c8c62c5Sragge #define M_CF_SHADW	0x02	/* Shadowing */
1536c8c62c5Sragge #define M_CF_576	0x01	/* 576 byte sectors */
1546c8c62c5Sragge 
1556c8c62c5Sragge /*
1566c8c62c5Sragge  * Unit flags
1576c8c62c5Sragge  */
1586c8c62c5Sragge #define M_UF_REPLC	0x8000	/* Controller initiated bad block replacement */
1596c8c62c5Sragge #define M_UF_INACT	0x4000	/* Inactive shadow set unit */
1606c8c62c5Sragge #define M_UF_WRTPH	0x2000	/* Write protect (hardware) */
1616c8c62c5Sragge #define M_UF_WRTPS	0x1000	/* Write protect (software or volume) */
1626c8c62c5Sragge #define M_UF_SCCHH	0x8000	/* Suppress caching (high speed) */
1636c8c62c5Sragge #define M_UF_SCCHL	0x4000	/* Suppress caching (low speed) */
1646c8c62c5Sragge #define M_UF_RMVBL	0x0080	/* Removable media */
1656c8c62c5Sragge #define M_UF_WBKNV	0x0040	/* Write back (non-volatile) */
1666c8c62c5Sragge #define M_UF_576	0x0004	/* 576 byte sectors */
1676c8c62c5Sragge #define M_UF_CMPWR	0x0002	/* Compare writes */
1686c8c62c5Sragge #define M_UF_CMPRD	0x0001	/* Compare reads */
1696c8c62c5Sragge 
1706c8c62c5Sragge /*
1716c8c62c5Sragge  * Error Log message format codes
1726c8c62c5Sragge  */
1736c8c62c5Sragge #define M_FM_CTLRERR	0x00	/* Controller error */
1746c8c62c5Sragge #define M_FM_BUSADDR	0x01	/* Host memory access error */
1756c8c62c5Sragge #define M_FM_DISKTRN	0x02	/* Disk transfer error */
1766c8c62c5Sragge #define M_FM_SDI	0x03	/* SDI error */
1776c8c62c5Sragge #define M_FM_SMLDSK	0x04	/* Small disk error */
1786c8c62c5Sragge #define M_FM_TAPETRN	0x05	/* Tape transfer error */
1796c8c62c5Sragge #define M_FM_STIERR	0x06	/* STI communication or command failure */
1806c8c62c5Sragge #define M_FM_STIDEL	0x07	/* STI drive error log */
1816c8c62c5Sragge #define M_FM_STIFEL	0x08	/* STI formatter error log */
1826c8c62c5Sragge 
1836c8c62c5Sragge /*
1846c8c62c5Sragge  * Error Log message flags
1856c8c62c5Sragge  */
1866c8c62c5Sragge #define M_LF_SUCC	0x80	/* Operation successful */
1876c8c62c5Sragge #define M_LF_CONT	0x40	/* Operation continuing */
1886c8c62c5Sragge #define M_LF_SQNRS	0x01	/* Sequence number reset */
1896c8c62c5Sragge 
1906c8c62c5Sragge /*
1916c8c62c5Sragge  * Status codes
1926c8c62c5Sragge  */
1936c8c62c5Sragge #define M_ST_MASK	0x1f	/* Status code mask */
1946c8c62c5Sragge #define M_ST_SUCCESS	0x00	/* Success */
1956c8c62c5Sragge #define M_ST_INVALCMD	0x01	/* Invalid command */
1966c8c62c5Sragge #define M_ST_ABORTED	0x02	/* Command aborted */
1976c8c62c5Sragge #define M_ST_OFFLINE	0x03	/* Unit offline */
1986c8c62c5Sragge #define M_ST_AVAILABLE	0x04	/* Unit available */
1996c8c62c5Sragge #define M_ST_MFMTERR	0x05	/* Media format error */
2006c8c62c5Sragge #define M_ST_WRPROT	0x06	/* Write protected */
2016c8c62c5Sragge #define M_ST_COMPERR	0x07	/* Compare error */
2026c8c62c5Sragge #define M_ST_DATAERR	0x08	/* Data error */
2036c8c62c5Sragge #define M_ST_HOSTBUFERR 0x09	/* Host buffer access error */
2046c8c62c5Sragge #define M_ST_CTLRERR	0x0a	/* Controller error */
2056c8c62c5Sragge #define M_ST_DRIVEERR	0x0b	/* Drive error */
2066c8c62c5Sragge #define M_ST_FORMATTERR 0x0c	/* Formatter error */
2076c8c62c5Sragge #define M_ST_BOT	0x0d	/* Beginning-of-tape */
2086c8c62c5Sragge #define M_ST_TAPEMARK	0x0e	/* Tape mark encountered */
2096c8c62c5Sragge #define M_ST_RDTRUNC	0x10	/* Record data truncated */
2106c8c62c5Sragge #define M_ST_DIAG	0x1f	/* Message from an internal diagnostic */
2116c8c62c5Sragge 
2126c8c62c5Sragge /*
2136c8c62c5Sragge  * Subcodes of M_ST_OFFLINE
2146c8c62c5Sragge  */
2156c8c62c5Sragge #define M_OFFLINE_UNKNOWN	(0 << 5) /* unknown or on other ctlr */
2166c8c62c5Sragge #define M_OFFLINE_UNMOUNTED	(1 << 5) /* unmounted or RUN/STOP at STOP */
2176c8c62c5Sragge #define M_OFFLINE_INOPERATIVE	(2 << 5) /* inoperative? */
2186c8c62c5Sragge #define M_OFFLINE_DUPLICATE	(4 << 5) /* duplicate unit number */
2196c8c62c5Sragge #define M_OFFLINE_INDIAGNOSTIC	(8 << 5) /* disabled by FS or diagnostic */
2206c8c62c5Sragge 
2216c8c62c5Sragge /*
2226c8c62c5Sragge  * An MSCP packet begins with a header giving the length of
2236c8c62c5Sragge  * the entire packet (including the header itself)(?), two bytes
2246c8c62c5Sragge  * of device specific data, and the a whole bunch of variants
2256c8c62c5Sragge  * depending on message type.
2266c8c62c5Sragge  *
2276c8c62c5Sragge  * N.B.:  In most cases we distinguish between a `command' and
2286c8c62c5Sragge  * an `end' variant as well.  The command variant is that which
2296c8c62c5Sragge  * is given to the controller; the `end' variant is its response.
2306c8c62c5Sragge  */
2316c8c62c5Sragge 
2326c8c62c5Sragge /*
2336c8c62c5Sragge  * Generic sequential message variant (command and response).
2346c8c62c5Sragge  */
2356c8c62c5Sragge struct mscpv_seq {
2366c8c62c5Sragge 	long	seq_bytecount;		/* byte count */
2376c8c62c5Sragge #define seq_rbn		seq_bytecount	/* aka RBN (replace) */
2386c8c62c5Sragge #define seq_outref	seq_bytecount	/* aka outref (abort/get cmd status) */
2396c8c62c5Sragge 	long	seq_buffer;		/* buffer descriptor */
2406c8c62c5Sragge 	long	seq_mapbase;		/* page map (first PTE) phys address */
2416c8c62c5Sragge 	long	seq_xxx1;	/* ? */ /* unused */
2426c8c62c5Sragge 	long	seq_lbn;		/* logical block number */
2436c8c62c5Sragge 	long	seq_xxx2;	/* ? */ /* unused */
2446c8c62c5Sragge 	long	*seq_addr;		/* pointer to cmd descriptor */
2456c8c62c5Sragge 	long	seq_software[4];	/* reserved to software; unused */
2466c8c62c5Sragge };
2476c8c62c5Sragge 
2486c8c62c5Sragge /*
2496c8c62c5Sragge  * Set Controller Characteristics command variant
2506c8c62c5Sragge  */
2516c8c62c5Sragge struct mscpv_sccc {
2526c8c62c5Sragge 	u_short sccc_version;		/* MSCP version number */
2536c8c62c5Sragge 	u_short sccc_ctlrflags;		/* controller flags */
2546c8c62c5Sragge 	u_short sccc_hosttimo;		/* host timeout */
2556c8c62c5Sragge 	u_short sccc_usefrac;		/* use fraction */
2566c8c62c5Sragge 	long	sccc_time;		/* time and date */
2576c8c62c5Sragge 	long	sccc_time1;		/* it's a quad field */
2586c8c62c5Sragge 	long	sccc_errlgfl;	/* ? */
2596c8c62c5Sragge 	short	sccc_xxx2;	/* ? */
2606c8c62c5Sragge 	short	sccc_copyspd;	/* ? */
2616c8c62c5Sragge };
2626c8c62c5Sragge 
2636c8c62c5Sragge /*
2646c8c62c5Sragge  * Set Controller Characteristics end variant
2656c8c62c5Sragge  */
2666c8c62c5Sragge struct mscpv_scce {
2676c8c62c5Sragge 	u_short scce_version;		/* MSCP version number */
2686c8c62c5Sragge 	u_short scce_ctlrflags;		/* controller flags */
2696c8c62c5Sragge 	u_short scce_ctlrtimo;		/* controller timeout */
2706c8c62c5Sragge 	u_short scce_ctlrcmdl;		/* ??? */
2716c8c62c5Sragge 	quad_t	scce_ctlrid;		/* controller ID */
2726c8c62c5Sragge 	long	scce_xxx[3];	/* ? */
2736c8c62c5Sragge 	long	scce_volser;		/* volume serial number */
2746c8c62c5Sragge };
2756c8c62c5Sragge 
2766c8c62c5Sragge /*
2776c8c62c5Sragge  * On Line command variant
2786c8c62c5Sragge  */
2796c8c62c5Sragge struct mscpv_onlc {
2806c8c62c5Sragge 	long	onlc_xxx1[4];	/* ? */
2816c8c62c5Sragge 	long	onlc_errlgfl;		/* error log flag? */
2826c8c62c5Sragge 	short	onlc_xxx2;	/* ? */
2836c8c62c5Sragge 	short	onlc_copyspd;		/* copy speed? */
2846c8c62c5Sragge };
2856c8c62c5Sragge 
2866c8c62c5Sragge /*
2876c8c62c5Sragge  * On Line end variant
2886c8c62c5Sragge  */
2896c8c62c5Sragge struct mscpv_onle {
2906c8c62c5Sragge 	long	onle_xxx1[3];	/* ? */
2916c8c62c5Sragge /*???*/ short	onle_xxx2;	/* ? */
2926c8c62c5Sragge 	u_char	onle_drivetype;		/* drive type index (same in guse) */
2936c8c62c5Sragge 	char	onle_xxx3;	/* ? */
2946c8c62c5Sragge 	long	onle_mediaid;		/* media type id (same in guse) */
2956c8c62c5Sragge 	long	onle_xxx4;	/* ? */
2966c8c62c5Sragge 	long	onle_unitsize;		/* unit size in sectors */
2976c8c62c5Sragge 	long	onle_volser;		/* volume serial number */
2986c8c62c5Sragge };
2996c8c62c5Sragge 
3006c8c62c5Sragge /*
3016c8c62c5Sragge  * Get Unit Status end variant (and Avail Attn?)
3026c8c62c5Sragge  */
3036c8c62c5Sragge struct mscpv_guse {
3046c8c62c5Sragge 	u_short guse_multunit;		/* multi-unit code */
3056c8c62c5Sragge 	u_short guse_unitflags;		/* unit flags */
3066c8c62c5Sragge 	long	guse_hostid;		/* host id */
3076c8c62c5Sragge 	long	guse_unitid0;	/*???*/
3086c8c62c5Sragge 	short	guse_unitid1;	/*???*/
3096c8c62c5Sragge 	u_char	guse_drivetype;		/* drive type index */
3106c8c62c5Sragge 	u_char	guse_unitid2;	/*???*/
3116c8c62c5Sragge 	long	guse_mediaid;		/* media type id (encoded) */
3126c8c62c5Sragge 	short	guse_shadowunit;	/* shadow unit */
3136c8c62c5Sragge 	short	guse_shadowstat;	/* shadow status */
3146c8c62c5Sragge 	u_short guse_nspt;		/* sectors per track */
3156c8c62c5Sragge 	u_short guse_group;		/* track group size */
3166c8c62c5Sragge 	u_short guse_ngpc;		/* groups per cylinder */
3176c8c62c5Sragge 	u_short guse_xxx;		/* reserved */
3186c8c62c5Sragge 	u_short guse_rctsize;		/* RCT size (sectors) */
3196c8c62c5Sragge 	u_char	guse_nrpt;		/* RBNs per track */
3206c8c62c5Sragge 	u_char	guse_nrct;		/* number of RCTs */
3216c8c62c5Sragge };
3226c8c62c5Sragge 
3236c8c62c5Sragge /*
3246c8c62c5Sragge  * Macros to break up and build media IDs.  An ID encodes the port
3256c8c62c5Sragge  * type in the top 10 bits, and the drive type in the remaining 22.
3266c8c62c5Sragge  * The 10 bits, and 15 of the 22, are in groups of 5, with the value
3276c8c62c5Sragge  * 0 representing space and values 1..26 representing A..Z.  The low
3286c8c62c5Sragge  * 7 bits represent a number in 0..127.	 Hence an RA81 on a UDA50
3296c8c62c5Sragge  * is <D><U><R><A>< >81, or 0x25641051.	 This encoding scheme is known
3306c8c62c5Sragge  * in part in uda.c.
3316c8c62c5Sragge  *
3326c8c62c5Sragge  * The casts below are just to make pcc generate better code.
3336c8c62c5Sragge  */
3346c8c62c5Sragge #define MSCP_MEDIA_PORT(id)	(((long)(id) >> 22) & 0x3ff)	/* port */
3356c8c62c5Sragge #define MSCP_MEDIA_DRIVE(id)	((long)(id) & 0x003fffff)	/* drive */
3366c8c62c5Sragge #define MSCP_MID_ECH(n, id)	(((int)(id) >> ((n) * 5 + 7)) & 0x1f)
3376c8c62c5Sragge #define MSCP_MID_CHAR(n, id) \
3386c8c62c5Sragge 	(MSCP_MID_ECH(n, id) ? MSCP_MID_ECH(n, id) + '@' : ' ')
3396c8c62c5Sragge #define MSCP_MID_NUM(id)	((id) & 0x7f)
3406c8c62c5Sragge /* for, e.g., RA81 */
3416c8c62c5Sragge #define MSCP_MKDRIVE2(a, b, n) \
3426c8c62c5Sragge 	(((a) - '@') << 17 | ((b) - '@') << 12 | (n))
3436c8c62c5Sragge /* for, e.g., RRD50 */
3446c8c62c5Sragge #define MSCP_MKDRIVE3(a, b, c, n) \
3456c8c62c5Sragge 	(((a) - '@') << 17 | ((b) - '@') << 12 | ((c) - '@') << 7 | (n))
3466c8c62c5Sragge 
3476c8c62c5Sragge /*
3486c8c62c5Sragge  * Error datagram variant.
3496c8c62c5Sragge  */
3506c8c62c5Sragge struct mscpv_erd {
3516c8c62c5Sragge 	quad_t	erd_ctlrid;		/* controller ID */
3526c8c62c5Sragge 	u_char	erd_ctlrsoftware;	/* controller software version */
3536c8c62c5Sragge 	u_char	erd_ctlrhardware;	/* controller hardware version */
3546c8c62c5Sragge 	u_short erd_multiunit;		/* multi-unit code (?) */
3556c8c62c5Sragge 	union {
3566c8c62c5Sragge 		u_long	un_busaddr;	/* bus address, if mem access err */
3576c8c62c5Sragge 		quad_t	un_unitid;	/* unit id, otherwise */
3586c8c62c5Sragge 	} erd_un1;
3596c8c62c5Sragge #define erd_busaddr	erd_un1.un_busaddr
3606c8c62c5Sragge #define erd_unitid	erd_un1.un_unitid
3616c8c62c5Sragge 	u_char	erd_unitsoftware;	/* unit software version */
3626c8c62c5Sragge 	u_char	erd_unithardware;	/* unit hardware version */
3636c8c62c5Sragge 	union {
3646c8c62c5Sragge 		u_char	un_b[2];	/* level, retry (if disk xfer err) */
3656c8c62c5Sragge 		u_short un_s;		/* cylinder (if small disk error) */
3666c8c62c5Sragge 	} erd_un2;
3676c8c62c5Sragge #define erd_level	erd_un2.un_b[0]
3686c8c62c5Sragge #define erd_retry	erd_un2.un_b[1]
3696c8c62c5Sragge #define erd_sdecyl	erd_un2.un_s
3706c8c62c5Sragge 	long	erd_volser;		/* volume serial number */
3716c8c62c5Sragge 	u_long	erd_hdr;		/* `header' (block number) */
3726c8c62c5Sragge 	u_char	erd_sdistat[12];	/* SDI status information (?) */
3736c8c62c5Sragge };
3746c8c62c5Sragge 
3756c8c62c5Sragge /*
3766c8c62c5Sragge  * I am making brash assumptions about the first four bytes of all
3776c8c62c5Sragge  * MSCP packets.  These appear to be true for both UDA50s and TMSCP
3786c8c62c5Sragge  * devices (TU81, TA81, TK50).	DEC claim that these four bytes are
3796c8c62c5Sragge  * not part of MSCP itself, yet at least the length is necessary
3806c8c62c5Sragge  * for, e.g., error checking.
3816c8c62c5Sragge  */
3826c8c62c5Sragge struct mscp {
3836c8c62c5Sragge 	u_short mscp_msglen;		/* length in bytes */
3846c8c62c5Sragge 	u_char	mscp_msgtc;		/* type (high 4 bits) and credits */
3856c8c62c5Sragge 	u_char	mscp_vcid;		/* virtual circuit ID */
3866c8c62c5Sragge 	long	mscp_cmdref;		/* command reference number */
3876c8c62c5Sragge 	u_short mscp_unit;		/* unit number */
3886c8c62c5Sragge 	u_short mscp_seqnum;		/* sequence number */
3896c8c62c5Sragge 	u_char	mscp_opcode;		/* opcode */
3906c8c62c5Sragge #define mscp_format	mscp_opcode	/* aka format (datagrams) */
3916c8c62c5Sragge 	u_char	mscp_flags;		/* flags */
3926c8c62c5Sragge 	u_short mscp_modifier;		/* modifier (commands) */
3936c8c62c5Sragge #define mscp_status	mscp_modifier	/* aka status (ends) */
3946c8c62c5Sragge #define mscp_event	mscp_modifier	/* aka event (datagrams) */
3956c8c62c5Sragge 	union {
3966c8c62c5Sragge 		struct	mscpv_seq un_seq;	/* generic sequential msg */
3976c8c62c5Sragge 		struct	mscpv_sccc un_sccc;	/* SCC command */
3986c8c62c5Sragge 		struct	mscpv_scce un_scce;	/* SCC end */
3996c8c62c5Sragge 		struct	mscpv_onlc un_onlc;	/* on line command */
4006c8c62c5Sragge 		struct	mscpv_onle un_onle;	/* on line end */
4016c8c62c5Sragge 		struct	mscpv_guse un_guse;	/* get unit status */
4026c8c62c5Sragge 		struct	mscpv_erd un_erd;	/* error datagram */
4036c8c62c5Sragge 	} mscp_un;
4046c8c62c5Sragge /*???*/ long	mscp_xxx;		/* pad to 64 bytes */
4056c8c62c5Sragge };
4066c8c62c5Sragge 
4076c8c62c5Sragge /*
4086c8c62c5Sragge  * Define message length according to the DEC specifications by dropping
4096c8c62c5Sragge  * the four byte header.
4106c8c62c5Sragge  */
4116c8c62c5Sragge #define MSCP_MSGLEN	(sizeof (struct mscp) - 4)
4126c8c62c5Sragge 
4136c8c62c5Sragge /*
4146c8c62c5Sragge  * Shorthand
4156c8c62c5Sragge  */
4166c8c62c5Sragge 
4176c8c62c5Sragge /*
4186c8c62c5Sragge  * Generic packet
4196c8c62c5Sragge  */
4206c8c62c5Sragge #define mscp_seq	mscp_un.un_seq
4216c8c62c5Sragge 
4226c8c62c5Sragge /*
4236c8c62c5Sragge  * Set Controller Characteristics packet
4246c8c62c5Sragge  */
4256c8c62c5Sragge #define mscp_sccc	mscp_un.un_sccc
4266c8c62c5Sragge 
4276c8c62c5Sragge /*
4286c8c62c5Sragge  * Set Controller Characteristics end packet
4296c8c62c5Sragge  */
4306c8c62c5Sragge #define mscp_scce	mscp_un.un_scce
4316c8c62c5Sragge 
4326c8c62c5Sragge /*
4336c8c62c5Sragge  * Online / Set Unit Characteristics command packet
4346c8c62c5Sragge  */
4356c8c62c5Sragge #define mscp_onlc	mscp_un.un_onlc
4366c8c62c5Sragge 
4376c8c62c5Sragge /*
4386c8c62c5Sragge  * Online end packet
4396c8c62c5Sragge  */
4406c8c62c5Sragge #define mscp_onle	mscp_un.un_onle
4416c8c62c5Sragge 
4426c8c62c5Sragge /*
4436c8c62c5Sragge  * Get Unit Status end packet
4446c8c62c5Sragge  */
4456c8c62c5Sragge #define mscp_guse	mscp_un.un_guse
4466c8c62c5Sragge 
4476c8c62c5Sragge /*
4486c8c62c5Sragge  * MSCP Error Log packet
4496c8c62c5Sragge  */
4506c8c62c5Sragge #define mscp_erd	mscp_un.un_erd
4516c8c62c5Sragge 
4526c8c62c5Sragge /*
4536c8c62c5Sragge  * MSCP seq_addr field actually belongs to overall packet.
4546c8c62c5Sragge  */
4556c8c62c5Sragge #define mscp_addr	mscp_seq.seq_addr
4566c8c62c5Sragge 
4576c8c62c5Sragge /*
4586c8c62c5Sragge  * Macros to break up mscp_msgtc, and types.
4596c8c62c5Sragge  */
4606c8c62c5Sragge #define MSCP_MSGTYPE(m) ((m) & 0xf0)
4616c8c62c5Sragge #define MSCP_CREDITS(m) ((m) & 0x0f)
4626c8c62c5Sragge 
4636c8c62c5Sragge #define MSCPT_SEQ		0x00	/* sequential message */
4646c8c62c5Sragge #define MSCPT_DATAGRAM		0x10	/* error datagram */
4656c8c62c5Sragge #define MSCPT_CREDITS		0x20	/* credit notification */
4666c8c62c5Sragge #define MSCPT_MAINTENANCE	0xf0	/* who knows */
4676c8c62c5Sragge 
4686c8c62c5Sragge 
4696c8c62c5Sragge /*
4706c8c62c5Sragge  * Here begin more perhaps brash assumptions about MSCP devices...
4716c8c62c5Sragge  */
4726c8c62c5Sragge 
4736c8c62c5Sragge /*
4746c8c62c5Sragge  * MSCP controllers have `command rings' and `response rings'.	A
4756c8c62c5Sragge  * command ring is a pool of MSCP packets that the host uses to give
4766c8c62c5Sragge  * commands to the controller; a response ring is a pool of MSCP
4776c8c62c5Sragge  * packets that the controller uses to give back responses.  Entries
4786c8c62c5Sragge  * in the command and response rings are `owned' by either the host
4796c8c62c5Sragge  * or the controller; only the owner is allowed to alter any of the
4806c8c62c5Sragge  * fields in the MSCP packet.  Thus, free command packets are owned
4816c8c62c5Sragge  * by the host, and free response packets by the controller.  When
4826c8c62c5Sragge  * the host gives a packet to the controller, it tells the controller
4836c8c62c5Sragge  * by touching a device register; when the controller gives a response
4846c8c62c5Sragge  * to the host, it generates an interrupt if enabled, and sets
4856c8c62c5Sragge  * a device register as well.
4866c8c62c5Sragge  *
4876c8c62c5Sragge  * The pool is `described' by a set of pointers to the packets, along
4886c8c62c5Sragge  * with the two flags below.
4896c8c62c5Sragge  */
4906c8c62c5Sragge #define MSCP_OWN	0x80000000	/* controller owns this packet */
4916c8c62c5Sragge #define MSCP_INT	0x40000000	/* controller should interrupt */
492