1 /*
2 * Copyright (c) 1998,1999,2000
3 * Traakan, Inc., Los Altos, CA
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
11 * disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 /*
30 * Project: NDMJOB
31 * Ident: $Id: $
32 *
33 * Description:
34 *
35 */
36
37
38 #include "smc_priv.h"
39 #include "scsiconst.h"
40
41
42 int
smc_scsi_xa(struct smc_ctrl_block * smc)43 smc_scsi_xa (struct smc_ctrl_block *smc)
44 {
45 int try = 0;
46 int rc;
47 int sense_key;
48 unsigned char * sense_data = smc->scsi_req.sense_data;
49
50 for (try = 0; try < 2; try++) {
51 rc = (*smc->issue_scsi_req)(smc);
52 if (rc || smc->scsi_req.completion_status != SMCSR_CS_GOOD) {
53 strcpy (smc->errmsg, "SCSI request failed");
54 if (rc == 0) rc = -1;
55 continue; /* retry */
56 }
57
58 switch (SCSI_STATUS_BYTE_CODE(smc->scsi_req.status_byte)) {
59 case SCSI_STATUS_GOOD:
60 return 0;
61
62 case SCSI_STATUS_CHECK_CONDITION:
63 /* sense data processed below */
64 break;
65
66 default:
67 strcpy (smc->errmsg, "SCSI unexpected status");
68 return -1;
69 }
70
71 sense_key = sense_data[2] & SCSI_SENSE_SENSE_KEY_MASK;
72
73 if (sense_key == SCSI_SENSE_KEY_UNIT_ATTENTION) {
74 int valid;
75 int asc, ascq, asq, cmd;
76 long info;
77
78 valid = sense_data[0] & SCSI_SENSE_VALID_BIT;
79 info = SMC_GET4(&sense_data[3]);
80 asc = sense_data[12];
81 ascq = sense_data[13];
82 asq = _ASQ(asc,ascq);
83 cmd = smc->scsi_req.cmd[0];
84
85 sprintf (smc->errmsg,
86 "SCSI attn s0=%x asq=%x,%x cmd=%x info=%lx",
87 sense_data[0],
88 asc, ascq, cmd, info);
89
90 rc = 1;
91 } else {
92 strcpy (smc->errmsg, "SCSI check condition");
93 rc = 1;
94 break; /* don't retry, investigate */
95 }
96 }
97
98 if (!rc) rc = -1;
99 return rc;
100 }
101
102
103 #define SINQ_MEDIA_CHANGER 0x08
104
105 int
smc_inquire(struct smc_ctrl_block * smc)106 smc_inquire (struct smc_ctrl_block *smc)
107 {
108 struct smc_scsi_req * sr = &smc->scsi_req;
109 unsigned char data[128];
110 int rc;
111 int i;
112
113 bzero (sr, sizeof *sr);
114 bzero (data, sizeof data);
115
116 sr->n_cmd = 6;
117 sr->cmd[0] = SCSI_CMD_INQUIRY;
118 sr->cmd[4] = sizeof data; /* allocation length */
119
120 sr->data = data;
121 sr->n_data_avail = sizeof data;
122 sr->data_dir = SMCSR_DD_IN;
123
124 rc = smc_scsi_xa (smc);
125 if (rc != 0) return rc;
126
127 if (data[0] != SINQ_MEDIA_CHANGER) {
128 strcpy (smc->errmsg, "Not a media changer");
129 return -1;
130 }
131
132 for (i = 28-1; i >= 0; i--) {
133 int c = data[8+i];
134
135 if (c != ' ')
136 break;
137 }
138
139 for (; i >= 0; i--) {
140 int c = data[8+i];
141
142 if (! (' ' <= c && c < 0x7F))
143 c = '*';
144 smc->ident[i] = c;
145 }
146
147 return 0;
148 }
149
150 int
smc_test_unit_ready(struct smc_ctrl_block * smc)151 smc_test_unit_ready (struct smc_ctrl_block *smc)
152 {
153 struct smc_scsi_req * sr = &smc->scsi_req;
154 int rc;
155
156 bzero (sr, sizeof *sr);
157
158 sr->n_cmd = 6;
159 sr->cmd[0] = SCSI_CMD_TEST_UNIT_READY;
160
161 rc = smc_scsi_xa (smc);
162
163 return rc;
164 }
165
166 int
smc_get_elem_aa(struct smc_ctrl_block * smc)167 smc_get_elem_aa (struct smc_ctrl_block *smc)
168 {
169 struct smc_scsi_req * sr = &smc->scsi_req;
170 unsigned char data[256];
171 int rc;
172
173 bzero (sr, sizeof *sr);
174 bzero (data, sizeof data);
175 bzero (&smc->elem_aa, sizeof smc->elem_aa);
176 smc->valid_elem_aa = 0;
177
178 sr->n_cmd = 6;
179 sr->cmd[0] = SCSI_CMD_MODE_SENSE_6;
180 sr->cmd[1] = 0x08; /* DBD */
181 sr->cmd[2] = 0x1D; /* current elem addrs */
182 sr->cmd[3] = 0; /* reserved */
183 sr->cmd[4] = 255; /* allocation length */
184 sr->cmd[5] = 0; /* reserved */
185
186 sr->data = data;
187 sr->n_data_avail = 255;
188 sr->data_dir = SMCSR_DD_IN;
189
190 rc = smc_scsi_xa (smc);
191 if (rc != 0) return rc;
192
193 if (data[0] < 18) {
194 strcpy (smc->errmsg, "short sense data");
195 return -1;
196 }
197
198
199 rc = smc_parse_element_address_assignment ((void*)&data[4],
200 &smc->elem_aa);
201 if (rc) {
202 strcpy (smc->errmsg, "elem_addr_assignment format error");
203 return -1;
204 }
205
206 smc->valid_elem_aa = 1;
207
208 return 0;
209 }
210
211 /*
212 * 17.2.2 INITIALIZE ELEMENT STATUS command
213 *
214 * The INITIALIZE ELEMENT STATUS command (see table 329) will cause the
215 * medium changer to check all elements for medium and any other status
216 * relevant to that element. The intent of this command is to enable the
217 * initiator to get a quick response from a following READ ELEMENT STATUS
218 * command. It may be useful to issue this command after a power failure,
219 * or if medium has been changed by an operator, or if configurations have
220 * been changed.
221 *
222 * Table 329 - INITIALIZE ELEMENT STATUS command
223 * +====-=======-========-========-========-========-========-========-======+
224 * | Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
225 * |Byte| | | | | | | | |
226 * |====+====================================================================|
227 * | 0 | Operation code (07h) |
228 * |----+--------------------------------------------------------------------|
229 * | 1 |Logical unit number | Reserved |
230 * |----+--------------------------------------------------------------------|
231 * | 2 | Reserved |
232 * |----+--------------------------------------------------------------------|
233 * | 3 | Reserved |
234 * |----+--------------------------------------------------------------------|
235 * | 4 | Reserved |
236 * |----+--------------------------------------------------------------------|
237 * | 5 | Control |
238 * +=========================================================================+
239 */
240
241
242 int
smc_init_elem_status(struct smc_ctrl_block * smc)243 smc_init_elem_status (struct smc_ctrl_block *smc)
244 {
245 struct smc_scsi_req * sr = &smc->scsi_req;
246 int rc;
247
248 bzero (sr, sizeof *sr);
249
250 sr->n_cmd = 6;
251 sr->cmd[0] = SCSI_CMD_INITIALIZE_ELEMENT_STATUS;
252
253 sr->data_dir = SMCSR_DD_NONE;
254
255 rc = smc_scsi_xa (smc);
256 if (rc != 0) return rc;
257
258 return 0;
259 }
260
261
262
263 /*
264 * 17.2.5 READ ELEMENT STATUS command
265 *
266 * The READ ELEMENT STATUS command (see table 332) requests that the
267 * target report the status of its internal elements to the initiator.
268 *
269 * Table 332 - READ ELEMENT STATUS command
270 * +====-=======-========-========-========-========-========-========-=======+
271 * | Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
272 * |Byte| | | | | | | | |
273 * |====+=====================================================================|
274 * | 0 | Operation code (B8h) |
275 * |----+---------------------------------------------------------------------|
276 * | 1 |Logical unit number | VolTag | Element type code |
277 * |----+---------------------------------------------------------------------|
278 * | 2 |(MSB) |
279 * |----+-- Starting element address --|
280 * | 3 | (LSB)|
281 * |----+---------------------------------------------------------------------|
282 * | 4 |(MSB) |
283 * |----+-- Number of elements --|
284 * | 5 | (LSB)|
285 * |----+---------------------------------------------------------------------|
286 * | 6 | Reserved |
287 * |----+---------------------------------------------------------------------|
288 * | 7 |(MSB) |
289 * |----+-- --|
290 * | 8 | Allocation length |
291 * |----+-- --|
292 * | 9 | (LSB)|
293 * |----+---------------------------------------------------------------------|
294 * |10 | Reserved |
295 * |----+---------------------------------------------------------------------|
296 * |11 | Control |
297 * +==========================================================================+
298 *
299 *
300 * A volume tag (VolTag) bit of one indicates that the target shall report
301 * volume tag information if this feature is supported. A value of zero
302 * indicates that volume tag information shall not be reported. If the
303 * volume tag feature is not supported this field shall be treated as
304 * reserved.
305 *
306 * The element type code field specifies the particular element type(s)
307 * selected for reporting by this command. A value of zero specifies that
308 * status for all element types shall be reported. The element type codes
309 * are defined in table 333.
310 *
311 * Table 333 - Element type code
312 * +=============-===================================================+
313 * | Code | Description |
314 * |-------------+---------------------------------------------------|
315 * | 0h | All element types reported, (valid in CDB only) |
316 * | 1h | Medium transport element |
317 * | 2h | Storage element |
318 * | 3h | Import export element |
319 * | 4h | Data transfer element |
320 * | 5h - Fh | Reserved |
321 * +=================================================================+
322 *
323 *
324 * The starting element address specifies the minimum element address to
325 * report. Only elements with an element type code permitted by the
326 * element type code specification, and an element address greater than or
327 * equal to the starting element address shall be reported. Element
328 * descriptor blocks are not generated for undefined element addresses.
329 *
330 * The number of elements specifies the maximum number of element
331 * descriptors to be created by the target for this command. The value
332 * specified by this field is not the range of element addresses to be
333 * considered for reporting but rather the number of defined elements to
334 * report. If the allocation length is not sufficient to transfer all the
335 * element descriptors, the target shall transfer all those descriptors
336 * that can be completely transferred and this shall not be considered an
337 * error.
338 */
339
340 int
smc_read_elem_status(struct smc_ctrl_block * smc)341 smc_read_elem_status (struct smc_ctrl_block *smc)
342 {
343 struct smc_scsi_req * sr = &smc->scsi_req;
344 unsigned char data[SMC_PAGE_LEN];
345 int rc;
346
347 retry:
348 bzero (sr, sizeof *sr);
349 bzero (data, sizeof data);
350 smc_cleanup_element_status_data(smc);
351 smc->n_elem_desc = 0;
352 smc->valid_elem_desc = 0;
353
354 sr->n_cmd = 12;
355 sr->cmd[0] = SCSI_CMD_READ_ELEMENT_STATUS;
356 if (!smc->dont_ask_for_voltags) {
357 sr->cmd[1] = 0x10; /* VolTag, all types */
358 } else {
359 sr->cmd[1] = 0x00; /* !VolTag, all types */
360 }
361 sr->cmd[2] = 0; /* starting elem MSB */
362 sr->cmd[3] = 0; /* starting elem LSB */
363 sr->cmd[4] = (SMC_MAX_ELEMENT >> 8) & 0xff;/* number of elem MSB */
364 sr->cmd[5] = (SMC_MAX_ELEMENT) & 0xff; /* number of elem LSB */
365 sr->cmd[6] = 0; /* reserved */
366 SMC_PUT3 (&sr->cmd[7], sizeof data);
367 sr->cmd[10] = 0; /* reserved */
368
369 sr->data = data;
370 sr->n_data_avail = sizeof data;
371 sr->data_dir = SMCSR_DD_IN;
372
373 rc = smc_scsi_xa (smc);
374 if (rc != 0) {
375 if (smc->dont_ask_for_voltags)
376 return rc;
377 smc->dont_ask_for_voltags = 1;
378 goto retry;
379 }
380
381 rc = smc_parse_element_status_data ((void*)data, sr->n_data_done,
382 smc, SMC_MAX_ELEMENT);
383 if (rc < 0) {
384 strcpy (smc->errmsg, "elem_status format error");
385 return -1;
386 }
387
388 smc->n_elem_desc = rc;
389
390 smc->valid_elem_aa = 1;
391
392 return 0;
393 }
394
395
396 int
smc_move(struct smc_ctrl_block * smc,unsigned from_addr,unsigned to_addr,int invert,unsigned chs_addr)397 smc_move (struct smc_ctrl_block *smc, unsigned from_addr,
398 unsigned to_addr, int invert, unsigned chs_addr)
399 {
400 struct smc_scsi_req * sr = &smc->scsi_req;
401 int rc;
402
403 bzero (sr, sizeof *sr);
404
405 sr->n_cmd = 12;
406 sr->cmd[0] = SCSI_CMD_MOVE_MEDIUM;
407 SMC_PUT2(&sr->cmd[2], chs_addr);
408 SMC_PUT2(&sr->cmd[4], from_addr);
409 SMC_PUT2(&sr->cmd[6], to_addr);
410 /* TODO: invert */
411
412 sr->data_dir = SMCSR_DD_NONE;
413
414 rc = smc_scsi_xa (smc);
415 if (rc != 0) return rc;
416
417 return 0;
418 }
419
420 int
smc_position(struct smc_ctrl_block * smc,unsigned to_addr,int invert)421 smc_position (struct smc_ctrl_block *smc, unsigned to_addr, int invert)
422 {
423 return -1;
424 }
425
426
427 int
smc_handy_move_to_drive(struct smc_ctrl_block * smc,unsigned from_se_ix)428 smc_handy_move_to_drive (struct smc_ctrl_block *smc, unsigned from_se_ix)
429 {
430 return -1;
431 }
432
433 int
smc_handy_move_from_drive(struct smc_ctrl_block * smc,unsigned to_se_ix)434 smc_handy_move_from_drive (struct smc_ctrl_block *smc, unsigned to_se_ix)
435 {
436 return -1;
437 }
438