xref: /netbsd/sys/dev/scsipi/scsi_changer.h (revision bf9ec67e)
1 /*	$NetBSD: scsi_changer.h,v 1.16 2001/09/02 19:35:20 thorpej Exp $	*/
2 
3 /*
4  * Copyright (c) 1996, 1999 Jason R. Thorpe <thorpej@and.com>
5  * All rights reserved.
6  *
7  * Partially based on an autochanger driver written by Stefan Grefen
8  * and on an autochanger driver written by the Systems Programming Group
9  * at the University of Utah Computer Science Department.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgements:
21  *	This product includes software developed by Jason R. Thorpe
22  *	for And Communications, http://www.and.com/
23  * 4. The name of the author may not be used to endorse or promote products
24  *    derived from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
33  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 /*
40  * SCSI changer interface description
41  */
42 
43 /*
44  * Partially derived from software written by Stefan Grefen
45  * (grefen@goofy.zdv.uni-mainz.de soon grefen@convex.com)
46  * based on the SCSI System by written Julian Elischer (julian@tfs.com)
47  * for TRW Financial Systems.
48  *
49  * TRW Financial Systems, in accordance with their agreement with Carnegie
50  * Mellon University, makes this software available to CMU to distribute
51  * or use in any manner that they see fit as long as this message is kept with
52  * the software. For this reason TFS also grants any other persons or
53  * organisations permission to use or modify this software.
54  *
55  * TFS supplies this software to be publicly redistributed
56  * on the understanding that TFS is not responsible for the correct
57  * functioning of this software in any circumstances.
58  *
59  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
60  */
61 
62 /*
63  * SCSI command format
64  */
65 
66 /*
67  * Exchange the medium in the source element with the medium
68  * located at the destination element.
69  */
70 struct scsi_exchange_medium {
71 	u_int8_t	opcode;
72 #define EXCHANGE_MEDIUM		0xa6
73 	u_int8_t	byte2;
74 	u_int8_t	tea[2];	/* transport element address */
75 	u_int8_t	src[2];	/* source address */
76 	u_int8_t	fdst[2]; /* first destination address */
77 	u_int8_t	sdst[2]; /* second destination address */
78 	u_int8_t	flags;
79 #define EXCHANGE_MEDIUM_INV1	0x01
80 #define EXCHANGE_MEDIUM_INV2	0x02
81 	u_int8_t	control;
82 };
83 
84 /*
85  * Cause the medium changer to check all elements for medium and any
86  * other status relevant to the element.
87  */
88 struct scsi_initialize_element_status {
89 	u_int8_t	opcode;
90 #define INITIALIZE_ELEMENT_STATUS	0x07
91 	u_int8_t	byte2;
92 	u_int8_t	reserved[3];
93 	u_int8_t	control;
94 };
95 
96 /*
97  * Request the changer to move a unit of media from the source element
98  * to the destination element.
99  */
100 struct scsi_move_medium {
101 	u_int8_t	opcode;
102 #define MOVE_MEDIUM	0xa5
103 	u_int8_t	byte2;
104 	u_int8_t	tea[2];	/* transport element address */
105 	u_int8_t	src[2];	/* source element address */
106 	u_int8_t	dst[2];	/* destination element address */
107 	u_int8_t	reserved[2];
108 	u_int8_t	flags;
109 #define MOVE_MEDIUM_INVERT	0x01
110 	u_int8_t	control;
111 };
112 
113 /*
114  * Position the specified transport element (picker) in front of
115  * the destination element specified.
116  */
117 struct scsi_position_to_element {
118 	u_int8_t	opcode;
119 #define POSITION_TO_ELEMENT	0x2b
120 	u_int8_t	byte2;
121 	u_int8_t	tea[2];	/* transport element address */
122 	u_int8_t	dst[2];	/* destination element address */
123 	u_int8_t	reserved[2];
124 	u_int8_t	flags;
125 #define POSITION_TO_ELEMENT_INVERT	0x01
126 	u_int8_t	control;
127 };
128 
129 /*
130  * Request that the changer report the status of its internal elements.
131  */
132 struct scsi_read_element_status {
133 	u_int8_t	opcode;
134 #define READ_ELEMENT_STATUS	0xb8
135 	u_int8_t	byte2;
136 #define READ_ELEMENT_STATUS_VOLTAG	0x10	/* report volume tag info */
137 	/* ...next 4 bits are an element type code... */
138 	u_int8_t	sea[2];		/* starting element address */
139 	u_int8_t	count[2];	/* number of elements */
140 	u_int8_t	reserved0;
141 	u_int8_t	len[3];		/* length of data buffer */
142 	u_int8_t	reserved1;
143 	u_int8_t	control;
144 };
145 
146 struct scsi_request_volume_element_address {
147 	u_int8_t	opcode;
148 #define REQUEST_VOLUME_ELEMENT_ADDRESS	0xb5
149 	u_int8_t	byte2;
150 #define REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG	0x10
151 	/* ...next 4 bits are an element type code... */
152 	u_int8_t	eaddr[2];	/* element address */
153 	u_int8_t	count[2];	/* number of elements */
154 	u_int8_t	reserved0;
155 	u_int8_t	len[3];		/* length of data buffer */
156 	u_int8_t	reserved1;
157 	u_int8_t	control;
158 };
159 
160 /* XXX scsi_release */
161 
162 /*
163  * Data returned by READ ELEMENT STATUS consists of an 8-byte header
164  * followed by one or more read_element_status_pages.
165  */
166 struct read_element_status_header {
167 	u_int8_t	fear[2];  /* first element address reported */
168 	u_int8_t	count[2]; /* number of elements available */
169 	u_int8_t	reserved;
170 	u_int8_t	nbytes[3]; /* byte count of all pages */
171 };
172 
173 /*
174  * Data returned by REQUEST VOLUME ELEMENT ADDRESS consists of an 8-byte
175  * header followed by one or more read_element_status pages (i.e. same
176  * data format as returned by READ ELEMENT STATUS, except for the initial
177  * header).
178  */
179 struct request_volume_element_address_header {
180 	u_int8_t	fear[2];  /* first element address reported */
181 	u_int8_t	count[2]; /* number of elements available */
182 	u_int8_t	sac;	  /* send action code */
183 #define	REQUEST_VOLUME_ELEMENT_ADDRESS_SACMASK	0x1f
184 	u_int8_t	nbytes[3];/* byte count of all pages */
185 };
186 
187 struct read_element_status_page_header {
188 	u_int8_t	type;	/* element type code; see type codes below */
189 	u_int8_t	flags;
190 #define READ_ELEMENT_STATUS_AVOLTAG	0x40
191 #define READ_ELEMENT_STATUS_PVOLTAG	0x80
192 	u_int8_t	edl[2];	/* element descriptor length */
193 	u_int8_t	reserved;
194 	u_int8_t	nbytes[3]; /* byte count of all descriptors */
195 };
196 
197 struct read_element_status_descriptor {
198 	u_int8_t	eaddr[2];	/* element address */
199 	u_int8_t	flags1;
200 
201 #define READ_ELEMENT_STATUS_FULL	0x01
202 #define READ_ELEMENT_STATUS_IMPEXP	0x02
203 #define READ_ELEMENT_STATUS_EXCEPT	0x04
204 #define READ_ELEMENT_STATUS_ACCESS	0x08
205 #define READ_ELEMENT_STATUS_EXENAB	0x10
206 #define READ_ELEMENT_STATUS_INENAB	0x20
207 
208 #define READ_ELEMENT_STATUS_MT_MASK1	0x05
209 #define READ_ELEMENT_STATUS_ST_MASK1	0x0c
210 #define READ_ELEMENT_STATUS_IE_MASK1	0x3f
211 #define READ_ELEMENT_STATUS_DT_MASK1	0x0c
212 
213 	u_int8_t	reserved0;
214 	u_int8_t	sense_code;
215 	u_int8_t	sense_qual;
216 
217 	/*
218 	 * dt_scsi_flags and dt_scsi_addr are valid only on data transport
219 	 * elements.  These bytes are undefined for all other element types.
220 	 */
221 	u_int8_t	dt_scsi_flags;
222 
223 #define READ_ELEMENT_STATUS_DT_LUNMASK	0x07
224 #define READ_ELEMENT_STATUS_DT_LUVALID	0x10
225 #define READ_ELEMENT_STATUS_DT_IDVALID	0x20
226 #define READ_ELEMENT_STATUS_DT_NOTBUS	0x80
227 
228 	u_int8_t	dt_scsi_addr;
229 
230 	u_int8_t	reserved1;
231 
232 	u_int8_t	flags2;
233 #define READ_ELEMENT_STATUS_INVERT	0x40
234 #define READ_ELEMENT_STATUS_SVALID	0x80
235 	u_int8_t	ssea[2];	/* source storage element address */
236 
237 	/*
238 	 * bytes 12-47:	Primary volume tag information.
239 	 *		(field omitted if PVOLTAG = 0)
240 	 *
241 	 * bytes 48-83:	Alternate volume tag information.
242 	 *		(field omitted if AVOLTAG = 0)
243 	 *
244 	 * bytes 84-87:	Reserved (moved up if either of the above fields
245 	 *		are omitted)
246 	 *
247 	 * bytes 88-end: Vendor-specific: (moved up if either of the
248 	 *		 above fields are missing)
249 	 */
250 };
251 
252 /*
253  * Volume Tag format:
254  *
255  * Volume Tags are a sequence of ASCII characters, unused portion is
256  * blank-filled.  There should be no blanks in the significant portion
257  * of the tag.  For maximum compatibility, volume tag characters should
258  * be limited to '0'..'9', 'A'..'Z', '_'.
259  */
260 struct changer_volume_tag {
261 	u_int8_t volid[32];	/* 32 bytes of ASCII, blank-terminated */
262 	u_int8_t reserved[2];
263 	u_int8_t volseq[2];	/* volume sequence number */
264 };
265 
266 /*
267  * Send a volume tag.
268  */
269 struct scsi_send_volume_tag {
270 	u_int8_t	opcode;
271 #define	SEND_VOLUME_TAG		0xb6
272 	u_int8_t	byte2;
273 	u_int8_t	eaddr[2];	/* element address */
274 	u_int8_t	reserved0;
275 	u_int8_t	sac;		/* send action code */
276 #define	SAC_TRANSLATE_ALL		0x00
277 #define	SAC_TRANSLATE_PRIMARY		0x01
278 #define	SAC_TRANSLATE_ALT		0x02
279 #define	SAC_TRANSLATE_ALL_NOSEQ		0x04
280 #define	SAC_TRANSLATE_PRIMARY_NOSEQ	0x05
281 #define	SAC_TRANSLATE_ALT_NOSEQ		0x06
282 #define	SAC_ASSERT_PRIMARY		0x08
283 #define	SAC_ASSERT_ALT			0x09
284 #define	SAC_REPLACE_PRIMARY		0x0a
285 #define	SAC_REPLACE_ALT			0x0b
286 #define	SAC_UNDEFINED_PRIMARY		0x0c
287 #define	SAC_UNDEFINED_ALT		0x0d
288 				/*	0x0e - 0x1b	reserved */
289 				/*	0x1c - 0x1f	vendor-specific */
290 	u_int8_t	reserved1[2];
291 	u_int8_t	length[2];	/* paremeter list length */
292 	u_int8_t	reserved2;
293 	u_int8_t	control;
294 };
295 
296 /* Element type codes */
297 #define ELEMENT_TYPE_MASK	0x0f	/* Note: these aren't bits */
298 #define ELEMENT_TYPE_ALL	0x00
299 #define ELEMENT_TYPE_MT		0x01
300 #define ELEMENT_TYPE_ST		0x02
301 #define ELEMENT_TYPE_IE		0x03
302 #define ELEMENT_TYPE_DT		0x04
303 
304 /*
305  * Device capabilities page.
306  *
307  * This page defines characteristics of the element types in the
308  * medium changer device.
309  *
310  * Note in the definitions below, the following abbreviations are
311  * used:
312  *		MT	Medium transport element (picker)
313  *		ST	Storage transport element (slot)
314  *		IE	Import/export element (portal)
315  *		DT	Data transfer element (tape/disk drive)
316  */
317 struct page_device_capabilities {
318 	u_int8_t	pg_code;	/* page code (0x1f) */
319 	u_int8_t	pg_length;	/* page length (0x12) */
320 
321 	/*
322 	 * The STOR_xx bits indicate that an element of a given
323 	 * type may provide independent storage for a unit of
324 	 * media.  The top four bits of this value are reserved.
325 	 */
326 	u_int8_t	stor;
327 #define STOR_MT		0x01
328 #define STOR_ST		0x02
329 #define STOR_IE		0x04
330 #define STOR_DT		0x08
331 
332 	u_int8_t	reserved0;
333 
334 	/*
335 	 * The MOVE_TO_yy bits indicate the changer supports
336 	 * moving a unit of medium from an element of a given type to an
337 	 * element of type yy.  This is used to determine if a given
338 	 * MOVE MEDIUM command is legal.  The top four bits of each
339 	 * of these values are reserved.
340 	 */
341 	u_int8_t	move_from_mt;
342 	u_int8_t	move_from_st;
343 	u_int8_t	move_from_ie;
344 	u_int8_t	move_from_dt;
345 #define MOVE_TO_MT	0x01
346 #define MOVE_TO_ST	0x02
347 #define MOVE_TO_IE	0x04
348 #define MOVE_TO_DT	0x08
349 
350 	u_int8_t	reserved1[4];
351 
352 	/*
353 	 * Similar to above, but for EXCHANGE MEDIUM.
354 	 */
355 	u_int8_t	exchange_with_mt;
356 	u_int8_t	exchange_with_st;
357 	u_int8_t	exchange_with_ie;
358 	u_int8_t	exchange_with_dt;
359 #define EXCHANGE_WITH_MT	0x01
360 #define EXCHANGE_WITH_ST	0x02
361 #define EXCHANGE_WITH_IE	0x04
362 #define EXCHANGE_WITH_DT	0x08
363 };
364 
365 /*
366  * Medium changer element address assignment page.
367  *
368  * Some of these fields can be a little confusing, so an explanation
369  * is in order.
370  *
371  * Each component within a a medium changer apparatus is called an
372  * "element".
373  *
374  * The "medium transport element address" is the address of the first
375  * picker (robotic arm).  "Number of medium transport elements" tells
376  * us how many pickers exist in the changer.
377  *
378  * The "first storage element address" is the address of the first
379  * slot in the tape or disk magazine.  "Number of storage elements" tells
380  * us how many slots exist in the changer.
381  *
382  * The "first import/export element address" is the address of the first
383  * medium portal accessible both by the medium changer and an outside
384  * human operator.  This is where the changer might deposit tapes destined
385  * for some vault.  The "number of import/export elements" tells us
386  * not many of these portals exist in the changer.  NOTE: this number may
387  * be 0.
388  *
389  * The "first data transfer element address" is the address of the first
390  * tape or disk drive in the changer.  "Number of data transfer elements"
391  * tells us how many drives exist in the changer.
392  */
393 struct page_element_address_assignment {
394 	u_int8_t	pg_code;	/* page code (0x1d) */
395 	u_int8_t	pg_length;	/* page length (0x12) */
396 
397 	/* Medium transport element address */
398 	u_int8_t	mtea[2];
399 
400 	/* Number of medium transport elements */
401 	u_int8_t	nmte[2];
402 
403 	/* First storage element address */
404 	u_int8_t	fsea[2];
405 
406 	/* Number of storage elements */
407 	u_int8_t	nse[2];
408 
409 	/* First import/export element address */
410 	u_int8_t	fieea[2];
411 
412 	/* Number of import/export elements */
413 	u_int8_t	niee[2];
414 
415 	/* First data transfer element address */
416 	u_int8_t	fdtea[2];
417 
418 	/* Number of data transfer elements */
419 	u_int8_t	ndte[2];
420 
421 	u_int8_t	reserved[2];
422 };
423 
424 /*
425  * Transport geometry parameters page.
426  *
427  * Defines whether each medium transport element is a member of a set of
428  * elements that share a common robotics subsystem and whether the element
429  * is capable of media rotation.  One transport geometry descriptor is
430  * transferred for each medium transport element, beginning with the first
431  * medium transport element (other than the default transport element address
432  * of 0).
433  */
434 struct page_transport_geometry_parameters {
435 	u_int8_t	pg_code;	/* page code (0x1e) */
436 	u_int8_t	pg_length;	/* page length; variable */
437 
438 	/* Transport geometry descriptor(s) are here. */
439 
440 	u_int8_t	misc;
441 #define CAN_ROTATE	0x01
442 
443 	/* Member number in transport element set. */
444 	u_int8_t	member;
445 };
446