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
491
492
493
494
|
/* $OpenBSD: mscp.h,v 1.2 1997/05/29 00:05:02 niklas Exp $ */
/* $NetBSD: mscp.h,v 1.2 1996/07/10 23:35:59 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 0x23 /* 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) (((long)(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 */
|