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