sbd_scsi.c revision 309bed43992ade65fbe1f15ef7a5e800545915f2
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
f4e76ddf09a338dc23da0904866290ac36274a5bNattuvetty Bhavyan * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* ----------------------- */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Refer Both */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* SPC-2 (rev 20) Table 10 */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* SPC-3 (rev 23) Table 31 */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* ----------------------- */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* PREVENT ALLOW MEDIUM REMOVAL with prevent == 0 */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((((cdb[0]) == SCMD_DOORLOCK) && (((cdb[4]) & 0x3) == 0))) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* SERVICE ACTION IN with READ MEDIA SERIAL NUMBER (0x01) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* MAINTENANCE IN with service actions REPORT ALIASES (0x0Bh) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* REPORT DEVICE IDENTIFIER (0x05) REPORT PRIORITY (0x0Eh) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* REPORT TARGET PORT GROUPS (0x0A) REPORT TIMESTAMP (0x0F) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* ----------------------- */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* SBC-3 (rev 17) Table 3 */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* ----------------------- */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* READ CAPACITY(10) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* READ CAPACITY(16) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* START STOP UNIT with START bit 0 and POWER CONDITION 0 */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[4]) & 0xF0) == 0) && (((cdb[4]) & 0x01) == 0))))
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto/* End of SCSI2_CONFLICT_FREE_CMDS */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void sbd_handle_sync_cache(struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid sbd_handle_read_xfer_completion(struct scsi_task *task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid sbd_handle_short_write_xfer_completion(scsi_task_t *task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid sbd_handle_short_write_transfers(scsi_task_t *task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetostatic void sbd_handle_sync_cache(struct scsi_task *task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid sbd_handle_mode_select_xfer(scsi_task_t *task, uint8_t *buf,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid sbd_handle_mode_select(scsi_task_t *task, stmf_data_buf_t *dbuf);
f4e76ddf09a338dc23da0904866290ac36274a5bNattuvetty Bhavyanextern void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoextern int sbd_pgr_reservation_conflict(scsi_task_t *);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoextern void sbd_pgr_remove_it_handle(sbd_lu_t *, sbd_it_data_t *);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoextern void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoextern void sbd_handle_pgr_out_cmd(scsi_task_t *, stmf_data_buf_t *);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoextern void sbd_handle_pgr_out_data(scsi_task_t *, stmf_data_buf_t *);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * IMPORTANT NOTE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * =================
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The whole world here is based on the assumption that everything within
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a scsi task executes in a single threaded manner, even the aborts.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Dont ever change that. There wont be any performance gain but there
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * will be tons of race conditions.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_do_read_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Lets try not to hog all the buffers the port has. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (task->task_cmd_xfer_length < (32 * 1024))) ? 2 :
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = scmd->len > dbuf->db_buf_size ? dbuf->db_buf_size : scmd->len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iolen = min(len - buflen, dbuf->db_sglist[ndx].seg_length);
427fcaf873956aad428be801380a44e59d38b8b5tim szeto if (sbd_data_read(sl, task, laddr, (uint64_t)iolen,
8e326937258295218b5a1f9a63fa6bb760376bbeZhong Wang dbuf->db_sglist[ndx].seg_addr) != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Do not need to do xfer anymore, just complete it */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_read_xfer_completion(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte maxsize = (scmd->len > (128*1024)) ? 128*1024 : scmd->len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * A bad port implementation can keep on failing the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the request but keep on sending us a false
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_read_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_nbytes_transferred += dbuf->db_data_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->len == 0 || scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return; /* wait for all buffers to complete */
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang /* allocate new dbuf */
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang maxsize = (scmd->len > (128*1024)) ? 128*1024 : scmd->len;
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang } while ((dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_read(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[10], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((initial_dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_xfer_data(task, dbuf, STMF_IOF_LU_DONE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_do_write_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting struct stmf_data_buf *dbuf, uint8_t dbuf_reusable)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Lets try not to hog all the buffers the port has. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (task->task_cmd_xfer_length < (32 * 1024))) ? 2 :
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting ((dbuf->db_flags & DB_DONT_REUSE) || (dbuf_reusable == 0))) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting /* free current dbuf and allocate a new one */
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting maxsize = (scmd->len > (128*1024)) ? 128*1024 :
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((dbuf == NULL) && (old_minsize > minsize) &&
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting len = scmd->len > dbuf->db_buf_size ? dbuf->db_buf_size :
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting scmd->nbufs++; /* outstanding port xfers and bufs used */
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if ((scmd->len != 0) && (scmd->nbufs < bufs_to_take)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_write_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *dbuf, uint8_t dbuf_reusable)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting * Decrement the count to indicate the port xfer
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting * into the dbuf has completed even though the buf is
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting * still in use here in the LU provider.
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting * Initiate the next port xfer to occur in parallel
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting * with writing this buf.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (buflen = 0, ndx = 0; (buflen < dbuf->db_data_size) &&
427fcaf873956aad428be801380a44e59d38b8b5tim szeto if (sbd_data_write(sl, task, laddr, (uint64_t)iolen,
8e326937258295218b5a1f9a63fa6bb760376bbeZhong Wang dbuf->db_sglist[ndx].seg_addr) != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->len == 0 || scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return; /* wait for all buffers to complete */
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * If SYNC_WRITE flag is on then we need to flush
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * cache before sending status.
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * Note: this may be a no-op because of how
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * SL_WRITEBACK_CACHE_DISABLE and
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * SL_FLUSH_ON_DISABLED_WRITECACHE are set, but not
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * worth code complexity of checking those in this code
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * path, SBD_SCSI_CMD_SYNC_WRITE is rarely set.
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita if ((scmd->flags & SBD_SCSI_CMD_SYNC_WRITE) &&
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita (sbd_flush_data_cache(sl, 0) != SBD_SUCCESS)) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita stmf_scsilib_send_status(task, STATUS_CHECK,
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita STMF_SAA_WRITE_ERROR);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita stmf_scsilib_send_status(task, STATUS_GOOD, 0);
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting sbd_do_write_xfer(task, scmd, dbuf, dbuf_reusable);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_write(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t op = task->task_cdb[0], do_immediate_data = 0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita uint8_t sync_wr_flag = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[10], uint32_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita } else if (op == SCMD_WRITE_VERIFY) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita len = READ_SCSI16(&task->task_cdb[7], uint32_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita sync_wr_flag = SBD_SCSI_CMD_SYNC_WRITE;
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita } else if (op == SCMD_WRITE_VERIFY_G5) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita len = READ_SCSI32(&task->task_cdb[6], uint32_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita sync_wr_flag = SBD_SCSI_CMD_SYNC_WRITE;
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita } else if (op == SCMD_WRITE_VERIFY_G4) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita len = READ_SCSI32(&task->task_cdb[10], uint32_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita sync_wr_flag = SBD_SCSI_CMD_SYNC_WRITE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if ((initial_dbuf != NULL) && (task->task_flags & TF_INITIAL_BURST)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* protocol error */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita scmd->flags = SBD_SCSI_CMD_ACTIVE | sync_wr_flag;
427fcaf873956aad428be801380a44e59d38b8b5tim szeto * Accout for data passed in this write command
427fcaf873956aad428be801380a44e59d38b8b5tim szeto (void) stmf_xfer_data(task, dbuf, STMF_IOF_STATS_ONLY);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_write_xfer_completion(task, scmd, dbuf, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Utility routine to handle small non performance data transfers to the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * initiators. dbuf is an initial data buf (if any), 'p' points to a data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * buffer which is source of data for transfer, cdb_xfer_size is the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * transfer size based on CDB, cmd_xfer_size is the actual amount of data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * which this command would transfer (the size of data pointed to by 'p').
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_short_read_transfers(scsi_task_t *task, stmf_data_buf_t *dbuf,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *p, uint32_t cdb_xfer_size, uint32_t cmd_xfer_size)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd_xfer_size = min(cmd_xfer_size, cdb_xfer_size);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = stmf_alloc_dbuf(task, cmd_xfer_size, &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (bufsize = 0, ndx = 0; bufsize < cmd_xfer_size; ndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_short_read_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_nbytes_transferred = dbuf->db_data_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_handle_short_write_transfers(scsi_task_t *task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_lu_private = kmem_zalloc(sizeof (sbd_cmd_t),
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto dbuf = stmf_alloc_dbuf(task, cdb_xfer_size, &minsize, 0);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_short_write_xfer_completion(task, dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_handle_short_write_xfer_completion(scsi_task_t *task,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * For now lets assume we will get only one sglist element
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * for short writes. If that ever changes, we should allocate
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * a local buffer and copy all the sg elements to one linear space.
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_nbytes_transferred = dbuf->db_data_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Lets find out who to call */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte dbuf->db_sglist[0].seg_addr, dbuf->db_data_size);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* This should never happen */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto s = sl->sl_lu_size >> sl->sl_data_blocksize_shift;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto blksize = ((uint16_t)1) << sl->sl_data_blocksize_shift;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (s & 0xffffffff00000000ull) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p, 8, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb_len = READ_SCSI32(&task->task_cdb[10], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_calc_geometry(uint64_t s, uint16_t blksize, uint8_t *nsectors,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto *ncyl = s / ((uint64_t)blksize * (uint64_t)(*nsectors) *
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p = buf; /* buf is assumed to be zeroed out and large enough */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Now validate the command */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((cdb[2] == 0) || (page == MODEPAGE_ALLPAGES) || (page == 0x08) ||
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (page == 0x0A) || (page == 0x03) || (page == 0x04)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((cmd_size < header_size) || (pc_valid == 0)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* We will update the length in the mode header at the end */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Block dev device specific param in mode param header has wp bit */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* We are not going to return any block descriptor */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto nbytes = ((uint16_t)1) << sl->sl_data_blocksize_shift;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_calc_geometry(s, nbytes, &nsectors, &nheads, &ncyl);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((page == 0x03) || (page == MODEPAGE_ALLPAGES)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n] = 0x03;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((page == 0x04) || (page == MODEPAGE_ALLPAGES)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n] = 0x04;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((page == MODEPAGE_CACHING) || (page == MODEPAGE_ALLPAGES)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_caching_page->mode_page.code = MODEPAGE_CACHING;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_caching_page->mode_page.ps = 1; /* A saveable page */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Current */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) == 0) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Changeable */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto n += (sizeof (struct mode_page) +
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((page == MODEPAGE_CTRL_MODE) || (page == MODEPAGE_ALLPAGES)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_control_page = (struct mode_control_scsi3 *)&p[n];
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_control_page->mode_page.code = MODEPAGE_CTRL_MODE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* If not looking for changeable values, report this. */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_control_page->que_mod = CTRL_QMOD_UNRESTRICT;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto n += (sizeof (struct mode_page) +
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (n > 255) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * Mode parameter header length doesn't include the number
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * of bytes in the length field, so adjust the count.
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * Byte count minus header length field size.
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Byte count minus header length field size. */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_short_read_transfers(task, initial_dbuf, buf,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_handle_mode_select(scsi_task_t *task, stmf_data_buf_t *dbuf)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto cmd_xfer_len = READ_SCSI16(&task->task_cdb[7], uint32_t);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* zero byte mode selects are allowed */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_short_write_transfers(task, dbuf, cmd_xfer_len);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_handle_mode_select_xfer(scsi_task_t *task, uint8_t *buf, uint32_t buflen)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bd_len = hdr_len == 4 ? buf[3] : READ_SCSI16(&buf[6], int);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((buf[0] != 8) || (buflen != ((uint32_t)buf[1] + 2))) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* All good. Lets handle the write cache change, if any */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* set on the device passed, now set the flags */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto it->sbd_it_ua_conditions |= SBD_UA_MODE_PARAMETERS_CHANGED;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * This function parse through a string, passed to it as a pointer to a string,
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * by adjusting the pointer to the first non-space character and returns
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * the count/length of the first bunch of non-space characters. Multiple
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * Management URLs are stored as a space delimited string in sl_mgmt_url
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * field of sbd_lu_t. This function is used to retrieve one url at a time.
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * i/p : pointer to pointer to a url string
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * o/p : Adjust the pointer to the url to the first non white character
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * and returns the length of the URL
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan if (*url == ' ' || *url == '\t' || *url == '\n') {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyansbd_handle_inquiry(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Basic protocol checks.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((((cdbp[1] & 1) == 0) && cdbp[2]) || cdbp[5]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Zero byte allocation length is not an error. Just
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * return success.
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan cmd_size = (((uint16_t)cdbp[3]) << 8) | cdbp[4];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Standard inquiry
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_rdf = 2; /* Response data format for SPC-3 */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Adding Version Descriptors */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* SAM-3 no version */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* transport */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan switch (task->task_lport->lport_id->protocol_id) {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Currently no claims of conformance */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Currently no claims of conformance */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* SPC-3 no version */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* SBC-2 no version */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p, cmd_size,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * EVPD handling
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Default 512 bytes may not be enough, increase bsize if necessary */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan if (cdbp[2] == 0x83 || cdbp[2] == 0x85) {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan page_length = 4 + (mgmt_url_size ? 1 : 0);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Supported VPD pages in ascending order */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[i++] = 0x80;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[i++] = 0x83;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[i++] = 0x85;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[i++] = 0x86;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(sl->sl_serial_no, p + 4, sl->sl_serial_no_size);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* if no serial num is specified set 4 spaces */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan xfer_size = stmf_scsilib_prepare_vpd_page83(task, p,
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan STMF_VPD_TP_GROUP|STMF_VPD_RELATIVE_TP_ID);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan stmf_scsilib_send_status(task, STATUS_CHECK,
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Creating Network Service Descriptors */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Null terminated and 4 Byte aligned */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * SPC-3r23 : Table 320 (Sec 7.6.5)
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * (Network service descriptor format
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * Note: Hard coding service type as
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * "Storage Configuration Service".
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* skip to next mgmt url if any */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Total descriptor length */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Bits 0, 1, and 2 will need to be updated
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to reflect the queue tag handling if/when
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * that is implemented. For now, we're going
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to claim support only for Simple TA.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p, cmd_size,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_alloc(sizeof (sbd_cmd_t), KM_NOSLEEP)) != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_remove_it_handle(sbd_lu_t *sl, sbd_it_data_t *it)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto DTRACE_PROBE2(itl__nexus__end, stmf_lu_t *, sl->sl_lu,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_check_and_clear_scsi2_reservation(sbd_lu_t *sl, sbd_it_data_t *it)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((sl->sl_flags & SL_LU_HAS_SCSI2_RESERVATION) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If we dont have any reservations, just get out. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Find the I_T nexus which is holding the reservation. */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We were passed an I_T nexus. If this nexus does not hold
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the reservation, do nothing. This is why this function is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * called "check_and_clear".
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_flags &= ~SBD_IT_HAS_SCSI2_RESERVATION;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_new_task(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it = (sbd_it_data_t *)kmem_zalloc(sizeof (*it), KM_NOSLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_session_id = task->task_session->ss_session_id;
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto DTRACE_PROBE1(itl__nexus__start, scsi_task *, task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_register_itl_handle(task->task_lu, task->task_lun_no,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else if (it->sbd_it_flags & SBD_IT_PGR_CHECK_FLAG) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * if we're transitioning between access
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * states, return NOT READY
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (sl->sl_access_state == SBD_LU_TRANSITION_TO_STANDBY ||
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte sl->sl_access_state == SBD_LU_TRANSITION_TO_ACTIVE) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Checking ua conditions as per SAM3R14 5.3.2 specified order */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((it->sbd_it_ua_conditions) && (task->task_cdb[0] != SCMD_INQUIRY)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK, saa);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Reservation conflict checks */
f4e76ddf09a338dc23da0904866290ac36274a5bNattuvetty Bhavyan if (sl->sl_access_state == SBD_LU_ACTIVE) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte } else if ((sl->sl_flags & SL_LU_HAS_SCSI2_RESERVATION) &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte ((it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) == 0)) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (!(SCSI2_CONFLICT_FREE_CMDS(task->task_cdb))) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Rest of the ua conndition checks */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((it->sbd_it_ua_conditions) && (task->task_cdb[0] != SCMD_INQUIRY)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (it->sbd_it_ua_conditions & SBD_UA_CAPACITY_CHANGED) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_ua_conditions &= ~SBD_UA_CAPACITY_CHANGED;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK, saa);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * is this a short write?
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * if so, we'll need to wait until we have the buffer
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * before proxying the command
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb0 == SCMD_READ) || (cdb0 == SCMD_WRITE)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_PORT_LOAD_HIGH) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* If not owner don't release it, just return good */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto it->sbd_it_flags &= ~SBD_IT_HAS_SCSI2_RESERVATION;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* If not owner, return conflict status */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_rs_owner_session_id = it->sbd_it_session_id;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * LU provider needs to store unretrieved sense data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (e.g. after power-on/reset). For now, we'll just
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * return good status with no sense.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb1 & ~1) || task->task_cdb[2] || task->task_cdb[3] ||
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Report Target Port Groups */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_handle_report_tpgs(task, initial_dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((cdb0 == SCMD_MODE_SENSE) || (cdb0 == SCMD_MODE_SENSE_G1)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((cdb0 == SCMD_MODE_SELECT) || (cdb0 == SCMD_MODE_SELECT_G1)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_TEST_UNIT_READY) { /* Test unit ready */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_READ_CAPACITY) { /* Read Capacity */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_SVC_ACTION_IN_G4) { /* Read Capacity or read long */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * } else if (cdb1 == SSVC_ACTION_READ_LONG_G4) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * sbd_handle_read(task, initial_dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * if (cdb0 == SCMD_SVC_ACTION_OUT_G4) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * if (cdb1 == SSVC_ACTION_WRITE_LONG_G4) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * sbd_handle_write(task, initial_dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * Something more likely needs to be done here.
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * Write and Verify use the same path as write, but don't clutter the
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * performance path above with checking for write_verify opcodes. We
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * rely on zfs's integrity checks for the "Verify" part of Write &
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * Verify. (Even if we did a read to "verify" we'd merely be reading
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * cache, not actual media.)
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * a) only support this if sbd_is_zvol, and
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * b) run the IO through the normal write path with a forced
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * sbd_flush_data_cache at the end.
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita if ((sl->sl_flags & SL_ZFS_META) && (
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita cdb0 == SCMD_WRITE_VERIFY ||
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita cdb0 == SCMD_WRITE_VERIFY_G4 ||
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita cdb0 == SCMD_WRITE_VERIFY_G5)) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita sbd_handle_write(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_OPCODE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_dbuf_xfer_done(struct scsi_task *task, struct stmf_data_buf *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((scmd == NULL) || ((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_read_xfer_completion(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_write_xfer_completion(task, scmd, dbuf, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_xfer_completion(task, scmd, dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_short_write_xfer_completion(task, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_PANIC, "Unknown cmd type, task = %p", (void *)task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto "sbd_send_status_done: this should not have been called");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Aborts are synchronus w.r.t. I/O AND
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * All the I/O which SBD does is synchronous AND
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Everything within a task is single threaded.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If this function is called, we are doing nothing with this task
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * inside of sbd module.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_abort(struct stmf_lu *lu, int abort_cmd, void *arg, uint32_t flags)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_check_and_clear_scsi2_reservation(sl, (sbd_it_data_t *)arg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_ctl(STMF_CMD_LU_ONLINE_COMPLETE, lu, &st);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_ctl(STMF_CMD_LU_OFFLINE_COMPLETE, lu, &st);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Fallthrough */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_info(uint32_t cmd, stmf_lu_t *lu, void *arg, uint8_t *buf,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_deregister_all_lu_itl_handles(lu) != STMF_SUCCESS) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((sl->sl_data_vtype == VREG) || (sl->sl_data_vtype == VBLK)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (VOP_FSYNC(sl->sl_data_vp, FSYNC, kcred, NULL))
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (((sl->sl_data_vtype == VCHR) || (sl->sl_data_vtype == VBLK)) &&
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ret = VOP_IOCTL(sl->sl_data_vp, DKIOCFLUSHWRITECACHE, NULL,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else if (ret != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine if this is a 10 or 16 byte CDB
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_cdb[0] == SCMD_SYNCHRONIZE_CACHE_G4)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine other requested parameters
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We don't have a non-volatile cache, so don't care about SYNC_NV.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Do not support the IMMED bit.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check to be sure we're not being asked to sync an LBA
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * that is out of range. While checking, verify reserved fields.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_cdb[1] & 0xf9) || task->task_cdb[14] ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[10], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_cdb[1] & 0xf9) || task->task_cdb[6] ||