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
smc_scsi_xa(struct smc_ctrl_block * smc)42 int smc_scsi_xa(struct smc_ctrl_block* smc)
43 {
44 int try
45 = 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, "SCSI attn s0=%x asq=%x,%x cmd=%x info=%lx",
86 sense_data[0], asc, ascq, cmd, info);
87
88 rc = 1;
89 } else {
90 strcpy(smc->errmsg, "SCSI check condition");
91 rc = 1;
92 break; /* don't retry, investigate */
93 }
94 }
95
96 if (!rc) rc = -1;
97 return rc;
98 }
99
100
101 #define SINQ_MEDIA_CHANGER 0x08
102
smc_inquire(struct smc_ctrl_block * smc)103 int smc_inquire(struct smc_ctrl_block* smc)
104 {
105 struct smc_scsi_req* sr = &smc->scsi_req;
106 unsigned char data[128];
107 int rc;
108 int i;
109
110 bzero(sr, sizeof *sr);
111 bzero(data, sizeof data);
112
113 sr->n_cmd = 6;
114 sr->cmd[0] = SCSI_CMD_INQUIRY;
115 sr->cmd[4] = sizeof data; /* allocation length */
116
117 sr->data = data;
118 sr->n_data_avail = sizeof data;
119 sr->data_dir = SMCSR_DD_IN;
120
121 rc = smc_scsi_xa(smc);
122 if (rc != 0) return rc;
123
124 if (data[0] != SINQ_MEDIA_CHANGER) {
125 strcpy(smc->errmsg, "Not a media changer");
126 return -1;
127 }
128
129 for (i = 28 - 1; i >= 0; i--) {
130 int c = data[8 + i];
131
132 if (c != ' ') break;
133 }
134
135 for (; i >= 0; i--) {
136 int c = data[8 + i];
137
138 if (!(' ' <= c && c < 0x7F)) c = '*';
139 smc->ident[i] = c;
140 }
141
142 return 0;
143 }
144
smc_test_unit_ready(struct smc_ctrl_block * smc)145 int smc_test_unit_ready(struct smc_ctrl_block* smc)
146 {
147 struct smc_scsi_req* sr = &smc->scsi_req;
148 int rc;
149
150 bzero(sr, sizeof *sr);
151
152 sr->n_cmd = 6;
153 sr->cmd[0] = SCSI_CMD_TEST_UNIT_READY;
154
155 rc = smc_scsi_xa(smc);
156
157 return rc;
158 }
159
smc_get_elem_aa(struct smc_ctrl_block * smc)160 int smc_get_elem_aa(struct smc_ctrl_block* smc)
161 {
162 struct smc_scsi_req* sr = &smc->scsi_req;
163 unsigned char data[256];
164 int rc;
165
166 bzero(sr, sizeof *sr);
167 bzero(data, sizeof data);
168 bzero(&smc->elem_aa, sizeof smc->elem_aa);
169 smc->valid_elem_aa = 0;
170
171 sr->n_cmd = 6;
172 sr->cmd[0] = SCSI_CMD_MODE_SENSE_6;
173 sr->cmd[1] = 0x08; /* DBD */
174 sr->cmd[2] = 0x1D; /* current elem addrs */
175 sr->cmd[3] = 0; /* reserved */
176 sr->cmd[4] = 255; /* allocation length */
177 sr->cmd[5] = 0; /* reserved */
178
179 sr->data = data;
180 sr->n_data_avail = 255;
181 sr->data_dir = SMCSR_DD_IN;
182
183 rc = smc_scsi_xa(smc);
184 if (rc != 0) return rc;
185
186 if (data[0] < 18) {
187 strcpy(smc->errmsg, "short sense data");
188 return -1;
189 }
190
191
192 rc = smc_parse_element_address_assignment((void*)&data[4], &smc->elem_aa);
193 if (rc) {
194 strcpy(smc->errmsg, "elem_addr_assignment format error");
195 return -1;
196 }
197
198 smc->valid_elem_aa = 1;
199
200 return 0;
201 }
202
203 /*
204 * 17.2.2 INITIALIZE ELEMENT STATUS command
205 *
206 * The INITIALIZE ELEMENT STATUS command (see table 329) will cause the
207 * medium changer to check all elements for medium and any other status
208 * relevant to that element. The intent of this command is to enable the
209 * initiator to get a quick response from a following READ ELEMENT STATUS
210 * command. It may be useful to issue this command after a power failure,
211 * or if medium has been changed by an operator, or if configurations have
212 * been changed.
213 *
214 * Table 329 - INITIALIZE ELEMENT STATUS command
215 * +====-=======-========-========-========-========-========-========-======+
216 * | Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
217 * |Byte| | | | | | | | |
218 * |====+====================================================================|
219 * | 0 | Operation code (07h) |
220 * |----+--------------------------------------------------------------------|
221 * | 1 |Logical unit number | Reserved |
222 * |----+--------------------------------------------------------------------|
223 * | 2 | Reserved |
224 * |----+--------------------------------------------------------------------|
225 * | 3 | Reserved |
226 * |----+--------------------------------------------------------------------|
227 * | 4 | Reserved |
228 * |----+--------------------------------------------------------------------|
229 * | 5 | Control |
230 * +=========================================================================+
231 */
232
233
smc_init_elem_status(struct smc_ctrl_block * smc)234 int smc_init_elem_status(struct smc_ctrl_block* smc)
235 {
236 struct smc_scsi_req* sr = &smc->scsi_req;
237 int rc;
238
239 bzero(sr, sizeof *sr);
240
241 sr->n_cmd = 6;
242 sr->cmd[0] = SCSI_CMD_INITIALIZE_ELEMENT_STATUS;
243
244 sr->data_dir = SMCSR_DD_NONE;
245
246 rc = smc_scsi_xa(smc);
247 if (rc != 0) return rc;
248
249 return 0;
250 }
251
252
253 /*
254 * 17.2.5 READ ELEMENT STATUS command
255 *
256 * The READ ELEMENT STATUS command (see table 332) requests that the
257 * target report the status of its internal elements to the initiator.
258 *
259 * Table 332 - READ ELEMENT STATUS command
260 * +====-=======-========-========-========-========-========-========-=======+
261 * | Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
262 * |Byte| | | | | | | | |
263 * |====+=====================================================================|
264 * | 0 | Operation code (B8h) |
265 * |----+---------------------------------------------------------------------|
266 * | 1 |Logical unit number | VolTag | Element type code |
267 * |----+---------------------------------------------------------------------|
268 * | 2 |(MSB) |
269 * |----+-- Starting element address --|
270 * | 3 | (LSB)|
271 * |----+---------------------------------------------------------------------|
272 * | 4 |(MSB) |
273 * |----+-- Number of elements --|
274 * | 5 | (LSB)|
275 * |----+---------------------------------------------------------------------|
276 * | 6 | Reserved |
277 * |----+---------------------------------------------------------------------|
278 * | 7 |(MSB) |
279 * |----+-- --|
280 * | 8 | Allocation length |
281 * |----+-- --|
282 * | 9 | (LSB)|
283 * |----+---------------------------------------------------------------------|
284 * |10 | Reserved |
285 * |----+---------------------------------------------------------------------|
286 * |11 | Control |
287 * +==========================================================================+
288 *
289 *
290 * A volume tag (VolTag) bit of one indicates that the target shall report
291 * volume tag information if this feature is supported. A value of zero
292 * indicates that volume tag information shall not be reported. If the
293 * volume tag feature is not supported this field shall be treated as
294 * reserved.
295 *
296 * The element type code field specifies the particular element type(s)
297 * selected for reporting by this command. A value of zero specifies that
298 * status for all element types shall be reported. The element type codes
299 * are defined in table 333.
300 *
301 * Table 333 - Element type code
302 * +=============-===================================================+
303 * | Code | Description |
304 * |-------------+---------------------------------------------------|
305 * | 0h | All element types reported, (valid in CDB only) |
306 * | 1h | Medium transport element |
307 * | 2h | Storage element |
308 * | 3h | Import export element |
309 * | 4h | Data transfer element |
310 * | 5h - Fh | Reserved |
311 * +=================================================================+
312 *
313 *
314 * The starting element address specifies the minimum element address to
315 * report. Only elements with an element type code permitted by the
316 * element type code specification, and an element address greater than or
317 * equal to the starting element address shall be reported. Element
318 * descriptor blocks are not generated for undefined element addresses.
319 *
320 * The number of elements specifies the maximum number of element
321 * descriptors to be created by the target for this command. The value
322 * specified by this field is not the range of element addresses to be
323 * considered for reporting but rather the number of defined elements to
324 * report. If the allocation length is not sufficient to transfer all the
325 * element descriptors, the target shall transfer all those descriptors
326 * that can be completely transferred and this shall not be considered an
327 * error.
328 */
329
smc_read_elem_status(struct smc_ctrl_block * smc)330 int smc_read_elem_status(struct smc_ctrl_block* smc)
331 {
332 struct smc_scsi_req* sr = &smc->scsi_req;
333 unsigned char data[SMC_PAGE_LEN];
334 int rc;
335
336 retry:
337 bzero(sr, sizeof *sr);
338 bzero(data, sizeof data);
339 smc_cleanup_element_status_data(smc);
340 smc->n_elem_desc = 0;
341 smc->valid_elem_desc = 0;
342
343 sr->n_cmd = 12;
344 sr->cmd[0] = SCSI_CMD_READ_ELEMENT_STATUS;
345 if (!smc->dont_ask_for_voltags) {
346 sr->cmd[1] = 0x10; /* VolTag, all types */
347 } else {
348 sr->cmd[1] = 0x00; /* !VolTag, all types */
349 }
350 sr->cmd[2] = 0; /* starting elem MSB */
351 sr->cmd[3] = 0; /* starting elem LSB */
352 sr->cmd[4] = (SMC_MAX_ELEMENT >> 8) & 0xff; /* number of elem MSB */
353 sr->cmd[5] = (SMC_MAX_ELEMENT)&0xff; /* number of elem LSB */
354 sr->cmd[6] = 0; /* reserved */
355 SMC_PUT3(&sr->cmd[7], sizeof data);
356 sr->cmd[10] = 0; /* reserved */
357
358 sr->data = data;
359 sr->n_data_avail = sizeof data;
360 sr->data_dir = SMCSR_DD_IN;
361
362 rc = smc_scsi_xa(smc);
363 if (rc != 0) {
364 if (smc->dont_ask_for_voltags) return rc;
365 smc->dont_ask_for_voltags = 1;
366 goto retry;
367 }
368
369 rc = smc_parse_element_status_data((void*)data, sr->n_data_done, smc,
370 SMC_MAX_ELEMENT);
371 if (rc < 0) {
372 strcpy(smc->errmsg, "elem_status format error");
373 return -1;
374 }
375
376 smc->n_elem_desc = rc;
377
378 smc->valid_elem_aa = 1;
379
380 return 0;
381 }
382
383
smc_move(struct smc_ctrl_block * smc,unsigned from_addr,unsigned to_addr,int invert,unsigned chs_addr)384 int smc_move(struct smc_ctrl_block* smc,
385 unsigned from_addr,
386 unsigned to_addr,
387 int invert,
388 unsigned chs_addr)
389 {
390 struct smc_scsi_req* sr = &smc->scsi_req;
391 int rc;
392
393 bzero(sr, sizeof *sr);
394
395 sr->n_cmd = 12;
396 sr->cmd[0] = SCSI_CMD_MOVE_MEDIUM;
397 SMC_PUT2(&sr->cmd[2], chs_addr);
398 SMC_PUT2(&sr->cmd[4], from_addr);
399 SMC_PUT2(&sr->cmd[6], to_addr);
400 /* TODO: invert */
401
402 sr->data_dir = SMCSR_DD_NONE;
403
404 rc = smc_scsi_xa(smc);
405 if (rc != 0) return rc;
406
407 return 0;
408 }
409
smc_position(struct smc_ctrl_block * smc,unsigned to_addr,int invert)410 int smc_position(struct smc_ctrl_block* smc, unsigned to_addr, int invert)
411 {
412 return -1;
413 }
414
415
smc_handy_move_to_drive(struct smc_ctrl_block * smc,unsigned from_se_ix)416 int smc_handy_move_to_drive(struct smc_ctrl_block* smc, unsigned from_se_ix)
417 {
418 return -1;
419 }
420
smc_handy_move_from_drive(struct smc_ctrl_block * smc,unsigned to_se_ix)421 int smc_handy_move_from_drive(struct smc_ctrl_block* smc, unsigned to_se_ix)
422 {
423 return -1;
424 }
425