1 /* $NetBSD: scsi_changer.h,v 1.9 1997/09/29 00:55:26 mjacob Exp $ */ 2 3 /* 4 * Copyright (c) 1996 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 #ifndef _SCSI_SCSI_CHANGER_H 63 #define _SCSI_SCSI_CHANGER_H 1 64 65 /* 66 * SCSI command format 67 */ 68 69 /* 70 * Exchange the medium in the source element with the medium 71 * located at the destination element. 72 */ 73 struct scsi_exchange_medium { 74 u_int8_t opcode; 75 #define EXCHANGE_MEDIUM 0xa6 76 u_int8_t byte2; 77 u_int8_t tea[2]; /* transport element address */ 78 u_int8_t src[2]; /* source address */ 79 u_int8_t fdst[2]; /* first destination address */ 80 u_int8_t sdst[2]; /* second destination address */ 81 u_int8_t flags; 82 #define EXCHANGE_MEDIUM_INV1 0x01 83 #define EXCHANGE_MEDIUM_INV2 0x02 84 u_int8_t control; 85 }; 86 87 /* 88 * Cause the medium changer to check all elements for medium and any 89 * other status relevant to the element. 90 */ 91 struct scsi_initialize_element_status { 92 u_int8_t opcode; 93 #define INITIALIZE_ELEMENT_STATUS 0x07 94 u_int8_t byte2; 95 u_int8_t reserved[3]; 96 u_int8_t control; 97 }; 98 99 /* 100 * Request the changer to move a unit of media from the source element 101 * to the destination element. 102 */ 103 struct scsi_move_medium { 104 u_int8_t opcode; 105 #define MOVE_MEDIUM 0xa5 106 u_int8_t byte2; 107 u_int8_t tea[2]; /* transport element address */ 108 u_int8_t src[2]; /* source element address */ 109 u_int8_t dst[2]; /* destination element address */ 110 u_int8_t reserved[2]; 111 u_int8_t flags; 112 #define MOVE_MEDIUM_INVERT 0x01 113 u_int8_t control; 114 }; 115 116 /* 117 * Position the specified transport element (picker) in front of 118 * the destination element specified. 119 */ 120 struct scsi_position_to_element { 121 u_int8_t opcode; 122 #define POSITION_TO_ELEMENT 0x2b 123 u_int8_t byte2; 124 u_int8_t tea[2]; /* transport element address */ 125 u_int8_t dst[2]; /* destination element address */ 126 u_int8_t reserved[2]; 127 u_int8_t flags; 128 #define POSITION_TO_ELEMENT_INVERT 0x01 129 u_int8_t control; 130 }; 131 132 /* 133 * Request that the changer report the status of its internal elements. 134 */ 135 struct scsi_read_element_status { 136 u_int8_t opcode; 137 #define READ_ELEMENT_STATUS 0xb8 138 u_int8_t byte2; 139 #define READ_ELEMENT_STATUS_VOLTAG 0x10 /* report volume tag info */ 140 /* ...next 4 bits are an element type code... */ 141 u_int8_t sea[2]; /* starting element address */ 142 u_int8_t count[2]; /* number of elements */ 143 u_int8_t reserved0; 144 u_int8_t len[3]; /* length of data buffer */ 145 u_int8_t reserved1; 146 u_int8_t control; 147 }; 148 149 struct scsi_request_volume_element_address { 150 u_int8_t opcode; 151 #define REQUEST_VOLUME_ELEMENT_ADDRESS 0xb5 152 u_int8_t byte2; 153 #define REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG 0x10 154 /* ...next 4 bits are an element type code... */ 155 u_int8_t eaddr[2]; /* element address */ 156 u_int8_t count[2]; /* number of elements */ 157 u_int8_t reserved0; 158 u_int8_t len[3]; /* length of data buffer */ 159 u_int8_t reserved1; 160 u_int8_t control; 161 }; 162 163 /* XXX scsi_release */ 164 165 /* 166 * Data returned by READ ELEMENT STATUS consists of an 8-byte header 167 * followed by one or more read_element_status_pages. 168 */ 169 struct read_element_status_header { 170 u_int8_t fear[2]; /* first element address reported */ 171 u_int8_t count[2]; /* number of elements available */ 172 u_int8_t reserved; 173 u_int8_t nbytes[3]; /* byte count of all pages */ 174 }; 175 176 struct read_element_status_page_header { 177 u_int8_t type; /* element type code; see type codes below */ 178 u_int8_t flags; 179 #define READ_ELEMENT_STATUS_AVOLTAG 0x40 180 #define READ_ELEMENT_STATUS_PVOLTAG 0x80 181 u_int8_t edl[2]; /* element descriptor length */ 182 u_int8_t reserved; 183 u_int8_t nbytes[3]; /* byte count of all descriptors */ 184 }; 185 186 struct read_element_status_descriptor { 187 u_int8_t eaddr[2]; /* element address */ 188 u_int8_t flags1; 189 190 #define READ_ELEMENT_STATUS_FULL 0x01 191 #define READ_ELEMENT_STATUS_IMPEXP 0x02 192 #define READ_ELEMENT_STATUS_EXCEPT 0x04 193 #define READ_ELEMENT_STATUS_ACCESS 0x08 194 #define READ_ELEMENT_STATUS_EXENAB 0x10 195 #define READ_ELEMENT_STATUS_INENAB 0x20 196 197 #define READ_ELEMENT_STATUS_MT_MASK1 0x05 198 #define READ_ELEMENT_STATUS_ST_MASK1 0x0c 199 #define READ_ELEMENT_STATUS_IE_MASK1 0x3f 200 #define READ_ELEMENT_STATUS_DT_MASK1 0x0c 201 202 u_int8_t reserved0; 203 u_int8_t sense_code; 204 u_int8_t sense_qual; 205 206 /* 207 * dt_scsi_flags and dt_scsi_addr are valid only on data transport 208 * elements. These bytes are undefined for all other element types. 209 */ 210 u_int8_t dt_scsi_flags; 211 212 #define READ_ELEMENT_STATUS_DT_LUNMASK 0x07 213 #define READ_ELEMENT_STATUS_DT_LUVALID 0x10 214 #define READ_ELEMENT_STATUS_DT_IDVALID 0x20 215 #define READ_ELEMENT_STATUS_DT_NOTBUS 0x80 216 217 u_int8_t dt_scsi_addr; 218 219 u_int8_t reserved1; 220 221 u_int8_t flags2; 222 #define READ_ELEMENT_STATUS_INVERT 0x40 223 #define READ_ELEMENT_STATUS_SVALID 0x80 224 u_int8_t ssea[2]; /* source storage element address */ 225 226 /* 227 * bytes 12-47: Primary volume tag information. 228 * (field omitted if PVOLTAG = 0) 229 * 230 * bytes 48-83: Alternate volume tag information. 231 * (field omitted if AVOLTAG = 0) 232 * 233 * bytes 84-87: Reserved (moved up if either of the above fields 234 * are omitted) 235 * 236 * bytes 88-end: Vendor-specific: (moved up if either of the 237 * above fields are missing) 238 */ 239 }; 240 241 /* XXX add data returned by REQUEST VOLUME ELEMENT ADDRESS */ 242 243 /* Element type codes */ 244 #define ELEMENT_TYPE_MASK 0x0f /* Note: these aren't bits */ 245 #define ELEMENT_TYPE_ALL 0x00 246 #define ELEMENT_TYPE_MT 0x01 247 #define ELEMENT_TYPE_ST 0x02 248 #define ELEMENT_TYPE_IE 0x03 249 #define ELEMENT_TYPE_DT 0x04 250 251 /* 252 * XXX The following definitions should be common to all SCSI device types. 253 */ 254 #define PGCODE_MASK 0x3f /* valid page number bits in pg_code */ 255 #define PGCODE_PS 0x80 /* indicates page is savable */ 256 257 /* 258 * Device capabilities page. 259 * 260 * This page defines characteristics of the elemenet types in the 261 * medium changer device. 262 * 263 * Note in the definitions below, the following abbreviations are 264 * used: 265 * MT Medium transport element (picker) 266 * ST Storage transport element (slot) 267 * IE Import/export element (portal) 268 * DT Data tranfer element (tape/disk drive) 269 */ 270 struct page_device_capabilities { 271 u_int8_t pg_code; /* page code (0x1f) */ 272 u_int8_t pg_length; /* page length (0x12) */ 273 274 /* 275 * The STOR_xx bits indicate that an element of a given 276 * type may provide independent storage for a unit of 277 * media. The top four bits of this value are reserved. 278 */ 279 u_int8_t stor; 280 #define STOR_MT 0x01 281 #define STOR_ST 0x02 282 #define STOR_IE 0x04 283 #define STOR_DT 0x08 284 285 u_int8_t reserved0; 286 287 /* 288 * The MOVE_TO_yy bits indicate the changer supports 289 * moving a unit of medium from an element of a given type to an 290 * element of type yy. This is used to determine if a given 291 * MOVE MEDIUM command is legal. The top four bits of each 292 * of these values are reserved. 293 */ 294 u_int8_t move_from_mt; 295 u_int8_t move_from_st; 296 u_int8_t move_from_ie; 297 u_int8_t move_from_dt; 298 #define MOVE_TO_MT 0x01 299 #define MOVE_TO_ST 0x02 300 #define MOVE_TO_IE 0x04 301 #define MOVE_TO_DT 0x08 302 303 u_int8_t reserved1[2]; 304 305 /* 306 * Similar to above, but for EXCHANGE MEDIUM. 307 */ 308 u_int8_t exchange_with_mt; 309 u_int8_t exchange_with_st; 310 u_int8_t exchange_with_ie; 311 u_int8_t exchange_with_dt; 312 #define EXCHANGE_WITH_MT 0x01 313 #define EXCHANGE_WITH_ST 0x02 314 #define EXCHANGE_WITH_IE 0x04 315 #define EXCHANGE_WITH_DT 0x08 316 }; 317 318 /* 319 * Medium changer elemement address assignment page. 320 * 321 * Some of these fields can be a little confusing, so an explanation 322 * is in order. 323 * 324 * Each component within a a medium changer apparatus is called an 325 * "element". 326 * 327 * The "medium transport element address" is the address of the first 328 * picker (robotic arm). "Number of medium transport elements" tells 329 * us how many pickers exist in the changer. 330 * 331 * The "first storage element address" is the address of the first 332 * slot in the tape or disk magazine. "Number of storage elements" tells 333 * us how many slots exist in the changer. 334 * 335 * The "first import/export element address" is the address of the first 336 * medium portal accessible both by the medium changer and an outside 337 * human operator. This is where the changer might deposit tapes destined 338 * for some vault. The "number of import/export elements" tells us 339 * not many of these portals exist in the changer. NOTE: this number may 340 * be 0. 341 * 342 * The "first data transfer element address" is the address of the first 343 * tape or disk drive in the changer. "Number of data transfer elements" 344 * tells us how many drives exist in the changer. 345 */ 346 struct page_element_address_assignment { 347 u_int8_t pg_code; /* page code (0x1d) */ 348 u_int8_t pg_length; /* page length (0x12) */ 349 350 /* Medium transport element address */ 351 u_int8_t mtea[2]; 352 353 /* Number of medium transport elements */ 354 u_int8_t nmte[2]; 355 356 /* First storage element address */ 357 u_int8_t fsea[2]; 358 359 /* Number of storage elements */ 360 u_int8_t nse[2]; 361 362 /* First import/export element address */ 363 u_int8_t fieea[2]; 364 365 /* Number of import/export elements */ 366 u_int8_t niee[2]; 367 368 /* First data transfer element address */ 369 u_int8_t fdtea[2]; 370 371 /* Number of data trafer elements */ 372 u_int8_t ndte[2]; 373 374 u_int8_t reserved[2]; 375 }; 376 377 /* 378 * Transport geometry parameters page. 379 * 380 * Defines whether each medium transport element is a member of a set of 381 * elements that share a common robotics subsystem and whether the element 382 * is capable of media rotation. One transport geometry descriptor is 383 * transferred for each medium transport element, beginning with the first 384 * medium transport element (other than the default transport element address 385 * of 0). 386 */ 387 struct page_transport_geometry_parameters { 388 u_int8_t pg_code; /* page code (0x1e) */ 389 u_int8_t pg_length; /* page length; variable */ 390 391 /* Transport geometry descriptor(s) are here. */ 392 393 u_int8_t misc; 394 #define CAN_ROTATE 0x01 395 396 /* Member number in transport element set. */ 397 u_int8_t member; 398 }; 399 400 #endif /* _SCSI_SCSI_CHANGER_H */ 401