summaryrefslogtreecommitdiff
path: root/sys/arch/vax/mscp/mscp.h
blob: c94f45d9b3551e40473af0f2aee8ba4245515eb0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
/*	$OpenBSD: mscp.h,v 1.5 2003/06/02 23:27:57 millert Exp $	*/
/*	$NetBSD: mscp.h,v 1.6 1999/05/29 19:11:16 ragge Exp $	*/

/*
 * Copyright (c) 1988 Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Chris Torek.
 *
 * 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. Neither the name of the University 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 REGENTS 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 REGENTS 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.
 *
 *	@(#)mscp.h	7.5 (Berkeley) 6/28/90
 */

/*
 * Definitions for the Mass Storage Control Protocol
 * I WISH I KNEW WHAT MORE OF THESE WERE.  IT SURE WOULD BE NICE
 * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
 */

/*
 * Control message opcodes
 */
#define M_OP_ABORT	0x01	/* Abort command */
#define M_OP_GETCMDST	0x02	/* Get command status command */
#define M_OP_GETUNITST	0x03	/* Get unit status command */
#define M_OP_SETCTLRC	0x04	/* Set controller characteristics command */
#define M_OP_SEREX	0x07	/* Serious exception end message */
#define M_OP_AVAILABLE	0x08	/* Available command */
#define M_OP_ONLINE	0x09	/* Online command */
#define M_OP_SETUNITC	0x0a	/* Set unit characteristics command */
#define M_OP_DTACCPATH	0x0b	/* Determine access paths command */
#define M_OP_ACCESS	0x10	/* Access command */
#define M_OP_COMPCD	0x11	/* Compare controller data command */
#define M_OP_ERASE	0x12	/* Erase command */
#define M_OP_FLUSH	0x13	/* Flush command */
#define M_OP_REPLACE	0x14	/* Replace command */
#define M_OP_COMPHD	0x20	/* Compare host data command */
#define M_OP_READ	0x21	/* Read command */
#define M_OP_WRITE	0x22	/* Write command */
#define M_OP_WRITM	0x24	/* Write mark command */
#define M_OP_POS	0x25	/* Positioning command */
#define M_OP_AVAILATTN	0x40	/* Available attention message */
#define M_OP_DUPUNIT	0x41	/* Duplicate unit number attention message */
#define M_OP_ACCPATH	0x42	/* Access path attention message */
#define M_OP_END	0x80	/* End message flag */


/*
 * Generic command modifiers
 */
#define M_MD_EXPRS	0x8000	/* Express request */
#define M_MD_COMP	0x4000	/* Compare */
#define M_MD_CLSEX	0x2000	/* Clear serious exception */
#define M_MD_ERROR	0x1000	/* Force error */
#define M_MD_SCCHH	0x0800	/* Suppress caching (high speed) */
#define M_MD_SCCHL	0x0400	/* Suppress caching (low speed) */
#define M_MD_SECOR	0x0200	/* Suppress error correction */
#define M_MD_SEREC	0x0100	/* Suppress error recovery */
#define M_MD_SSHDW	0x0080	/* Suppress shadowing */
#define M_MD_WBKNV	0x0040	/* Write back (non-volatile) */
#define M_MD_WBKVL	0x0020	/* Write back (volatile) */
#define M_MD_WRSEQ	0x0010	/* Write shadow set one unit at a time */

/*
 * tape command modifiers
 */
#define M_MD_IMMEDIATE	0x0040	/* Immediate completion */
#define M_MD_UNLOAD	0x0010	/* Unload tape */
#define M_MD_REVERSE	0x0008	/* Reverse action */
#define M_MD_OBJCOUNT	0x0004	/* Object count */
#define M_MD_REWIND	0x0002	/* Rewind */

/*
 * AVAILABLE command modifiers
 */
#define M_AVM_ALLCD	0x0002	/* All class drivers */
#define M_AVM_SPINDOWN	0x0001	/* Spin down */

/*
 * FLUSH command modifiers
 */
#define M_FLM_FLUSHENU	0x0001	/* Flush entire unit */
#define M_FLM_VOLATILE	0x0002	/* Volatile only */

/*
 * GET UNIT STATUS command modifiers
 */
#define M_GUM_NEXTUNIT	0x0001	/* Next unit */

/*
 * ONLINE command modifiers
 */
#define M_OLM_RIP	0x0001	/* Allow self destruction */
#define M_OLM_IGNMF	0x0002	/* Ignore media format error */

/*
 * ONLINE and SET UNIT CHARACTERISTICS command modifiers
 */
#define M_OSM_ALTERHI	0x0020	/* Alter host identifier */
#define M_OSM_SHADOWSP	0x0010	/* Shadow unit specified */
#define M_OSM_CLEARWBL	0x0008	/* Clear write-back data lost */
#define M_OSM_SETWRPROT 0x0004	/* Set write protect */

/*
 * REPLACE command modifiers
 */
#define M_RPM_PRIMARY	0x0001	/* Primary replacement block */

/*
 * End message flags
 */
#define M_EF_BBLKR	0x80	/* Bad block reported */
#define M_EF_BBLKU	0x40	/* Bad block unreported */
#define M_EF_ERLOG	0x20	/* Error log generated */
#define M_EF_SEREX	0x10	/* Serious exception */
#define M_EF_EOT	0x08	/* at end-of-tape */
#define M_EF_POSLOST	0x04	/* position lost */

/*
 * Controller flags
 */
#define M_CF_ATTN	0x80	/* Enable attention messages */
#define M_CF_MISC	0x40	/* Enable miscellaneous error log messages */
#define M_CF_OTHER	0x20	/* Enable other host's error log messages */
#define M_CF_THIS	0x10	/* Enable this host's error log messages */
#define M_CF_MLTHS	0x04	/* Multi-host */
#define M_CF_SHADW	0x02	/* Shadowing */
#define M_CF_576	0x01	/* 576 byte sectors */

/*
 * Unit flags
 */
#define M_UF_REPLC	0x8000	/* Controller initiated bad block replacement */
#define M_UF_INACT	0x4000	/* Inactive shadow set unit */
#define M_UF_WRTPH	0x2000	/* Write protect (hardware) */
#define M_UF_WRTPS	0x1000	/* Write protect (software or volume) */
#define M_UF_SCCHH	0x8000	/* Suppress caching (high speed) */
#define M_UF_SCCHL	0x4000	/* Suppress caching (low speed) */
#define M_UF_RMVBL	0x0080	/* Removable media */
#define M_UF_WBKNV	0x0040	/* Write back (non-volatile) */
#define M_UF_576	0x0004	/* 576 byte sectors */
#define M_UF_CMPWR	0x0002	/* Compare writes */
#define M_UF_CMPRD	0x0001	/* Compare reads */

/*
 * Error Log message format codes
 */
#define M_FM_CTLRERR	0x00	/* Controller error */
#define M_FM_BUSADDR	0x01	/* Host memory access error */
#define M_FM_DISKTRN	0x02	/* Disk transfer error */
#define M_FM_SDI	0x03	/* SDI error */
#define M_FM_SMLDSK	0x04	/* Small disk error */
#define M_FM_TAPETRN	0x05	/* Tape transfer error */
#define M_FM_STIERR	0x06	/* STI communication or command failure */
#define M_FM_STIDEL	0x07	/* STI drive error log */
#define M_FM_STIFEL	0x08	/* STI formatter error log */

/*
 * Error Log message flags
 */
#define M_LF_SUCC	0x80	/* Operation successful */
#define M_LF_CONT	0x40	/* Operation continuing */
#define M_LF_SQNRS	0x01	/* Sequence number reset */

/*
 * Status codes
 */
#define M_ST_MASK	0x1f	/* Status code mask */
#define M_ST_SUCCESS	0x00	/* Success */
#define M_ST_INVALCMD	0x01	/* Invalid command */
#define M_ST_ABORTED	0x02	/* Command aborted */
#define M_ST_OFFLINE	0x03	/* Unit offline */
#define M_ST_AVAILABLE	0x04	/* Unit available */
#define M_ST_MFMTERR	0x05	/* Media format error */
#define M_ST_WRPROT	0x06	/* Write protected */
#define M_ST_COMPERR	0x07	/* Compare error */
#define M_ST_DATAERR	0x08	/* Data error */
#define M_ST_HOSTBUFERR 0x09	/* Host buffer access error */
#define M_ST_CTLRERR	0x0a	/* Controller error */
#define M_ST_DRIVEERR	0x0b	/* Drive error */
#define M_ST_FORMATTERR 0x0c	/* Formatter error */
#define M_ST_BOT	0x0d	/* Beginning-of-tape */
#define M_ST_TAPEMARK	0x0e	/* Tape mark encountered */
#define M_ST_RDTRUNC	0x10	/* Record data truncated */
#define M_ST_DIAG	0x1f	/* Message from an internal diagnostic */

/*
 * Subcodes of M_ST_OFFLINE
 */
#define M_OFFLINE_UNKNOWN	(0 << 5) /* unknown or on other ctlr */
#define M_OFFLINE_UNMOUNTED	(1 << 5) /* unmounted or RUN/STOP at STOP */
#define M_OFFLINE_INOPERATIVE	(2 << 5) /* inoperative? */
#define M_OFFLINE_DUPLICATE	(4 << 5) /* duplicate unit number */
#define M_OFFLINE_INDIAGNOSTIC	(8 << 5) /* disabled by FS or diagnostic */

/*
 * An MSCP packet begins with a header giving the length of
 * the entire packet (including the header itself)(?), two bytes
 * of device specific data, and the a whole bunch of variants
 * depending on message type.
 *
 * N.B.:  In most cases we distinguish between a `command' and
 * an `end' variant as well.  The command variant is that which
 * is given to the controller; the `end' variant is its response.
 */

/*
 * Generic sequential message variant (command and response).
 */
struct mscpv_seq {
	long	seq_bytecount;		/* byte count */
#define seq_rbn		seq_bytecount	/* aka RBN (replace) */
#define seq_outref	seq_bytecount	/* aka outref (abort/get cmd status) */
	long	seq_buffer;		/* buffer descriptor */
	long	seq_mapbase;		/* page map (first PTE) phys address */
	long	seq_xxx1;	/* ? */ /* unused */
	long	seq_lbn;		/* logical block number */
	long	seq_xxx2;	/* ? */ /* unused */
	long	*seq_addr;		/* pointer to cmd descriptor */
	long	seq_software[4];	/* reserved to software; unused */
};

/*
 * Set Controller Characteristics command variant
 */
struct mscpv_sccc {
	u_short sccc_version;		/* MSCP version number */
	u_short sccc_ctlrflags;		/* controller flags */
	u_short sccc_hosttimo;		/* host timeout */
	u_short sccc_usefrac;		/* use fraction */
	long	sccc_time;		/* time and date */
	long	sccc_time1;		/* it's a quad field */
	long	sccc_errlgfl;	/* ? */
	short	sccc_xxx2;	/* ? */
	short	sccc_copyspd;	/* ? */
};

/*
 * Set Controller Characteristics end variant
 */
struct mscpv_scce {
	u_short scce_version;		/* MSCP version number */
	u_short scce_ctlrflags;		/* controller flags */
	u_short scce_ctlrtimo;		/* controller timeout */
	u_short scce_ctlrcmdl;		/* ??? */
	quad_t	scce_ctlrid;		/* controller ID */
	long	scce_xxx[3];	/* ? */
	long	scce_volser;		/* volume serial number */
};

/*
 * On Line command variant
 */
struct mscpv_onlc {
	long	onlc_xxx1[4];	/* ? */
	long	onlc_errlgfl;		/* error log flag? */
	short	onlc_xxx2;	/* ? */
	short	onlc_copyspd;		/* copy speed? */
};

/*
 * On Line end variant
 */
struct mscpv_onle {
	long	onle_xxx1[3];	/* ? */
/*???*/ short	onle_xxx2;	/* ? */
	u_char	onle_drivetype;		/* drive type index (same in guse) */
	char	onle_xxx3;	/* ? */
	long	onle_mediaid;		/* media type id (same in guse) */
	long	onle_xxx4;	/* ? */
	long	onle_unitsize;		/* unit size in sectors */
	long	onle_volser;		/* volume serial number */
};

/*
 * Get Unit Status end variant (and Avail Attn?)
 */
struct mscpv_guse {
	u_short guse_multunit;		/* multi-unit code */
	u_short guse_unitflags;		/* unit flags */
	long	guse_hostid;		/* host id */
	long	guse_unitid0;	/*???*/
	short	guse_unitid1;	/*???*/
	u_char	guse_drivetype;		/* drive type index */
	u_char	guse_unitid2;	/*???*/
	long	guse_mediaid;		/* media type id (encoded) */
	short	guse_shadowunit;	/* shadow unit */
	short	guse_shadowstat;	/* shadow status */
	u_short guse_nspt;		/* sectors per track */
	u_short guse_group;		/* track group size */
	u_short guse_ngpc;		/* groups per cylinder */
	u_short guse_xxx;		/* reserved */
	u_short guse_rctsize;		/* RCT size (sectors) */
	u_char	guse_nrpt;		/* RBNs per track */
	u_char	guse_nrct;		/* number of RCTs */
};

/*
 * Macros to break up and build media IDs.  An ID encodes the port
 * type in the top 10 bits, and the drive type in the remaining 22.
 * The 10 bits, and 15 of the 22, are in groups of 5, with the value
 * 0 representing space and values 1..26 representing A..Z.  The low
 * 7 bits represent a number in 0..127.	 Hence an RA81 on a UDA50
 * is <D><U><R><A>< >81, or 0x25641051.	 This encoding scheme is known
 * in part in uda.c.
 *
 * The casts below are just to make pcc generate better code.
 */
#define MSCP_MEDIA_PORT(id)	(((long)(id) >> 22) & 0x3ff)	/* port */
#define MSCP_MEDIA_DRIVE(id)	((long)(id) & 0x003fffff)	/* drive */
#define MSCP_MID_ECH(n, id)	(((int)(id) >> ((n) * 5 + 7)) & 0x1f)
#define MSCP_MID_CHAR(n, id) \
	(MSCP_MID_ECH(n, id) ? MSCP_MID_ECH(n, id) + '@' : ' ')
#define MSCP_MID_NUM(id)	((id) & 0x7f)
/* for, e.g., RA81 */
#define MSCP_MKDRIVE2(a, b, n) \
	(((a) - '@') << 17 | ((b) - '@') << 12 | (n))
/* for, e.g., RRD50 */
#define MSCP_MKDRIVE3(a, b, c, n) \
	(((a) - '@') << 17 | ((b) - '@') << 12 | ((c) - '@') << 7 | (n))

/*
 * Error datagram variant.
 */
struct mscpv_erd {
	quad_t	erd_ctlrid;		/* controller ID */
	u_char	erd_ctlrsoftware;	/* controller software version */
	u_char	erd_ctlrhardware;	/* controller hardware version */
	u_short erd_multiunit;		/* multi-unit code (?) */
	union {
		u_long	un_busaddr;	/* bus address, if mem access err */
		quad_t	un_unitid;	/* unit id, otherwise */
	} erd_un1;
#define erd_busaddr	erd_un1.un_busaddr
#define erd_unitid	erd_un1.un_unitid
	u_char	erd_unitsoftware;	/* unit software version */
	u_char	erd_unithardware;	/* unit hardware version */
	union {
		u_char	un_b[2];	/* level, retry (if disk xfer err) */
		u_short un_s;		/* cylinder (if small disk error) */
	} erd_un2;
#define erd_level	erd_un2.un_b[0]
#define erd_retry	erd_un2.un_b[1]
#define erd_sdecyl	erd_un2.un_s
	long	erd_volser;		/* volume serial number */
	u_long	erd_hdr;		/* `header' (block number) */
	u_char	erd_sdistat[12];	/* SDI status information (?) */
};

/*
 * I am making brash assumptions about the first four bytes of all
 * MSCP packets.  These appear to be true for both UDA50s and TMSCP
 * devices (TU81, TA81, TK50).	DEC claim that these four bytes are
 * not part of MSCP itself, yet at least the length is necessary
 * for, e.g., error checking.
 */
struct mscp {
	u_short mscp_msglen;		/* length in bytes */
	u_char	mscp_msgtc;		/* type (high 4 bits) and credits */
	u_char	mscp_vcid;		/* virtual circuit ID */
	long	mscp_cmdref;		/* command reference number */
	u_short mscp_unit;		/* unit number */
	u_short mscp_seqnum;		/* sequence number */
	u_char	mscp_opcode;		/* opcode */
#define mscp_format	mscp_opcode	/* aka format (datagrams) */
	u_char	mscp_flags;		/* flags */
	u_short mscp_modifier;		/* modifier (commands) */
#define mscp_status	mscp_modifier	/* aka status (ends) */
#define mscp_event	mscp_modifier	/* aka event (datagrams) */
	union {
		struct	mscpv_seq un_seq;	/* generic sequential msg */
		struct	mscpv_sccc un_sccc;	/* SCC command */
		struct	mscpv_scce un_scce;	/* SCC end */
		struct	mscpv_onlc un_onlc;	/* on line command */
		struct	mscpv_onle un_onle;	/* on line end */
		struct	mscpv_guse un_guse;	/* get unit status */
		struct	mscpv_erd un_erd;	/* error datagram */
	} mscp_un;
/*???*/ long	mscp_xxx;		/* pad to 64 bytes */
};

/*
 * Define message length according to the DEC specifications by dropping
 * the four byte header.
 */
#define MSCP_MSGLEN	(sizeof (struct mscp) - 4)

/*
 * Shorthand
 */

/*
 * Generic packet
 */
#define mscp_seq	mscp_un.un_seq

/*
 * Set Controller Characteristics packet
 */
#define mscp_sccc	mscp_un.un_sccc

/*
 * Set Controller Characteristics end packet
 */
#define mscp_scce	mscp_un.un_scce

/*
 * Online / Set Unit Characteristics command packet
 */
#define mscp_onlc	mscp_un.un_onlc

/*
 * Online end packet
 */
#define mscp_onle	mscp_un.un_onle

/*
 * Get Unit Status end packet
 */
#define mscp_guse	mscp_un.un_guse

/*
 * MSCP Error Log packet
 */
#define mscp_erd	mscp_un.un_erd

/*
 * MSCP seq_addr field actually belongs to overall packet.
 */
#define mscp_addr	mscp_seq.seq_addr

/*
 * Macros to break up mscp_msgtc, and types.
 */
#define MSCP_MSGTYPE(m) ((m) & 0xf0)
#define MSCP_CREDITS(m) ((m) & 0x0f)

#define MSCPT_SEQ		0x00	/* sequential message */
#define MSCPT_DATAGRAM		0x10	/* error datagram */
#define MSCPT_CREDITS		0x20	/* credit notification */
#define MSCPT_MAINTENANCE	0xf0	/* who knows */


/*
 * Here begin more perhaps brash assumptions about MSCP devices...
 */

/*
 * MSCP controllers have `command rings' and `response rings'.	A
 * command ring is a pool of MSCP packets that the host uses to give
 * commands to the controller; a response ring is a pool of MSCP
 * packets that the controller uses to give back responses.  Entries
 * in the command and response rings are `owned' by either the host
 * or the controller; only the owner is allowed to alter any of the
 * fields in the MSCP packet.  Thus, free command packets are owned
 * by the host, and free response packets by the controller.  When
 * the host gives a packet to the controller, it tells the controller
 * by touching a device register; when the controller gives a response
 * to the host, it generates an interrupt if enabled, and sets
 * a device register as well.
 *
 * The pool is `described' by a set of pointers to the packets, along
 * with the two flags below.
 */
#define MSCP_OWN	0x80000000	/* controller owns this packet */
#define MSCP_INT	0x40000000	/* controller should interrupt */