sbd_scsi.c revision fcf3ce441efd61da9bb2884968af01cb7c1452cc
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
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 *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or http://www.opensolaris.org/os/licensing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
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 *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/conf.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/file.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/ddi.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/sunddi.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/modctl.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/scsi/scsi.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/scsi/impl/scsi_reset_notify.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/scsi/generic/mode.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/disp.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/byteorder.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/atomic.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <stmf.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <lpif.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <portif.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <stmf_ioctl.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <stmf_sbd.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sbd_impl.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t sbd_lu_reset_state(stmf_lu_t *lu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void sbd_handle_sync_cache(struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid sbd_handle_read_xfer_completion(struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd, struct stmf_data_buf *dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
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 Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_do_read_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst = (sbd_store_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t len, buflen, iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int ndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int bufs_to_take;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Lets try not to hog all the buffers the port has. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bufs_to_take = ((task->task_max_nbufs > 2) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (task->task_cmd_xfer_length < (32 * 1024))) ? 2 :
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_max_nbufs;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = scmd->len > dbuf->db_buf_size ? dbuf->db_buf_size : scmd->len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte laddr = scmd->addr + scmd->current_ro + slu->sl_sli->sli_lu_data_offset;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (buflen = 0, ndx = 0; (buflen < len) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ndx < dbuf->db_sglist_length); ndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iolen = min(len - buflen, dbuf->db_sglist[ndx].seg_length);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iolen == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (sst->sst_data_read(sst, laddr, (uint64_t)iolen,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_sglist[0].seg_addr) != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Do not need to do xfer anymore, just complete it */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_data_size = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_xfer_status = STMF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_read_xfer_completion(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte buflen += iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte laddr += (uint64_t)iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_relative_offset = scmd->current_ro;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_data_size = buflen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_flags = DB_DIRECTION_TO_RPORT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_xfer_data(task, dbuf, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->len -= buflen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->current_ro += buflen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->len && (scmd->nbufs < bufs_to_take)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t maxsize, minsize, old_minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte maxsize = (scmd->len > (128*1024)) ? 128*1024 : scmd->len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte minsize = maxsize >> 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte do {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * A bad port implementation can keep on failing the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the request but keep on sending us a false
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * minsize.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte old_minsize = minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (minsize >= 512));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->nbufs++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_do_read_xfer(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_read_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf->db_xfer_status != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_xfer_status, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
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 stmf_free_dbuf(task, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->nbufs--;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->nbufs)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return; /* wait for all buffers to complete */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_READ_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_do_read_xfer(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_read(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t lba, laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t op = task->task_cdb[0];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst = (sbd_store_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_data_buf_t *dbuf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int fast_path;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (op == SCMD_READ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI21(&task->task_cdb[1], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = (uint32_t)task->task_cdb[4];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = 256;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_READ_G1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI16(&task->task_cdb[7], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_READ_G5) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[6], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_READ_G4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[10], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_OPCODE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte laddr = lba << slu->sl_shift_count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len <<= slu->sl_shift_count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((laddr + (uint64_t)len) > slu->sl_sli->sli_lu_data_size) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_LBA_OUT_OF_RANGE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len != task->task_expected_xfer_length) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fast_path = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = (len > task->task_expected_xfer_length) ?
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length : len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fast_path = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (initial_dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t maxsize, minsize, old_minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte maxsize = (len > (128*1024)) ? 128*1024 : len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte minsize = maxsize >> 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte do {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte old_minsize = minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte initial_dbuf = stmf_alloc_dbuf(task, maxsize,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((initial_dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (minsize >= 512));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (initial_dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_ALLOC_FAILURE, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = initial_dbuf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((dbuf->db_buf_size >= len) && fast_path &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (dbuf->db_sglist_length == 1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (sst->sst_data_read(sst,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte laddr + slu->sl_sli->sli_lu_data_offset, (uint64_t)len,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_sglist[0].seg_addr) == STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_relative_offset = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_data_size = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_flags = DB_SEND_STATUS_GOOD |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DB_DIRECTION_TO_RPORT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_xfer_data(task, dbuf, STMF_IOF_LU_DONE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_READ_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_lu_private) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_lu_private = scmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags = SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->cmd_type = SBD_CMD_SCSI_READ;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->nbufs = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->addr = laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->len = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->current_ro = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_do_read_xfer(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_do_write_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int bufs_to_take;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Lets try not to hog all the buffers the port has. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bufs_to_take = ((task->task_max_nbufs > 2) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (task->task_cmd_xfer_length < (32 * 1024))) ? 2 :
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_max_nbufs;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = scmd->len > dbuf->db_buf_size ? dbuf->db_buf_size : scmd->len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_relative_offset = scmd->current_ro;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_data_size = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_flags = DB_DIRECTION_FROM_RPORT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_xfer_data(task, dbuf, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->len -= len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->current_ro += len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->len && (scmd->nbufs < bufs_to_take)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t maxsize, minsize, old_minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte maxsize = (scmd->len > (128*1024)) ? 128*1024 : scmd->len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte minsize = maxsize >> 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte do {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte old_minsize = minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (minsize >= 512));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->nbufs++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_do_write_xfer(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
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)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst = (sbd_store_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t buflen, iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int ndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf->db_xfer_status != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_xfer_status, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte goto WRITE_XFER_DONE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte laddr = scmd->addr + dbuf->db_relative_offset +
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_sli->sli_lu_data_offset;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (buflen = 0, ndx = 0; (buflen < dbuf->db_data_size) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ndx < dbuf->db_sglist_length); ndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iolen = min(dbuf->db_data_size - buflen,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_sglist[ndx].seg_length);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iolen == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (sst->sst_data_write(sst, laddr, (uint64_t)iolen,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_sglist[0].seg_addr) != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte buflen += iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte laddr += (uint64_t)iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_nbytes_transferred += buflen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteWRITE_XFER_DONE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->len == 0 || scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_free_dbuf(task, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->nbufs--;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->nbufs)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return; /* wait for all buffers to complete */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_WRITE_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf_reusable == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t maxsize, minsize, old_minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* free current dbuf and allocate a new one */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_free_dbuf(task, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte maxsize = (scmd->len > (128*1024)) ? 128*1024 : scmd->len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte minsize = maxsize >> 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte do {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte old_minsize = minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (minsize >= 512));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->nbufs --;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->nbufs == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_ALLOC_FAILURE, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_do_write_xfer(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_write(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t lba, laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t op = task->task_cdb[0], do_immediate_data = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst = (sbd_store_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_data_buf_t *dbuf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (op == SCMD_WRITE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI21(&task->task_cdb[1], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = (uint32_t)task->task_cdb[4];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = 256;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_WRITE_G1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI16(&task->task_cdb[7], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_WRITE_G5) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[6], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_WRITE_G4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[10], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_OPCODE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte laddr = lba << slu->sl_shift_count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len <<= slu->sl_shift_count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((laddr + (uint64_t)len) > slu->sl_sli->sli_lu_data_size) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_LBA_OUT_OF_RANGE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = (len > task->task_expected_xfer_length) ?
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length : len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (initial_dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t maxsize, minsize, old_minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte maxsize = (len > (128*1024)) ? 128*1024 : len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte minsize = maxsize >> 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte do {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte old_minsize = minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte initial_dbuf = stmf_alloc_dbuf(task, maxsize,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((initial_dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (minsize >= 512));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (initial_dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_ALLOC_FAILURE, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (task->task_flags & TF_INITIAL_BURST) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (initial_dbuf->db_data_size > len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (initial_dbuf->db_data_size >
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* protocol error */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_INVALID_ARG, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte initial_dbuf->db_data_size = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte do_immediate_data = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = initial_dbuf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_lu_private) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_lu_private = scmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags = SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->cmd_type = SBD_CMD_SCSI_WRITE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->nbufs = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->addr = laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->len = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->current_ro = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (do_immediate_data) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->len -= dbuf->db_data_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->current_ro += dbuf->db_data_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_xfer_status = STMF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_write_xfer_completion(task, scmd, dbuf, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_do_write_xfer(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
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 Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
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{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t bufsize, ndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd_xfer_size = min(cmd_xfer_size, cdb_xfer_size);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = cmd_xfer_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length = cmd_xfer_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd_xfer_size = min(cmd_xfer_size,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cmd_xfer_size == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t minsize = cmd_xfer_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = stmf_alloc_dbuf(task, cmd_xfer_size, &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_ALLOC_FAILURE, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (bufsize = 0, ndx = 0; bufsize < cmd_xfer_size; ndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *d;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t s;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte d = dbuf->db_sglist[ndx].seg_addr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte s = min((cmd_xfer_size - bufsize),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_sglist[ndx].seg_length);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(p+bufsize, d, s);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bufsize += s;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_relative_offset = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_data_size = cmd_xfer_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_flags = DB_DIRECTION_TO_RPORT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_lu_private == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_lu_private =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->cmd_type = SBD_CMD_SMALL_READ;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags = SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_xfer_data(task, dbuf, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_short_read_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf->db_xfer_status != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_xfer_status, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_nbytes_transferred = dbuf->db_data_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_read_capacity(struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst = (sbd_store_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_info_t *sli = slu->sl_sli;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t cdb_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t p[32];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t s;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte s = sli->sli_lu_data_size >> slu->sl_shift_count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte s--;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (task->task_cdb[0]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SCMD_READ_CAPACITY:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (s & 0xffffffff00000000ull) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[0] = p[1] = p[2] = p[3] = 0xFF;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[0] = (s >> 24) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[1] = (s >> 16) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[2] = (s >> 8) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[3] = s & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[4] = 0; p[5] = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[6] = (sli->sli_blocksize >> 8) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[7] = sli->sli_blocksize & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p, 8, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SCMD_SVC_ACTION_IN_G4:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb_len = READ_SCSI32(&task->task_cdb[10], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(p, 32);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[0] = (s >> 56) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[1] = (s >> 48) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[2] = (s >> 40) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[3] = (s >> 32) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[4] = (s >> 24) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[5] = (s >> 16) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[6] = (s >> 8) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[7] = s & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[10] = (sli->sli_blocksize >> 8) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[11] = sli->sli_blocksize & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb_len, 32);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic uint8_t sbd_p3[] =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {3, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 2, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte 0, 0, 0, 0, 0x80, 0, 0, 0};
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic uint8_t sbd_p4[] =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {4, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte 0, 0, 0, 0, 0x15, 0x18, 0, 0};
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic uint8_t sbd_pa[] = {0xa, 0xa, 0, 0x10, 0, 0, 0, 0, 0, 0, 0, 0};
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic uint8_t sbd_bd[] = {0, 0, 0, 0, 0, 0, 0x02, 0};
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_mode_sense(struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst = (sbd_store_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_info_t *sli = slu->sl_sli;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t cmd_size, hdrsize, xfer_size, ncyl;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t payload_buf[8 + 8 + 24 + 24 + 12];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *payload, *p;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t ctrl, page;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint16_t ps;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t s = sli->sli_lu_data_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t dbd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p = &task->task_cdb[0];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte page = p[2] & 0x3F;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ctrl = (p[2] >> 6) & 3;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbd = p[1] & 0x08;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte hdrsize = (p[0] == SCMD_MODE_SENSE) ? 4 : 8;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd_size = (p[0] == SCMD_MODE_SENSE) ? p[4] :
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte READ_SCSI16(&p[7], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (page) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x03:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ps = hdrsize + sizeof (sbd_p3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x04:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ps = hdrsize + sizeof (sbd_p4);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x0A:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ps = hdrsize + sizeof (sbd_pa);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MODEPAGE_ALLPAGES:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ps = hdrsize + sizeof (sbd_p3) + sizeof (sbd_p4)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte + sizeof (sbd_pa);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the buffer is big enough, include the block
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * descriptor; otherwise, leave it out.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cmd_size < ps) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbd = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbd == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ps += 8;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte xfer_size = min(cmd_size, ps);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((xfer_size < hdrsize) || (ctrl == 1) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (((task->task_additional_flags &
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte TASK_AF_NO_EXPECTED_XFER_LENGTH) == 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (xfer_size > task->task_expected_xfer_length))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(payload_buf, xfer_size);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (p[0] == SCMD_MODE_SENSE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload_buf[0] = ps - 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ps -= 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *((uint16_t *)payload_buf) = BE_16(ps);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload = payload_buf + hdrsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (page) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x03:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(sbd_p3, payload, sizeof (sbd_p3));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x0A:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(sbd_pa, payload, sizeof (sbd_pa));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case MODEPAGE_ALLPAGES:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbd == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload_buf[3] = sizeof (sbd_bd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(sbd_bd, payload, sizeof (sbd_bd));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload += sizeof (sbd_bd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(sbd_p3, payload, sizeof (sbd_p3));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload += sizeof (sbd_p3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(sbd_pa, payload, sizeof (sbd_pa));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload += sizeof (sbd_pa);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHROUGH */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x04:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(sbd_p4, payload, sizeof (sbd_p4));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (s > 1024 * 1024 * 1024) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload[5] = 16;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload[5] = 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ncyl = (uint32_t)((s/(((uint64_t)payload[5]) * 32 * 512)) + 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload[4] = (uchar_t)ncyl;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload[3] = (uchar_t)(ncyl >> 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte payload[2] = (uchar_t)(ncyl >> 16);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, payload_buf,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd_size, xfer_size);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_inquiry(struct scsi_task *task, struct stmf_data_buf *initial_dbuf,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *p, int bsize)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *cdbp = (uint8_t *)&task->task_cdb[0];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t cmd_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t page_length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Basic protocol checks.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((((cdbp[1] & 1) == 0) && cdbp[2]) || cdbp[5]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Zero byte allocation length is not an error. Just
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * return success.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd_size = (((uint32_t)cdbp[3]) << 8) | cdbp[4];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cmd_size == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags &
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Standard inquiry
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdbp[1] & 1) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct scsi_inquiry *inq = (struct scsi_inquiry *)p;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte page_length = 31;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(inq, page_length + 5);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_dtype = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_ansi = 5; /* SPC-3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_hisup = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_rdf = 2; /* Response data format for SPC-3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_len = page_length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_tpgs = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_cmdque = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) strncpy((char *)inq->inq_vid, "SUN ", 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) strncpy((char *)inq->inq_pid, "COMSTAR ", 16);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) strncpy((char *)inq->inq_revision, "1.0 ", 4);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p, cmd_size,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte min(cmd_size, page_length + 5));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * EVPD handling
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (cdbp[2]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x00:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte page_length = 3;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(p, page_length + 4);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[0] = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[3] = page_length; /* we support 3 pages, 0, 0x83, 0x86 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[5] = 0x83;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[6] = 0x86;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x83:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte page_length = stmf_scsilib_prepare_vpd_page83(task, p,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bsize, 0, STMF_VPD_LU_ID|STMF_VPD_TARGET_ID|
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_VPD_TP_GROUP|STMF_VPD_RELATIVE_TP_ID) - 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x86:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte page_length = 0x3c;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(p, page_length + 4);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[0] = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[1] = 0x86; /* Page 86 response */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[3] = page_length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
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 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[5] = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p, cmd_size,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte min(cmd_size, page_length + 4));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_task_alloc(struct scsi_task *task)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_lu_private =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_alloc(sizeof (sbd_cmd_t), KM_NOSLEEP)) != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_ALLOC_FAILURE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_remove_it_handle(sbd_lu_t *slu, sbd_it_data_t *it)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_it_data_t **ppit;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ppit = &slu->sl_it_list; *ppit != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ppit = &((*ppit)->sbd_it_next)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((*ppit) == it) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *ppit = it->sbd_it_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(it, sizeof (*it));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_check_and_clear_scsi2_reservation(sbd_lu_t *slu, sbd_it_data_t *it)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((slu->sl_flags & SBD_LU_HAS_SCSI2_RESERVATION) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If we dont have any reservations, just get out. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Find the I_T nexus which is holding the reservation. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(it->sbd_it_session_id ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_rs_owner_session_id);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(it != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
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 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_flags &= ~SBD_IT_HAS_SCSI2_RESERVATION;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_flags &= ~SBD_IT_HAS_SCSI2_RESERVATION;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * returns non-zero, if this command can be allowed to run even if the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * lu has been reserved by another initiator.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteint
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_reserve_allow(scsi_task_t *task)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t cdb0 = task->task_cdb[0];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t cdb1 = task->task_cdb[1];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb0 == SCMD_INQUIRY) || (cdb0 == SCMD_READ_CAPACITY) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((cdb0 == SCMD_SVC_ACTION_IN_G4) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (cdb1 == SSVC_ACTION_READ_CAPACITY_G4))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_new_task(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst = (sbd_store_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_it_data_t *it;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t cdb0, cdb1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((it = task->task_lu_itl_handle) == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it->sbd_it_session_id ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_session->ss_session_id) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_BUSY, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it = (sbd_it_data_t *)kmem_zalloc(sizeof (*it), KM_NOSLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_BUSY, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_session_id = task->task_session->ss_session_id;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(task->task_lun_no, it->sbd_it_lun, 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_next = slu->sl_it_list;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_it_list = it;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_register_itl_handle(task->task_lu, task->task_lun_no,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_session, it->sbd_it_session_id, it)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_remove_it_handle(slu, it);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_BUSY, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_lu_itl_handle = it;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_ua_conditions = SBD_UA_POR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_mgmt_function) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_handle_task_mgmt(task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((slu->sl_flags & SBD_LU_HAS_SCSI2_RESERVATION) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!sbd_reserve_allow(task)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STATUS_RESERVATION_CONFLICT, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((it->sbd_it_ua_conditions) && (task->task_cdb[0] != SCMD_INQUIRY)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t saa = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it->sbd_it_ua_conditions & SBD_UA_POR) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_ua_conditions &= ~SBD_UA_POR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte saa = STMF_SAA_POR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (it->sbd_it_ua_conditions & SBD_UA_CAPACITY_CHANGED) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_ua_conditions &= ~SBD_UA_CAPACITY_CHANGED;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_cdb[0] == SCMD_READ_CAPACITY) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((task->task_cdb[0] == SCMD_SVC_ACTION_IN_G4) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (task->task_cdb[1] ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte SSVC_ACTION_READ_CAPACITY_G4))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte saa = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte saa = STMF_SAA_CAPACITY_DATA_HAS_CHANGED;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_ua_conditions = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte saa = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (saa) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK, saa);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb0 = task->task_cdb[0] & 0x1F;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb0 == SCMD_READ) || (cdb0 == SCMD_WRITE)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_PORT_LOAD_HIGH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_QFULL, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_READ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_read(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_write(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb0 = task->task_cdb[0];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb1 = task->task_cdb[1];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_TEST_UNIT_READY) { /* Test unit ready */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_READ_CAPACITY) { /* Read Capacity */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_read_capacity(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_INQUIRY) { /* Inquiry */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *p;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p = (uint8_t *)kmem_zalloc(512, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_inquiry(task, initial_dbuf, p, 512);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(p, 512);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_SVC_ACTION_IN_G4) { /* Read Capacity or read long */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb1 == SSVC_ACTION_READ_CAPACITY_G4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_read_capacity(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * } else if (cdb1 == SSVC_ACTION_READ_LONG_G4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * sbd_handle_read(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if (cdb0 == SCMD_SVC_ACTION_OUT_G4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if (cdb1 == SSVC_ACTION_WRITE_LONG_G4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * sbd_handle_write(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_START_STOP) { /* Start stop */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX Implement power management */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#if 0
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX Remove #if 0 above */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb0 == SCMD_MODE_SELECT) || (cdb0 == SCMD_MODE_SELECT_G1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_mode_select(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb0 == SCMD_MODE_SENSE) || (cdb0 == SCMD_MODE_SENSE_G1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_mode_sense(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_REQUEST_SENSE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
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 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb1 & ~1) || task->task_cdb[2] || task->task_cdb[3] ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cdb[5]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_VERIFY) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Something more likely needs to be done here.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb0 == SCMD_RESERVE) || (cdb0 == SCMD_RELEASE)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (slu->sl_flags & SBD_LU_HAS_SCSI2_RESERVATION) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it->sbd_it_session_id !=
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_rs_owner_session_id) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This can only happen if things were in
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * flux.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STATUS_RESERVATION_CONFLICT, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_RELEASE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_flags &= ~SBD_LU_HAS_SCSI2_RESERVATION;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_flags &= ~SBD_IT_HAS_SCSI2_RESERVATION;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_RESERVE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_flags |= SBD_LU_HAS_SCSI2_RESERVATION;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_flags |= SBD_IT_HAS_SCSI2_RESERVATION;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_rs_owner_session_id = it->sbd_it_session_id;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&slu->sl_it_list_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_SYNCHRONIZE_CACHE ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb0 == SCMD_SYNCHRONIZE_CACHE_G4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_sync_cache(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Report Target Port Groups */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb0 == SCMD_MAINTENANCE_IN) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((cdb1 & 0x1F) == 0x0A)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_handle_report_tpgs(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_OPCODE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_dbuf_xfer_done(struct scsi_task *task, struct stmf_data_buf *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((scmd == NULL) || ((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->cmd_type == SBD_CMD_SCSI_READ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_read_xfer_completion(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (scmd->cmd_type == SBD_CMD_SCSI_WRITE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_write_xfer_completion(task, scmd, dbuf, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (scmd->cmd_type == SBD_CMD_SMALL_READ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_xfer_completion(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_PANIC, "Unknown cmd type, task = %p", (void *)task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_send_status_done(struct scsi_task *task)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_PANIC,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "sbd_send_status_done: this should not have been called");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_task_free(struct scsi_task *task)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_lu_private) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->flags & SBD_SCSI_CMD_ACTIVE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_PANIC, "cmd is active, task = %p",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void *)task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(scmd, sizeof (sbd_cmd_t));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
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 * IT MEANS
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If this function is called, we are doing nothing with this task
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * inside of sbd module.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_abort(struct stmf_lu *lu, int abort_cmd, void *arg, uint32_t flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst = (sbd_store_t *)lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scsi_task_t *task;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (abort_cmd == STMF_LU_RESET_STATE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (sbd_lu_reset_state(lu));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (abort_cmd == STMF_LU_ITL_HANDLE_REMOVED) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_check_and_clear_scsi2_reservation(slu,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (sbd_it_data_t *)arg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_remove_it_handle(slu, (sbd_it_data_t *)arg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(abort_cmd == STMF_LU_ABORT_TASK);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task = (scsi_task_t *)arg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_lu_private) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->flags & SBD_SCSI_CMD_ACTIVE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_ABORT_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_NOT_FOUND);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_ctl(struct stmf_lu *lu, int cmd, void *arg)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst = (sbd_store_t *)lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_change_status_t st;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT((cmd == STMF_CMD_LU_ONLINE) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (cmd == STMF_CMD_LU_OFFLINE) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (cmd == STMF_ACK_LU_ONLINE_COMPLETE) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (cmd == STMF_ACK_LU_OFFLINE_COMPLETE));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = STMF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_additional_info = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (cmd) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case STMF_CMD_LU_ONLINE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (slu->sl_state == STMF_STATE_ONLINE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = STMF_ALREADY;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else if (slu->sl_state != STMF_STATE_OFFLINE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = STMF_FAILURE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (st.st_completion_status == STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state = STMF_STATE_ONLINING;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state_not_acked = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = sst->sst_online(sst);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (st.st_completion_status != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state = STMF_STATE_OFFLINE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state_not_acked = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state = STMF_STATE_ONLINE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_ctl(STMF_CMD_LU_ONLINE_COMPLETE, lu, &st);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case STMF_CMD_LU_OFFLINE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (slu->sl_state == STMF_STATE_OFFLINE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = STMF_ALREADY;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else if (slu->sl_state != STMF_STATE_ONLINE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = STMF_FAILURE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (st.st_completion_status == STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state = STMF_STATE_OFFLINING;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state_not_acked = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = sst->sst_offline(sst);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (st.st_completion_status != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state = STMF_STATE_ONLINE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state_not_acked = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state = STMF_STATE_OFFLINE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_ctl(STMF_CMD_LU_OFFLINE_COMPLETE, lu, &st);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case STMF_ACK_LU_ONLINE_COMPLETE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Fallthrough */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case STMF_ACK_LU_OFFLINE_COMPLETE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte slu->sl_state_not_acked = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_info(uint32_t cmd, stmf_lu_t *lu, void *arg, uint8_t *buf,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t *bufsizep)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_NOT_SUPPORTED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_lu_reset_state(stmf_lu_t *lu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst = (sbd_store_t *)lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_check_and_clear_scsi2_reservation(slu, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_deregister_all_lu_itl_handles(lu) != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_FAILURE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_sync_cache(struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_store_t *sst =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (sbd_store_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t lba, laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int is_g4 = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int immed;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine if this is a 10 or 16 byte CDB
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_cdb[0] == SCMD_SYNCHRONIZE_CACHE_G4)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte is_g4 = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine other requested parameters
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
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 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte immed = (task->task_cdb[1] & 0x02);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (immed) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
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 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (is_g4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_cdb[1] & 0xf9) || task->task_cdb[14] ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cdb[15]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[10], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_cdb[1] & 0xf9) || task->task_cdb[6] ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cdb[9]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI16(&task->task_cdb[7], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte laddr = lba << slu->sl_shift_count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len <<= slu->sl_shift_count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((laddr + (uint64_t)len) > slu->sl_sli->sli_lu_data_size) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_LBA_OUT_OF_RANGE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (sst->sst_data_flush(sst) != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_WRITE_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}