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