usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c
changeset 13297 4b9dc4ca8e9f
parent 12750 f559965e4a2f
child 13382 d84aa76f7cd2
equal deleted inserted replaced
13296:f7734d6b8e80 13297:4b9dc4ca8e9f
    18  *
    18  *
    19  * CDDL HEADER END
    19  * CDDL HEADER END
    20  */
    20  */
    21 /*
    21 /*
    22  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
    22  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
       
    23  *
       
    24  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
    23  */
    25  */
    24 
    26 
    25 #include <sys/conf.h>
    27 #include <sys/conf.h>
    26 #include <sys/file.h>
    28 #include <sys/file.h>
    27 #include <sys/ddi.h>
    29 #include <sys/ddi.h>
    96 void sbd_handle_mode_select_xfer(scsi_task_t *task, uint8_t *buf,
    98 void sbd_handle_mode_select_xfer(scsi_task_t *task, uint8_t *buf,
    97     uint32_t buflen);
    99     uint32_t buflen);
    98 void sbd_handle_mode_select(scsi_task_t *task, stmf_data_buf_t *dbuf);
   100 void sbd_handle_mode_select(scsi_task_t *task, stmf_data_buf_t *dbuf);
    99 void sbd_handle_identifying_info(scsi_task_t *task, stmf_data_buf_t *dbuf);
   101 void sbd_handle_identifying_info(scsi_task_t *task, stmf_data_buf_t *dbuf);
   100 
   102 
       
   103 static void sbd_handle_unmap_xfer(scsi_task_t *task, uint8_t *buf,
       
   104     uint32_t buflen);
       
   105 static void sbd_handle_unmap(scsi_task_t *task, stmf_data_buf_t *dbuf);
       
   106 static void sbd_handle_write_same(scsi_task_t *task);
       
   107 
   101 extern void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *);
   108 extern void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *);
   102 extern int sbd_pgr_reservation_conflict(scsi_task_t *);
   109 extern int sbd_pgr_reservation_conflict(scsi_task_t *);
   103 extern void sbd_pgr_reset(sbd_lu_t *);
   110 extern void sbd_pgr_reset(sbd_lu_t *);
   104 extern void sbd_pgr_remove_it_handle(sbd_lu_t *, sbd_it_data_t *);
   111 extern void sbd_pgr_remove_it_handle(sbd_lu_t *, sbd_it_data_t *);
   105 extern void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *);
   112 extern void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *);
  1752 		} else {
  1759 		} else {
  1753 			sbd_handle_mode_select_xfer(task,
  1760 			sbd_handle_mode_select_xfer(task,
  1754 			    dbuf->db_sglist[0].seg_addr, dbuf->db_data_size);
  1761 			    dbuf->db_sglist[0].seg_addr, dbuf->db_data_size);
  1755 		}
  1762 		}
  1756 		break;
  1763 		break;
       
  1764 	case SCMD_UNMAP:
       
  1765 		sbd_handle_unmap_xfer(task,
       
  1766 		    dbuf->db_sglist[0].seg_addr, dbuf->db_data_size);
       
  1767 		break;
  1757 	case SCMD_PERSISTENT_RESERVE_OUT:
  1768 	case SCMD_PERSISTENT_RESERVE_OUT:
  1758 		if (sl->sl_access_state == SBD_LU_STANDBY) {
  1769 		if (sl->sl_access_state == SBD_LU_STANDBY) {
  1759 			st_ret = stmf_proxy_scsi_cmd(task, dbuf);
  1770 			st_ret = stmf_proxy_scsi_cmd(task, dbuf);
  1760 			if (st_ret != STMF_SUCCESS) {
  1771 			if (st_ret != STMF_SUCCESS) {
  1761 				stmf_scsilib_send_status(task, STATUS_CHECK,
  1772 				stmf_scsilib_send_status(task, STATUS_CHECK,
  1813 		p[5] = (s >> 16) & 0xff;
  1824 		p[5] = (s >> 16) & 0xff;
  1814 		p[6] = (s >> 8) & 0xff;
  1825 		p[6] = (s >> 8) & 0xff;
  1815 		p[7] = s & 0xff;
  1826 		p[7] = s & 0xff;
  1816 		p[10] = (blksize >> 8) & 0xff;
  1827 		p[10] = (blksize >> 8) & 0xff;
  1817 		p[11] = blksize & 0xff;
  1828 		p[11] = blksize & 0xff;
       
  1829 		if (sl->sl_flags & SL_UNMAP_ENABLED) {
       
  1830 			p[14] = 0x80;
       
  1831 		}
  1818 		sbd_handle_short_read_transfers(task, initial_dbuf, p,
  1832 		sbd_handle_short_read_transfers(task, initial_dbuf, p,
  1819 		    cdb_len, 32);
  1833 		    cdb_len, 32);
  1820 		break;
  1834 		break;
  1821 	}
  1835 	}
  1822 }
  1836 }
  2214 		url_length++;
  2228 		url_length++;
  2215 	}
  2229 	}
  2216 	return (url_length);
  2230 	return (url_length);
  2217 }
  2231 }
  2218 
  2232 
       
  2233 static void
       
  2234 sbd_handle_write_same(scsi_task_t *task)
       
  2235 {
       
  2236 	sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
       
  2237 	uint64_t addr, len;
       
  2238 	uint8_t *p;
       
  2239 
       
  2240 	task->task_cmd_xfer_length = 0;
       
  2241 	if (task->task_additional_flags &
       
  2242 	    TASK_AF_NO_EXPECTED_XFER_LENGTH) {
       
  2243 		task->task_expected_xfer_length = 0;
       
  2244 	}
       
  2245 	if (task->task_cdb[1] & 0xF7) {
       
  2246 		stmf_scsilib_send_status(task, STATUS_CHECK,
       
  2247 		    STMF_SAA_INVALID_FIELD_IN_CDB);
       
  2248 		return;
       
  2249 	}
       
  2250 	p = &task->task_cdb[2];
       
  2251 	addr = READ_SCSI64(p, uint64_t);
       
  2252 	addr <<= sl->sl_data_blocksize_shift;
       
  2253 	len = READ_SCSI32(p+8, uint64_t);
       
  2254 	len <<= sl->sl_data_blocksize_shift;
       
  2255 
       
  2256 	/* TODO -> full write_same support with data checks... */
       
  2257 	if (sbd_unmap(sl, addr, len) != 0) {
       
  2258 		stmf_scsilib_send_status(task, STATUS_CHECK,
       
  2259 		    STMF_SAA_LBA_OUT_OF_RANGE);
       
  2260 		return;
       
  2261 	}
       
  2262 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
       
  2263 }
       
  2264 
       
  2265 static void
       
  2266 sbd_handle_unmap(scsi_task_t *task, stmf_data_buf_t *dbuf)
       
  2267 {
       
  2268 	uint32_t cmd_xfer_len;
       
  2269 
       
  2270 	cmd_xfer_len = READ_SCSI16(&task->task_cdb[7], uint32_t);
       
  2271 
       
  2272 	if (task->task_cdb[1] & 1) {
       
  2273 		stmf_scsilib_send_status(task, STATUS_CHECK,
       
  2274 		    STMF_SAA_INVALID_FIELD_IN_CDB);
       
  2275 		return;
       
  2276 	}
       
  2277 
       
  2278 	if (cmd_xfer_len == 0) {
       
  2279 		task->task_cmd_xfer_length = 0;
       
  2280 		if (task->task_additional_flags &
       
  2281 		    TASK_AF_NO_EXPECTED_XFER_LENGTH) {
       
  2282 			task->task_expected_xfer_length = 0;
       
  2283 		}
       
  2284 		stmf_scsilib_send_status(task, STATUS_GOOD, 0);
       
  2285 		return;
       
  2286 	}
       
  2287 
       
  2288 	sbd_handle_short_write_transfers(task, dbuf, cmd_xfer_len);
       
  2289 }
       
  2290 
       
  2291 static void
       
  2292 sbd_handle_unmap_xfer(scsi_task_t *task, uint8_t *buf, uint32_t buflen)
       
  2293 {
       
  2294 	sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
       
  2295 	uint32_t ulen, dlen, num_desc;
       
  2296 	uint64_t addr, len;
       
  2297 	uint8_t *p;
       
  2298 	int ret;
       
  2299 
       
  2300 	if (buflen < 24) {
       
  2301 		stmf_scsilib_send_status(task, STATUS_CHECK,
       
  2302 		    STMF_SAA_INVALID_FIELD_IN_CDB);
       
  2303 		return;
       
  2304 	}
       
  2305 	ulen = READ_SCSI16(buf, uint32_t);
       
  2306 	dlen = READ_SCSI16(buf + 2, uint32_t);
       
  2307 	num_desc = dlen >> 4;
       
  2308 	if (((ulen + 2) != buflen) || ((dlen + 8) != buflen) || (dlen & 0xf) ||
       
  2309 	    (num_desc == 0)) {
       
  2310 		stmf_scsilib_send_status(task, STATUS_CHECK,
       
  2311 		    STMF_SAA_INVALID_FIELD_IN_CDB);
       
  2312 		return;
       
  2313 	}
       
  2314 
       
  2315 	for (p = buf + 8; num_desc; num_desc--, p += 16) {
       
  2316 		addr = READ_SCSI64(p, uint64_t);
       
  2317 		addr <<= sl->sl_data_blocksize_shift;
       
  2318 		len = READ_SCSI32(p+8, uint64_t);
       
  2319 		len <<= sl->sl_data_blocksize_shift;
       
  2320 		ret = sbd_unmap(sl, addr, len);
       
  2321 		if (ret != 0) {
       
  2322 			stmf_scsilib_send_status(task, STATUS_CHECK,
       
  2323 			    STMF_SAA_LBA_OUT_OF_RANGE);
       
  2324 			return;
       
  2325 		}
       
  2326 	}
       
  2327 
       
  2328 unmap_done:
       
  2329 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
       
  2330 }
       
  2331 
  2219 void
  2332 void
  2220 sbd_handle_inquiry(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
  2333 sbd_handle_inquiry(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
  2221 {
  2334 {
  2222 	sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
  2335 	sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
  2223 	uint8_t *cdbp = (uint8_t *)&task->task_cdb[0];
  2336 	uint8_t *cdbp = (uint8_t *)&task->task_cdb[0];
  2226 	uint8_t page_length;
  2339 	uint8_t page_length;
  2227 	uint16_t bsize = 512;
  2340 	uint16_t bsize = 512;
  2228 	uint16_t cmd_size;
  2341 	uint16_t cmd_size;
  2229 	uint32_t xfer_size = 4;
  2342 	uint32_t xfer_size = 4;
  2230 	uint32_t mgmt_url_size = 0;
  2343 	uint32_t mgmt_url_size = 0;
       
  2344 	uint8_t exp;
       
  2345 	uint64_t s;
  2231 	char *mgmt_url = NULL;
  2346 	char *mgmt_url = NULL;
  2232 
  2347 
  2233 
  2348 
  2234 	byte0 = DTYPE_DIRECT;
  2349 	byte0 = DTYPE_DIRECT;
  2235 	/*
  2350 	/*
  2378 	p = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP);
  2493 	p = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP);
  2379 
  2494 
  2380 	switch (cdbp[2]) {
  2495 	switch (cdbp[2]) {
  2381 	case 0x00:
  2496 	case 0x00:
  2382 		page_length = 4 + (mgmt_url_size ? 1 : 0);
  2497 		page_length = 4 + (mgmt_url_size ? 1 : 0);
       
  2498 		if (sl->sl_flags & SL_UNMAP_ENABLED)
       
  2499 			page_length += 2;
  2383 
  2500 
  2384 		p[0] = byte0;
  2501 		p[0] = byte0;
  2385 		p[3] = page_length;
  2502 		p[3] = page_length;
  2386 		/* Supported VPD pages in ascending order */
  2503 		/* Supported VPD pages in ascending order */
  2387 		{
  2504 		{
  2390 			p[i++] = 0x80;
  2507 			p[i++] = 0x80;
  2391 			p[i++] = 0x83;
  2508 			p[i++] = 0x83;
  2392 			if (mgmt_url_size != 0)
  2509 			if (mgmt_url_size != 0)
  2393 				p[i++] = 0x85;
  2510 				p[i++] = 0x85;
  2394 			p[i++] = 0x86;
  2511 			p[i++] = 0x86;
       
  2512 			if (sl->sl_flags & SL_UNMAP_ENABLED) {
       
  2513 				p[i++] = 0xb0;
       
  2514 				p[i++] = 0xb2;
       
  2515 			}
  2395 		}
  2516 		}
  2396 		xfer_size = page_length + 4;
  2517 		xfer_size = page_length + 4;
  2397 		break;
  2518 		break;
  2398 
  2519 
  2399 	case 0x80:
  2520 	case 0x80:
  2477 		 * to reflect the queue tag handling if/when
  2598 		 * to reflect the queue tag handling if/when
  2478 		 * that is implemented.  For now, we're going
  2599 		 * that is implemented.  For now, we're going
  2479 		 * to claim support only for Simple TA.
  2600 		 * to claim support only for Simple TA.
  2480 		 */
  2601 		 */
  2481 		p[5] = 1;
  2602 		p[5] = 1;
       
  2603 		xfer_size = page_length + 4;
       
  2604 		break;
       
  2605 
       
  2606 	case 0xb0:
       
  2607 		if ((sl->sl_flags & SL_UNMAP_ENABLED) == 0) {
       
  2608 			stmf_scsilib_send_status(task, STATUS_CHECK,
       
  2609 			    STMF_SAA_INVALID_FIELD_IN_CDB);
       
  2610 			goto err_done;
       
  2611 		}
       
  2612 		page_length = 0x3c;
       
  2613 		p[0] = byte0;
       
  2614 		p[1] = 0xb0;
       
  2615 		p[3] = page_length;
       
  2616 		p[20] = p[21] = p[22] = p[23] = 0xFF;
       
  2617 		p[24] = p[25] = p[26] = p[27] = 0xFF;
       
  2618 		xfer_size = page_length + 4;
       
  2619 		break;
       
  2620 
       
  2621 	case 0xb2:
       
  2622 		if ((sl->sl_flags & SL_UNMAP_ENABLED) == 0) {
       
  2623 			stmf_scsilib_send_status(task, STATUS_CHECK,
       
  2624 			    STMF_SAA_INVALID_FIELD_IN_CDB);
       
  2625 			goto err_done;
       
  2626 		}
       
  2627 		page_length = 4;
       
  2628 		p[0] = byte0;
       
  2629 		p[1] = 0xb2;
       
  2630 		p[3] = page_length;
       
  2631 
       
  2632 		exp = (uint8_t)sl->sl_data_blocksize_shift;
       
  2633 		s = sl->sl_lu_size >> sl->sl_data_blocksize_shift;
       
  2634 		while (s & ((uint64_t)0xFFFFFFFF80000000ull)) {
       
  2635 			s >>= 1;
       
  2636 			exp++;
       
  2637 		}
       
  2638 		p[4] = exp;
       
  2639 		p[5] = 0xc0;
  2482 		xfer_size = page_length + 4;
  2640 		xfer_size = page_length + 4;
  2483 		break;
  2641 		break;
  2484 
  2642 
  2485 	default:
  2643 	default:
  2486 		stmf_scsilib_send_status(task, STATUS_CHECK,
  2644 		stmf_scsilib_send_status(task, STATUS_CHECK,
  2906 	if ((cdb0 == SCMD_MODE_SELECT) || (cdb0 == SCMD_MODE_SELECT_G1)) {
  3064 	if ((cdb0 == SCMD_MODE_SELECT) || (cdb0 == SCMD_MODE_SELECT_G1)) {
  2907 		sbd_handle_mode_select(task, initial_dbuf);
  3065 		sbd_handle_mode_select(task, initial_dbuf);
  2908 		return;
  3066 		return;
  2909 	}
  3067 	}
  2910 
  3068 
       
  3069 	if ((cdb0 == SCMD_UNMAP) && (sl->sl_flags & SL_UNMAP_ENABLED)) {
       
  3070 		sbd_handle_unmap(task, initial_dbuf);
       
  3071 		return;
       
  3072 	}
       
  3073 
       
  3074 	if ((cdb0 == SCMD_WRITE_SAME_G4) && (sl->sl_flags & SL_UNMAP_ENABLED)) {
       
  3075 		sbd_handle_write_same(task);
       
  3076 		return;
       
  3077 	}
       
  3078 
  2911 	if (cdb0 == SCMD_TEST_UNIT_READY) {	/* Test unit ready */
  3079 	if (cdb0 == SCMD_TEST_UNIT_READY) {	/* Test unit ready */
  2912 		task->task_cmd_xfer_length = 0;
  3080 		task->task_cmd_xfer_length = 0;
  2913 		stmf_scsilib_send_status(task, STATUS_GOOD, 0);
  3081 		stmf_scsilib_send_status(task, STATUS_GOOD, 0);
  2914 		return;
  3082 		return;
  2915 	}
  3083 	}