1 /* $NetBSD: scsi_changer.h,v 1.20 2005/12/11 12:23:50 christos 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