Annotation of embedaddon/istgt/src/istgt_lu_pass.c, revision 1.1.1.2
1.1 misho 1: /*
1.1.1.2 ! misho 2: * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
1.1 misho 3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17: * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24: * SUCH DAMAGE.
25: *
26: */
27:
28: #ifdef HAVE_CONFIG_H
29: #include "config.h"
30: #endif
31:
32: #include <inttypes.h>
33: #include <stdint.h>
34:
35: #include <stdio.h>
36: #include <string.h>
37: #include <pthread.h>
38:
39: #include <fcntl.h>
40: #include <unistd.h>
41:
42: #ifdef HAVE_LIBCAM
43: #include <camlib.h>
44: #include <cam/cam.h>
45: #include <cam/cam_ccb.h>
46: #include <cam/scsi/scsi_message.h>
47:
48: #include "istgt.h"
49: #include "istgt_ver.h"
50: #include "istgt_log.h"
51: #include "istgt_misc.h"
52: #include "istgt_lu.h"
53: #include "istgt_proto.h"
54: #include "istgt_scsi.h"
55:
1.1.1.2 ! misho 56: #if !defined(__GNUC__)
! 57: #undef __attribute__
! 58: #define __attribute__(x)
! 59: #endif
! 60:
1.1 misho 61: //#define ISTGT_TRACE_PASS
62:
63: #define ISTGT_LU_CAM_TIMEOUT 60000 /* 60sec. */
64:
65: typedef struct istgt_lu_pass_t {
66: ISTGT_LU_Ptr lu;
67: int num;
68: int lun;
69:
70: const char *file;
71: uint64_t size;
72: uint64_t blocklen;
73: uint64_t blockcnt;
74:
75: char *device;
76: int unit;
77: struct cam_device *cam_dev;
78: union ccb *ccb;
79:
80: int timeout;
81:
82: uint8_t *inq_standard;
83: int inq_standard_len;
84: int inq_pd;
85: int inq_rmb;
86: int inq_ver;
87: int inq_fmt;
88: uint64_t ms_blocklen;
89: uint64_t ms_blockcnt;
90: } ISTGT_LU_PASS;
91:
1.1.1.2 ! misho 92: #define BUILD_SENSE(SK,ASC,ASCQ) \
! 93: do { \
! 94: *sense_len = \
! 95: istgt_lu_pass_build_sense_data(spec, sense_data, \
! 96: ISTGT_SCSI_SENSE_ ## SK, \
! 97: (ASC), (ASCQ)); \
1.1 misho 98: } while (0)
99:
100: static int istgt_lu_pass_build_sense_data(ISTGT_LU_PASS *spec, uint8_t *data, int sk, int asc, int ascq);
101:
102: static void
103: istgt_lu_pass_parse_sense_key(uint8_t *sense_data, int *skp, int *ascp, int *ascqp)
104: {
105: int rsp;
106: int sk, asc, ascq;
107:
108: if (sense_data == NULL) {
109: if (skp != NULL)
110: *skp = -1;
111: if (ascp != NULL)
112: *ascp = -1;
113: if (ascqp != NULL)
114: *ascqp = -1;
115: return;
116: }
117:
118: rsp = BGET8W(&sense_data[0], 6, 7);
119: switch (rsp) {
120: case 0x70: /* Current Fixed */
121: sk = BGET8W(&sense_data[2], 3, 4);
122: asc = sense_data[12];
123: ascq = sense_data[13];
124: break;
125: case 0x71: /* Deferred Fixed */
126: sk = BGET8W(&sense_data[2], 3, 4);
127: asc = sense_data[12];
128: ascq = sense_data[13];
129: break;
130: case 0x72: /* Current Descriptor */
131: sk = BGET8W(&sense_data[2], 3, 4);
132: asc = sense_data[2];
133: ascq = sense_data[3];
134: break;
135: case 0x73: /* Deferred Descriptor */
136: sk = BGET8W(&sense_data[2], 3, 4);
137: asc = sense_data[2];
138: ascq = sense_data[3];
139: break;
140: default:
141: sk = asc = ascq = -1;
142: break;
143: }
144:
145: if (skp != NULL)
146: *skp = sk;
147: if (ascp != NULL)
148: *ascp = asc;
149: if (ascqp != NULL)
150: *ascqp = ascq;
151: }
152:
153: static void
154: istgt_lu_pass_print_sense_key(uint8_t *sense_data)
155: {
156: int sk, asc, ascq;
157:
158: istgt_lu_pass_parse_sense_key(sense_data, &sk, &asc, &ascq);
159: if (sk >= 0) {
160: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
1.1.1.2 ! misho 161: "SK=0x%x, ASC=0x%x, ASCQ=0x%x\n",
! 162: sk, asc, ascq);
1.1 misho 163: }
164: }
165:
166: static int
167: istgt_lu_pass_set_inquiry(ISTGT_LU_PASS *spec)
168: {
169: uint8_t buf[MAX_TMPBUF];
170: uint8_t cdb[16];
171: uint32_t flags;
172: uint8_t *data;
173: int cdb_len;
174: int data_len;
175: int data_alloc_len;
176: int retry = 1;
177: int rc;
178:
179: memset(buf, 0, sizeof buf);
180: memset(cdb, 0, sizeof cdb);
181: data = buf;
182: if (sizeof buf > 0xff) {
183: data_alloc_len = 0xff;
184: } else {
185: data_alloc_len = sizeof buf;
186: }
187:
188: /* issue standard INQUIRY */
189: cdb[0] = SPC_INQUIRY;
190: cdb[1] = 0;
191: cdb[2] = 0;
192: DSET16(&cdb[3], data_alloc_len); /* ALLOCATION LENGTH */
193: cdb[5] = 0;
194: cdb_len = 6;
195: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "CDB", cdb, cdb_len);
196:
197: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, cdb, cdb_len);
198: flags = CAM_DIR_IN;
199: flags |= CAM_DEV_QFRZDIS;
200: cam_fill_csio(&spec->ccb->csio, retry, NULL, flags, MSG_SIMPLE_Q_TAG,
1.1.1.2 ! misho 201: data, data_alloc_len, SSD_FULL_SIZE, cdb_len,
! 202: spec->timeout);
1.1 misho 203: rc = cam_send_ccb(spec->cam_dev, spec->ccb);
204: if (rc < 0) {
205: ISTGT_ERRLOG("cam_send_ccb() failed\n");
206: return -1;
207: }
208:
209: if ((spec->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
210: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
1.1.1.2 ! misho 211: "request error CAM=0x%x, SCSI=0x%x\n",
! 212: spec->ccb->ccb_h.status,
! 213: spec->ccb->csio.scsi_status);
1.1 misho 214: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "SENSE",
1.1.1.2 ! misho 215: (uint8_t *) &spec->ccb->csio.sense_data,
! 216: SSD_FULL_SIZE);
1.1 misho 217: istgt_lu_pass_print_sense_key((uint8_t *) &spec->ccb->csio.sense_data);
218: return -1;
219: }
220: data_len = spec->ccb->csio.dxfer_len;
221: data_len -= spec->ccb->csio.resid;
222:
223: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "INQUIRY", data, data_len);
224: spec->inq_standard = xmalloc(data_len);
225: spec->inq_standard_len = data_len;
226: memcpy(spec->inq_standard, data, data_len);
227:
228: return 0;
229: }
230:
231: static int
232: istgt_lu_pass_set_modesense(ISTGT_LU_PASS *spec)
233: {
234: uint8_t buf[MAX_TMPBUF];
235: uint8_t cdb[16];
236: uint32_t flags;
237: uint8_t *data;
238: int cdb_len;
239: int data_len;
240: int data_alloc_len;
241: int req_len;
242: int retry = 1;
243: int sk, asc, ascq;
244: int rc;
245:
246: memset(buf, 0, sizeof buf);
247: memset(cdb, 0, sizeof cdb);
248: data = buf;
249: if (sizeof buf > 0xff) {
250: data_alloc_len = 0xff;
251: } else {
252: data_alloc_len = sizeof buf;
253: }
254:
255: if (spec->inq_pd == SPC_PERIPHERAL_DEVICE_TYPE_DVD) {
256: /* MMC have only 10 */
257: goto retry_sense10;
258: }
259: retry_sense6:
260: spec->ms_blockcnt = 0;
261: spec->ms_blocklen = 0;
262: memset(cdb, 0, sizeof cdb);
263: /* issue MODE SENSE(6) */
264: data_alloc_len = 4 + 8; /* only block descriptor */
265: req_len = 4 + 8;
266: cdb[0] = SPC_MODE_SENSE_6;
267: BDADD8(&cdb[1], 0, 3); /* DBD */
268: BDSET8W(&cdb[2], 0x00, 7, 2); /* PC */
269: //BDADD8W(&cdb[2], 0x00, 5, 6); /* PAGE CODE */
270: BDADD8W(&cdb[2], 0x3f, 5, 6); /* PAGE CODE */
271: cdb[3] = 0x00; /* SUBPAGE CODE */
272: cdb[4] = data_alloc_len; /* ALLOCATION LENGTH */
273: cdb_len = 6;
274: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "CDB", cdb, cdb_len);
275:
276: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, cdb, cdb_len);
277: flags = CAM_DIR_IN;
278: flags |= CAM_DEV_QFRZDIS;
279: cam_fill_csio(&spec->ccb->csio, retry, NULL, flags, MSG_SIMPLE_Q_TAG,
1.1.1.2 ! misho 280: data, data_alloc_len, SSD_FULL_SIZE, cdb_len,
! 281: spec->timeout);
1.1 misho 282: rc = cam_send_ccb(spec->cam_dev, spec->ccb);
283: if (rc < 0) {
284: ISTGT_ERRLOG("cam_send_ccb() failed\n");
285: return -1;
286: }
287:
288: if ((spec->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
289: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
1.1.1.2 ! misho 290: "request error CAM=0x%x, SCSI=0x%x\n",
! 291: spec->ccb->ccb_h.status,
! 292: spec->ccb->csio.scsi_status);
1.1 misho 293: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "SENSE",
1.1.1.2 ! misho 294: (uint8_t *) &spec->ccb->csio.sense_data,
! 295: SSD_FULL_SIZE);
1.1 misho 296: istgt_lu_pass_print_sense_key((uint8_t *) &spec->ccb->csio.sense_data);
297: istgt_lu_pass_parse_sense_key((uint8_t *) &spec->ccb->csio.sense_data,
1.1.1.2 ! misho 298: &sk, &asc, &ascq);
1.1 misho 299: if (sk == ISTGT_SCSI_SENSE_ILLEGAL_REQUEST) {
300: if (asc == 0x20 && ascq == 0x00) {
301: /* INVALID COMMAND OPERATION CODE */
302: goto retry_sense10;
303: } else if (asc == 0x24 && ascq == 0x00) {
304: /* INVALID FIELD IN CDB */
305: goto retry_sense10;
306: }
307: }
308: if (sk == ISTGT_SCSI_SENSE_UNIT_ATTENTION) {
309: if (asc == 0x28 && ascq == 0x00) {
310: /* NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED */
311: goto retry_sense6;
312: }
313: if (asc == 0x29 && ascq == 0x00) {
314: /* POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */
315: goto retry_sense6;
316: } else if (asc == 0x29 && ascq == 0x01) {
317: /* POWER ON OCCURRED */
318: goto retry_sense6;
319: } else if (asc == 0x29 && ascq == 0x02) {
320: /* SCSI BUS RESET OCCURRED */
321: goto retry_sense6;
322: } else if (asc == 0x29 && ascq == 0x03) {
323: /* BUS DEVICE RESET FUNCTION OCCURRED */
324: goto retry_sense6;
325: } else if (asc == 0x29 && ascq == 0x04) {
326: /* DEVICE INTERNAL RESET */
327: goto retry_sense6;
328: } else if (asc == 0x29 && ascq == 0x05) {
329: /* TRANSCEIVER MODE CHANGED TO SINGLE-ENDED */
330: goto retry_sense6;
331: } else if (asc == 0x29 && ascq == 0x06) {
332: /* TRANSCEIVER MODE CHANGED TO LVD */
333: goto retry_sense6;
334: } else if (asc == 0x29 && ascq == 0x07) {
335: /* I_T NEXUS LOSS OCCURRED */
336: goto retry_sense6;
337: }
338: }
339: return -1;
340: }
341: data_len = spec->ccb->csio.dxfer_len;
342: data_len -= spec->ccb->csio.resid;
343: if (data_len < req_len) {
344: ISTGT_ERRLOG("result is short\n");
345: return -1;
346: }
347:
348: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "MODE SENSE(6)", data, data_len);
349: if (DGET8(&data[3]) != 0) { /* BLOCK DESCRIPTOR LENGTH */
350: if (spec->inq_pd == SPC_PERIPHERAL_DEVICE_TYPE_DISK) {
351: spec->ms_blockcnt = DGET32(&data[4+0]);
352: spec->ms_blocklen = DGET24(&data[4+5]);
353: } else {
354: spec->ms_blockcnt = DGET24(&data[4+1]);
355: spec->ms_blocklen = DGET24(&data[4+5]);
356: }
357: } else {
358: goto retry_sense10;
359: }
360:
361: if ((spec->inq_pd == SPC_PERIPHERAL_DEVICE_TYPE_DISK
362: && spec->ms_blockcnt == 0xffffffffU)
363: || (spec->inq_pd != SPC_PERIPHERAL_DEVICE_TYPE_DISK
364: && spec->ms_blockcnt == 0x00ffffffU)) {
365: retry_sense10:
366: spec->ms_blockcnt = 0;
367: spec->ms_blocklen = 0;
368: memset(cdb, 0, sizeof cdb);
369: /* issue MODE SENSE(10) */
370: data_alloc_len = 8 + 16; /* only block descriptor */
371: req_len = 8 + 16;
372: cdb[0] = SPC_MODE_SENSE_10;
373: BDSET8(&cdb[1], 1, 4); /* LLBAA */
374: BDADD8(&cdb[1], 0, 3); /* DBD */
375: BDSET8W(&cdb[2], 0x00, 7, 2); /* PC */
376: //BDADD8W(&cdb[2], 0x00, 5, 6); /* PAGE CODE */
377: BDADD8W(&cdb[2], 0x3f, 5, 6); /* PAGE CODE */
378: cdb[3] = 0x00; /* SUBPAGE CODE */
379: DSET16(&cdb[7], data_alloc_len); /* ALLOCATION LENGTH */
380: cdb_len = 10;
381: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "CDB", cdb, cdb_len);
382:
383: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, cdb, cdb_len);
384: flags = CAM_DIR_IN;
385: flags |= CAM_DEV_QFRZDIS;
386: cam_fill_csio(&spec->ccb->csio, retry, NULL, flags, MSG_SIMPLE_Q_TAG,
1.1.1.2 ! misho 387: data, data_alloc_len, SSD_FULL_SIZE, cdb_len,
! 388: spec->timeout);
1.1 misho 389: rc = cam_send_ccb(spec->cam_dev, spec->ccb);
390: if (rc < 0) {
391: ISTGT_ERRLOG("cam_send_ccb() failed\n");
392: return -1;
393: }
394:
395: if ((spec->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
396: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
1.1.1.2 ! misho 397: "request error CAM=0x%x, SCSI=0x%x\n",
! 398: spec->ccb->ccb_h.status,
! 399: spec->ccb->csio.scsi_status);
1.1 misho 400: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "SENSE",
1.1.1.2 ! misho 401: (uint8_t *) &spec->ccb->csio.sense_data,
! 402: SSD_FULL_SIZE);
1.1 misho 403: istgt_lu_pass_print_sense_key((uint8_t *) &spec->ccb->csio.sense_data);
404: istgt_lu_pass_parse_sense_key((uint8_t *) &spec->ccb->csio.sense_data,
1.1.1.2 ! misho 405: &sk, &asc, &ascq);
1.1 misho 406: if (sk == ISTGT_SCSI_SENSE_ILLEGAL_REQUEST) {
407: if (spec->inq_ver < SPC_VERSION_SPC3) {
408: //ISTGT_WARNLOG("MODE SENSE was not supported\n");
409: return 0;
410: }
411: if (asc == 0x20 && ascq == 0x00) {
412: /* INVALID COMMAND OPERATION CODE */
413: return 0;
414: } else if (asc == 0x24 && ascq == 0x00) {
415: /* INVALID FIELD IN CDB */
416: return 0;
417: }
418: }
419: if (sk == ISTGT_SCSI_SENSE_UNIT_ATTENTION) {
420: if (asc == 0x28 && ascq == 0x00) {
421: /* NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED */
422: goto retry_sense10;
423: }
424: if (asc == 0x29 && ascq == 0x00) {
425: /* POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */
426: goto retry_sense10;
427: } else if (asc == 0x29 && ascq == 0x01) {
428: /* POWER ON OCCURRED */
429: goto retry_sense10;
430: } else if (asc == 0x29 && ascq == 0x02) {
431: /* SCSI BUS RESET OCCURRED */
432: goto retry_sense10;
433: } else if (asc == 0x29 && ascq == 0x03) {
434: /* BUS DEVICE RESET FUNCTION OCCURRED */
435: goto retry_sense10;
436: } else if (asc == 0x29 && ascq == 0x04) {
437: /* DEVICE INTERNAL RESET */
438: goto retry_sense10;
439: } else if (asc == 0x29 && ascq == 0x05) {
440: /* TRANSCEIVER MODE CHANGED TO SINGLE-ENDED */
441: goto retry_sense10;
442: } else if (asc == 0x29 && ascq == 0x06) {
443: /* TRANSCEIVER MODE CHANGED TO LVD */
444: goto retry_sense10;
445: } else if (asc == 0x29 && ascq == 0x07) {
446: /* I_T NEXUS LOSS OCCURRED */
447: goto retry_sense10;
448: }
449: }
450: return -1;
451: }
452: data_len = spec->ccb->csio.dxfer_len;
453: data_len -= spec->ccb->csio.resid;
454: if (data_len < req_len) {
455: ISTGT_ERRLOG("result is short\n");
456: return -1;
457: }
458:
459: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "MODE SENSE(10)", data, data_len);
460: if (DGET16(&data[6]) != 0) { /* BLOCK DESCRIPTOR LENGTH */
461: spec->ms_blockcnt = DGET64(&data[8+0]);
462: spec->ms_blocklen = DGET32(&data[8+12]);
463: }
464: }
465:
466: return 0;
467: }
468:
469: static int
470: istgt_lu_pass_set_capacity(ISTGT_LU_PASS *spec)
471: {
472: uint8_t buf[MAX_TMPBUF];
473: uint8_t cdb[16];
474: uint32_t flags;
475: uint8_t *data;
476: int cdb_len;
477: int data_len;
478: int data_alloc_len;
479: int req_len;
480: int retry = 1;
481: int sk, asc, ascq;
482: int rc;
483:
484: memset(buf, 0, sizeof buf);
485: memset(cdb, 0, sizeof cdb);
486: data = buf;
487: if (sizeof buf > 0xff) {
488: data_alloc_len = 0xff;
489: } else {
490: data_alloc_len = sizeof buf;
491: }
492:
493: /* issue READ CAPACITY (10) */
494: retry_capacity10:
495: memset(cdb, 0, sizeof cdb);
496: data_alloc_len = 8;
497: req_len = 8;
498: if (spec->inq_pd == SPC_PERIPHERAL_DEVICE_TYPE_DISK) {
499: cdb[0] = SBC_READ_CAPACITY_10;
500: cdb_len = 10;
501: } else if (spec->inq_pd == SPC_PERIPHERAL_DEVICE_TYPE_DVD) {
502: cdb[0] = MMC_READ_CAPACITY;
503: cdb_len = 10;
504: } else {
505: ISTGT_ERRLOG("unsupported device\n");
506: return -1;
507: }
508: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "CDB", cdb, cdb_len);
509:
510: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, cdb, cdb_len);
511: flags = CAM_DIR_IN;
512: flags |= CAM_DEV_QFRZDIS;
513: cam_fill_csio(&spec->ccb->csio, retry, NULL, flags, MSG_SIMPLE_Q_TAG,
1.1.1.2 ! misho 514: data, data_alloc_len, SSD_FULL_SIZE, cdb_len,
! 515: spec->timeout);
1.1 misho 516: rc = cam_send_ccb(spec->cam_dev, spec->ccb);
517: if (rc < 0) {
518: ISTGT_ERRLOG("cam_send_ccb() failed\n");
519: return -1;
520: }
521:
522: if ((spec->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
523: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
1.1.1.2 ! misho 524: "request error CAM=0x%x, SCSI=0x%x\n",
! 525: spec->ccb->ccb_h.status,
! 526: spec->ccb->csio.scsi_status);
1.1 misho 527: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "SENSE",
1.1.1.2 ! misho 528: (uint8_t *) &spec->ccb->csio.sense_data,
! 529: SSD_FULL_SIZE);
1.1 misho 530: istgt_lu_pass_print_sense_key((uint8_t *) &spec->ccb->csio.sense_data);
531: istgt_lu_pass_parse_sense_key((uint8_t *) &spec->ccb->csio.sense_data,
1.1.1.2 ! misho 532: &sk, &asc, &ascq);
1.1 misho 533: if (sk == ISTGT_SCSI_SENSE_NOT_READY) {
534: if (asc == 0x04 && ascq == 0x01) {
535: /* LOGICAL UNIT IS IN PROCESS OF BECOMING READY */
536: sleep(2);
537: goto retry_capacity10;
538: }
539: if (asc == 0x3a && ascq == 0x00) {
540: /* MEDIUM NOT PRESENT */
541: goto medium_not_present;
542: } else if (asc == 0x3a && ascq == 0x01) {
543: /* MEDIUM NOT PRESENT - TRAY CLOSED */
544: goto medium_not_present;
545: } else if (asc == 0x3a && ascq == 0x02) {
546: /* MEDIUM NOT PRESENT - TRAY OPEN */
547: goto medium_not_present;
548: } else if (asc == 0x3a && ascq == 0x03) {
549: /* MEDIUM NOT PRESENT - LOADABLE */
550: goto medium_not_present;
551: } else if (asc == 0x3a && ascq == 0x04) {
552: /* MEDIUM NOT PRESENT - MEDIUM AUXILIARY MEMORY ACCESSIBLE */
553: goto medium_not_present;
554: }
555: ISTGT_ERRLOG("device not ready\n");
556: return -1;
557: }
558: if (sk == ISTGT_SCSI_SENSE_UNIT_ATTENTION) {
559: if (asc == 0x28 && ascq == 0x00) {
560: /* NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED */
561: goto retry_capacity10;
562: }
563: if (asc == 0x29 && ascq == 0x00) {
564: /* POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */
565: goto retry_capacity10;
566: } else if (asc == 0x29 && ascq == 0x01) {
567: /* POWER ON OCCURRED */
568: goto retry_capacity10;
569: } else if (asc == 0x29 && ascq == 0x02) {
570: /* SCSI BUS RESET OCCURRED */
571: goto retry_capacity10;
572: } else if (asc == 0x29 && ascq == 0x03) {
573: /* BUS DEVICE RESET FUNCTION OCCURRED */
574: goto retry_capacity10;
575: } else if (asc == 0x29 && ascq == 0x04) {
576: /* DEVICE INTERNAL RESET */
577: goto retry_capacity10;
578: } else if (asc == 0x29 && ascq == 0x05) {
579: /* TRANSCEIVER MODE CHANGED TO SINGLE-ENDED */
580: goto retry_capacity10;
581: } else if (asc == 0x29 && ascq == 0x06) {
582: /* TRANSCEIVER MODE CHANGED TO LVD */
583: goto retry_capacity10;
584: } else if (asc == 0x29 && ascq == 0x07) {
585: /* I_T NEXUS LOSS OCCURRED */
586: goto retry_capacity10;
587: }
588: }
589: return -1;
590: }
591: data_len = spec->ccb->csio.dxfer_len;
592: data_len -= spec->ccb->csio.resid;
593: if (data_len < req_len) {
594: ISTGT_ERRLOG("result is short\n");
595: return -1;
596: }
597:
598: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "READ CAPACITY(10)", data, data_len);
599: spec->blockcnt = (uint64_t) DGET32(&data[0]); // last LBA
600: spec->blocklen = (uint64_t) DGET32(&data[4]);
601:
602: if (spec->blockcnt == 0xffffffffU) {
603: retry_capacity16:
604: memset(cdb, 0, sizeof cdb);
605: /* issue READ CAPACITY(16) */
606: data_alloc_len = 32;
607: req_len = 32;
608: if (spec->inq_pd == SPC_PERIPHERAL_DEVICE_TYPE_DISK) {
609: cdb[0] = SPC_SERVICE_ACTION_IN_16;
610: /* SERVICE ACTION */
611: BDSET8W(&cdb[1], SBC_SAI_READ_CAPACITY_16, 4, 5);
612: /* ALLOCATION LENGTH */
613: DSET16(&cdb[10], data_alloc_len);
614: cdb_len = 16;
615: } else if (spec->inq_pd == SPC_PERIPHERAL_DEVICE_TYPE_DVD) {
616: ISTGT_ERRLOG("unsupported device\n");
617: return -1;
618: } else {
619: ISTGT_ERRLOG("unsupported device\n");
620: return -1;
621: }
622: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "CDB", cdb, cdb_len);
623:
624: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, cdb, cdb_len);
625: flags = CAM_DIR_IN;
626: flags |= CAM_DEV_QFRZDIS;
627: cam_fill_csio(&spec->ccb->csio, retry, NULL, flags, MSG_SIMPLE_Q_TAG,
1.1.1.2 ! misho 628: data, data_alloc_len, SSD_FULL_SIZE, cdb_len,
! 629: spec->timeout);
1.1 misho 630: rc = cam_send_ccb(spec->cam_dev, spec->ccb);
631: if (rc < 0) {
632: ISTGT_ERRLOG("cam_send_ccb() failed\n");
633: return -1;
634: }
635:
636: if ((spec->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
637: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
1.1.1.2 ! misho 638: "request error CAM=0x%x, SCSI=0x%x\n",
! 639: spec->ccb->ccb_h.status,
! 640: spec->ccb->csio.scsi_status);
1.1 misho 641: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "SENSE",
1.1.1.2 ! misho 642: (uint8_t *) &spec->ccb->csio.sense_data,
! 643: SSD_FULL_SIZE);
1.1 misho 644: istgt_lu_pass_print_sense_key((uint8_t *) &spec->ccb->csio.sense_data);
645: istgt_lu_pass_parse_sense_key((uint8_t *) &spec->ccb->csio.sense_data,
1.1.1.2 ! misho 646: &sk, &asc, &ascq);
1.1 misho 647: if (sk == ISTGT_SCSI_SENSE_NOT_READY) {
648: if (asc == 0x04 && ascq == 0x01) {
649: /* LOGICAL UNIT IS IN PROCESS OF BECOMING READY */
650: sleep(2);
651: goto retry_capacity16;
652: }
653: if (asc == 0x3a && ascq == 0x00) {
654: /* MEDIUM NOT PRESENT */
655: goto medium_not_present;
656: } else if (asc == 0x3a && ascq == 0x01) {
657: /* MEDIUM NOT PRESENT - TRAY CLOSED */
658: goto medium_not_present;
659: } else if (asc == 0x3a && ascq == 0x02) {
660: /* MEDIUM NOT PRESENT - TRAY OPEN */
661: goto medium_not_present;
662: } else if (asc == 0x3a && ascq == 0x03) {
663: /* MEDIUM NOT PRESENT - LOADABLE */
664: goto medium_not_present;
665: } else if (asc == 0x3a && ascq == 0x04) {
666: /* MEDIUM NOT PRESENT - MEDIUM AUXILIARY MEMORY ACCESSIBLE */
667: goto medium_not_present;
668: }
669: ISTGT_ERRLOG("device not ready\n");
670: return -1;
671: }
672: if (sk == ISTGT_SCSI_SENSE_UNIT_ATTENTION) {
673: if (asc == 0x28 && ascq == 0x00) {
674: /* NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED */
675: goto retry_capacity16;
676: }
677: if (asc == 0x29 && ascq == 0x00) {
678: /* POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */
679: goto retry_capacity16;
680: } else if (asc == 0x29 && ascq == 0x01) {
681: /* POWER ON OCCURRED */
682: goto retry_capacity16;
683: } else if (asc == 0x29 && ascq == 0x02) {
684: /* SCSI BUS RESET OCCURRED */
685: goto retry_capacity16;
686: } else if (asc == 0x29 && ascq == 0x03) {
687: /* BUS DEVICE RESET FUNCTION OCCURRED */
688: goto retry_capacity16;
689: } else if (asc == 0x29 && ascq == 0x04) {
690: /* DEVICE INTERNAL RESET */
691: goto retry_capacity16;
692: } else if (asc == 0x29 && ascq == 0x05) {
693: /* TRANSCEIVER MODE CHANGED TO SINGLE-ENDED */
694: goto retry_capacity16;
695: } else if (asc == 0x29 && ascq == 0x06) {
696: /* TRANSCEIVER MODE CHANGED TO LVD */
697: goto retry_capacity16;
698: } else if (asc == 0x29 && ascq == 0x07) {
699: /* I_T NEXUS LOSS OCCURRED */
700: goto retry_capacity16;
701: }
702: }
703: return -1;
704: }
705: data_len = spec->ccb->csio.dxfer_len;
706: data_len -= spec->ccb->csio.resid;
707: if (data_len < req_len) {
708: ISTGT_ERRLOG("result is short\n");
709: return -1;
710: }
711:
712: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "READ CAPACITY(16)",
1.1.1.2 ! misho 713: data, data_len);
1.1 misho 714: spec->blockcnt = DGET64(&data[0]); // last LBA
715: spec->blocklen = (uint64_t) DGET32(&data[8]);
716: }
717:
718: spec->blockcnt++;
719: spec->size = spec->blockcnt * spec->blocklen;
720: return 0;
721:
722: medium_not_present:
723: spec->blockcnt = 0;
724: spec->blocklen = 0;
725: spec->size = 0;
726: return 0;
727: }
728:
729: int
1.1.1.2 ! misho 730: istgt_lu_pass_init(ISTGT_Ptr istgt __attribute__((__unused__)), ISTGT_LU_Ptr lu)
1.1 misho 731: {
732: char buf[MAX_TMPBUF];
733: ISTGT_LU_PASS *spec;
734: uint64_t gb_size;
735: uint64_t mb_size;
736: int mb_digit;
737: int flags;
738: int rc;
739: int pq, pd, rmb;
740: int ver, fmt;
741: int i;
742:
743: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_pass_init\n");
744:
745: printf("LU%d PASS-THROUGH UNIT\n", lu->num);
746: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d TargetName=%s\n",
747: lu->num, lu->name);
748: for (i = 0; i < lu->maxlun; i++) {
749: if (lu->lun[i].type == ISTGT_LU_LUN_TYPE_NONE) {
750: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d: LUN%d none\n",
1.1.1.2 ! misho 751: lu->num, i);
1.1 misho 752: lu->lun[i].spec = NULL;
753: continue;
754: }
755: if (lu->lun[i].type != ISTGT_LU_LUN_TYPE_DEVICE) {
756: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
757: return -1;
758: }
759: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d: LUN%d device\n",
1.1.1.2 ! misho 760: lu->num, i);
1.1 misho 761:
762: spec = xmalloc(sizeof *spec);
763: memset(spec, 0, sizeof *spec);
764: spec->lu = lu;
765: spec->num = lu->num;
766: spec->lun = i;
767:
768: spec->timeout = ISTGT_LU_CAM_TIMEOUT;
769: spec->inq_standard = NULL;
770: spec->inq_standard_len = 0;
771: spec->inq_pd = 0;
772: spec->inq_rmb = 0;
773: spec->inq_ver = 0;
774:
775: spec->file = lu->lun[i].u.device.file;
776: spec->size = 0;
777: spec->blocklen = 0;
778: spec->blockcnt = 0;
779:
780: printf("LU%d: LUN%d file=%s\n",
1.1.1.2 ! misho 781: lu->num, i, spec->file);
1.1 misho 782:
783: flags = lu->readonly ? O_RDONLY : O_RDWR;
784: rc = cam_get_device(spec->file, buf, sizeof buf,
1.1.1.2 ! misho 785: &spec->unit);
1.1 misho 786: if (rc < 0) {
787: ISTGT_ERRLOG("LU%d: LUN%d: cam_get_device() failed\n", lu->num, i);
788: xfree(spec);
789: return -1;
790: }
791: spec->device = xstrdup(buf);
792: spec->cam_dev = cam_open_spec_device(spec->device, spec->unit,
1.1.1.2 ! misho 793: flags, NULL);
1.1 misho 794: if (spec->cam_dev == NULL) {
795: ISTGT_ERRLOG("LU%d: LUN%d: cam_open() failed\n", lu->num, i);
796: xfree(spec->device);
797: xfree(spec);
798: return -1;
799: }
800: spec->ccb = cam_getccb(spec->cam_dev);
801: if (spec->ccb == NULL) {
802: ISTGT_ERRLOG("LU%d: LUN%d: cam_getccb() failed\n", lu->num, i);
803: cam_close_spec_device(spec->cam_dev);
804: xfree(spec->device);
805: xfree(spec);
806: return -1;
807: }
808: memset((uint8_t *) spec->ccb + sizeof(struct ccb_hdr), 0,
809: sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
810:
811: rc = istgt_lu_pass_set_inquiry(spec);
812: if (rc < 0) {
813: ISTGT_ERRLOG("LU%d: LUN%d: lu_pass_set_inquiry() failed\n",
1.1.1.2 ! misho 814: lu->num, i);
1.1 misho 815: error_return:
816: cam_freeccb(spec->ccb);
817: cam_close_spec_device(spec->cam_dev);
818: xfree(spec->device);
819: xfree(spec);
820: return -1;
821: }
822:
823: /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
824: pq = BGET8W(&spec->inq_standard[0], 7, 3);
825: pd = BGET8W(&spec->inq_standard[0], 4, 5);
826: /* RMB(7) */
827: rmb = BGET8W(&spec->inq_standard[1], 7, 1);
828: /* VERSION ANSI(2-0) */
829: ver = BGET8W(&spec->inq_standard[2], 2, 3);
830: /* NORMACA(5) HISUP(4) RESPONSE DATA FORMAT(3-0) */
831: fmt = BGET8W(&spec->inq_standard[3], 3, 4);
832:
833: printf("LU%d: LUN%d pq=0x%x, pd=0x%x, rmb=%d, ver=%d, fmt=%d\n",
834: lu->num, i,
835: pq, pd, rmb, ver, fmt);
836:
837: if (pq != 0x00) {
838: ISTGT_ERRLOG("unsupported peripheral qualifier (%x)\n", pq);
839: goto error_return;
840: }
841:
842: switch (pd) {
843: case SPC_PERIPHERAL_DEVICE_TYPE_DISK:
844: printf("LU%d: LUN%d Direct access block device\n", lu->num, i);
845: break;
846: case SPC_PERIPHERAL_DEVICE_TYPE_TAPE:
847: printf("LU%d: LUN%d Sequential-access device\n", lu->num, i);
848: break;
849: case SPC_PERIPHERAL_DEVICE_TYPE_DVD:
850: printf("LU%d: LUN%d CD/DVD device\n", lu->num, i);
851: break;
852: case SPC_PERIPHERAL_DEVICE_TYPE_CHANGER:
853: printf("LU%d: LUN%d Medium changer device\n", lu->num, i);
854: break;
855: default:
856: ISTGT_ERRLOG("unsupported peripheral device type (%x)\n", pd);
857: goto error_return;
858: }
859:
860: switch (ver) {
861: case SPC_VERSION_NONE:
862: printf("LU%d: LUN%d version NONE\n", lu->num, i);
863: break;
864: case SPC_VERSION_SPC:
865: printf("LU%d: LUN%d version SPC\n", lu->num, i);
866: break;
867: case SPC_VERSION_SPC2:
868: printf("LU%d: LUN%d version SPC2\n", lu->num, i);
869: break;
870: case SPC_VERSION_SPC3:
871: printf("LU%d: LUN%d version SPC3\n", lu->num, i);
872: break;
873: case SPC_VERSION_SPC4:
874: printf("LU%d: LUN%d version SPC4\n", lu->num, i);
875: break;
876: case 0x01:
877: printf("LU%d: LUN%d version SCSI1\n", lu->num, i);
878: break;
879: case 0x02:
880: printf("LU%d: LUN%d version SCSI2\n", lu->num, i);
881: break;
882: default:
883: ISTGT_ERRLOG("LU%d: LUN%d: unsupported version(%d)\n",
1.1.1.2 ! misho 884: lu->num, i, ver);
1.1 misho 885: goto error_return;
886: }
887: switch (fmt) {
888: case 0x00:
889: printf("LU%d: LUN%d format SCSI1\n", lu->num, i);
890: break;
891: case 0x01:
892: printf("LU%d: LUN%d format CCS\n", lu->num, i);
893: break;
894: case 0x02:
895: printf("LU%d: LUN%d format SCSI2/SPC\n", lu->num, i);
896: break;
897: default:
898: ISTGT_ERRLOG("LU%d: LUN%d: unsupported format(%d)\n",
1.1.1.2 ! misho 899: lu->num, i, fmt);
1.1 misho 900: goto error_return;
901: }
902:
903: spec->inq_pd = pd;
904: spec->inq_rmb = rmb;
905: spec->inq_ver = ver;
906: spec->inq_fmt = fmt;
907:
908: if (pd != SPC_PERIPHERAL_DEVICE_TYPE_CHANGER) {
909: rc = istgt_lu_pass_set_modesense(spec);
910: if (rc < 0) {
911: #if 0
912: ISTGT_ERRLOG("LU%d: LUN%d: lu_pass_set_modesense() failed\n",
1.1.1.2 ! misho 913: lu->num, i);
1.1 misho 914: goto error_return;
915: #else
916: spec->ms_blockcnt = 0;
917: spec->ms_blocklen = 0;
918: #endif
919: }
920: } else {
921: spec->ms_blockcnt = 0;
922: spec->ms_blocklen = 0;
923: }
924:
925: if (pd == SPC_PERIPHERAL_DEVICE_TYPE_TAPE
926: || pd == SPC_PERIPHERAL_DEVICE_TYPE_CHANGER) {
927: spec->timeout *= 10;
928: }
929: if (pd == SPC_PERIPHERAL_DEVICE_TYPE_DISK
930: || pd == SPC_PERIPHERAL_DEVICE_TYPE_DVD) {
931: rc = istgt_lu_pass_set_capacity(spec);
932: if (rc < 0) {
933: ISTGT_ERRLOG("LU%d: LUN%d: lu_pass_set_capacity() failed\n",
1.1.1.2 ! misho 934: lu->num, i);
1.1 misho 935: goto error_return;
936: }
937: } else {
938: spec->blockcnt = 0;
939: spec->blocklen = 0;
940: spec->size = 0;
941: }
942: if (spec->ms_blocklen == 0) {
943: if (spec->blocklen == 0) {
944: if (pd == SPC_PERIPHERAL_DEVICE_TYPE_DVD) {
945: spec->ms_blocklen = 2048;
946: } else {
947: spec->ms_blocklen = 512;
948: }
949: } else {
950: spec->ms_blocklen = spec->blocklen;
951: }
952: }
953:
954: if (pd != SPC_PERIPHERAL_DEVICE_TYPE_CHANGER) {
955: printf("LU%d: LUN%d block descriptor\n", lu->num, i);
956: printf("LU%d: LUN%d %"PRIu64" blocks, %"PRIu64" bytes/block\n",
1.1.1.2 ! misho 957: lu->num, i, spec->ms_blockcnt, spec->ms_blocklen);
1.1 misho 958:
959: if (spec->inq_rmb && spec->blockcnt == 0) {
960: printf("LU%d: LUN%d medium not present\n", lu->num, i);
961: } else {
962: printf("LU%d: LUN%d medium capacity\n", lu->num, i);
963: printf("LU%d: LUN%d %"PRIu64" blocks, %"PRIu64" bytes/block\n",
964: lu->num, i, spec->blockcnt, spec->blocklen);
1.1.1.2 ! misho 965:
1.1 misho 966: gb_size = spec->size / ISTGT_LU_1GB;
967: mb_size = (spec->size % ISTGT_LU_1GB) / ISTGT_LU_1MB;
968: if (gb_size > 0) {
969: mb_digit = (int) (((mb_size * 100) / 1024) / 10);
970: printf("LU%d: LUN%d %"PRIu64".%dGB\n",
1.1.1.2 ! misho 971: lu->num, i, gb_size, mb_digit);
1.1 misho 972: } else {
973: printf("LU%d: LUN%d %"PRIu64"MB\n",
1.1.1.2 ! misho 974: lu->num, i, mb_size);
1.1 misho 975: }
976: }
977: }
978:
979: printf("LU%d: LUN%d %spass through for %s\n",
980: lu->num, i,
981: lu->readonly ? "readonly " : "", lu->name);
982:
983: lu->lun[i].spec = spec;
984: }
985:
986: return 0;
987: }
988:
989: int
1.1.1.2 ! misho 990: istgt_lu_pass_shutdown(ISTGT_Ptr istgt __attribute__((__unused__)), ISTGT_LU_Ptr lu)
1.1 misho 991: {
992: ISTGT_LU_PASS *spec;
993: int i;
994:
995: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_pass_shutdown\n");
996:
997: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d TargetName=%s\n",
998: lu->num, lu->name);
999: for (i = 0; i < lu->maxlun; i++) {
1000: if (lu->lun[i].type == ISTGT_LU_LUN_TYPE_NONE) {
1001: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d: LUN%d none\n",
1.1.1.2 ! misho 1002: lu->num, i);
1.1 misho 1003: continue;
1004: }
1005: if (lu->lun[i].type != ISTGT_LU_LUN_TYPE_DEVICE) {
1006: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
1007: return -1;
1008: }
1009: spec = (ISTGT_LU_PASS *) lu->lun[i].spec;
1010:
1011: if (spec->ccb != NULL) {
1012: cam_freeccb(spec->ccb);
1013: spec->ccb = NULL;
1014: }
1015: if (spec->cam_dev != NULL) {
1016: cam_close_spec_device(spec->cam_dev);
1017: spec->cam_dev = NULL;
1018: }
1019: if (spec->device != NULL) {
1020: xfree(spec->device);
1021: spec->device = NULL;
1022: }
1023: xfree(spec);
1024: lu->lun[i].spec = NULL;
1025: }
1026:
1027: return 0;
1028: }
1029:
1030: static int
1031: istgt_scsi_get_cdb_len(uint8_t *cdb)
1032: {
1033: int group;
1034: int cdblen = 0;
1035:
1036: if (cdb == NULL)
1037: return 0;
1038:
1039: group = (cdb[0] >> 5) & 0x07;
1040: switch (group) {
1041: case 0x00:
1042: /* 6byte commands */
1043: cdblen = 6;
1044: break;
1045: case 0x01:
1046: /* 10byte commands */
1047: cdblen = 10;
1048: break;
1049: case 0x02:
1050: /* 10byte commands */
1051: cdblen = 10;
1052: break;
1053: case 0x03:
1054: /* reserved */
1055: if (cdb[0] == 0x7f) {
1056: /* variable length */
1057: cdblen = 8 + (cdb[7] & 0xff);
1058: } else {
1059: /* XXX */
1060: cdblen = 6;
1061: }
1062: break;
1063: case 0x04:
1064: /* 16byte commands */
1065: cdblen = 16;
1066: break;
1067: case 0x05:
1068: /* 12byte commands */
1069: cdblen = 12;
1070: break;
1071: case 0x06:
1072: case 0x07:
1073: /* vendor specific */
1074: cdblen = 6;
1075: break;
1076: }
1077: return cdblen;
1078: }
1079:
1080: static int
1081: istgt_lu_pass_transfer_data(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd, uint8_t *buf, size_t bufsize, size_t len)
1082: {
1083: int rc;
1084:
1085: if (len > bufsize) {
1.1.1.2 ! misho 1086: ISTGT_ERRLOG("bufsize(%zd) too small\n", bufsize);
1.1 misho 1087: return -1;
1088: }
1089: rc = istgt_iscsi_transfer_out(conn, lu_cmd, buf, bufsize, len);
1090: if (rc < 0) {
1091: ISTGT_ERRLOG("iscsi_transfer_out()\n");
1092: return -1;
1093: }
1094: return 0;
1095: }
1096:
1097: static int
1.1.1.2 ! misho 1098: istgt_lu_pass_do_cam(ISTGT_LU_PASS *spec, CONN_Ptr conn __attribute__((__unused__)), ISTGT_LU_CMD_Ptr lu_cmd)
1.1 misho 1099: {
1100: uint32_t flags;
1101: uint8_t *cdb;
1102: uint8_t *data;
1103: int cdb_len;
1104: int data_len;
1105: uint8_t *sense_data;
1.1.1.2 ! misho 1106: size_t *sense_len;
! 1107: size_t len;
1.1 misho 1108: int R_bit, W_bit;
1109: int transfer_len;
1110: int retry = 1;
1111: int sk, asc, ascq;
1112: int rc;
1113:
1114: cdb = lu_cmd->cdb;
1115: data = lu_cmd->data;
1.1.1.2 ! misho 1116: //data_alloc_len = lu_cmd->alloc_len;
1.1 misho 1117: sense_data = lu_cmd->sense_data;
1118: sense_len = &lu_cmd->sense_data_len;
1119: *sense_len = 0;
1120: R_bit = lu_cmd->R_bit;
1121: W_bit = lu_cmd->W_bit;
1122: transfer_len = lu_cmd->transfer_len;
1123:
1124: cdb_len = istgt_scsi_get_cdb_len(cdb);
1125: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "CDB", cdb, cdb_len);
1126:
1127: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, cdb, cdb_len);
1128: flags = CAM_DIR_NONE;
1129: if (R_bit != 0) {
1130: flags = CAM_DIR_IN;
1131: } else if (W_bit != 0) {
1132: flags = CAM_DIR_OUT;
1133: }
1134: flags |= CAM_DEV_QFRZDIS;
1135: cam_fill_csio(&spec->ccb->csio, retry, NULL, flags, MSG_SIMPLE_Q_TAG,
1.1.1.2 ! misho 1136: data, transfer_len, SSD_FULL_SIZE, cdb_len,
! 1137: spec->timeout);
1.1 misho 1138: rc = cam_send_ccb(spec->cam_dev, spec->ccb);
1139: if (rc < 0) {
1140: ISTGT_ERRLOG("cam_send_ccb() failed\n");
1141: /* INTERNAL TARGET FAILURE */
1142: BUILD_SENSE(HARDWARE_ERROR, 0x44, 0x00);
1143: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1144: return -1;
1145: }
1146:
1147: if ((spec->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1148: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
1.1.1.2 ! misho 1149: "request error CAM=0x%x, SCSI=0x%x\n",
! 1150: spec->ccb->ccb_h.status,
! 1151: spec->ccb->csio.scsi_status);
1.1 misho 1152: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "SENSE",
1.1.1.2 ! misho 1153: (uint8_t *) &spec->ccb->csio.sense_data,
! 1154: SSD_FULL_SIZE);
1.1 misho 1155: if ((spec->ccb->ccb_h.status & CAM_STATUS_MASK)
1156: == CAM_SCSI_STATUS_ERROR) {
1157: memcpy(sense_data + 2, &spec->ccb->csio.sense_data, SSD_FULL_SIZE);
1158: DSET16(&sense_data[0], SSD_FULL_SIZE);
1159: *sense_len = SSD_FULL_SIZE + 2;
1160: lu_cmd->status = spec->ccb->csio.scsi_status;
1161: #if 0
1162: if (lu_cmd->status == 0) {
1163: /* INTERNAL TARGET FAILURE */
1164: BUILD_SENSE(HARDWARE_ERROR, 0x44, 0x00);
1165: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1166: }
1167: #endif
1168: /* adjust fixed format length */
1169: if (BGET8W(&sense_data[2+0], 6, 7) == 0x70
1170: || BGET8W(&sense_data[2+0], 6, 7) == 0x71) {
1171: len = DGET8(&sense_data[2+7]);
1172: len += 8;
1173: if (len < SSD_FULL_SIZE) {
1174: *sense_len = len + 2;
1175: DSET16(&sense_data[0], len);
1176: }
1177: }
1178: istgt_lu_pass_print_sense_key(sense_data + 2);
1179: istgt_lu_pass_parse_sense_key(sense_data + 2,
1.1.1.2 ! misho 1180: &sk, &asc, &ascq);
1.1 misho 1181: } else {
1182: #if 0
1183: /* INTERNAL TARGET FAILURE */
1184: BUILD_SENSE(HARDWARE_ERROR, 0x44, 0x00);
1185: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1186: #endif
1187: memcpy(sense_data + 2, &spec->ccb->csio.sense_data, SSD_FULL_SIZE);
1188: DSET16(&sense_data[0], SSD_FULL_SIZE);
1189: *sense_len = SSD_FULL_SIZE + 2;
1190: lu_cmd->status = spec->ccb->csio.scsi_status;
1191: /* adjust fixed format length */
1192: if (BGET8W(&sense_data[2+0], 6, 7) == 0x70
1193: || BGET8W(&sense_data[2+0], 6, 7) == 0x71) {
1194: len = DGET8(&sense_data[2+7]);
1195: len += 8;
1196: if (len < SSD_FULL_SIZE) {
1197: *sense_len = len + 2;
1198: DSET16(&sense_data[0], len);
1199: }
1200: }
1201: istgt_lu_pass_print_sense_key(sense_data + 2);
1202: istgt_lu_pass_parse_sense_key(sense_data + 2,
1.1.1.2 ! misho 1203: &sk, &asc, &ascq);
1.1 misho 1204: }
1205: return -1;
1206: }
1207: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "dxfer=%d, resid=%d, sense=%d\n",
1.1.1.2 ! misho 1208: spec->ccb->csio.dxfer_len,
! 1209: spec->ccb->csio.resid,
! 1210: spec->ccb->csio.sense_resid);
1.1 misho 1211: data_len = spec->ccb->csio.dxfer_len;
1212: data_len -= spec->ccb->csio.resid;
1213:
1214: if (R_bit != 0 || W_bit != 0) {
1215: #if 0
1216: if (data_len > 256) {
1217: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "DOCAM", data, 256);
1218: } else {
1219: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "DOCAM", data, data_len);
1220: }
1221: #endif
1.1.1.2 ! misho 1222: lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
1.1 misho 1223: } else {
1224: lu_cmd->data_len = 0;
1225: }
1226:
1227: lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
1228: return 0;
1229: }
1230:
1231: static int
1.1.1.2 ! misho 1232: istgt_lu_pass_do_cam_seg(ISTGT_LU_PASS *spec, CONN_Ptr conn __attribute__((__unused__)), ISTGT_LU_CMD_Ptr lu_cmd)
1.1 misho 1233: {
1234: uint64_t llba;
1235: uint32_t lcnt;
1236: uint32_t flags;
1237: uint8_t fixcdb[16];
1238: uint8_t *cdb;
1239: uint8_t *data;
1240: int pad_len;
1241: int cdb_len;
1242: int data_len;
1243: int data_alloc_len;
1244: uint8_t *sense_data;
1.1.1.2 ! misho 1245: size_t *sense_len;
! 1246: size_t len, cnt;
1.1 misho 1247: int R_bit, W_bit;
1248: int transfer_len;
1249: int retry = 1;
1250: int offset;
1251: int seglen;
1252: int sk, asc, ascq;
1253: int rc;
1254:
1255: cdb = lu_cmd->cdb;
1256: data = lu_cmd->data;
1257: data_alloc_len = lu_cmd->alloc_len;
1258: sense_data = lu_cmd->sense_data;
1259: sense_len = &lu_cmd->sense_data_len;
1260: *sense_len = 0;
1261: R_bit = lu_cmd->R_bit;
1262: W_bit = lu_cmd->W_bit;
1263: transfer_len = lu_cmd->transfer_len;
1264:
1265: cdb_len = istgt_scsi_get_cdb_len(cdb);
1266: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "CDB", cdb, cdb_len);
1267:
1268: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, cdb, cdb_len);
1269: flags = CAM_DIR_NONE;
1270: if (R_bit != 0) {
1271: flags = CAM_DIR_IN;
1272: } else if (W_bit != 0) {
1273: flags = CAM_DIR_OUT;
1274: }
1275: flags |= CAM_DEV_QFRZDIS;
1276:
1277: //#define MAX_SEGLEN (65536-4096)
1278: #define MAX_SEGLEN (65536)
1279: pad_len = (int) ((uintptr_t) data & (4096 - 1));
1280: if (pad_len != 0) {
1281: pad_len = 4096 - pad_len;
1282: data += pad_len;
1283: data_alloc_len -= pad_len;
1284: }
1285: data_len = 0;
1286: seglen = MAX_SEGLEN;
1287: seglen -= MAX_SEGLEN % (int) spec->ms_blocklen;
1288: len = 0;
1289: for (offset = 0; offset < transfer_len; offset += seglen) {
1290: len = DMIN32(seglen, (transfer_len - offset));
1291: cnt = len / (int) spec->ms_blocklen;
1292: switch(cdb[0]) {
1293: case SBC_READ_6:
1294: memcpy(fixcdb, cdb, cdb_len);
1295: llba = (uint64_t) DGET16(&cdb[2]);
1296: lcnt = (uint32_t) DGET8(&cdb[4]);
1297: llba += offset / spec->ms_blocklen;
1298: lcnt = (uint64_t) cnt;
1299: DSET16(&fixcdb[2], (uint16_t) llba);
1300: DSET8(&fixcdb[4], (uint8_t) lcnt);
1301: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, fixcdb, cdb_len);
1302: break;
1303:
1304: case SBC_READ_10:
1305: memcpy(fixcdb, cdb, cdb_len);
1306: llba = (uint64_t) DGET32(&cdb[2]);
1307: lcnt = (uint32_t) DGET16(&cdb[7]);
1308: llba += offset / spec->ms_blocklen;
1309: lcnt = (uint64_t) cnt;
1310: DSET32(&fixcdb[2], (uint32_t) llba);
1311: DSET16(&fixcdb[7], (uint16_t) lcnt);
1312: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, fixcdb, cdb_len);
1313: break;
1314:
1315: case SBC_READ_12:
1316: memcpy(fixcdb, cdb, cdb_len);
1317: llba = (uint64_t) DGET32(&cdb[2]);
1318: lcnt = (uint32_t) DGET32(&cdb[6]);
1319: llba += offset / spec->ms_blocklen;
1320: lcnt = (uint64_t) cnt;
1321: DSET32(&fixcdb[2], (uint32_t) llba);
1322: DSET32(&fixcdb[6], (uint32_t) lcnt);
1323: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, fixcdb, cdb_len);
1324: break;
1325:
1326: case SBC_READ_16:
1327: memcpy(fixcdb, cdb, cdb_len);
1328: llba = (uint64_t) DGET64(&cdb[2]);
1329: lcnt = (uint32_t) DGET32(&cdb[10]);
1330: llba += offset / spec->ms_blocklen;
1331: lcnt = (uint64_t) cnt;
1332: DSET64(&fixcdb[2], (uint64_t) llba);
1333: DSET32(&fixcdb[10], (uint32_t) lcnt);
1334: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, fixcdb, cdb_len);
1335: break;
1336:
1337: case SBC_WRITE_6:
1338: memcpy(fixcdb, cdb, cdb_len);
1339: llba = (uint64_t) DGET16(&cdb[2]);
1340: lcnt = (uint32_t) DGET8(&cdb[4]);
1341: llba += offset / spec->ms_blocklen;
1342: lcnt = (uint64_t) cnt;
1343: DSET16(&fixcdb[2], (uint16_t) llba);
1344: DSET8(&fixcdb[4], (uint8_t) lcnt);
1345: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, fixcdb, cdb_len);
1346: break;
1347:
1348: case SBC_WRITE_10:
1349: case SBC_WRITE_AND_VERIFY_10:
1350: memcpy(fixcdb, cdb, cdb_len);
1351: llba = (uint64_t) DGET32(&cdb[2]);
1352: lcnt = (uint32_t) DGET16(&cdb[7]);
1353: llba += offset / spec->ms_blocklen;
1354: lcnt = (uint64_t) cnt;
1355: DSET32(&fixcdb[2], (uint32_t) llba);
1356: DSET16(&fixcdb[7], (uint16_t) lcnt);
1357: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, fixcdb, cdb_len);
1358: break;
1359:
1360: case SBC_WRITE_12:
1361: case SBC_WRITE_AND_VERIFY_12:
1362: memcpy(fixcdb, cdb, cdb_len);
1363: llba = (uint64_t) DGET32(&cdb[2]);
1364: lcnt = (uint32_t) DGET32(&cdb[6]);
1365: llba += offset / spec->ms_blocklen;
1366: lcnt = (uint64_t) cnt;
1367: DSET32(&fixcdb[2], (uint32_t) llba);
1368: DSET32(&fixcdb[6], (uint32_t) lcnt);
1369: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, fixcdb, cdb_len);
1370: break;
1371:
1372: case SBC_WRITE_16:
1373: case SBC_WRITE_AND_VERIFY_16:
1374: memcpy(fixcdb, cdb, cdb_len);
1375: llba = (uint64_t) DGET64(&cdb[2]);
1376: lcnt = (uint32_t) DGET32(&cdb[10]);
1377: llba += offset / spec->ms_blocklen;
1378: lcnt = (uint64_t) cnt;
1379: DSET64(&fixcdb[2], (uint64_t) llba);
1380: DSET32(&fixcdb[10], (uint32_t) lcnt);
1381: memcpy(spec->ccb->csio.cdb_io.cdb_bytes, fixcdb, cdb_len);
1382: break;
1383:
1384: default:
1385: ISTGT_ERRLOG("unsupported OP=0x%x\n", cdb[0]);
1386: /* INTERNAL TARGET FAILURE */
1387: BUILD_SENSE(HARDWARE_ERROR, 0x44, 0x00);
1388: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1389: return -1;
1390: }
1391:
1392: cam_fill_csio(&spec->ccb->csio, retry, NULL, flags, MSG_SIMPLE_Q_TAG,
1.1.1.2 ! misho 1393: data + offset, len, SSD_FULL_SIZE, cdb_len,
! 1394: spec->timeout);
1.1 misho 1395: rc = cam_send_ccb(spec->cam_dev, spec->ccb);
1396: if (rc < 0) {
1397: ISTGT_ERRLOG("cam_send_ccb() failed\n");
1398: /* INTERNAL TARGET FAILURE */
1399: BUILD_SENSE(HARDWARE_ERROR, 0x44, 0x00);
1400: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1401: return -1;
1402: }
1403:
1404: if ((spec->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1405: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
1.1.1.2 ! misho 1406: "request error CAM=0x%x, SCSI=0x%x\n",
! 1407: spec->ccb->ccb_h.status,
! 1408: spec->ccb->csio.scsi_status);
1.1 misho 1409: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "SENSE",
1.1.1.2 ! misho 1410: (uint8_t *) &spec->ccb->csio.sense_data,
! 1411: SSD_FULL_SIZE);
1.1 misho 1412: if ((spec->ccb->ccb_h.status & CAM_STATUS_MASK)
1.1.1.2 ! misho 1413: == CAM_SCSI_STATUS_ERROR) {
1.1 misho 1414: memcpy(sense_data + 2, &spec->ccb->csio.sense_data, SSD_FULL_SIZE);
1415: DSET16(&sense_data[0], SSD_FULL_SIZE);
1416: *sense_len = SSD_FULL_SIZE + 2;
1417: lu_cmd->status = spec->ccb->csio.scsi_status;
1418: #if 0
1419: if (lu_cmd->status == 0) {
1420: /* INTERNAL TARGET FAILURE */
1421: BUILD_SENSE(HARDWARE_ERROR, 0x44, 0x00);
1422: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1423: }
1424: #endif
1425: /* adjust fixed format length */
1426: if (BGET8W(&sense_data[2+0], 6, 7) == 0x70
1.1.1.2 ! misho 1427: || BGET8W(&sense_data[2+0], 6, 7) == 0x71) {
1.1 misho 1428: len = DGET8(&sense_data[2+7]);
1429: len += 8;
1430: if (len < SSD_FULL_SIZE) {
1431: *sense_len = len + 2;
1432: DSET16(&sense_data[0], len);
1433: }
1434: }
1435: istgt_lu_pass_print_sense_key(sense_data + 2);
1436: istgt_lu_pass_parse_sense_key(sense_data + 2,
1.1.1.2 ! misho 1437: &sk, &asc, &ascq);
1.1 misho 1438: } else {
1439: #if 0
1440: /* INTERNAL TARGET FAILURE */
1441: BUILD_SENSE(HARDWARE_ERROR, 0x44, 0x00);
1442: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1443: #endif
1444: memcpy(sense_data + 2, &spec->ccb->csio.sense_data, SSD_FULL_SIZE);
1445: DSET16(&sense_data[0], SSD_FULL_SIZE);
1446: *sense_len = SSD_FULL_SIZE + 2;
1447: lu_cmd->status = spec->ccb->csio.scsi_status;
1448: /* adjust fixed format length */
1449: if (BGET8W(&sense_data[2+0], 6, 7) == 0x70
1.1.1.2 ! misho 1450: || BGET8W(&sense_data[2+0], 6, 7) == 0x71) {
1.1 misho 1451: len = DGET8(&sense_data[2+7]);
1452: len += 8;
1453: if (len < SSD_FULL_SIZE) {
1454: *sense_len = len + 2;
1455: DSET16(&sense_data[0], len);
1456: }
1457: }
1458: istgt_lu_pass_print_sense_key(sense_data + 2);
1459: istgt_lu_pass_parse_sense_key(sense_data + 2,
1.1.1.2 ! misho 1460: &sk, &asc, &ascq);
1.1 misho 1461: }
1462: return -1;
1463: }
1464: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "dxfer=%d, resid=%d, sense=%d\n",
1.1.1.2 ! misho 1465: spec->ccb->csio.dxfer_len,
! 1466: spec->ccb->csio.resid,
! 1467: spec->ccb->csio.sense_resid);
1.1 misho 1468: if (spec->ccb->csio.resid != 0) {
1469: /* INTERNAL TARGET FAILURE */
1470: BUILD_SENSE(HARDWARE_ERROR, 0x44, 0x00);
1471: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1472: return -1;
1473: }
1474: data_len += spec->ccb->csio.dxfer_len;
1475: data_len -= spec->ccb->csio.resid;
1476: }
1477:
1478: if (pad_len != 0) {
1479: memcpy(lu_cmd->data, lu_cmd->data + pad_len, data_len);
1480: }
1481: if (R_bit !=0 || W_bit != 0) {
1482: #if 0
1483: if (data_len > 256) {
1484: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "DOCAM", data, 256);
1485: } else {
1486: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "DOCAM", data, data_len);
1487: }
1488: #endif
1.1.1.2 ! misho 1489: lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
1.1 misho 1490: } else {
1491: lu_cmd->data_len = 0;
1492: }
1493:
1494: lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
1495: return 0;
1496: }
1497:
1498: static int
1.1.1.2 ! misho 1499: istgt_lu_pass_build_sense_data(ISTGT_LU_PASS *spec __attribute__((__unused__)), uint8_t *data, int sk, int asc, int ascq)
1.1 misho 1500: {
1501: int rc;
1502:
1503: rc = istgt_lu_scsi_build_sense_data(data, sk, asc, ascq);
1504: if (rc < 0) {
1505: return -1;
1506: }
1507: return rc;
1508: }
1509:
1510: int
1511: istgt_lu_pass_reset(ISTGT_LU_Ptr lu, int lun)
1512: {
1513: ISTGT_LU_PASS *spec;
1514:
1515: if (lun >= lu->maxlun) {
1516: return -1;
1517: }
1518: if (lu->lun[lun].type == ISTGT_LU_LUN_TYPE_NONE) {
1519: return -1;
1520: }
1521: spec = (ISTGT_LU_PASS *) lu->lun[lun].spec;
1522:
1523: #if 0
1524: if (spec->lock) {
1525: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "unlock by reset\n");
1526: spec->lock = 0;
1527: }
1528: #endif
1529:
1530: return 0;
1531: }
1532:
1533: int
1534: istgt_lu_pass_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd)
1535: {
1536: ISTGT_LU_Ptr lu;
1537: ISTGT_LU_PASS *spec;
1538: uint8_t *data;
1539: uint8_t *cdb;
1540: uint64_t fmt_lun;
1541: uint64_t lun;
1542: uint64_t method;
1543: uint32_t allocation_len;
1544: int data_len;
1545: int data_alloc_len;
1546: uint32_t transfer_len;
1547: uint8_t *sense_data;
1.1.1.2 ! misho 1548: size_t *sense_len;
1.1 misho 1549: int rc;
1550:
1551: if (lu_cmd == NULL)
1552: return -1;
1553: lu = lu_cmd->lu;
1554: if (lu == NULL) {
1555: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1556: return -1;
1557: }
1558: spec = NULL;
1559: cdb = lu_cmd->cdb;
1560: data = lu_cmd->data;
1561: data_alloc_len = lu_cmd->alloc_len;
1562: sense_data = lu_cmd->sense_data;
1563: sense_len = &lu_cmd->sense_data_len;
1564: *sense_len = 0;
1565:
1566: fmt_lun = lu_cmd->lun;
1567: method = (fmt_lun >> 62) & 0x03U;
1568: fmt_lun = fmt_lun >> 48;
1569: if (method == 0x00U) {
1570: lun = fmt_lun & 0x00ffU;
1571: } else if (method == 0x01U) {
1572: lun = fmt_lun & 0x3fffU;
1573: } else {
1574: lun = 0xffffU;
1575: }
1.1.1.2 ! misho 1576: if (lun >= (uint64_t) lu->maxlun) {
1.1 misho 1577: #ifdef ISTGT_TRACE_PASS
1578: ISTGT_ERRLOG("LU%d: LUN%4.4"PRIx64" invalid\n",
1.1.1.2 ! misho 1579: lu->num, lun);
1.1 misho 1580: #endif /* ISTGT_TRACE_PASS */
1581: if (cdb[0] == SPC_INQUIRY) {
1582: allocation_len = DGET16(&cdb[3]);
1.1.1.2 ! misho 1583: if (allocation_len > (size_t) data_alloc_len) {
1.1 misho 1584: ISTGT_ERRLOG("data_alloc_len(%d) too small\n",
1.1.1.2 ! misho 1585: data_alloc_len);
1.1 misho 1586: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1587: return -1;
1588: }
1589: memset(data, 0, allocation_len);
1590: /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
1591: BDSET8W(&data[0], 0x03, 7, 3);
1592: BDADD8W(&data[0], 0x1f, 4, 5);
1593: data_len = 96;
1594: memset(&data[1], 0, data_len - 1);
1595: /* ADDITIONAL LENGTH */
1596: data[4] = data_len - 5;
1.1.1.2 ! misho 1597: lu_cmd->data_len = DMIN32((size_t)data_len, lu_cmd->transfer_len);
1.1 misho 1598: lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
1599: return 0;
1600: } else {
1601: /* LOGICAL UNIT NOT SUPPORTED */
1602: BUILD_SENSE(ILLEGAL_REQUEST, 0x25, 0x00);
1603: lu_cmd->data_len = 0;
1604: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1605: return 0;
1606: }
1607: }
1608: spec = (ISTGT_LU_PASS *) lu->lun[lun].spec;
1609: if (spec == NULL) {
1610: /* LOGICAL UNIT NOT SUPPORTED */
1611: BUILD_SENSE(ILLEGAL_REQUEST, 0x25, 0x00);
1612: lu_cmd->data_len = 0;
1613: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1614: return 0;
1615: }
1616:
1617: ISTGT_TRACELOG(ISTGT_TRACE_SCSI, "SCSI OP=0x%x, LUN=0x%16.16"PRIx64"\n",
1.1.1.2 ! misho 1618: cdb[0], lu_cmd->lun);
1.1 misho 1619: #ifdef ISTGT_TRACE_PASS
1620: if (cdb[0] != SPC_TEST_UNIT_READY) {
1621: istgt_scsi_dump_cdb(cdb);
1622: }
1623: #endif /* ISTGT_TRACE_DISK */
1624:
1625: if (lu_cmd->W_bit != 0) {
1626: transfer_len = lu_cmd->transfer_len;
1627: rc = istgt_lu_pass_transfer_data(conn, lu_cmd, lu_cmd->iobuf,
1.1.1.2 ! misho 1628: lu_cmd->iobufsize, transfer_len);
1.1 misho 1629: if (rc < 0) {
1630: ISTGT_ERRLOG("lu_pass_transfer_data() failed\n");
1631: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1632: return -1;
1633: }
1634: lu_cmd->data = lu_cmd->iobuf;
1635: lu_cmd->alloc_len = lu_cmd->iobufsize;
1636: }
1637:
1638: switch (spec->inq_pd) {
1639: case SPC_PERIPHERAL_DEVICE_TYPE_DISK:
1640: switch (cdb[0]) {
1641: case SBC_READ_6:
1642: case SBC_READ_10:
1643: case SBC_READ_12:
1644: case SBC_READ_16:
1645: case SBC_WRITE_6:
1646: case SBC_WRITE_12:
1647: case SBC_WRITE_AND_VERIFY_12:
1648: case SBC_WRITE_10:
1649: case SBC_WRITE_AND_VERIFY_10:
1650: case SBC_WRITE_16:
1651: case SBC_WRITE_AND_VERIFY_16:
1652: lu_cmd->data = lu_cmd->iobuf;
1653: lu_cmd->alloc_len = lu_cmd->iobufsize;
1654: if (lu_cmd->transfer_len > lu_cmd->alloc_len) {
1.1.1.2 ! misho 1655: ISTGT_ERRLOG("alloc_len(%zd) too small\n", lu_cmd->alloc_len);
1.1 misho 1656: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1657: return -1;
1658: }
1659: rc = istgt_lu_pass_do_cam_seg(spec, conn, lu_cmd);
1660: if (rc < 0) {
1661: /* build by function */
1662: break;
1663: }
1664: lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
1665: break;
1666: default:
1667: rc = istgt_lu_pass_do_cam(spec, conn, lu_cmd);
1668: if (rc < 0) {
1669: /* build by function */
1670: break;
1671: }
1672: lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
1673: break;
1674: }
1675: break;
1676: case SPC_PERIPHERAL_DEVICE_TYPE_TAPE:
1677: switch (cdb[0]) {
1678: default:
1679: rc = istgt_lu_pass_do_cam(spec, conn, lu_cmd);
1680: if (rc < 0) {
1681: /* build by function */
1682: break;
1683: }
1684: lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
1685: break;
1686: }
1687: break;
1688: case SPC_PERIPHERAL_DEVICE_TYPE_DVD:
1689: switch (cdb[0]) {
1690: case MMC_READ_10:
1691: case MMC_READ_12:
1692: case MMC_WRITE_10:
1693: case MMC_WRITE_AND_VERIFY_10:
1694: case MMC_WRITE_12:
1695: lu_cmd->data = lu_cmd->iobuf;
1696: lu_cmd->alloc_len = lu_cmd->iobufsize;
1697: if (lu_cmd->transfer_len > lu_cmd->alloc_len) {
1.1.1.2 ! misho 1698: ISTGT_ERRLOG("alloc_len(%zd) too small\n", lu_cmd->alloc_len);
1.1 misho 1699: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1700: return -1;
1701: }
1702: rc = istgt_lu_pass_do_cam_seg(spec, conn, lu_cmd);
1703: if (rc < 0) {
1704: /* build by function */
1705: break;
1706: }
1707: lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
1708: break;
1709: #ifdef ISTGT_TRACE_PASS
1710: case MMC_GET_EVENT_STATUS_NOTIFICATION:
1711: rc = istgt_lu_pass_do_cam(spec, conn, lu_cmd);
1712: if (rc < 0) {
1713: /* build by function */
1714: break;
1715: }
1716: ISTGT_TRACEDUMP(ISTGT_TRACE_DEBUG, "EVENT",
1.1.1.2 ! misho 1717: lu_cmd->data, lu_cmd->data_len);
1.1 misho 1718: lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
1719: break;
1720: #endif /* ISTGT_TRACE_PASS */
1721: default:
1722: rc = istgt_lu_pass_do_cam(spec, conn, lu_cmd);
1723: if (rc < 0) {
1724: /* build by function */
1725: break;
1726: }
1727: lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
1728: break;
1729: }
1730: break;
1731: case SPC_PERIPHERAL_DEVICE_TYPE_CHANGER:
1732: switch (cdb[0]) {
1733: default:
1734: rc = istgt_lu_pass_do_cam(spec, conn, lu_cmd);
1735: if (rc < 0) {
1736: /* build by function */
1737: break;
1738: }
1739: lu_cmd->status = ISTGT_SCSI_STATUS_GOOD;
1740: break;
1741: }
1742: break;
1743: default:
1744: ISTGT_ERRLOG("unsupported peripheral device type (%x)\n",
1.1.1.2 ! misho 1745: spec->inq_pd);
1.1 misho 1746: /* LOGICAL UNIT NOT SUPPORTED */
1747: BUILD_SENSE(ILLEGAL_REQUEST, 0x25, 0x00);
1748: lu_cmd->data_len = 0;
1749: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
1750: break;
1751: }
1752:
1753: ISTGT_TRACELOG(ISTGT_TRACE_SCSI,
1.1.1.2 ! misho 1754: "SCSI OP=0x%x, LUN=0x%16.16"PRIx64" status=0x%x,"
! 1755: " complete\n",
! 1756: cdb[0], lu_cmd->lun, lu_cmd->status);
1.1 misho 1757: return 0;
1758: }
1759: #else /* HAVE_LIBCAM */
1760: #include "istgt.h"
1761: #include "istgt_ver.h"
1762: #include "istgt_log.h"
1763: #include "istgt_misc.h"
1764: #include "istgt_lu.h"
1765: #include "istgt_proto.h"
1766: #include "istgt_scsi.h"
1767:
1768: int
1.1.1.2 ! misho 1769: istgt_lu_pass_init(ISTGT_Ptr istgt __attribute__((__unused__)), ISTGT_LU_Ptr lu __attribute__((__unused__)))
1.1 misho 1770: {
1771: return 0;
1772: }
1773:
1774: int
1.1.1.2 ! misho 1775: istgt_lu_pass_shutdown(ISTGT_Ptr istgt __attribute__((__unused__)), ISTGT_LU_Ptr lu __attribute__((__unused__)))
1.1 misho 1776: {
1777: return 0;
1778: }
1779:
1780: int
1.1.1.2 ! misho 1781: istgt_lu_pass_reset(ISTGT_LU_Ptr lu __attribute__((__unused__)), int lun __attribute__((__unused__)))
1.1 misho 1782: {
1783: return 0;
1784: }
1785:
1786: int
1.1.1.2 ! misho 1787: istgt_lu_pass_execute(CONN_Ptr conn __attribute__((__unused__)), ISTGT_LU_CMD_Ptr lu_cmd __attribute__((__unused__)))
1.1 misho 1788: {
1789: ISTGT_TRACELOG(ISTGT_TRACE_SCSI, "unsupported unit\n");
1790: return -1;
1791: }
1792: #endif /* HAVE_LIBCAM */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>