xref: /original-bsd/sys/vax/vax/mscp.h (revision 05bc5180)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Chris Torek.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)mscp.h	7.5 (Berkeley) 06/28/90
11  */
12 
13 /*
14  * Definitions for the Mass Storage Control Protocol
15  * I WISH I KNEW WHAT MORE OF THESE WERE.  IT SURE WOULD BE NICE
16  * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
17  */
18 
19 /*
20  * Control message opcodes
21  */
22 #define	M_OP_ABORT	0x01	/* Abort command */
23 #define	M_OP_GETCMDST	0x02	/* Get command status command */
24 #define	M_OP_GETUNITST	0x03	/* Get unit status command */
25 #define	M_OP_SETCTLRC	0x04	/* Set controller characteristics command */
26 #define	M_OP_SEREX	0x07	/* Serious exception end message */
27 #define	M_OP_AVAILABLE	0x08	/* Available command */
28 #define	M_OP_ONLINE	0x09	/* Online command */
29 #define	M_OP_SETUNITC	0x0a	/* Set unit characteristics command */
30 #define	M_OP_DTACCPATH	0x0b	/* Determine access paths command */
31 #define	M_OP_ACCESS	0x10	/* Access command */
32 #define	M_OP_COMPCD	0x11	/* Compare controller data command */
33 #define	M_OP_ERASE	0x12	/* Erase command */
34 #define	M_OP_FLUSH	0x13	/* Flush command */
35 #define	M_OP_REPLACE	0x14	/* Replace command */
36 #define	M_OP_COMPHD	0x20	/* Compare host data command */
37 #define	M_OP_READ	0x21	/* Read command */
38 #define	M_OP_WRITE	0x22	/* Write command */
39 #define	M_OP_AVAILATTN	0x40	/* Available attention message */
40 #define	M_OP_DUPUNIT	0x41	/* Duplicate unit number attention message */
41 #define	M_OP_ACCPATH	0x42	/* Access path attention message */
42 #define	M_OP_END	0x80	/* End message flag */
43 
44 
45 /*
46  * Generic command modifiers
47  */
48 #define	M_MD_EXPRS	0x8000	/* Express request */
49 #define	M_MD_COMP	0x4000	/* Compare */
50 #define	M_MD_CLSEX	0x2000	/* Clear serious exception */
51 #define	M_MD_ERROR	0x1000	/* Force error */
52 #define	M_MD_SCCHH	0x0800	/* Suppress caching (high speed) */
53 #define	M_MD_SCCHL	0x0400	/* Suppress caching (low speed) */
54 #define	M_MD_SECOR	0x0200	/* Suppress error correction */
55 #define	M_MD_SEREC	0x0100	/* Suppress error recovery */
56 #define	M_MD_SSHDW	0x0080	/* Suppress shadowing */
57 #define	M_MD_WBKNV	0x0040	/* Write back (non-volatile) */
58 #define	M_MD_WBKVL	0x0020	/* Write back (volatile) */
59 #define	M_MD_WRSEQ	0x0010	/* Write shadow set one unit at a time */
60 
61 /*
62  * AVAILABLE command modifiers
63  */
64 #define	M_AVM_ALLCD	0x0002	/* All class drivers */
65 #define	M_AVM_SPINDOWN	0x0001	/* Spin down */
66 
67 /*
68  * FLUSH command modifiers
69  */
70 #define	M_FLM_FLUSHENU	0x0001	/* Flush entire unit */
71 #define	M_FLM_VOLATILE	0x0002	/* Volatile only */
72 
73 /*
74  * GET UNIT STATUS command modifiers
75  */
76 #define	M_GUM_NEXTUNIT	0x0001	/* Next unit */
77 
78 /*
79  * ONLINE command modifiers
80  */
81 #define	M_OLM_RIP	0x0001	/* Allow self destruction */
82 #define	M_OLM_IGNMF	0x0002	/* Ignore media format error */
83 
84 /*
85  * ONLINE and SET UNIT CHARACTERISTICS command modifiers
86  */
87 #define	M_OSM_ALTERHI	0x0020	/* Alter host identifier */
88 #define	M_OSM_SHADOWSP	0x0010	/* Shadow unit specified */
89 #define	M_OSM_CLEARWBL	0x0008	/* Clear write-back data lost */
90 #define	M_OSM_SETWRPROT	0x0004	/* Set write protect */
91 
92 /*
93  * REPLACE command modifiers
94  */
95 #define	M_RPM_PRIMARY	0x0001	/* Primary replacement block */
96 
97 /*
98  * End message flags
99  */
100 #define	M_EF_BBLKR	0x80	/* Bad block reported */
101 #define	M_EF_BBLKU	0x40	/* Bad block unreported */
102 #define	M_EF_ERLOG	0x20	/* Error log generated */
103 #define	M_EF_SEREX	0x10	/* Serious exception */
104 
105 /*
106  * Controller flags
107  */
108 #define	M_CF_ATTN	0x80	/* Enable attention messages */
109 #define	M_CF_MISC	0x40	/* Enable miscellaneous error log messages */
110 #define	M_CF_OTHER	0x20	/* Enable other host's error log messages */
111 #define	M_CF_THIS	0x10	/* Enable this host's error log messages */
112 #define	M_CF_MLTHS	0x04	/* Multi-host */
113 #define	M_CF_SHADW	0x02	/* Shadowing */
114 #define	M_CF_576	0x01	/* 576 byte sectors */
115 
116 /*
117  * Unit flags
118  */
119 #define	M_UF_REPLC	0x8000	/* Controller initiated bad block replacement */
120 #define	M_UF_INACT	0x4000	/* Inactive shadow set unit */
121 #define	M_UF_WRTPH	0x2000	/* Write protect (hardware) */
122 #define	M_UF_WRTPS	0x1000	/* Write protect (software or volume) */
123 #define	M_UF_SCCHH	0x8000	/* Suppress caching (high speed) */
124 #define	M_UF_SCCHL	0x4000	/* Suppress caching (low speed) */
125 #define	M_UF_RMVBL	0x0080	/* Removable media */
126 #define	M_UF_WBKNV	0x0040	/* Write back (non-volatile) */
127 #define	M_UF_576	0x0004	/* 576 byte sectors */
128 #define	M_UF_CMPWR	0x0002	/* Compare writes */
129 #define	M_UF_CMPRD	0x0001	/* Compare reads */
130 
131 /*
132  * Error Log message format codes
133  */
134 #define	M_FM_CTLRERR	0x00	/* Controller error */
135 #define	M_FM_BUSADDR	0x01	/* Host memory access error */
136 #define	M_FM_DISKTRN	0x02	/* Disk transfer error */
137 #define	M_FM_SDI	0x03	/* SDI error */
138 #define	M_FM_SMLDSK	0x04	/* Small disk error */
139 
140 /*
141  * Error Log message flags
142  */
143 #define	M_LF_SUCC	0x80	/* Operation successful */
144 #define	M_LF_CONT	0x40	/* Operation continuing */
145 #define	M_LF_SQNRS	0x01	/* Sequence number reset */
146 
147 /*
148  * Status codes
149  */
150 #define	M_ST_MASK	0x1f	/* Status code mask */
151 #define	M_ST_SUCCESS	0x00	/* Success */
152 #define	M_ST_INVALCMD	0x01	/* Invalid command */
153 #define	M_ST_ABORTED	0x02	/* Command aborted */
154 #define	M_ST_OFFLINE	0x03	/* Unit offline */
155 #define	M_ST_AVAILABLE	0x04	/* Unit available */
156 #define	M_ST_MFMTERR	0x05	/* Media format error */
157 #define	M_ST_WRPROT	0x06	/* Write protected */
158 #define	M_ST_COMPERR	0x07	/* Compare error */
159 #define	M_ST_DATAERR	0x08	/* Data error */
160 #define	M_ST_HOSTBUFERR	0x09	/* Host buffer access error */
161 #define	M_ST_CTLRERR	0x0a	/* Controller error */
162 #define	M_ST_DRIVEERR	0x0b	/* Drive error */
163 #define	M_ST_DIAG	0x1f	/* Message from an internal diagnostic */
164 
165 /*
166  * Subcodes of M_ST_OFFLINE
167  */
168 #define	M_OFFLINE_UNKNOWN	(0 << 5) /* unknown or on other ctlr */
169 #define	M_OFFLINE_UNMOUNTED	(1 << 5) /* unmounted or RUN/STOP at STOP */
170 #define	M_OFFLINE_INOPERATIVE	(2 << 5) /* inoperative? */
171 #define	M_OFFLINE_DUPLICATE	(4 << 5) /* duplicate unit number */
172 #define	M_OFFLINE_INDIAGNOSTIC	(8 << 5) /* disabled by FS or diagnostic */
173 
174 /*
175  * An MSCP packet begins with a header giving the length of
176  * the entire packet (including the header itself)(?), two bytes
177  * of device specific data, and the a whole bunch of variants
178  * depending on message type.
179  *
180  * N.B.:  In most cases we distinguish between a `command' and
181  * an `end' variant as well.  The command variant is that which
182  * is given to the controller; the `end' variant is its response.
183  */
184 
185 /*
186  * Generic sequential message variant (command and response).
187  */
188 struct mscpv_seq {
189 	long	seq_bytecount;		/* byte count */
190 #define	seq_rbn		seq_bytecount	/* aka RBN (replace) */
191 #define	seq_outref	seq_bytecount	/* aka outref (abort/get cmd status) */
192 	long	seq_buffer;		/* buffer descriptor */
193 	long	seq_mapbase;		/* page map (first PTE) phys address */
194 	long	seq_xxx1;	/* ? */	/* unused */
195 	long	seq_lbn;		/* logical block number */
196 	long	seq_xxx2;	/* ? */	/* unused */
197 	long	*seq_addr;		/* pointer to cmd descriptor */
198 	long	seq_software[4];	/* reserved to software; unused */
199 };
200 
201 /*
202  * Set Controller Characteristics command variant
203  */
204 struct mscpv_sccc {
205 	u_short	sccc_version;		/* MSCP version number */
206 	u_short	sccc_ctlrflags;		/* controller flags */
207 	u_short	sccc_hosttimo;		/* host timeout */
208 	u_short	sccc_usefrac;		/* use fraction */
209 	long	sccc_time;		/* time and date */
210 	long	sccc_xxx1;	/* ? */
211 	long	sccc_errlgfl;	/* ? */
212 	short	sccc_xxx2;	/* ? */
213 	short	sccc_copyspd;	/* ? */
214 };
215 
216 /*
217  * Set Controller Characteristics end variant
218  */
219 struct mscpv_scce {
220 	u_short	scce_version;		/* MSCP version number */
221 	u_short	scce_ctlrflags;		/* controller flags */
222 	u_short	scce_ctlrtimo;		/* controller timeout */
223 	u_short	scce_ctlrcmdl;		/* ??? */
224 	quad	scce_ctlrid;		/* controller ID */
225 	long	scce_xxx[3];	/* ? */
226 	long	scce_volser;		/* volume serial number */
227 };
228 
229 /*
230  * On Line command variant
231  */
232 struct mscpv_onlc {
233 	long	onlc_xxx1[4];	/* ? */
234 	long	onlc_errlgfl;		/* error log flag? */
235 	short	onlc_xxx2;	/* ? */
236 	short	onlc_copyspd;		/* copy speed? */
237 };
238 
239 /*
240  * On Line end variant
241  */
242 struct mscpv_onle {
243 	long	onle_xxx1[3];	/* ? */
244 /*???*/	short	onle_xxx2;	/* ? */
245 	u_char	onle_drivetype;		/* drive type index (same in guse) */
246 	char	onle_xxx3;	/* ? */
247 	long	onle_mediaid;		/* media type id (same in guse) */
248 	long	onle_xxx4;	/* ? */
249 	long	onle_unitsize;		/* unit size in sectors */
250 	long	onle_volser;		/* volume serial number */
251 };
252 
253 /*
254  * Get Unit Status end variant (and Avail Attn?)
255  */
256 struct mscpv_guse {
257 	u_short	guse_multunit;		/* multi-unit code */
258 	u_short	guse_unitflags;		/* unit flags */
259 	long	guse_hostid;		/* host id */
260 	long	guse_unitid0;	/*???*/
261 	short	guse_unitid1;	/*???*/
262 	u_char	guse_drivetype;		/* drive type index */
263 	u_char	guse_unitid2;	/*???*/
264 	long	guse_mediaid;		/* media type id (encoded) */
265 	short	guse_shadowunit;	/* shadow unit */
266 	short	guse_shadowstat;	/* shadow status */
267 	u_short	guse_nspt;		/* sectors per track */
268 	u_short	guse_group;		/* track group size */
269 	u_short	guse_ngpc;		/* groups per cylinder */
270 	u_short	guse_xxx;		/* reserved */
271 	u_short	guse_rctsize;		/* RCT size (sectors) */
272 	u_char	guse_nrpt;		/* RBNs per track */
273 	u_char	guse_nrct;		/* number of RCTs */
274 };
275 
276 /*
277  * Macros to break up and build media IDs.  An ID encodes the port
278  * type in the top 10 bits, and the drive type in the remaining 22.
279  * The 10 bits, and 15 of the 22, are in groups of 5, with the value
280  * 0 representing space and values 1..26 representing A..Z.  The low
281  * 7 bits represent a number in 0..127.  Hence an RA81 on a UDA50
282  * is <D><U><R><A>< >81, or 0x25641051.  This encoding scheme is known
283  * in part in uda.c.
284  *
285  * The casts below are just to make pcc generate better code.
286  */
287 #define	MSCP_MEDIA_PORT(id)	(((long)(id) >> 22) & 0x3ff)	/* port */
288 #define	MSCP_MEDIA_DRIVE(id)	((long)(id) & 0x003fffff)	/* drive */
289 #define	MSCP_MID_ECH(n, id)	(((long)(id) >> ((n) * 5 + 7)) & 0x1f)
290 #define	MSCP_MID_CHAR(n, id) \
291 	(MSCP_MID_ECH(n, id) ? MSCP_MID_ECH(n, id) + '@' : ' ')
292 #define	MSCP_MID_NUM(id)	((id) & 0x7f)
293 /* for, e.g., RA81 */
294 #define	MSCP_MKDRIVE2(a, b, n) \
295 	(((a) - '@') << 17 | ((b) - '@') << 12 | (n))
296 /* for, e.g., RRD50 */
297 #define	MSCP_MKDRIVE3(a, b, c, n) \
298 	(((a) - '@') << 17 | ((b) - '@') << 12 | ((c) - '@') << 7 | (n))
299 
300 /*
301  * Error datagram variant.
302  */
303 struct mscpv_erd {
304 	quad	erd_ctlrid;		/* controller ID */
305 	u_char	erd_ctlrsoftware;	/* controller software version */
306 	u_char	erd_ctlrhardware;	/* controller hardware version */
307 	u_short	erd_multiunit;		/* multi-unit code (?) */
308 	union {
309 		u_long	un_busaddr;	/* bus address, if mem access err */
310 		quad	un_unitid;	/* unit id, otherwise */
311 	} erd_un1;
312 #define	erd_busaddr	erd_un1.un_busaddr
313 #define	erd_unitid	erd_un1.un_unitid
314 	u_char	erd_unitsoftware;	/* unit software version */
315 	u_char	erd_unithardware;	/* unit hardware version */
316 	union {
317 		u_char	un_b[2];	/* level, retry (if disk xfer err) */
318 		u_short	un_s;		/* cylinder (if small disk error) */
319 	} erd_un2;
320 #define	erd_level	erd_un2.un_b[0]
321 #define	erd_retry	erd_un2.un_b[1]
322 #define	erd_sdecyl	erd_un2.un_s
323 	long	erd_volser;		/* volume serial number */
324 	u_long	erd_hdr;		/* `header' (block number) */
325 	u_char	erd_sdistat[12];	/* SDI status information (?) */
326 };
327 
328 /*
329  * I am making brash assumptions about the first four bytes of all
330  * MSCP packets.  These appear to be true for both UDA50s and TMSCP
331  * devices (TU81, TA81, TK50).  DEC claim that these four bytes are
332  * not part of MSCP itself, yet at least the length is necessary
333  * for, e.g., error checking.
334  */
335 struct mscp {
336 	u_short	mscp_msglen;		/* length in bytes */
337 	u_char	mscp_msgtc;		/* type (high 4 bits) and credits */
338 	u_char	mscp_vcid;		/* virtual circuit ID */
339 	long	mscp_cmdref;		/* command reference number */
340 	u_short	mscp_unit;		/* unit number */
341 	u_short	mscp_seqnum;		/* sequence number */
342 	u_char	mscp_opcode;		/* opcode */
343 #define	mscp_format	mscp_opcode	/* aka format (datagrams) */
344 	u_char	mscp_flags;		/* flags */
345 	u_short	mscp_modifier;		/* modifier (commands) */
346 #define	mscp_status	mscp_modifier	/* aka status (ends) */
347 #define	mscp_event	mscp_modifier	/* aka event (datagrams) */
348 	union {
349 		struct	mscpv_seq un_seq;	/* generic sequential msg */
350 		struct	mscpv_sccc un_sccc;	/* SCC command */
351 		struct	mscpv_scce un_scce;	/* SCC end */
352 		struct	mscpv_onlc un_onlc;	/* on line command */
353 		struct	mscpv_onle un_onle;	/* on line end */
354 		struct	mscpv_guse un_guse;	/* get unit status */
355 		struct	mscpv_erd un_erd;	/* error datagram */
356 	} mscp_un;
357 /*???*/	long	mscp_xxx;		/* pad to 64 bytes */
358 };
359 
360 /*
361  * Define message length according to the DEC specifications by dropping
362  * the four byte header.
363  */
364 #define	MSCP_MSGLEN	(sizeof (struct mscp) - 4)
365 
366 /*
367  * Shorthand
368  */
369 
370 /*
371  * Generic packet
372  */
373 #define	mscp_seq	mscp_un.un_seq
374 
375 /*
376  * Set Controller Characteristics packet
377  */
378 #define	mscp_sccc	mscp_un.un_sccc
379 
380 /*
381  * Set Controller Characteristics end packet
382  */
383 #define	mscp_scce	mscp_un.un_scce
384 
385 /*
386  * Online / Set Unit Characteristics command packet
387  */
388 #define	mscp_onlc	mscp_un.un_onlc
389 
390 /*
391  * Online end packet
392  */
393 #define	mscp_onle	mscp_un.un_onle
394 
395 /*
396  * Get Unit Status end packet
397  */
398 #define	mscp_guse	mscp_un.un_guse
399 
400 /*
401  * MSCP Error Log packet
402  */
403 #define	mscp_erd	mscp_un.un_erd
404 
405 /*
406  * MSCP seq_addr field actually belongs to overall packet.
407  */
408 #define	mscp_addr	mscp_seq.seq_addr
409 
410 /*
411  * Macros to break up mscp_msgtc, and types.
412  */
413 #define	MSCP_MSGTYPE(m)	((m) & 0xf0)
414 #define	MSCP_CREDITS(m)	((m) & 0x0f)
415 
416 #define	MSCPT_SEQ		0x00	/* sequential message */
417 #define	MSCPT_DATAGRAM		0x10	/* error datagram */
418 #define	MSCPT_CREDITS		0x20	/* credit notification */
419 #define	MSCPT_MAINTENANCE	0xf0	/* who knows */
420 
421 
422 /*
423  * Here begin more perhaps brash assumptions about MSCP devices...
424  */
425 
426 /*
427  * MSCP controllers have `command rings' and `response rings'.  A
428  * command ring is a pool of MSCP packets that the host uses to give
429  * commands to the controller; a response ring is a pool of MSCP
430  * packets that the controller uses to give back responses.  Entries
431  * in the command and response rings are `owned' by either the host
432  * or the controller; only the owner is allowed to alter any of the
433  * fields in the MSCP packet.  Thus, free command packets are owned
434  * by the host, and free response packets by the controller.  When
435  * the host gives a packet to the controller, it tells the controller
436  * by touching a device register; when the controller gives a response
437  * to the host, it generates an interrupt if enabled, and sets
438  * a device register as well.
439  *
440  * The pool is `described' by a set of pointers to the packets, along
441  * with the two flags below.
442  */
443 #define	MSCP_OWN	0x80000000	/* controller owns this packet */
444 #define	MSCP_INT	0x40000000	/* controller should interrupt */
445