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
|
/* $FreeBSD$ */
/* $NetBSD: scsi_changer.h,v 1.11 1998/02/13 08:28:32 enami Exp $ */
/*
* Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
* All rights reserved.
*
* Partially based on an autochanger driver written by Stefan Grefen
* and on an autochanger driver written by the Systems Programming Group
* at the University of Utah Computer Science Department.
*
* 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 acknowledgements:
* This product includes software developed by Jason R. Thorpe
* for And Communications, http://www.and.com/
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/*
* SCSI changer interface description
*/
/*
* Partially derived from software written by Stefan Grefen
* (grefen@goofy.zdv.uni-mainz.de soon grefen@convex.com)
* based on the SCSI System by written Julian Elischer (julian@tfs.com)
* for TRW Financial Systems.
*
* TRW Financial Systems, in accordance with their agreement with Carnegie
* Mellon University, makes this software available to CMU to distribute
* or use in any manner that they see fit as long as this message is kept with
* the software. For this reason TFS also grants any other persons or
* organisations permission to use or modify this software.
*
* TFS supplies this software to be publicly redistributed
* on the understanding that TFS is not responsible for the correct
* functioning of this software in any circumstances.
*
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*/
#ifndef _SCSI_SCSI_CH_H
#define _SCSI_SCSI_CH_H 1
#include <sys/cdefs.h>
/*
* SCSI command format
*/
/*
* Exchange the medium in the source element with the medium
* located at the destination element.
*/
struct scsi_exchange_medium {
u_int8_t opcode;
#define EXCHANGE_MEDIUM 0xa6
u_int8_t byte2;
u_int8_t tea[2]; /* transport element address */
u_int8_t src[2]; /* source address */
u_int8_t fdst[2]; /* first destination address */
u_int8_t sdst[2]; /* second destination address */
u_int8_t invert;
#define EXCHANGE_MEDIUM_INV1 0x01
#define EXCHANGE_MEDIUM_INV2 0x02
u_int8_t control;
};
/*
* Cause the medium changer to check all elements for medium and any
* other status relevant to the element.
*/
struct scsi_initialize_element_status {
u_int8_t opcode;
#define INITIALIZE_ELEMENT_STATUS 0x07
u_int8_t byte2;
u_int8_t reserved[3];
u_int8_t control;
};
/*
* Request the changer to move a unit of media from the source element
* to the destination element.
*/
struct scsi_move_medium {
u_int8_t opcode;
#define MOVE_MEDIUM 0xa5
u_int8_t byte2;
u_int8_t tea[2]; /* transport element address */
u_int8_t src[2]; /* source element address */
u_int8_t dst[2]; /* destination element address */
u_int8_t reserved[2];
u_int8_t invert;
#define MOVE_MEDIUM_INVERT 0x01
u_int8_t control;
};
/*
* Position the specified transport element (picker) in front of
* the destination element specified.
*/
struct scsi_position_to_element {
u_int8_t opcode;
#define POSITION_TO_ELEMENT 0x2b
u_int8_t byte2;
u_int8_t tea[2]; /* transport element address */
u_int8_t dst[2]; /* destination element address */
u_int8_t reserved[2];
u_int8_t invert;
#define POSITION_TO_ELEMENT_INVERT 0x01
u_int8_t control;
};
/*
* Request that the changer report the status of its internal elements.
*/
struct scsi_read_element_status {
u_int8_t opcode;
#define READ_ELEMENT_STATUS 0xb8
u_int8_t byte2;
#define READ_ELEMENT_STATUS_VOLTAG 0x10 /* report volume tag info */
/* ...next 4 bits are an element type code... */
u_int8_t sea[2]; /* starting element address */
u_int8_t count[2]; /* number of elements */
u_int8_t reserved0;
u_int8_t len[3]; /* length of data buffer */
u_int8_t reserved1;
u_int8_t control;
};
struct scsi_request_volume_element_address {
u_int8_t opcode;
#define REQUEST_VOLUME_ELEMENT_ADDRESS 0xb5
u_int8_t byte2;
#define REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG 0x10
/* ...next 4 bits are an element type code... */
u_int8_t eaddr[2]; /* element address */
u_int8_t count[2]; /* number of elements */
u_int8_t reserved0;
u_int8_t len[3]; /* length of data buffer */
u_int8_t reserved1;
u_int8_t control;
};
/* XXX scsi_release */
/*
* Changer-specific mode page numbers.
*/
#define CH_ELEMENT_ADDR_ASSIGN_PAGE 0x1D
#define CH_TRANS_GEOM_PARAMS_PAGE 0x1E
#define CH_DEVICE_CAP_PAGE 0x1F
/*
* Data returned by READ ELEMENT STATUS consists of an 8-byte header
* followed by one or more read_element_status_pages.
*/
struct read_element_status_header {
u_int8_t fear[2]; /* first element address reported */
u_int8_t count[2]; /* number of elements available */
u_int8_t reserved;
u_int8_t nbytes[3]; /* byte count of all pages */
};
struct read_element_status_page_header {
u_int8_t type; /* element type code; see type codes below */
u_int8_t flags;
#define READ_ELEMENT_STATUS_AVOLTAG 0x40
#define READ_ELEMENT_STATUS_PVOLTAG 0x80
u_int8_t edl[2]; /* element descriptor length */
u_int8_t reserved;
u_int8_t nbytes[3]; /* byte count of all descriptors */
};
/*
* Format of a volume tag
*/
struct volume_tag {
u_int8_t vif[32]; /* volume identification field */
u_int8_t reserved[2];
u_int8_t vsn[2]; /* volume sequence number */
};
struct read_element_status_descriptor {
u_int8_t eaddr[2]; /* element address */
u_int8_t flags1;
#define READ_ELEMENT_STATUS_FULL 0x01
#define READ_ELEMENT_STATUS_IMPEXP 0x02
#define READ_ELEMENT_STATUS_EXCEPT 0x04
#define READ_ELEMENT_STATUS_ACCESS 0x08
#define READ_ELEMENT_STATUS_EXENAB 0x10
#define READ_ELEMENT_STATUS_INENAB 0x20
#define READ_ELEMENT_STATUS_MT_MASK1 0x05
#define READ_ELEMENT_STATUS_ST_MASK1 0x0c
#define READ_ELEMENT_STATUS_IE_MASK1 0x3f
#define READ_ELEMENT_STATUS_DT_MASK1 0x0c
u_int8_t reserved0;
u_int8_t sense_code;
u_int8_t sense_qual;
/*
* dt_scsi_flags and dt_scsi_addr are valid only on data transport
* elements. These bytes are undefined for all other element types.
*/
u_int8_t dt_scsi_flags;
#define READ_ELEMENT_STATUS_DT_LUNMASK 0x07
#define READ_ELEMENT_STATUS_DT_LUVALID 0x10
#define READ_ELEMENT_STATUS_DT_IDVALID 0x20
#define READ_ELEMENT_STATUS_DT_NOTBUS 0x80
u_int8_t dt_scsi_addr;
u_int8_t reserved1;
u_int8_t flags2;
#define READ_ELEMENT_STATUS_INVERT 0x40
#define READ_ELEMENT_STATUS_SVALID 0x80
u_int8_t ssea[2]; /* source storage element address */
struct volume_tag pvoltag; /* omitted if PVOLTAG == 0 */
struct volume_tag avoltag; /* omitted if AVOLTAG == 0 */
/* Other data may follow */
};
/* XXX add data returned by REQUEST VOLUME ELEMENT ADDRESS */
/* Element type codes */
#define ELEMENT_TYPE_MASK 0x0f /* Note: these aren't bits */
#define ELEMENT_TYPE_ALL 0x00
#define ELEMENT_TYPE_MT 0x01
#define ELEMENT_TYPE_ST 0x02
#define ELEMENT_TYPE_IE 0x03
#define ELEMENT_TYPE_DT 0x04
/*
* XXX The following definitions should be common to all SCSI device types.
*/
#define PGCODE_MASK 0x3f /* valid page number bits in pg_code */
#define PGCODE_PS 0x80 /* indicates page is savable */
/*
* Send volume tag information to the changer
*/
struct scsi_send_volume_tag {
u_int8_t opcode;
#define SEND_VOLUME_TAG 0xb6
u_int8_t byte2;
u_int8_t ea[2]; /* element address */
u_int8_t reserved2;
u_int8_t sac; /* send action code */
#define SEND_VOLUME_TAG_ASSERT_PRIMARY 0x08
#define SEND_VOLUME_TAG_ASSERT_ALTERNATE 0x09
#define SEND_VOLUME_TAG_REPLACE_PRIMARY 0x0a
#define SEND_VOLUME_TAG_REPLACE_ALTERNATE 0x0b
#define SEND_VOLUME_TAG_UNDEFINED_PRIMARY 0x0c
#define SEND_VOLUME_TAG_UNDEFINED_ALTERNATE 0x0d
u_int8_t reserved4[2];
u_int8_t pll[2]; /* parameter list length */
u_int8_t reserved5;
u_int8_t control;
};
/*
* Parameter format for SEND VOLUME TAG
*/
struct scsi_send_volume_tag_parameters {
u_int8_t vitf[32]; /* volume tag identification template */
u_int8_t reserved1[2];
u_int8_t minvsn[2]; /* minimum volume sequence number */
u_int8_t reserved2[2];
u_int8_t maxvsn[2]; /* maximum volume sequence number */
};
/*
* Device capabilities page.
*
* This page defines characteristics of the elemenet types in the
* medium changer device.
*
* Note in the definitions below, the following abbreviations are
* used:
* MT Medium transport element (picker)
* ST Storage transport element (slot)
* IE Import/export element (portal)
* DT Data tranfer element (tape/disk drive)
*/
struct page_device_capabilities {
u_int8_t pg_code; /* page code (0x1f) */
u_int8_t pg_length; /* page length (0x12) */
/*
* The STOR_xx bits indicate that an element of a given
* type may provide independent storage for a unit of
* media. The top four bits of this value are reserved.
*/
u_int8_t stor;
#define STOR_MT 0x01
#define STOR_ST 0x02
#define STOR_IE 0x04
#define STOR_DT 0x08
u_int8_t reserved0;
/*
* The MOVE_TO_yy bits indicate the changer supports
* moving a unit of medium from an element of a given type to an
* element of type yy. This is used to determine if a given
* MOVE MEDIUM command is legal. The top four bits of each
* of these values are reserved.
*/
u_int8_t move_from_mt;
u_int8_t move_from_st;
u_int8_t move_from_ie;
u_int8_t move_from_dt;
#define MOVE_TO_MT 0x01
#define MOVE_TO_ST 0x02
#define MOVE_TO_IE 0x04
#define MOVE_TO_DT 0x08
u_int8_t reserved1[4];
/*
* Similar to above, but for EXCHANGE MEDIUM.
*/
u_int8_t exchange_with_mt;
u_int8_t exchange_with_st;
u_int8_t exchange_with_ie;
u_int8_t exchange_with_dt;
#define EXCHANGE_WITH_MT 0x01
#define EXCHANGE_WITH_ST 0x02
#define EXCHANGE_WITH_IE 0x04
#define EXCHANGE_WITH_DT 0x08
};
/*
* Medium changer elemement address assignment page.
*
* Some of these fields can be a little confusing, so an explanation
* is in order.
*
* Each component within a a medium changer apparatus is called an
* "element".
*
* The "medium transport element address" is the address of the first
* picker (robotic arm). "Number of medium transport elements" tells
* us how many pickers exist in the changer.
*
* The "first storage element address" is the address of the first
* slot in the tape or disk magazine. "Number of storage elements" tells
* us how many slots exist in the changer.
*
* The "first import/export element address" is the address of the first
* medium portal accessible both by the medium changer and an outside
* human operator. This is where the changer might deposit tapes destined
* for some vault. The "number of import/export elements" tells us
* not many of these portals exist in the changer. NOTE: this number may
* be 0.
*
* The "first data transfer element address" is the address of the first
* tape or disk drive in the changer. "Number of data transfer elements"
* tells us how many drives exist in the changer.
*/
struct page_element_address_assignment {
u_int8_t pg_code; /* page code (0x1d) */
u_int8_t pg_length; /* page length (0x12) */
/* Medium transport element address */
u_int8_t mtea[2];
/* Number of medium transport elements */
u_int8_t nmte[2];
/* First storage element address */
u_int8_t fsea[2];
/* Number of storage elements */
u_int8_t nse[2];
/* First import/export element address */
u_int8_t fieea[2];
/* Number of import/export elements */
u_int8_t niee[2];
/* First data transfer element address */
u_int8_t fdtea[2];
/* Number of data trafer elements */
u_int8_t ndte[2];
u_int8_t reserved[2];
};
/*
* Transport geometry parameters page.
*
* Defines whether each medium transport element is a member of a set of
* elements that share a common robotics subsystem and whether the element
* is capable of media rotation. One transport geometry descriptor is
* transferred for each medium transport element, beginning with the first
* medium transport element (other than the default transport element address
* of 0).
*/
struct page_transport_geometry_parameters {
u_int8_t pg_code; /* page code (0x1e) */
u_int8_t pg_length; /* page length; variable */
/* Transport geometry descriptor(s) are here. */
u_int8_t misc;
#define CAN_ROTATE 0x01
/* Member number in transport element set. */
u_int8_t member;
};
__BEGIN_DECLS
void scsi_move_medium(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
u_int8_t tag_action, u_int32_t tea, u_int32_t src,
u_int32_t dst, int invert, u_int8_t sense_len,
u_int32_t timeout);
void scsi_exchange_medium(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
u_int8_t tag_action, u_int32_t tea, u_int32_t src,
u_int32_t dst1, u_int32_t dst2, int invert1,
int invert2, u_int8_t sense_len, u_int32_t timeout);
void scsi_position_to_element(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
u_int8_t tag_action, u_int32_t tea, u_int32_t dst,
int invert, u_int8_t sense_len,
u_int32_t timeout);
void scsi_read_element_status(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
u_int8_t tag_action, int voltag, u_int32_t sea,
u_int32_t count, u_int8_t *data_ptr,
u_int32_t dxfer_len, u_int8_t sense_len,
u_int32_t timeout);
void scsi_initialize_element_status(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
u_int8_t tag_action, u_int8_t sense_len,
u_int32_t timeout);
void scsi_send_volume_tag(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
u_int8_t tag_action,
u_int16_t element_address,
u_int8_t send_action_code,
struct scsi_send_volume_tag_parameters *parameters,
u_int8_t sense_len, u_int32_t timeout);
__END_DECLS
#endif /* _SCSI_SCSI_CH_H */
|