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