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, |
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]; |
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 } |