f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skd.c: Solaris 11/10 Driver for sTec, Inc. S112x PCIe SSD card
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Solaris driver is based on the Linux driver authored by:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Authors/Alphabetical: Dragan Stancevic <dstancevic@stec-inc.com>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Gordon Waidhofer <gwaidhofer@stec-inc.com>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * John Hamilton <jhamilton@stec-inc.com>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * This file and its contents are supplied under the terms of the
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Common Development and Distribution License ("CDDL"), version 1.0.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * You may only use this file in accordance with the terms of version
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * 1.0 of the CDDL.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * A full copy of the text of the CDDL should have accompanied this
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * source. A copy of the CDDL is also available via the Internet at
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * http://www.illumos.org/license/CDDL.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Copyright 2013 STEC, Inc. All rights reserved.
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/types.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/stream.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/cmn_err.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/kmem.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/file.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/buf.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/uio.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/cred.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/modctl.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/debug.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/modctl.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/list.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/sysmacros.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/errno.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/pcie.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/pci.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/ddi.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/dditypes.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/sunddi.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/atomic.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/mutex.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/param.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/devops.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/blkdev.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include <sys/queue.h>
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld#include <sys/scsi/impl/inquiry.h>
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include "skd_s1120.h"
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#include "skd.h"
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaint skd_dbg_level = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetavoid *skd_state = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaint skd_disable_msi = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaint skd_disable_msix = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* Initialized in _init() and tunable, see _init(). */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaclock_t skd_timer_ticks;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* I/O DMA attributes structures. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic ddi_dma_attr_t skd_64bit_io_dma_attr = {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DMA_ATTR_V0, /* dma_attr_version */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_LOW_ADDRESS, /* low DMA address range */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_HIGH_64BIT_ADDRESS, /* high DMA address range */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_XFER_COUNTER, /* DMA counter register */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_ADDRESS_ALIGNMENT, /* DMA address alignment */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_BURSTSIZES, /* DMA burstsizes */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_MIN_XFER_SIZE, /* min effective DMA size */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_MAX_XFER_SIZE, /* max DMA xfer size */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_SEGMENT_BOUNDARY, /* segment boundary */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_SG_LIST_LENGTH, /* s/g list length */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_GRANULARITY, /* granularity of device */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DMA_XFER_FLAGS /* DMA transfer flags */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta};
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaint skd_isr_type = -1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#define SKD_MAX_QUEUE_DEPTH 255
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#define SKD_MAX_QUEUE_DEPTH_DEFAULT 64
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaint skd_max_queue_depth = SKD_MAX_QUEUE_DEPTH_DEFAULT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#define SKD_MAX_REQ_PER_MSG 14
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#define SKD_MAX_REQ_PER_MSG_DEFAULT 1
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaint skd_max_req_per_msg = SKD_MAX_REQ_PER_MSG_DEFAULT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#define SKD_MAX_N_SG_PER_REQ 4096
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaint skd_sgs_per_request = SKD_N_SG_PER_REQ_DEFAULT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_sys_quiesce_dev(dev_info_t *);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_quiesce_dev(skd_device_t *);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_list_skmsg(skd_device_t *, int);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_list_skreq(skd_device_t *, int);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_format_internal_skspcl(struct skd_device *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_start(skd_device_t *);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_destroy_mutex(skd_device_t *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_enable_interrupts(struct skd_device *);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_request_fn_not_online(skd_device_t *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_send_internal_skspcl(struct skd_device *,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *, uint8_t);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_queue(skd_device_t *, skd_buf_private_t *);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void *skd_alloc_dma_mem(skd_device_t *, dma_mem_t *, uint8_t);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_release_intr(skd_device_t *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_isr_fwstate(struct skd_device *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_isr_msg_from_dev(struct skd_device *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_soft_reset(struct skd_device *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_refresh_device_data(struct skd_device *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_update_props(skd_device_t *, dev_info_t *);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_end_request_abnormal(struct skd_device *, skd_buf_private_t *,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int, int);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic char *skd_pci_info(struct skd_device *skdev, char *str, size_t len);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic skd_buf_private_t *skd_get_queued_pbuf(skd_device_t *);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_bd_driveinfo(void *arg, bd_drive_t *drive);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_bd_mediainfo(void *arg, bd_media_t *media);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_bd_read(void *arg, bd_xfer_t *xfer);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_bd_write(void *arg, bd_xfer_t *xfer);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_devid_init(void *arg, dev_info_t *, ddi_devid_t *);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic bd_ops_t skd_bd_ops = {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta BD_OPS_VERSION_0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_bd_driveinfo,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_bd_mediainfo,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_devid_init,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta NULL, /* sync_cache */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_bd_read,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_bd_write,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta};
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic ddi_device_acc_attr_t dev_acc_attr = {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_DEVICE_ATTR_V0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_STRUCTURE_LE_ACC,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_STRICTORDER_ACC
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta};
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Solaris module loading/unloading structures
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastruct dev_ops skd_dev_ops = {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DEVO_REV, /* devo_rev */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta 0, /* refcnt */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_no_info, /* getinfo */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta nulldev, /* identify */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta nulldev, /* probe */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_attach, /* attach */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_detach, /* detach */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta nodev, /* reset */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta NULL, /* char/block ops */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta NULL, /* bus operations */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta NULL, /* power management */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_sys_quiesce_dev /* quiesce */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta};
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic struct modldrv modldrv = {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &mod_driverops, /* type of module: driver */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "sTec skd v" DRV_VER_COMPL, /* name of module */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &skd_dev_ops /* driver dev_ops */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta};
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic struct modlinkage modlinkage = {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta MODREV_1,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &modldrv,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta NULL
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta};
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * sTec-required wrapper for debug printing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*PRINTFLIKE2*/
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic inline void
f52228b83292315dabb975359cdcf9db662845b2Joe BetetaDcmn_err(int lvl, const char *fmt, ...)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta va_list ap;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_dbg_level == 0)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta va_start(ap, fmt);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta vcmn_err(lvl, fmt, ap);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta va_end(ap);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Solaris module loading/unloading routines
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: _init, performs initial installation
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: None.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Returns the value returned by the ddi_softstate_init function
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * on a failure to create the device state structure or the result
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * of the module install routines.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaint
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta_init(void)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rval = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int tgts = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta tgts |= 0x02;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta tgts |= 0x08; /* In #ifdef NEXENTA block from original sTec drop. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * drv_usectohz() is a function, so can't initialize it at
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * instantiation.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_timer_ticks = drv_usectohz(1000000);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "<# Installing skd Driver dbg-lvl=%d %s %x>",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_dbg_level, DRV_BUILD_ID, tgts);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rval = ddi_soft_state_init(&skd_state, sizeof (skd_device_t), 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rval != DDI_SUCCESS)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rval);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bd_mod_init(&skd_dev_ops);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rval = mod_install(&modlinkage);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rval != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_soft_state_fini(&skd_state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bd_mod_fini(&skd_dev_ops);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rval);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: _info, returns information about loadable module.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: modinfo, pointer to module information structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Value returned by mod_info().
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaint
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta_info(struct modinfo *modinfop)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (mod_info(&modlinkage, modinfop));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * _fini Prepares a module for unloading. It is called when the system
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * wants to unload a module. If the module determines that it can
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * be unloaded, then _fini() returns the value returned by
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * mod_remove(). Upon successful return from _fini() no other
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * routine in the module will be called before _init() is called.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: None.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: DDI_SUCCESS or DDI_FAILURE.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaint
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta_fini(void)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rval;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rval = mod_remove(&modlinkage);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rval == DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_soft_state_fini(&skd_state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bd_mod_fini(&skd_dev_ops);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rval);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Solaris Register read/write routines
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_reg_write64, writes a 64-bit value to specified address
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * val - 64-bit value to be written.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * offset - offset from PCI base address.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Local vars are to keep lint silent. Any compiler worth its weight will
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * optimize it all right out...
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic inline void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_reg_write64(struct skd_device *skdev, uint64_t val, uint32_t offset)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint64_t *addr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT((offset & 0x7) == 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* LINTED */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta addr = (uint64_t *)(skdev->dev_iobase + offset);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_put64(skdev->dev_handle, addr, val);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_reg_read32, reads a 32-bit value to specified address
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * offset - offset from PCI base address.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: val, 32-bit value read from specified PCI address.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic inline uint32_t
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_reg_read32(struct skd_device *skdev, uint32_t offset)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t *addr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT((offset & 0x3) == 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* LINTED */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta addr = (uint32_t *)(skdev->dev_iobase + offset);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (ddi_get32(skdev->dev_handle, addr));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_reg_write32, writes a 32-bit value to specified address
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * val - value to be written.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * offset - offset from PCI base address.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic inline void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_reg_write32(struct skd_device *skdev, uint32_t val, uint32_t offset)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t *addr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT((offset & 0x3) == 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* LINTED */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta addr = (uint32_t *)(skdev->dev_iobase + offset);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_put32(skdev->dev_handle, addr, val);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Solaris skd routines
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_name, generates the name of the driver.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: char pointer to generated driver name.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic const char *
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_name(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) snprintf(skdev->id_str, sizeof (skdev->id_str), "%s:", DRV_NAME);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (skdev->id_str);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_pci_find_capability, searches the PCI capability
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * list for the specified capability.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * cap - capability sought.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Returns position where capability was found.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * If not found, returns zero.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_pci_find_capability(struct skd_device *skdev, int cap)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint16_t status;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t pos, id, hdr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int ttl = 48;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta status = pci_config_get16(skdev->pci_handle, PCI_CONF_STAT);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (!(status & PCI_STAT_CAP))
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta hdr = pci_config_get8(skdev->pci_handle, PCI_CONF_HEADER);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((hdr & PCI_HEADER_TYPE_M) != 0)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pos = pci_config_get8(skdev->pci_handle, PCI_CONF_CAP_PTR);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta while (ttl-- && pos >= 0x40) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pos &= ~3;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta id = pci_config_get8(skdev->pci_handle, pos+PCI_CAP_ID);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (id == 0xff)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (id == cap)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (pos);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pos = pci_config_get8(skdev->pci_handle, pos+PCI_CAP_NEXT_PTR);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_io_done, called to conclude an I/O operation.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * pbuf - I/O request
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * error - contain error value.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * mode - debug only.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_io_done(skd_device_t *skdev, skd_buf_private_t *pbuf,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int error, int mode)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bd_xfer_t *xfer;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(pbuf != NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta xfer = pbuf->x_xfer;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (mode) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_IODONE_WIOC:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->iodone_wioc++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_IODONE_WNIOC:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->iodone_wnioc++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_IODONE_WDEBUG:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->iodone_wdebug++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->iodone_unknown++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (error) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->ios_errors++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "!%s:skd_io_done:ERR=%d %lld-%ld %s", skdev->name,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta error, xfer->x_blkno, xfer->x_nblks,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (pbuf->dir & B_READ) ? "Read" : "Write");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta kmem_free(pbuf, sizeof (skd_buf_private_t));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bd_xfer_done(xfer, error);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * QUIESCE DEVICE
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_sys_quiesce_dev, quiets the device
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: dip - dev info strucuture
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Zero.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_sys_quiesce_dev(dev_info_t *dip)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_device_t *skdev;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev = ddi_get_soft_state(skd_state, ddi_get_instance(dip));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* make sure Dcmn_err() doesn't actually print anything */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_dbg_level = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_disable_interrupts(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_soft_reset(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_quiesce_dev, quiets the device, but doesn't really do much.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - Device state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: -EINVAL if device is not in proper state otherwise
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * returns zero.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_quiesce_dev(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rc = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_dbg_level)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_quiece_dev:");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (skdev->state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_IMMINENT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: stopping queue", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_ONLINE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_STOPPING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_SYNCING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_PAUSING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_PAUSED:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_STARTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_RESTARTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_RESUMING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = -EINVAL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "state [%d] not implemented", skdev->state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rc);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * UNQUIESCE DEVICE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Note: Assumes lock is held to protect device state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_unquiesce_dev, awkens the device
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - Device state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: -EINVAL if device is not in proper state otherwise
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * returns zero.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_unquiesce_dev(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_unquiece_dev:");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_log_skdev(skdev, "unquiesce");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->state == SKD_DRVR_STATE_ONLINE) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "**** device already ONLINE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->drive_state != FIT_SR_DRIVE_ONLINE) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * If there has been an state change to other than
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * ONLINE, we will rely on controller state change
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * to come back online and restart the queue.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * The BUSY state means that driver is ready to
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * continue normal processing but waiting for controller
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * to become available.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_BUSY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "drive BUSY state\n");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Drive just come online, driver is either in startup,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * paused performing a task, or bust waiting for hardware.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (skdev->state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_PAUSED:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_IMMINENT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_ERASE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_STARTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_RESTARTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_FAULT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_IDLE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_LOAD:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_ONLINE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: sTec s1120 ONLINE", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: Starting request queue", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "%s: queue depth limit=%d hard=%d soft=%d lowat=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_limit,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->hard_queue_depth_limit,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->soft_queue_depth_limit,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_lowat);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->gendisk_on = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cv_signal(&skdev->cv_waitq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_DISAPPEARED:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "**** driver state %d, not implemented \n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (-EBUSY);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * READ/WRITE REQUESTS
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_blkdev_preop_sg_list, builds the S/G list from info
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * passed in by the blkdev driver.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skreq - request structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * sg_byte_count - data transfer byte count.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*ARGSUSED*/
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_blkdev_preop_sg_list(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_request_context *skreq, uint32_t *sg_byte_count)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bd_xfer_t *xfer;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_buf_private_t *pbuf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int i, bcount = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint_t n_sg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *sg_byte_count = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skreq->sg_data_dir == SKD_DATA_DIR_HOST_TO_CARD ||
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->sg_data_dir == SKD_DATA_DIR_CARD_TO_HOST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf = skreq->pbuf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(pbuf != NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta xfer = pbuf->x_xfer;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta n_sg = xfer->x_ndmac;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(n_sg <= skdev->sgs_per_request);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->n_sg = n_sg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->io_dma_handle = xfer->x_dmah;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->total_sg_bcount = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < n_sg; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_dma_cookie_t *cookiep = &xfer->x_dmac;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_sg_descriptor *sgd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t cnt = (uint32_t)cookiep->dmac_size;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bcount += cnt;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd = &skreq->sksg_list[i];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->control = FIT_SGD_CONTROL_NOT_LAST;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->byte_count = cnt;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->host_side_addr = cookiep->dmac_laddress;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->dev_side_addr = 0; /* not used */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *sg_byte_count += cnt;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->total_sg_bcount += cnt;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((i + 1) != n_sg)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_dma_nextcookie(skreq->io_dma_handle, &xfer->x_dmac);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->sksg_list[n_sg - 1].next_desc_ptr = 0LL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->sksg_list[n_sg - 1].control = FIT_SGD_CONTROL_LAST;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_dma_sync(skreq->sksg_dma_address.dma_handle, 0, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_DMA_SYNC_FORDEV);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_blkdev_postop_sg_list, deallocates DMA
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skreq - skreq data structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_blkdev_postop_sg_list(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_request_context *skreq)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * restore the next ptr for next IO request so we
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * don't have to set it every time.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->sksg_list[skreq->n_sg - 1].next_desc_ptr =
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->sksg_dma_address.cookies->dmac_laddress +
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ((skreq->n_sg) * sizeof (struct fit_sg_descriptor));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_start, initiates an I/O.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: EAGAIN if devicfe is not ONLINE.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * On error, if the caller is the blkdev driver, return
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * the error value. Otherwise, return zero.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_start(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_fitmsg_context *skmsg = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_msg_hdr *fmh = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_request_context *skreq = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct waitqueue *waitq = &skdev->waitqueue;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_scsi_request *scsi_req;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_buf_private_t *pbuf = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int bcount;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t lba;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t count;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t timo_slot;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta void *cmd_ptr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t sg_byte_count = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Stop conditions:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * - There are no more native requests
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * - There are already the maximum number of requests is progress
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * - There are no more skd_request_context entries
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * - There are no more FIT msg buffers
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (;;) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Are too many requests already in progress? */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->queue_depth_busy >= skdev->queue_depth_limit) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "qdepth %d, limit %d\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_busy,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_limit);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SIMPLEQ_EMPTY(waitq)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Is a skd_request_context available? */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq = skdev->skreq_free_list;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skreq == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skreq->state == SKD_REQ_STATE_IDLE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT((skreq->id & SKD_ID_INCR) == 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skreq_free_list = skreq->next;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->state = SKD_REQ_STATE_BUSY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->id += SKD_ID_INCR;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Start a new FIT msg if there is none in progress. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skmsg == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Are there any FIT msg buffers available? */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg = skdev->skmsg_free_list;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skmsg == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skmsg->state == SKD_MSG_STATE_IDLE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT((skmsg->id & SKD_ID_INCR) == 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skmsg_free_list = skmsg->next;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->state = SKD_MSG_STATE_BUSY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->id += SKD_ID_INCR;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Initialize the FIT msg header */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta fmh = (struct fit_msg_hdr *)skmsg->msg_buf64;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bzero(fmh, sizeof (*fmh)); /* Too expensive */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta fmh->protocol_id = FIT_PROTOCOL_ID_SOFIT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->length = sizeof (struct fit_msg_hdr);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * At this point we are committed to either start or reject
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * the native request. Note that a FIT msg may have just been
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * started but contains no SoFIT requests yet.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Now - dequeue pbuf.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf = skd_get_queued_pbuf(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->pbuf = pbuf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta lba = pbuf->x_xfer->x_blkno;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta count = pbuf->x_xfer->x_nblks;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->did_complete = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->fitmsg_id = skmsg->id;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "pbuf=%p lba=%u(0x%x) count=%u(0x%x) dir=%x\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)pbuf, lba, lba, count, count, pbuf->dir);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Transcode the request.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmd_ptr = &skmsg->msg_buf[skmsg->length];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bzero(cmd_ptr, 32); /* This is too expensive */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req = cmd_ptr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->hdr.tag = skreq->id;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->hdr.sg_list_dma_address =
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cpu_to_be64(skreq->sksg_dma_address.cookies->dmac_laddress);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[1] = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[2] = (lba & 0xff000000) >> 24;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[3] = (lba & 0xff0000) >> 16;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[4] = (lba & 0xff00) >> 8;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[5] = (lba & 0xff);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[6] = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[7] = (count & 0xff00) >> 8;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[8] = count & 0xff;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[9] = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (pbuf->dir & B_READ) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[0] = 0x28;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->sg_data_dir = SKD_DATA_DIR_CARD_TO_HOST;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[0] = 0x2a;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->sg_data_dir = SKD_DATA_DIR_HOST_TO_CARD;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_blkdev_preop_sg_list(skdev, skreq, &sg_byte_count);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->hdr.sg_list_len_bytes = cpu_to_be32(sg_byte_count);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bcount = (sg_byte_count + 511) / 512;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[7] = (bcount & 0xff00) >> 8;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi_req->cdb[8] = bcount & 0xff;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "skd_start: pbuf=%p skreq->id=%x opc=%x ====>>>>>",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)pbuf, skreq->id, *scsi_req->cdb);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->length += sizeof (struct skd_scsi_request);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta fmh->num_protocol_cmds_coalesced++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Update the active request counts.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Capture the timeout timestamp.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->timeout_stamp = skdev->timeout_stamp;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta timo_slot = skreq->timeout_stamp & SKD_TIMEOUT_SLOT_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta atomic_inc_32(&skdev->timeout_slot[timo_slot]);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta atomic_inc_32(&skdev->queue_depth_busy);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "req=0x%x busy=%d timo_slot=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->id, skdev->queue_depth_busy, timo_slot);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * If the FIT msg buffer is full send it.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skmsg->length >= SKD_N_FITMSG_BYTES ||
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta fmh->num_protocol_cmds_coalesced >= skd_max_req_per_msg) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta atomic_inc_64(&skdev->active_cmds);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf->skreq = skreq;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->fitmsg_sent1++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_fitmsg(skdev, skmsg);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta fmh = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Is a FIT msg in progress? If it is empty put the buffer back
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * on the free list. If it is non-empty send what we got.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * This minimizes latency when there are fewer requests than
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * what fits in a FIT msg.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skmsg != NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skmsg->length > sizeof (struct fit_msg_hdr));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "sending msg=%p, len %d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)skmsg, skmsg->length);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->active_cmds++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->fitmsg_sent2++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_fitmsg(skdev, skmsg);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_end_request
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skreq - request structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * error - I/O error value.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_end_request(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_request_context *skreq, int error)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->ios_completed++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_io_done(skdev, skreq->pbuf, error, SKD_IODONE_WIOC);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->pbuf = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->did_complete = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_end_request_abnormal
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * pbuf - I/O request.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * error - I/O error value.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * mode - debug
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_end_request_abnormal(skd_device_t *skdev, skd_buf_private_t *pbuf,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int error, int mode)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_io_done(skdev, pbuf, error, mode);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_request_fn_not_online, handles the condition
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * of the device not being online.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: nothing (void).
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_request_fn_not_online(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int error;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_buf_private_t *pbuf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skdev->state != SKD_DRVR_STATE_ONLINE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_log_skdev(skdev, "req_not_online");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (skdev->state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_PAUSING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_PAUSED:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_STARTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_RESTARTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_WAIT_BOOT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * In case of starting, we haven't started the queue,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * so we can't get here... but requests are
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * possibly hanging out waiting for us because we
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * reported the dev/skd/0 already. They'll wait
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * forever if connect doesn't complete.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * What to do??? delay dev/skd/0 ??
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_IMMINENT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_ERASE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_DRAINING_TIMEOUT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_SANITIZE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_STOPPING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_SYNCING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_FAULT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_DISAPPEARED:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta error = -EIO;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * If we get here, terminate all pending block requeusts
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * with EIO and any scsi pass thru with appropriate sense
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(WAITQ_LOCK_HELD(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SIMPLEQ_EMPTY(&skdev->waitqueue))
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta while ((pbuf = skd_get_queued_pbuf(skdev)))
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_end_request_abnormal(skdev, pbuf, error, SKD_IODONE_WNIOC);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cv_signal(&skdev->cv_waitq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * TIMER
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_timer_tick_not_online(struct skd_device *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_timer_tick, monitors requests for timeouts.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_timer_tick(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t timo_slot;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_active = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->state != SKD_DRVR_STATE_ONLINE) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_timer_tick_not_online(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto timer_func_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timeout_stamp++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta timo_slot = skdev->timeout_stamp & SKD_TIMEOUT_SLOT_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * All requests that happened during the previous use of
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * this slot should be done by now. The previous use was
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * over 7 seconds ago.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->timeout_slot[timo_slot] == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto timer_func_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Something is overdue */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "found %d timeouts, draining busy=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timeout_slot[timo_slot],
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_busy);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_SECONDS(3);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_DRAINING_TIMEOUT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timo_slot = timo_slot;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetatimer_func_out:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_active = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_timer_tick_not_online, handles various device
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * state transitions.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_timer_tick_not_online(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_skd_timer_tick_not_online: state=%d tmo=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state, skdev->timer_countdown);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skdev->state != SKD_DRVR_STATE_ONLINE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (skdev->state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_IDLE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_LOAD:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_SANITIZE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!drive busy sanitize[%x], driver[%x]\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->drive_state, skdev->state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_IMMINENT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_ERASE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "busy[%x], countdown=%d\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state, skdev->timer_countdown);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->timer_countdown > 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown--;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!busy[%x], timedout=%d, restarting device.",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state, skdev->timer_countdown);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_restart_device(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_WAIT_BOOT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_STARTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->timer_countdown > 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown--;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * For now, we fault the drive. Could attempt resets to
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * revcover at some point.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_FAULT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!(%s): DriveFault Connect Timeout (%x)",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev), skdev->drive_state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* start the queue so we can respond with error to requests */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* wakeup anyone waiting for startup complete */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->gendisk_on = -1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cv_signal(&skdev->cv_waitq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_PAUSING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_PAUSED:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_DRAINING_TIMEOUT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "!%s: draining busy [%d] tick[%d] qdb[%d] tmls[%d]\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timo_slot,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_busy,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timeout_slot[skdev->timo_slot]);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* if the slot has cleared we can let the I/O continue */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->timeout_slot[skdev->timo_slot] == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "Slot drained, starting queue.");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_ONLINE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->timer_countdown > 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown--;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_restart_device(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_RESTARTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->timer_countdown > 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown--;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * For now, we fault the drive. Could attempt resets to
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * revcover at some point.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_FAULT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!(%s): DriveFault Reconnect Timeout (%x)\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev), skdev->drive_state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Recovering does two things:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * 1. completes IO with error
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * 2. reclaims dma resources
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * When is it safe to recover requests?
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * - if the drive state is faulted
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * - if the state is still soft reset after out timeout
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * - if the drive registers are dead (state = FF)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((skdev->drive_state == FIT_SR_DRIVE_SOFT_RESET) ||
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (skdev->drive_state == FIT_SR_DRIVE_FAULT) ||
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (skdev->drive_state == FIT_SR_DRIVE_STATE_MASK)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * It never came out of soft reset. Try to
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * recover the requests and then let them
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * fail. This is to mitigate hung processes.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Acquire the interrupt lock since these lists are
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * manipulated by interrupt handlers.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(!WAITQ_LOCK_HELD(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta INTR_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_recover_requests(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta INTR_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* start the queue so we can respond with error to requests */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* wakeup anyone waiting for startup complete */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->gendisk_on = -1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cv_signal(&skdev->cv_waitq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_RESUMING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_STOPPING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_SYNCING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_FAULT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_DISAPPEARED:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_timer, kicks off the timer processing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_timer(void *arg)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_device_t *skdev = (skd_device_t *)arg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Someone set us to 0, don't bother rescheduling. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->skd_timer_timeout_id != 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Pardon the drop-and-then-acquire logic here. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_timer_tick(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Restart timer, if not being stopped. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->skd_timer_timeout_id != 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skd_timer_timeout_id =
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta timeout(skd_timer, arg, skd_timer_ticks);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_start_timer, kicks off the 1-second timer.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Zero.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_start_timer(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Start one second driver timer. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skdev->skd_timer_timeout_id == 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Do first "timeout tick" right away, but not in this
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * thread.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skd_timer_timeout_id = timeout(skd_timer, skdev, 1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * INTERNAL REQUESTS -- generated by driver itself
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_format_internal_skspcl, setups the internal
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * FIT request message.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: One.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_format_internal_skspcl(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *skspcl = &skdev->internal_skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_sg_descriptor *sgd = &skspcl->req.sksg_list[0];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_msg_hdr *fmh;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint64_t dma_address;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_scsi_request *scsi;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta fmh = (struct fit_msg_hdr *)&skspcl->msg_buf64[0];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta fmh->protocol_id = FIT_PROTOCOL_ID_SOFIT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta fmh->num_protocol_cmds_coalesced = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Instead of 64-bytes in, use 8-(64-bit-words) for linted alignment. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi = (struct skd_scsi_request *)&skspcl->msg_buf64[8];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bzero(scsi, sizeof (*scsi));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta dma_address = skspcl->req.sksg_dma_address.cookies->_dmu._dmac_ll;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->hdr.sg_list_dma_address = cpu_to_be64(dma_address);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->control = FIT_SGD_CONTROL_LAST;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->byte_count = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->host_side_addr = skspcl->db_dma_address.cookies->_dmu._dmac_ll;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->dev_side_addr = 0; /* not used */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->next_desc_ptr = 0LL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_send_internal_skspcl, send internal requests to
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * the hardware.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skspcl - request structure
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * opcode - just what it says
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetavoid
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_send_internal_skspcl(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *skspcl, uint8_t opcode)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_sg_descriptor *sgd = &skspcl->req.sksg_list[0];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_scsi_request *scsi;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SKD_REQ_STATE_IDLE != skspcl->req.state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * A refresh is already in progress.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Just wait for it to finish.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(0 == (skspcl->req.id & SKD_ID_INCR));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->req.state = SKD_REQ_STATE_BUSY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->req.id += SKD_ID_INCR;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Instead of 64-bytes in, use 8-(64-bit-words) for linted alignment. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi = (struct skd_scsi_request *)&skspcl->msg_buf64[8];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->hdr.tag = skspcl->req.id;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "internal skspcl: opcode=%x req.id=%x ==========>",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta opcode, skspcl->req.id);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (opcode) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case TEST_UNIT_READY:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[0] = TEST_UNIT_READY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[1] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[2] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[3] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[4] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[5] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->byte_count = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->hdr.sg_list_len_bytes = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case READ_CAPACITY_EXT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[0] = READ_CAPACITY_EXT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[1] = 0x10;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[2] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[3] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[4] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[5] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[6] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[7] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[8] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[9] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[10] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[11] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[12] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[13] = 0x20;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[14] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[15] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->byte_count = SKD_N_READ_CAP_EXT_BYTES;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case 0x28:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) memset(skspcl->data_buf, 0x65, SKD_N_INTERNAL_BYTES);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[0] = 0x28;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[1] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[2] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[3] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[4] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[5] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[6] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[7] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[8] = 0x01;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[9] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->byte_count = SKD_N_INTERNAL_BYTES;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->hdr.sg_list_len_bytes = cpu_to_be32(SKD_N_INTERNAL_BYTES);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case INQUIRY:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[0] = INQUIRY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[1] = 0x01; /* evpd */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[2] = 0x80; /* serial number page */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[3] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[4] = 0x10;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[5] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->byte_count = 16; /* SKD_N_INQ_BYTES */;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case INQUIRY2:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[0] = INQUIRY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[1] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[2] = 0x00; /* serial number page */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[3] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[4] = 0x24;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[5] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->byte_count = 36; /* SKD_N_INQ_BYTES */;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SYNCHRONIZE_CACHE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[0] = SYNCHRONIZE_CACHE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[1] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[2] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[3] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[4] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[5] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[6] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[7] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[8] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->cdb[9] = 0x00;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->byte_count = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta scsi->hdr.sg_list_len_bytes = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT("Don't know what to send");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_special_fitmsg(skdev, skspcl);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_refresh_device_data, sends a TUR command.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_refresh_device_data(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *skspcl = &skdev->internal_skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "refresh_device_data: state=%d", skdev->state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_internal_skspcl(skdev, skspcl, TEST_UNIT_READY);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_complete_internal, handles the completion of
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * driver-initiated I/O requests.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skcomp - completion structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skerr - error structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skspcl - request structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_complete_internal(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta volatile struct fit_completion_entry_v1 *skcomp,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta volatile struct fit_comp_error_info *skerr,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *skspcl)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t *buf = skspcl->data_buf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t status = 2;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Instead of 64-bytes in, use 8-(64-bit-words) for linted alignment. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_scsi_request *scsi =
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (struct skd_scsi_request *)&skspcl->msg_buf64[8];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skspcl == &skdev->internal_skspcl);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_dma_sync(skspcl->db_dma_address.dma_handle, 0, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_DMA_SYNC_FORKERNEL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_dma_sync(skspcl->mb_dma_address.dma_handle, 0, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_DMA_SYNC_FORKERNEL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "complete internal %x", scsi->cdb[0]);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->req.completion = *skcomp;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->req.state = SKD_REQ_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->req.id += SKD_ID_INCR;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta status = skspcl->req.completion.status;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "<<<<====== complete_internal: opc=%x", *scsi->cdb);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (scsi->cdb[0]) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case TEST_UNIT_READY:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SAM_STAT_GOOD == status) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_internal_skspcl(skdev, skspcl,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta READ_CAPACITY_EXT);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->state == SKD_DRVR_STATE_STOPPING) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "!%s: TUR failed, don't send anymore"
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "state 0x%x", skdev->name, skdev->state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: TUR failed, retry skerr",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_internal_skspcl(skdev, skspcl, 0x00);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case READ_CAPACITY_EXT: {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint64_t cap, Nblocks;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint64_t xbuf[1];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->read_cap_is_valid = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SAM_STAT_GOOD == status) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bcopy(buf, xbuf, 8);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cap = be64_to_cpu(*xbuf);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->read_cap_last_lba = cap;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->read_cap_blocksize =
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (buf[8] << 24) | (buf[9] << 16) |
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (buf[10] << 8) | buf[11];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cap *= skdev->read_cap_blocksize;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " Last LBA: %" PRIu64 " (0x%" PRIx64
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "), blk sz: %d, Capacity: %" PRIu64 "GB\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->read_cap_last_lba,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->read_cap_last_lba,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->read_cap_blocksize,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cap >> 30ULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Nblocks = skdev->read_cap_last_lba + 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->Nblocks = Nblocks;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->read_cap_is_valid = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_internal_skspcl(skdev, skspcl, INQUIRY2);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "**** READCAP failed, retry TUR");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_internal_skspcl(skdev, skspcl,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta TEST_UNIT_READY);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case INQUIRY:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->inquiry_is_valid = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SAM_STAT_GOOD == status) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->inquiry_is_valid = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (scsi->cdb[1] == 0x1) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bcopy(&buf[4], skdev->inq_serial_num, 12);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->inq_serial_num[12] = '\0';
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta char *tmp = skdev->inq_vendor_id;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bcopy(&buf[8], tmp, 8);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta tmp[8] = '\0';
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta tmp = skdev->inq_product_id;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bcopy(&buf[16], tmp, 16);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta tmp[16] = '\0';
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta tmp = skdev->inq_product_rev;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bcopy(&buf[32], tmp, 4);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta tmp[4] = '\0';
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->state != SKD_DRVR_STATE_ONLINE)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_unquiesce_dev(skdev) < 0)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "** failed, to ONLINE device");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SYNCHRONIZE_CACHE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->sync_done = (SAM_STAT_GOOD == status) ? 1 : -1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cv_signal(&skdev->cv_waitq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT("we didn't send this");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * FIT MESSAGES
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_send_fitmsg, send a FIT message to the hardware.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skmsg - FIT message structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_send_fitmsg(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_fitmsg_context *skmsg)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint64_t qcmd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_msg_hdr *fmh;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "msgbuf's DMA addr: 0x%" PRIx64 ", qdepth_busy=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->mb_dma_address.cookies->dmac_laddress,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_busy);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "msg_buf 0x%p, offset %x", (void *)skmsg->msg_buf,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->offset);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta qcmd = skmsg->mb_dma_address.cookies->dmac_laddress;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta qcmd |= FIT_QCMD_QID_NORMAL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta fmh = (struct fit_msg_hdr *)skmsg->msg_buf64;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->outstanding = fmh->num_protocol_cmds_coalesced;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->dbg_level > 1) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t *bp = skmsg->msg_buf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < skmsg->length; i += 8) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " msg[%2d] %02x %02x %02x %02x "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "%02x %02x %02x %02x",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta i, bp[i + 0], bp[i + 1], bp[i + 2],
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bp[i + 3], bp[i + 4], bp[i + 5],
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bp[i + 6], bp[i + 7]);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (i == 0) i = 64 - 8;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_dma_sync(skmsg->mb_dma_address.dma_handle, 0, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_DMA_SYNC_FORDEV);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skmsg->length > sizeof (struct fit_msg_hdr));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skmsg->length > 256) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta qcmd |= FIT_QCMD_MSGSIZE_512;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else if (skmsg->length > 128) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta qcmd |= FIT_QCMD_MSGSIZE_256;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else if (skmsg->length > 64) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta qcmd |= FIT_QCMD_MSGSIZE_128;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->ios_started++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEQ(skdev, qcmd, FIT_Q_COMMAND);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_send_special_fitmsg, send a special FIT message
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * to the hardware used driver-originated I/O requests.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skspcl - skspcl structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_send_special_fitmsg(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *skspcl)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint64_t qcmd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "send_special_fitmsg: pt 1");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->dbg_level > 1) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t *bp = skspcl->msg_buf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < SKD_N_SPECIAL_FITMSG_BYTES; i += 8) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta " spcl[%2d] %02x %02x %02x %02x "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "%02x %02x %02x %02x\n", i,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bp[i + 0], bp[i + 1], bp[i + 2], bp[i + 3],
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bp[i + 4], bp[i + 5], bp[i + 6], bp[i + 7]);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (i == 0) i = 64 - 8;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < skspcl->req.n_sg; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_sg_descriptor *sgd =
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &skspcl->req.sksg_list[i];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, " sg[%d] count=%u ctrl=0x%x "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "addr=0x%" PRIx64 " next=0x%" PRIx64,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta i, sgd->byte_count, sgd->control,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sgd->host_side_addr, sgd->next_desc_ptr);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_dma_sync(skspcl->mb_dma_address.dma_handle, 0, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_DMA_SYNC_FORDEV);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_dma_sync(skspcl->db_dma_address.dma_handle, 0, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_DMA_SYNC_FORDEV);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Special FIT msgs are always 128 bytes: a 64-byte FIT hdr
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * and one 64-byte SSDI command.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta qcmd = skspcl->mb_dma_address.cookies->dmac_laddress;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta qcmd |= FIT_QCMD_QID_NORMAL + FIT_QCMD_MSGSIZE_128;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEQ(skdev, qcmd, FIT_Q_COMMAND);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * COMPLETION QUEUE
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_complete_other(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta volatile struct fit_completion_entry_v1 *skcomp,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta volatile struct fit_comp_error_info *skerr);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastruct sns_info {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t type;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t stat;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t key;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t asc;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t ascq;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t mask;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta enum skd_check_status_action action;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta};
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic struct sns_info skd_chkstat_table[] = {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Good */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta {0x70, 0x02, RECOVERED_ERROR, 0, 0, 0x1c, SKD_CHECK_STATUS_REPORT_GOOD},
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Smart alerts */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta {0x70, 0x02, NO_SENSE, 0x0B, 0x00, 0x1E, /* warnings */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_CHECK_STATUS_REPORT_SMART_ALERT},
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta {0x70, 0x02, NO_SENSE, 0x5D, 0x00, 0x1E, /* thresholds */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_CHECK_STATUS_REPORT_SMART_ALERT},
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta {0x70, 0x02, RECOVERED_ERROR, 0x0B, 0x01, 0x1F, /* temp over trigger */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_CHECK_STATUS_REPORT_SMART_ALERT},
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Retry (with limits) */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta {0x70, 0x02, ABORTED_COMMAND, 0, 0, 0x1C, /* DMA errors */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_CHECK_STATUS_REQUEUE_REQUEST},
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta {0x70, 0x02, UNIT_ATTENTION, 0x0B, 0x00, 0x1E, /* warnings */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_CHECK_STATUS_REQUEUE_REQUEST},
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta {0x70, 0x02, UNIT_ATTENTION, 0x5D, 0x00, 0x1E, /* thresholds */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_CHECK_STATUS_REQUEUE_REQUEST},
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta {0x70, 0x02, UNIT_ATTENTION, 0x80, 0x30, 0x1F, /* backup power */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_CHECK_STATUS_REQUEUE_REQUEST},
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Busy (or about to be) */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta {0x70, 0x02, UNIT_ATTENTION, 0x3f, 0x01, 0x1F, /* fw changed */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_CHECK_STATUS_BUSY_IMMINENT},
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta};
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_check_status, checks the return status from a
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * completed I/O request.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * cmp_status - SCSI status byte.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skerr - the error data structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Depending on the error condition, return the action
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * to be taken as specified in the skd_chkstat_table.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * If no corresponding value is found in the table
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * return SKD_CHECK_STATUS_REPORT_GOOD is no error otherwise
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * return SKD_CHECK_STATUS_REPORT_ERROR.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic enum skd_check_status_action
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_check_status(struct skd_device *skdev, uint8_t cmp_status,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta volatile struct fit_comp_error_info *skerr)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Look up status and sense data to decide how to handle the error
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * from the device.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * mask says which fields must match e.g., mask=0x18 means check
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * type and stat, ignore key, asc, ascq.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int i, n;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s): key/asc/ascq %02x/%02x/%02x",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev), skerr->key, skerr->code, skerr->qual);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "stat: t=%02x stat=%02x k=%02x c=%02x q=%02x",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skerr->type, cmp_status, skerr->key, skerr->code, skerr->qual);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Does the info match an entry in the good category? */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta n = sizeof (skd_chkstat_table) / sizeof (skd_chkstat_table[0]);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < n; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct sns_info *sns = &skd_chkstat_table[i];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (sns->mask & 0x10)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skerr->type != sns->type) continue;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (sns->mask & 0x08)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (cmp_status != sns->stat) continue;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (sns->mask & 0x04)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skerr->key != sns->key) continue;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (sns->mask & 0x02)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skerr->code != sns->asc) continue;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (sns->mask & 0x01)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skerr->qual != sns->ascq) continue;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (sns->action == SKD_CHECK_STATUS_REPORT_SMART_ALERT) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!(%s):SMART Alert: sense key/asc/ascq"
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta " %02x/%02x/%02x",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev), skerr->key,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skerr->code, skerr->qual);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_check_status: returning %x",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sns->action);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (sns->action);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * No other match, so nonzero status means error,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * zero status means good
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (cmp_status) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "!%s: status check: qdepth=%d skmfl=%p (%d) skrfl=%p (%d)",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_busy,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)skdev->skmsg_free_list, skd_list_skmsg(skdev, 0),
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)skdev->skreq_free_list, skd_list_skreq(skdev, 0));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s: t=%02x stat=%02x k=%02x c=%02x q=%02x",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, skerr->type, cmp_status, skerr->key,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skerr->code, skerr->qual);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (SKD_CHECK_STATUS_REPORT_ERROR);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "status check good default");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (SKD_CHECK_STATUS_REPORT_GOOD);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_isr_completion_posted, handles I/O completions.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_isr_completion_posted(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta volatile struct fit_completion_entry_v1 *skcmp = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta volatile struct fit_comp_error_info *skerr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_fitmsg_context *skmsg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_request_context *skreq;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_buf_private_t *pbuf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint16_t req_id;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t req_slot;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t timo_slot;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t msg_slot;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint16_t cmp_cntxt = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t cmp_status = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint8_t cmp_cycle = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t cmp_bytes = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_dma_sync(skdev->cq_dma_address.dma_handle, 0, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_DMA_SYNC_FORKERNEL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (;;) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skdev->skcomp_ix < SKD_N_COMPLETION_ENTRY);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skcmp = &skdev->skcomp_table[skdev->skcomp_ix];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmp_cycle = skcmp->cycle;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmp_cntxt = skcmp->tag;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmp_status = skcmp->status;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmp_bytes = be32_to_cpu(skcmp->num_returned_bytes);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skerr = &skdev->skerr_table[skdev->skcomp_ix];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "cycle=%d ix=%d got cycle=%d cmdctxt=0x%x stat=%d "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "qdepth_busy=%d rbytes=0x%x proto=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skcomp_cycle, skdev->skcomp_ix,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmp_cycle, cmp_cntxt, cmp_status,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_busy, cmp_bytes, skdev->proto_ver);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (cmp_cycle != skdev->skcomp_cycle) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s:end of completions", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->n_req++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Update the completion queue head index and possibly
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * the completion cycle count.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skcomp_ix++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->skcomp_ix >= SKD_N_COMPLETION_ENTRY) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skcomp_ix = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skcomp_cycle++; /* 8-bit wrap-around */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * The command context is a unique 32-bit ID. The low order
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * bits help locate the request. The request is usually a
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * r/w request (see skd_start() above) or a special request.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta req_id = cmp_cntxt;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta req_slot = req_id & SKD_ID_SLOT_AND_TABLE_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "<<<< completion_posted 1: req_id=%x req_slot=%x",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta req_id, req_slot);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Is this other than a r/w request? */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (req_slot >= skdev->num_req_context) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * This is not a completion for a r/w request.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_complete_other(skdev, skcmp, skerr);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta continue;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq = &skdev->skreq_table[req_slot];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Make sure the request ID for the slot matches.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skreq->id == req_id);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SKD_REQ_STATE_ABORTED == skreq->state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "reclaim req %p id=%04x\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)skreq, skreq->id);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * a previously timed out command can
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * now be cleaned up
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta msg_slot = skreq->fitmsg_id & SKD_ID_SLOT_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(msg_slot < skdev->num_fitmsg_context);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg = &skdev->skmsg_table[msg_slot];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skmsg->id == skreq->fitmsg_id) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skmsg->outstanding > 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->outstanding--;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skmsg->outstanding == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(SKD_MSG_STATE_BUSY ==
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->state = SKD_MSG_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->id += SKD_ID_INCR;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->next = skdev->skmsg_free_list;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skmsg_free_list = skmsg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Reclaim the skd_request_context
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->state = SKD_REQ_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->id += SKD_ID_INCR;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->next = skdev->skreq_free_list;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skreq_free_list = skreq;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta continue;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->completion.status = cmp_status;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf = skreq->pbuf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(pbuf != NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "<<<< completion_posted 2: pbuf=%p "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "req_id=%x req_slot=%x", (void *)pbuf, req_id, req_slot);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (cmp_status && skdev->disks_initialized) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s: "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "I/O err: pbuf=%p blkno=%lld (%llx) nbklks=%ld ",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, (void *)pbuf, pbuf->x_xfer->x_blkno,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf->x_xfer->x_blkno, pbuf->x_xfer->x_nblks);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skdev->active_cmds);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta atomic_dec_64(&skdev->active_cmds);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SAM_STAT_GOOD == cmp_status) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Release DMA resources for the request. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (pbuf->x_xfer->x_nblks != 0)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_blkdev_postop_sg_list(skdev, skreq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_end_request(skdev, skreq, 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (skd_check_status(skdev, cmp_status, skerr)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_CHECK_STATUS_REPORT_GOOD:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_CHECK_STATUS_REPORT_SMART_ALERT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_end_request(skdev, skreq, 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_CHECK_STATUS_BUSY_IMMINENT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_log_skreq(skdev, skreq, "retry(busy)");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_queue(skdev, pbuf);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_BUSY_IMMINENT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_MINUTES(20);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) skd_quiesce_dev(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* FALLTHRU */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_CHECK_STATUS_REPORT_ERROR:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* fall thru to report error */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Save the entire completion
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * and error entries for
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * later error interpretation.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->completion = *skcmp;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->err_info = *skerr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_end_request(skdev, skreq, -EIO);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Reclaim the FIT msg buffer if this is
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * the first of the requests it carried to
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * be completed. The FIT msg buffer used to
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * send this request cannot be reused until
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * we are sure the s1120 card has copied
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * it to its memory. The FIT msg might have
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * contained several requests. As soon as
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * any of them are completed we know that
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * the entire FIT msg was transferred.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Only the first completed request will
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * match the FIT msg buffer id. The FIT
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * msg buffer id is immediately updated.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * When subsequent requests complete the FIT
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * msg buffer id won't match, so we know
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * quite cheaply that it is already done.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta msg_slot = skreq->fitmsg_id & SKD_ID_SLOT_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(msg_slot < skdev->num_fitmsg_context);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg = &skdev->skmsg_table[msg_slot];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skmsg->id == skreq->fitmsg_id) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(SKD_MSG_STATE_BUSY == skmsg->state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->state = SKD_MSG_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->id += SKD_ID_INCR;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->next = skdev->skmsg_free_list;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skmsg_free_list = skmsg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Decrease the number of active requests.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * This also decrements the count in the
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * timeout slot.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta timo_slot = skreq->timeout_stamp & SKD_TIMEOUT_SLOT_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skdev->timeout_slot[timo_slot] > 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skdev->queue_depth_busy > 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta atomic_dec_32(&skdev->timeout_slot[timo_slot]);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta atomic_dec_32(&skdev->queue_depth_busy);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Reclaim the skd_request_context
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->state = SKD_REQ_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->id += SKD_ID_INCR;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->next = skdev->skreq_free_list;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skreq_free_list = skreq;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * make sure the lock is held by caller.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((skdev->state == SKD_DRVR_STATE_PAUSING) &&
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (0 == skdev->queue_depth_busy)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_PAUSED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cv_signal(&skdev->cv_waitq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } /* for(;;) */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_complete_other, handle the completion of a
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * non-r/w request.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skcomp - FIT completion structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skerr - error structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_complete_other(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta volatile struct fit_completion_entry_v1 *skcomp,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta volatile struct fit_comp_error_info *skerr)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t req_id = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t req_table;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t req_slot;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta req_id = skcomp->tag;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta req_table = req_id & SKD_ID_TABLE_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta req_slot = req_id & SKD_ID_SLOT_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "complete_other: table=0x%x id=0x%x slot=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta req_table, req_id, req_slot);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Based on the request id, determine how to dispatch this completion.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * This swich/case is finding the good cases and forwarding the
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * completion entry. Errors are reported below the switch.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(req_table == SKD_ID_INTERNAL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(req_slot == 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl = &skdev->internal_skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skspcl->req.id == req_id);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skspcl->req.state == SKD_REQ_STATE_BUSY);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "<<<<== complete_other: ID_INTERNAL");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_complete_internal(skdev, skcomp, skerr, skspcl);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_reset_skcomp, does what it says, resetting completion
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * tables.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_reset_skcomp(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t nbytes;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta nbytes = sizeof (struct fit_completion_entry_v1) *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_N_COMPLETION_ENTRY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta nbytes += sizeof (struct fit_comp_error_info) * SKD_N_COMPLETION_ENTRY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->skcomp_table)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bzero(skdev->skcomp_table, nbytes);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skcomp_ix = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skcomp_cycle = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * INTERRUPTS
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_isr_aif, handles the device interrupts.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: arg - skdev device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * intvec - not referenced
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: DDI_INTR_CLAIMED if interrupt is handled otherwise
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * return DDI_INTR_UNCLAIMED.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic uint_t
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_isr_aif(caddr_t arg, caddr_t intvec)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t intstat;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t ack;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rc = DDI_INTR_UNCLAIMED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_device *skdev;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev = (skd_device_t *)(uintptr_t)arg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skdev != NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->intr_cntr++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_isr_aif: intr=%" PRId64 "\n", skdev->intr_cntr);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (;;) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(!WAITQ_LOCK_HELD(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta INTR_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta intstat = SKD_READL(skdev, FIT_INT_STATUS_HOST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ack = FIT_INT_DEF_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ack &= intstat;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "intstat=0x%x ack=0x%x", intstat, ack);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * As long as there is an int pending on device, keep
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * running loop. When none, get out, but if we've never
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * done any processing, call completion handler?
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (ack == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * No interrupts on device, but run the completion
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * processor anyway?
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rc == DDI_INTR_UNCLAIMED &&
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state == SKD_DRVR_STATE_ONLINE) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "1: Want isr_comp_posted call");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_isr_completion_posted(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta INTR_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = DDI_INTR_CLAIMED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, ack, FIT_INT_STATUS_HOST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((skdev->state != SKD_DRVR_STATE_LOAD) &&
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (skdev->state != SKD_DRVR_STATE_STOPPING)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (intstat & FIT_ISH_COMPLETION_POSTED) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "2: Want isr_comp_posted call");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_isr_completion_posted(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (intstat & FIT_ISH_FW_STATE_CHANGE) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "isr: fwstate change");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_isr_fwstate(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->state == SKD_DRVR_STATE_FAULT ||
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state ==
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_DRVR_STATE_DISAPPEARED) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta INTR_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rc);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (intstat & FIT_ISH_MSG_FROM_DEV) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "isr: msg_from_dev change");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_isr_msg_from_dev(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta INTR_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (!SIMPLEQ_EMPTY(&skdev->waitqueue))
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rc);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_drive_fault, set the drive state to DRV_STATE_FAULT.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_drive_fault(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_FAULT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!(%s): Drive FAULT\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_drive_disappeared, set the drive state to DISAPPEARED..
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_drive_disappeared(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_DISAPPEARED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!(%s): Drive DISAPPEARED\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_isr_fwstate, handles the various device states.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_isr_fwstate(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t sense;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t state;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int prev_driver_state;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t mtd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta prev_driver_state = skdev->state;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sense = SKD_READL(skdev, FIT_STATUS);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta state = sense & FIT_SR_DRIVE_STATE_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "s1120 state %s(%d)=>%s(%d)",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_drive_state_to_str(skdev->drive_state), skdev->drive_state,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_drive_state_to_str(state), state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->drive_state = state;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (skdev->drive_state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_INIT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->state == SKD_DRVR_STATE_PROTOCOL_MISMATCH) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_disable_interrupts(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->state == SKD_DRVR_STATE_RESTARTING) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_recover_requests(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->state == SKD_DRVR_STATE_WAIT_BOOT) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown =
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_TIMER_SECONDS(SKD_STARTING_TO);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_STARTING;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_soft_reset(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mtd = FIT_MXD_CONS(FIT_MTD_FITFW_INIT, 0, 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->last_mtd = mtd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_ONLINE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_limit = skdev->soft_queue_depth_limit;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->queue_depth_limit > skdev->hard_queue_depth_limit) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_limit =
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->hard_queue_depth_limit;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_lowat = skdev->queue_depth_limit * 2 / 3 + 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->queue_depth_lowat < 1)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_lowat = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "%s queue depth limit=%d hard=%d soft=%d lowat=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DRV_NAME,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_limit,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->hard_queue_depth_limit,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->soft_queue_depth_limit,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_lowat);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_refresh_device_data(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_BUSY:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_BUSY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_MINUTES(20);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) skd_quiesce_dev(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_BUSY_SANITIZE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_BUSY_SANITIZE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_BUSY_ERASE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_BUSY_ERASE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_MINUTES(20);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_OFFLINE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_SOFT_RESET:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_RESTARTING;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (skdev->state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_STARTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_RESTARTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_RESTARTING;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_FW_BOOTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "ISR FIT_SR_DRIVE_FW_BOOTING %s", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_WAIT_BOOT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_SECONDS(SKD_WAIT_BOOT_TO);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_DEGRADED:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_PCIE_LINK_DOWN:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_NEED_FW_DOWNLOAD:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_FAULT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_drive_fault(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_recover_requests(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case 0xFF:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_drive_disappeared(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_recover_requests(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Uknown FW State. Wait for a state we recognize.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "Driver state %s(%d)=>%s(%d)",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_skdev_state_to_str(prev_driver_state), prev_driver_state,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_skdev_state_to_str(skdev->state), skdev->state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_recover_requests, attempts to recover requests.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_recover_requests(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(INTR_LOCK_HELD(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < skdev->num_req_context; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_request_context *skreq = &skdev->skreq_table[i];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skreq->state == SKD_REQ_STATE_BUSY) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_log_skreq(skdev, skreq, "requeue");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(0 != (skreq->id & SKD_ID_INCR));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skreq->pbuf != NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Release DMA resources for the request. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_blkdev_postop_sg_list(skdev, skreq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_end_request(skdev, skreq, EAGAIN);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->pbuf = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->state = SKD_REQ_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->id += SKD_ID_INCR;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (i > 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq[-1].next = skreq;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->next = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skreq_free_list = skdev->skreq_table;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < skdev->num_fitmsg_context; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_fitmsg_context *skmsg = &skdev->skmsg_table[i];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skmsg->state == SKD_MSG_STATE_BUSY) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_log_skmsg(skdev, skmsg, "salvaged");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT((skmsg->id & SKD_ID_INCR) != 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->state = SKD_MSG_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->id &= ~SKD_ID_INCR;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (i > 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg[-1].next = skmsg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->next = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skmsg_free_list = skdev->skmsg_table;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < SKD_N_TIMEOUT_SLOT; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timeout_slot[i] = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_busy = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_isr_msg_from_dev, handles a message from the device.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_isr_msg_from_dev(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t mfd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t mtd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_isr_msg_from_dev:");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mfd = SKD_READL(skdev, FIT_MSG_FROM_DEVICE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "mfd=0x%x last_mtd=0x%x\n", mfd, skdev->last_mtd);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * ignore any mtd that is an ack for something we didn't send
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (FIT_MXD_TYPE(mfd) != FIT_MXD_TYPE(skdev->last_mtd)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (FIT_MXD_TYPE(mfd)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_MTD_FITFW_INIT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->proto_ver = FIT_PROTOCOL_MAJOR_VER(mfd);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->proto_ver != FIT_PROTOCOL_VERSION_1) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!(%s): protocol mismatch\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!(%s): got=%d support=%d\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, skdev->proto_ver,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta FIT_PROTOCOL_VERSION_1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!(%s): please upgrade driver\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_PROTOCOL_MISMATCH;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_soft_reset(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mtd = FIT_MXD_CONS(FIT_MTD_GET_CMDQ_DEPTH, 0, 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->last_mtd = mtd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_MTD_GET_CMDQ_DEPTH:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->hard_queue_depth_limit = FIT_MXD_DATA(mfd);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mtd = FIT_MXD_CONS(FIT_MTD_SET_COMPQ_DEPTH, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_N_COMPLETION_ENTRY);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->last_mtd = mtd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_MTD_SET_COMPQ_DEPTH:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEQ(skdev, skdev->cq_dma_address.cookies->dmac_laddress,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta FIT_MSG_TO_DEVICE_ARG);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mtd = FIT_MXD_CONS(FIT_MTD_SET_COMPQ_ADDR, 0, 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->last_mtd = mtd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_MTD_SET_COMPQ_ADDR:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_reset_skcomp(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mtd = FIT_MXD_CONS(FIT_MTD_ARM_QUEUE, 0, 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->last_mtd = mtd;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_MTD_ARM_QUEUE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->last_mtd = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * State should be, or soon will be, FIT_SR_DRIVE_ONLINE.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_disable_interrupts, issues command to disable
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * device interrupts.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_disable_interrupts(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t sense;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_disable_interrupts:");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sense = SKD_READL(skdev, FIT_CONTROL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sense &= ~FIT_CR_ENABLE_INTERRUPTS;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, sense, FIT_CONTROL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "sense 0x%x", sense);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Note that the 1s is written. A 1-bit means
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * disable, a 0 means enable.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, ~0, FIT_INT_MASK_HOST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_enable_interrupts, issues command to enable
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * device interrupts.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_enable_interrupts(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t val;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_enable_interrupts:");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* unmask interrupts first */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta val = FIT_ISH_FW_STATE_CHANGE +
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta FIT_ISH_COMPLETION_POSTED +
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta FIT_ISH_MSG_FROM_DEV;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Note that the compliment of mask is written. A 1-bit means
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * disable, a 0 means enable.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, ~val, FIT_INT_MASK_HOST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "interrupt mask=0x%x", ~val);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta val = SKD_READL(skdev, FIT_CONTROL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta val |= FIT_CR_ENABLE_INTERRUPTS;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "control=0x%x", val);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, val, FIT_CONTROL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_soft_reset, issues a soft reset to the hardware.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_soft_reset(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t val;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_soft_reset:");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta val = SKD_READL(skdev, FIT_CONTROL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta val |= (FIT_CR_SOFT_RESET);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "soft_reset: control=0x%x", val);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, val, FIT_CONTROL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_start_device, gets the device going.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_start_device(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t state;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int delay_action = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_start_device:");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* ack all ghost interrupts */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, FIT_INT_DEF_MASK, FIT_INT_STATUS_HOST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta state = SKD_READL(skdev, FIT_STATUS);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "initial status=0x%x", state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta state &= FIT_SR_DRIVE_STATE_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->drive_state = state;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->last_mtd = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_STARTING;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_SECONDS(SKD_STARTING_TO);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_enable_interrupts(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (skdev->drive_state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_OFFLINE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s): Drive offline...",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_FW_BOOTING:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "FIT_SR_DRIVE_FW_BOOTING %s\n", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_WAIT_BOOT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_SECONDS(SKD_WAIT_BOOT_TO);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_BUSY_SANITIZE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s): Start: BUSY_SANITIZE\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_BUSY_SANITIZE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_SECONDS(60);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_BUSY_ERASE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s): Start: BUSY_ERASE\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_BUSY_ERASE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_SECONDS(60);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_INIT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_ONLINE:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_soft_reset(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_BUSY:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s): Drive Busy...\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_BUSY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_SECONDS(60);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_SOFT_RESET:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s) drive soft reset in prog\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_FAULT:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Fault state is bad...soft reset won't do it...
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Hard reset, maybe, but does it work on device?
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * For now, just fault so the system doesn't hang.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_drive_fault(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta delay_action = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case 0xFF:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_drive_disappeared(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta delay_action = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s) Start: unknown state %x\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_name(skdev), skdev->drive_state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta state = SKD_READL(skdev, FIT_CONTROL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "FIT Control Status=0x%x\n", state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta state = SKD_READL(skdev, FIT_INT_STATUS_HOST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "Intr Status=0x%x\n", state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta state = SKD_READL(skdev, FIT_INT_MASK_HOST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "Intr Mask=0x%x\n", state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta state = SKD_READL(skdev, FIT_MSG_FROM_DEVICE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "Msg from Dev=0x%x\n", state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta state = SKD_READL(skdev, FIT_HW_VERSION);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "HW version=0x%x\n", state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (delay_action) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* start the queue so we can respond with error to requests */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "Starting %s queue\n", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->gendisk_on = -1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cv_signal(&skdev->cv_waitq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_restart_device, restart the hardware.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_restart_device(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t state;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_restart_device:");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* ack all ghost interrupts */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, FIT_INT_DEF_MASK, FIT_INT_STATUS_HOST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta state = SKD_READL(skdev, FIT_STATUS);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_restart_device: drive status=0x%x\n", state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta state &= FIT_SR_DRIVE_STATE_MASK;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->drive_state = state;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->last_mtd = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_RESTARTING;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timer_countdown = SKD_TIMER_MINUTES(4);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_soft_reset(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_stop_device, stops the device.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_stop_device(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta clock_t cur_ticks, tmo;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int secs;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *skspcl = &skdev->internal_skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SKD_DRVR_STATE_ONLINE != skdev->state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s): skd_stop_device not online no sync\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto stop_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SKD_REQ_STATE_IDLE != skspcl->req.state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s): skd_stop_device no special\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto stop_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_SYNCING;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->sync_done = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_internal_skspcl(skdev, skspcl, SYNCHRONIZE_CACHE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta secs = 10;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_enter(&skdev->skd_internalio_mutex);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta while (skdev->sync_done == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cur_ticks = ddi_get_lbolt();
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta tmo = cur_ticks + drv_usectohz(1000000 * secs);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (cv_timedwait(&skdev->cv_waitq,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &skdev->skd_internalio_mutex, tmo) == -1) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Oops - timed out */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "stop_device - %d secs TMO", secs);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_exit(&skdev->skd_internalio_mutex);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (skdev->sync_done) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case 0:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s): skd_stop_device no sync\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case 1:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s): skd_stop_device sync done\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "(%s): skd_stop_device sync error\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastop_out:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_STOPPING;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_disable_interrupts(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* ensure all ints on device are cleared */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, FIT_INT_DEF_MASK, FIT_INT_STATUS_HOST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* soft reset the device to unload with a clean slate */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_WRITEL(skdev, FIT_CR_SOFT_RESET, FIT_CONTROL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * CONSTRUCT
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_cons_skcomp(struct skd_device *);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_cons_skmsg(struct skd_device *);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_cons_skreq(struct skd_device *);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int skd_cons_sksb(struct skd_device *);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic struct fit_sg_descriptor *skd_cons_sg_list(struct skd_device *, uint32_t,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta dma_mem_t *);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_construct, calls other routines to build device
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * interface structures.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * instance - DDI instance number.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Returns DDI_FAILURE on any failure otherwise returns
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * DDI_SUCCESS.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_construct(skd_device_t *skdev, int instance)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rc = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->state = SKD_DRVR_STATE_LOAD;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->irq_type = skd_isr_type;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->soft_queue_depth_limit = skd_max_queue_depth;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->hard_queue_depth_limit = 10; /* until GET_CMDQ_DEPTH */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->num_req_context = skd_max_queue_depth;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->num_fitmsg_context = skd_max_queue_depth;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_limit = skdev->hard_queue_depth_limit;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_lowat = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->proto_ver = 99; /* initialize to invalid value */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->sgs_per_request = skd_sgs_per_request;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->dbg_level = skd_dbg_level;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = skd_cons_skcomp(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rc < 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto err_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = skd_cons_skmsg(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rc < 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto err_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = skd_cons_skreq(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rc < 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto err_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = skd_cons_sksb(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rc < 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto err_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "CONSTRUCT VICTORY");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_SUCCESS);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaerr_out:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "construct failed\n");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_destruct(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_free_phys, frees DMA memory.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * mem - DMA info.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_free_phys(skd_device_t *skdev, dma_mem_t *mem)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta _NOTE(ARGUNUSED(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (mem == NULL || mem->dma_handle == NULL)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_dma_unbind_handle(mem->dma_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (mem->acc_handle != NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_dma_mem_free(&mem->acc_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->acc_handle = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->bp = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_dma_free_handle(&mem->dma_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->dma_handle = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_alloc_dma_mem, allocates DMA memory.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * mem - DMA data structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * sleep - indicates whether called routine can sleep.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * atype - specified 32 or 64 bit allocation.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Void pointer to mem->bp on success else NULL.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * NOTE: There are some failure modes even if sleep is set
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * to KM_SLEEP, so callers MUST check the return code even
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * if KM_SLEEP is passed in.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void *
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_alloc_dma_mem(skd_device_t *skdev, dma_mem_t *mem, uint8_t atype)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta size_t rlen;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint_t cnt;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_dma_attr_t dma_attr = skd_64bit_io_dma_attr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_device_acc_attr_t acc_attr = {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_DEVICE_ATTR_V0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_STRUCTURE_LE_ACC,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_STRICTORDER_ACC
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta };
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (atype == ATYPE_32BIT)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta dma_attr.dma_attr_addr_hi = SKD_DMA_HIGH_32BIT_ADDRESS;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta dma_attr.dma_attr_sgllen = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Allocate DMA memory.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (ddi_dma_alloc_handle(skdev->dip, &dma_attr, DDI_DMA_SLEEP, NULL,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &mem->dma_handle) != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!alloc_dma_mem-1, failed");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->dma_handle = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (ddi_dma_mem_alloc(mem->dma_handle, mem->size, &acc_attr,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&mem->bp, &rlen,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &mem->acc_handle) != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!skd_alloc_dma_mem-2, failed");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_dma_free_handle(&mem->dma_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->dma_handle = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->acc_handle = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->bp = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bzero(mem->bp, mem->size);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (ddi_dma_addr_bind_handle(mem->dma_handle, NULL, mem->bp,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->size, (DDI_DMA_CONSISTENT | DDI_DMA_RDWR), DDI_DMA_SLEEP, NULL,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &mem->cookie, &cnt) != DDI_DMA_MAPPED) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!skd_alloc_dma_mem-3, failed");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_dma_mem_free(&mem->acc_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_dma_free_handle(&mem->dma_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (cnt > 1) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_dma_unbind_handle(mem->dma_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!skd_alloc_dma_mem-4, failed, "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "cookie_count %d > 1", cnt);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_phys(skdev, mem);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->cookies = &mem->cookie;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->cookies->dmac_size = mem->size;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (mem->bp);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_cons_skcomp, allocates space for the skcomp table.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: -ENOMEM if no memory otherwise NULL.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_cons_skcomp(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint64_t *dma_alloc;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_completion_entry_v1 *skcomp;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rc = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t nbytes;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta dma_mem_t *mem;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta nbytes = sizeof (*skcomp) * SKD_N_COMPLETION_ENTRY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta nbytes += sizeof (struct fit_comp_error_info) * SKD_N_COMPLETION_ENTRY;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "cons_skcomp: nbytes=%d,entries=%d", nbytes,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_N_COMPLETION_ENTRY);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem = &skdev->cq_dma_address;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->size = nbytes;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta dma_alloc = skd_alloc_dma_mem(skdev, mem, ATYPE_64BIT);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skcomp = (struct fit_completion_entry_v1 *)dma_alloc;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skcomp == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = -ENOMEM;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto err_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bzero(skcomp, nbytes);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "cons_skcomp: skcomp=%p nbytes=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)skcomp, nbytes);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skcomp_table = skcomp;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skerr_table = (struct fit_comp_error_info *)(dma_alloc +
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (SKD_N_COMPLETION_ENTRY * sizeof (*skcomp) / sizeof (uint64_t)));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaerr_out:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rc);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_cons_skmsg, allocates space for the skmsg table.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: -ENOMEM if no memory otherwise NULL.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_cons_skmsg(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta dma_mem_t *mem;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rc = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skmsg_table kzalloc, struct %lu, count %u total %lu",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (ulong_t)sizeof (struct skd_fitmsg_context),
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->num_fitmsg_context,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (ulong_t)(sizeof (struct skd_fitmsg_context) *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->num_fitmsg_context));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skmsg_table = (struct skd_fitmsg_context *)kmem_zalloc(
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sizeof (struct skd_fitmsg_context) * skdev->num_fitmsg_context,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta KM_SLEEP);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < skdev->num_fitmsg_context; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_fitmsg_context *skmsg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg = &skdev->skmsg_table[i];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->id = i + SKD_ID_FIT_MSG;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->state = SKD_MSG_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem = &skmsg->mb_dma_address;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->size = SKD_N_FITMSG_BYTES + 64;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->msg_buf = skd_alloc_dma_mem(skdev, mem, ATYPE_64BIT);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (NULL == skmsg->msg_buf) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = -ENOMEM;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta i++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->offset = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bzero(skmsg->msg_buf, SKD_N_FITMSG_BYTES);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->next = &skmsg[1];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Free list is in order starting with the 0th entry. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skmsg_table[i - 1].next = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skmsg_free_list = skdev->skmsg_table;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rc);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_cons_skreq, allocates space for the skreq table.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: -ENOMEM if no memory otherwise NULL.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_cons_skreq(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rc = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "skreq_table kmem_zalloc, struct %lu, count %u total %lu",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (ulong_t)sizeof (struct skd_request_context),
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->num_req_context,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (ulong_t) (sizeof (struct skd_request_context) *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->num_req_context));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skreq_table = (struct skd_request_context *)kmem_zalloc(
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sizeof (struct skd_request_context) * skdev->num_req_context,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta KM_SLEEP);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < skdev->num_req_context; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_request_context *skreq;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq = &skdev->skreq_table[i];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->id = (uint16_t)(i + SKD_ID_RW_REQUEST);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->state = SKD_REQ_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->sksg_list = skd_cons_sg_list(skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->sgs_per_request,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &skreq->sksg_dma_address);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (NULL == skreq->sksg_list) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = -ENOMEM;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto err_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->next = &skreq[1];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Free list is in order starting with the 0th entry. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skreq_table[i - 1].next = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skreq_free_list = skdev->skreq_table;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaerr_out:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rc);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_cons_sksb, allocates space for the skspcl msg buf
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * and data buf.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: -ENOMEM if no memory otherwise NULL.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_cons_sksb(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rc = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta dma_mem_t *mem;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t nbytes;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl = &skdev->internal_skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->req.id = 0 + SKD_ID_INTERNAL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->req.state = SKD_REQ_STATE_IDLE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta nbytes = SKD_N_INTERNAL_BYTES;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem = &skspcl->db_dma_address;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->size = nbytes;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* data_buf's DMA pointer is skspcl->db_dma_address */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->data_buf = skd_alloc_dma_mem(skdev, mem, ATYPE_64BIT);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skspcl->data_buf == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = -ENOMEM;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto err_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bzero(skspcl->data_buf, nbytes);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta nbytes = SKD_N_SPECIAL_FITMSG_BYTES;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem = &skspcl->mb_dma_address;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->size = nbytes;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* msg_buf DMA pointer is skspcl->mb_dma_address */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->msg_buf = skd_alloc_dma_mem(skdev, mem, ATYPE_64BIT);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skspcl->msg_buf == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = -ENOMEM;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto err_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bzero(skspcl->msg_buf, nbytes);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->req.sksg_list = skd_cons_sg_list(skdev, 1,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &skspcl->req.sksg_dma_address);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skspcl->req.sksg_list == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = -ENOMEM;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto err_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_format_internal_skspcl(skdev) == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = -EINVAL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto err_out;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaerr_out:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rc);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_cons_sg_list, allocates the S/G list.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * n_sg - Number of scatter-gather entries.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * ret_dma_addr - S/G list DMA pointer.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: A list of FIT message descriptors.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic struct fit_sg_descriptor
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta*skd_cons_sg_list(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t n_sg, dma_mem_t *ret_dma_addr)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_sg_descriptor *sg_list;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t nbytes;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta dma_mem_t *mem;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta nbytes = sizeof (*sg_list) * n_sg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem = ret_dma_addr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mem->size = nbytes;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* sg_list's DMA pointer is *ret_dma_addr */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sg_list = skd_alloc_dma_mem(skdev, mem, ATYPE_32BIT);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (sg_list != NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint64_t dma_address = ret_dma_addr->cookie.dmac_laddress;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bzero(sg_list, nbytes);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < n_sg - 1; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint64_t ndp_off;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ndp_off = (i + 1) * sizeof (struct fit_sg_descriptor);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sg_list[i].next_desc_ptr = dma_address + ndp_off;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sg_list[i].next_desc_ptr = 0LL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (sg_list);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * DESTRUCT (FREE)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_free_skcomp(struct skd_device *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_free_skmsg(struct skd_device *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_free_skreq(struct skd_device *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_free_sksb(struct skd_device *skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void skd_free_sg_list(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_sg_descriptor *sg_list,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t n_sg, dma_mem_t dma_addr);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_destruct, call various rouines to deallocate
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * space acquired during initialization.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_destruct(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "destruct sksb");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_sksb(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "destruct skreq");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_skreq(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "destruct skmsg");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_skmsg(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "destruct skcomp");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_skcomp(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "DESTRUCT VICTORY");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_free_skcomp, deallocates skcomp table DMA resources.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_free_skcomp(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->skcomp_table != NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_phys(skdev, &skdev->cq_dma_address);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skcomp_table = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_free_skmsg, deallocates skmsg table DMA resources.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_free_skmsg(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (NULL == skdev->skmsg_table)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < skdev->num_fitmsg_context; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_fitmsg_context *skmsg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg = &skdev->skmsg_table[i];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skmsg->msg_buf != NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_phys(skdev, &skmsg->mb_dma_address);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->msg_buf = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta kmem_free(skdev->skmsg_table, sizeof (struct skd_fitmsg_context) *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->num_fitmsg_context);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skmsg_table = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_free_skreq, deallocates skspcl table DMA resources.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_free_skreq(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (NULL == skdev->skreq_table)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < skdev->num_req_context; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_request_context *skreq;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq = &skdev->skreq_table[i];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_sg_list(skdev, skreq->sksg_list,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->sgs_per_request, skreq->sksg_dma_address);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->sksg_list = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta kmem_free(skdev->skreq_table, sizeof (struct skd_request_context) *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->num_req_context);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skreq_table = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_free_sksb, deallocates skspcl data buf and
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * msg buf DMA resources.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_free_sksb(struct skd_device *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl = &skdev->internal_skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skspcl->data_buf != NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_phys(skdev, &skspcl->db_dma_address);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->data_buf = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skspcl->msg_buf != NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_phys(skdev, &skspcl->mb_dma_address);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->msg_buf = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_sg_list(skdev, skspcl->req.sksg_list, 1,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->req.sksg_dma_address);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl->req.sksg_list = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_free_sg_list, deallocates S/G DMA resources.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * sg_list - S/G list itself.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * n_sg - nukmber of segments
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * dma_addr - S/G list DMA address.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_free_sg_list(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct fit_sg_descriptor *sg_list,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t n_sg, dma_mem_t dma_addr)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (sg_list != NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_free_phys(skdev, &dma_addr);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_queue, queues the I/O request.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * pbuf - I/O request
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_queue(skd_device_t *skdev, skd_buf_private_t *pbuf)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct waitqueue *waitq;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(skdev != NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(pbuf != NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(WAITQ_LOCK_HELD(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta waitq = &skdev->waitqueue;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (SIMPLEQ_EMPTY(waitq))
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SIMPLEQ_INSERT_HEAD(waitq, pbuf, sq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta else
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SIMPLEQ_INSERT_TAIL(waitq, pbuf, sq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_list_skreq, displays the skreq table entries.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * list - flag, if true displays the entry address.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Returns number of skmsg entries found.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_list_skreq(skd_device_t *skdev, int list)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int inx = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_request_context *skreq;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (list) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skreq_table[0]\n");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq = &skdev->skreq_table[0];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta while (skreq) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (list)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "%d: skreq=%p state=%d id=%x fid=%x "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "pbuf=%p dir=%d comp=%d\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta inx, (void *)skreq, skreq->state,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->id, skreq->fitmsg_id,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)skreq->pbuf,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->sg_data_dir, skreq->did_complete);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta inx++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq = skreq->next;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta inx = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq = skdev->skreq_free_list;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (list)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skreq_free_list\n");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta while (skreq) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (list)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%d: skreq=%p state=%d id=%x fid=%x "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "pbuf=%p dir=%d\n", inx, (void *)skreq,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->state, skreq->id, skreq->fitmsg_id,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)skreq->pbuf, skreq->sg_data_dir);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta inx++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq = skreq->next;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (inx);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_list_skmsg, displays the skmsg table entries.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * list - flag, if true displays the entry address.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Returns number of skmsg entries found.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_list_skmsg(skd_device_t *skdev, int list)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int inx = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_fitmsg_context *skmsgp;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsgp = &skdev->skmsg_table[0];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (list) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skmsg_table[0]\n");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta while (skmsgp) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (list)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%d: skmsgp=%p id=%x outs=%d "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "l=%d o=%d nxt=%p\n", inx, (void *)skmsgp,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsgp->id, skmsgp->outstanding,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsgp->length, skmsgp->offset,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)skmsgp->next);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta inx++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsgp = skmsgp->next;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta inx = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (list)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skmsg_free_list\n");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsgp = skdev->skmsg_free_list;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta while (skmsgp) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (list)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%d: skmsgp=%p id=%x outs=%d l=%d "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "o=%d nxt=%p\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta inx, (void *)skmsgp, skmsgp->id,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsgp->outstanding, skmsgp->length,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsgp->offset, (void *)skmsgp->next);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta inx++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsgp = skmsgp->next;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (inx);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_get_queue_pbuf, retrieves top of queue entry and
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * delinks entry from the queue.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * drive - device number
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Returns the top of the job queue entry.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic skd_buf_private_t
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta*skd_get_queued_pbuf(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_buf_private_t *pbuf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ASSERT(WAITQ_LOCK_HELD(skdev));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf = SIMPLEQ_FIRST(&skdev->waitqueue);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (pbuf != NULL)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SIMPLEQ_REMOVE_HEAD(&skdev->waitqueue, sq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (pbuf);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * PCI DRIVER GLUE
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_pci_info, logs certain device PCI info.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: str which contains the device speed info..
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic char *
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_pci_info(struct skd_device *skdev, char *str, size_t len)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int pcie_reg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta str[0] = '\0';
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pcie_reg = skd_pci_find_capability(skdev, PCI_CAP_ID_EXP);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (pcie_reg) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint16_t lstat, lspeed, lwidth;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pcie_reg += 0x12;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta lstat = pci_config_get16(skdev->pci_handle, pcie_reg);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta lspeed = lstat & (0xF);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta lwidth = (lstat & 0x3F0) >> 4;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) snprintf(str, len, "PCIe (%s rev %d)",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta lspeed == 1 ? "2.5GT/s" :
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta lspeed == 2 ? "5.0GT/s" : "<unknown>",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta lwidth);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (str);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * MODULE GLUE
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_init, initializes certain values.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Zero.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_init(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "skd_init: v%s-b%s\n", DRV_VERSION, DRV_BUILD_ID);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_max_queue_depth < 1 ||
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_max_queue_depth > SKD_MAX_QUEUE_DEPTH) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "skd_max_q_depth %d invalid, re-set to %d\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_max_queue_depth, SKD_MAX_QUEUE_DEPTH_DEFAULT);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_max_queue_depth = SKD_MAX_QUEUE_DEPTH_DEFAULT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_max_req_per_msg < 1 || skd_max_req_per_msg > 14) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "skd_max_req_per_msg %d invalid, set to %d\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_max_req_per_msg, SKD_MAX_REQ_PER_MSG_DEFAULT);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_max_req_per_msg = SKD_MAX_REQ_PER_MSG_DEFAULT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_sgs_per_request < 1 || skd_sgs_per_request > 4096) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "skd_sg_per_request %d invalid, set to %d\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_sgs_per_request, SKD_N_SG_PER_REQ_DEFAULT);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_sgs_per_request = SKD_N_SG_PER_REQ_DEFAULT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_dbg_level < 0 || skd_dbg_level > 2) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "skd_dbg_level %d invalid, re-set to %d\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_dbg_level, 0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_dbg_level = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_exit, exits the driver & logs the fact.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: none.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_exit(void)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "skd v%s unloading", DRV_VERSION);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_drive_state_to_str, converts binary drive state
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * to its corresponding string value.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: Drive state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: String representing drive state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaconst char *
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_drive_state_to_str(int state)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_OFFLINE: return ("OFFLINE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_INIT: return ("INIT");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_ONLINE: return ("ONLINE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_BUSY: return ("BUSY");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_FAULT: return ("FAULT");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_DEGRADED: return ("DEGRADED");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_PCIE_LINK_DOWN: return ("LINK_DOWN");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_SOFT_RESET: return ("SOFT_RESET");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_NEED_FW_DOWNLOAD: return ("NEED_FW");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_INIT_FAULT: return ("INIT_FAULT");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_BUSY_SANITIZE:return ("BUSY_SANITIZE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_BUSY_ERASE: return ("BUSY_ERASE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case FIT_SR_DRIVE_FW_BOOTING: return ("FW_BOOTING");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default: return ("???");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_skdev_state_to_str, converts binary driver state
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * to its corresponding string value.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: Driver state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: String representing driver state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic const char *
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_skdev_state_to_str(enum skd_drvr_state state)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_LOAD: return ("LOAD");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_IDLE: return ("IDLE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY: return ("BUSY");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_STARTING: return ("STARTING");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_ONLINE: return ("ONLINE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_PAUSING: return ("PAUSING");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_PAUSED: return ("PAUSED");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_DRAINING_TIMEOUT: return ("DRAINING_TIMEOUT");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_RESTARTING: return ("RESTARTING");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_RESUMING: return ("RESUMING");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_STOPPING: return ("STOPPING");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_SYNCING: return ("SYNCING");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_FAULT: return ("FAULT");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_DISAPPEARED: return ("DISAPPEARED");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_ERASE: return ("BUSY_ERASE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_SANITIZE:return ("BUSY_SANITIZE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_BUSY_IMMINENT: return ("BUSY_IMMINENT");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_DRVR_STATE_WAIT_BOOT: return ("WAIT_BOOT");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default: return ("???");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_skmsg_state_to_str, converts binary driver state
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * to its corresponding string value.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: Msg state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: String representing msg state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic const char *
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_skmsg_state_to_str(enum skd_fit_msg_state state)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_MSG_STATE_IDLE: return ("IDLE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_MSG_STATE_BUSY: return ("BUSY");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default: return ("???");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_skreq_state_to_str, converts binary req state
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * to its corresponding string value.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: Req state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: String representing req state.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic const char *
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_skreq_state_to_str(enum skd_req_state state)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (state) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_REQ_STATE_IDLE: return ("IDLE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_REQ_STATE_SETUP: return ("SETUP");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_REQ_STATE_BUSY: return ("BUSY");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_REQ_STATE_COMPLETED: return ("COMPLETED");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_REQ_STATE_TIMEOUT: return ("TIMEOUT");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case SKD_REQ_STATE_ABORTED: return ("ABORTED");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default: return ("???");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_log_skdev, logs device state & parameters.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * event - event (string) to log.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_log_skdev(struct skd_device *skdev, const char *event)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "log_skdev(%s) skdev=%p event='%s'",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, (void *)skdev, event);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " drive_state=%s(%d) driver_state=%s(%d)",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_drive_state_to_str(skdev->drive_state), skdev->drive_state,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_skdev_state_to_str(skdev->state), skdev->state);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " busy=%d limit=%d soft=%d hard=%d lowat=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_busy, skdev->queue_depth_limit,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->soft_queue_depth_limit, skdev->hard_queue_depth_limit,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->queue_depth_lowat);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " timestamp=0x%x cycle=%d cycle_ix=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->timeout_stamp, skdev->skcomp_cycle, skdev->skcomp_ix);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_log_skmsg, logs the skmsg event.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skmsg - FIT message structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * event - event string to log.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_log_skmsg(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_fitmsg_context *skmsg, const char *event)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "log_skmsg:(%s) skmsg=%p event='%s'",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, (void *)skmsg, event);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " state=%s(%d) id=0x%04x length=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_skmsg_state_to_str(skmsg->state), skmsg->state,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skmsg->id, skmsg->length);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_log_skreq, logs the skreq event.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skreq -skreq structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * event - event string to log.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_log_skreq(struct skd_device *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_request_context *skreq, const char *event)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_buf_private_t *pbuf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "log_skreq: (%s) skreq=%p pbuf=%p event='%s'",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, (void *)skreq, (void *)skreq->pbuf, event);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " state=%s(%d) id=0x%04x fitmsg=0x%04x",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_skreq_state_to_str(skreq->state), skreq->state,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->id, skreq->fitmsg_id);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " timo=0x%x sg_dir=%d n_sg=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skreq->timeout_stamp, skreq->sg_data_dir, skreq->n_sg);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((pbuf = skreq->pbuf) != NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t lba, count;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta lba = pbuf->x_xfer->x_blkno;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta count = pbuf->x_xfer->x_nblks;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " pbuf=%p lba=%u(0x%x) count=%u(0x%x) ",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)pbuf, lba, lba, count, count);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " dir=%s "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta " intrs=%" PRId64 " qdepth=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (pbuf->dir & B_READ) ? "Read" : "Write",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->intr_cntr, skdev->queue_depth_busy);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " req=NULL\n");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_init_mutex, initializes all mutexes.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: DDI_FAILURE on failure otherwise DDI_SUCCESS.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_init_mutex(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta void *intr;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_CONT, "(%s%d): init_mutex flags=%x", DRV_NAME,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->instance, skdev->flags);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta intr = (void *)(uintptr_t)skdev->intr_pri;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->flags & SKD_MUTEX_INITED)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "init_mutex: Oh-Oh - already INITED");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* mutexes to protect the adapter state structure. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_init(&skdev->skd_lock_mutex, NULL, MUTEX_DRIVER,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_INTR_PRI(intr));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_init(&skdev->skd_intr_mutex, NULL, MUTEX_DRIVER,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_INTR_PRI(intr));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_init(&skdev->waitqueue_mutex, NULL, MUTEX_DRIVER,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_INTR_PRI(intr));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_init(&skdev->skd_internalio_mutex, NULL, MUTEX_DRIVER,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_INTR_PRI(intr));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cv_init(&skdev->cv_waitq, NULL, CV_DRIVER, NULL);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->flags |= SKD_MUTEX_INITED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->flags & SKD_MUTEX_DESTROYED)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->flags &= ~SKD_MUTEX_DESTROYED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_CONT, "init_mutex (%s%d): done, flags=%x", DRV_NAME,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->instance, skdev->flags);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_SUCCESS);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_destroy_mutex, destroys all mutexes.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_destroy_mutex(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((skdev->flags & SKD_MUTEX_DESTROYED) == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->flags & SKD_MUTEX_INITED) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_destroy(&skdev->waitqueue_mutex);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_destroy(&skdev->skd_intr_mutex);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_destroy(&skdev->skd_lock_mutex);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_destroy(&skdev->skd_internalio_mutex);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cv_destroy(&skdev->cv_waitq);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->flags |= SKD_MUTEX_DESTROYED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->flags & SKD_MUTEX_INITED)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->flags &= ~SKD_MUTEX_INITED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_setup_intr, setup the interrupt handling
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * intr_type - requested DDI interrupt type.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: DDI_FAILURE on failure otherwise DDI_SUCCESS.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_setup_intr(skd_device_t *skdev, int intr_type)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int32_t count = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int32_t avail = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int32_t actual = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int32_t ret;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_CONT, "(%s%d): setup_intr", DRV_NAME, skdev->instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Get number of interrupts the platform h/w supports */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (((ret = ddi_intr_get_nintrs(skdev->dip, intr_type, &count)) !=
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_SUCCESS) || count == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!intr_setup failed, nintrs ret=%xh, cnt=%xh",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ret, count);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Get number of available system interrupts */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (((ret = ddi_intr_get_navail(skdev->dip, intr_type, &avail)) !=
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_SUCCESS) || avail == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!intr_setup failed, navail ret=%xh, "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "avail=%xh", ret, avail);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (intr_type == DDI_INTR_TYPE_MSIX && avail < SKD_MSIX_MAXAIF) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!intr_setup failed, min MSI-X h/w vectors "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "req'd: %d, avail: %d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_MSIX_MAXAIF, count);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Allocate space for interrupt handles */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->hsize = sizeof (ddi_intr_handle_t) * avail;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->htable = kmem_zalloc(skdev->hsize, KM_SLEEP);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Allocate the interrupts */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((ret = ddi_intr_alloc(skdev->dip, skdev->htable, intr_type,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta 0, count, &actual, 0)) != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!intr_setup failed, intr_alloc ret=%xh, "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "count = %xh, " "actual=%xh", ret, count, actual);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_release_intr(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->intr_cnt = actual;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (intr_type == DDI_INTR_TYPE_FIXED)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_intr_set_pri(skdev->htable[0], 10);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Get interrupt priority */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((ret = ddi_intr_get_pri(skdev->htable[0], &skdev->intr_pri)) !=
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!intr_setup failed, get_pri ret=%xh", ret);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_release_intr(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (ret);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Add the interrupt handlers */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < actual; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((ret = ddi_intr_add_handler(skdev->htable[i],
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_isr_aif, (void *)skdev, (void *)((ulong_t)i))) !=
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!intr_setup failed, addh#=%xh, "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "act=%xh, ret=%xh", i, actual, ret);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_release_intr(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (ret);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Setup mutexes */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((ret = skd_init_mutex(skdev)) != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!intr_setup failed, mutex init ret=%xh", ret);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_release_intr(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (ret);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Get the capabilities */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_intr_get_cap(skdev->htable[0], &skdev->intr_cap);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Enable interrupts */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->intr_cap & DDI_INTR_FLAG_BLOCK) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((ret = ddi_intr_block_enable(skdev->htable,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->intr_cnt)) != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!failed, intr_setup block enable, "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "ret=%xh", ret);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_destroy_mutex(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_release_intr(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (ret);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < skdev->intr_cnt; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((ret = ddi_intr_enable(skdev->htable[i])) !=
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!intr_setup failed, "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "intr enable, ret=%xh", ret);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_destroy_mutex(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_release_intr(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (ret);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (intr_type == DDI_INTR_TYPE_FIXED)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_intr_clr_mask(skdev->htable[0]);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->irq_type = intr_type;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_SUCCESS);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_disable_intr, disable interrupt handling.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_disable_intr(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t i, rval;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->intr_cap & DDI_INTR_FLAG_BLOCK) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Remove AIF block interrupts (MSI/MSI-X) */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((rval = ddi_intr_block_disable(skdev->htable,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->intr_cnt)) != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!failed intr block disable, rval=%x",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rval);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Remove AIF non-block interrupts (fixed). */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (i = 0; i < skdev->intr_cnt; i++) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((rval = ddi_intr_disable(skdev->htable[i])) !=
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!failed intr disable, "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "intr#=%xh, " "rval=%xh", i, rval);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_release_intr, disables interrupt handling.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_release_intr(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int32_t i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rval;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_CONT, "REL_INTR intr_cnt=%d", skdev->intr_cnt);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->irq_type == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_CONT, "release_intr: (%s%d): done",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DRV_NAME, skdev->instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->htable != NULL && skdev->hsize > 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta i = (int32_t)skdev->hsize / (int32_t)sizeof (ddi_intr_handle_t);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta while (i-- > 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->htable[i] == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "htable[%x]=0h", i);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta continue;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((rval = ddi_intr_disable(skdev->htable[i])) !=
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_SUCCESS)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "release_intr: intr_disable "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "htable[%d], rval=%d", i, rval);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (i < skdev->intr_cnt) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((rval = ddi_intr_remove_handler(
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->htable[i])) != DDI_SUCCESS)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!release_intr: "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "intr_remove_handler FAILED, "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "rval=%d", rval);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "release_intr: "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "remove_handler htable[%d]", i);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((rval = ddi_intr_free(skdev->htable[i])) !=
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_SUCCESS)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!release_intr: intr_free "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "FAILED, rval=%d", rval);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "release_intr: intr_free htable[%d]",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta i);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta kmem_free(skdev->htable, skdev->hsize);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->htable = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->hsize = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->intr_cnt = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->intr_pri = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->intr_cap = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->irq_type = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_dealloc_resources, deallocate resources allocated
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * during attach.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: dip - DDI device info pointer.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * seq - bit flag representing allocated item.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * instance - device instance.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_dealloc_resources(dev_info_t *dip, skd_device_t *skdev,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint32_t seq, int instance)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev == NULL)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (seq & SKD_CONSTRUCTED)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_destruct(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (seq & SKD_INTR_ADDED) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_disable_intr(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_release_intr(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (seq & SKD_DEV_IOBASE_MAPPED)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_regs_map_free(&skdev->dev_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (seq & SKD_IOMAP_IOBASE_MAPPED)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_regs_map_free(&skdev->iomap_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (seq & SKD_REGS_MAPPED)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_regs_map_free(&skdev->iobase_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (seq & SKD_CONFIG_SPACE_SETUP)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pci_config_teardown(&skdev->pci_handle);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (seq & SKD_SOFT_STATE_ALLOCED) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->pathname &&
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (skdev->flags & SKD_PATHNAME_ALLOCED)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta kmem_free(skdev->pathname,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta strlen(skdev->pathname)+1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->s1120_devid)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_devid_free(skdev->s1120_devid);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_setup_interrupt, sets up the appropriate interrupt type
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * msi, msix, or fixed.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: DDI_FAILURE on failure otherwise DDI_SUCCESS.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_setup_interrupts(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int32_t rval = DDI_FAILURE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int32_t i;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int32_t itypes = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * See what types of interrupts this adapter and platform support
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((i = ddi_intr_get_supported_types(skdev->dip, &itypes)) !=
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "intr supported types failed, rval=%xh, ", i);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s:supported interrupts types: %x",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, itypes);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta itypes &= skdev->irq_type;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (!skd_disable_msix && (itypes & DDI_INTR_TYPE_MSIX) &&
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (rval = skd_setup_intr(skdev, DDI_INTR_TYPE_MSIX)) == DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "!%s: successful MSI-X setup",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else if (!skd_disable_msi && (itypes & DDI_INTR_TYPE_MSI) &&
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (rval = skd_setup_intr(skdev, DDI_INTR_TYPE_MSI)) == DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "!%s: successful MSI setup",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else if ((itypes & DDI_INTR_TYPE_FIXED) &&
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (rval = skd_setup_intr(skdev, DDI_INTR_TYPE_FIXED))
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta == DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "!%s: successful fixed intr setup",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s: no supported interrupt types",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_CONT, "%s: setup interrupts done", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rval);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_get_properties, retrieves properties from skd.conf.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * dip - dev_info data structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_get_properties(dev_info_t *dip, skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int prop_value;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_isr_type = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "intr-type-cap", -1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta prop_value = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "max-scsi-reqs", -1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (prop_value >= 1 && prop_value <= SKD_MAX_QUEUE_DEPTH)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_max_queue_depth = prop_value;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta prop_value = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "max-scsi-reqs-per-msg", -1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (prop_value >= 1 && prop_value <= SKD_MAX_REQ_PER_MSG)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_max_req_per_msg = prop_value;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta prop_value = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "max-sgs-per-req", -1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (prop_value >= 1 && prop_value <= SKD_MAX_N_SG_PER_REQ)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_sgs_per_request = prop_value;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta prop_value = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "dbg-level", -1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (prop_value >= 1 && prop_value <= 2)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_dbg_level = prop_value;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_wait_for_s1120, wait for device to finish
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * its initialization.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: DDI_SUCCESS or DDI_FAILURE.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_wait_for_s1120(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta clock_t cur_ticks, tmo;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int loop_cntr = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rc = DDI_FAILURE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_enter(&skdev->skd_internalio_mutex);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta while (skdev->gendisk_on == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cur_ticks = ddi_get_lbolt();
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta tmo = cur_ticks + drv_usectohz(MICROSEC);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (cv_timedwait(&skdev->cv_waitq,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &skdev->skd_internalio_mutex, tmo) == -1) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Oops - timed out */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (loop_cntr++ > 10)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta mutex_exit(&skdev->skd_internalio_mutex);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->gendisk_on == 1)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = DDI_SUCCESS;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rc);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_update_props, updates certain device properties.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * dip - dev info structure
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_update_props(skd_device_t *skdev, dev_info_t *dip)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int blksize = 512;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((ddi_prop_update_int64(DDI_DEV_T_NONE, dip, "device-nblocks",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->Nblocks) != DDI_SUCCESS) ||
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (ddi_prop_update_int(DDI_DEV_T_NONE, dip, "device-blksize",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta blksize) != DDI_SUCCESS)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_NOTE, "%s: FAILED to create driver properties",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_setup_devid, sets up device ID info.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * devid - Device ID for the DDI.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: DDI_SUCCESS or DDI_FAILURE.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_setup_devid(skd_device_t *skdev, ddi_devid_t *devid)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rc, sz_model, sz_sn, sz;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld sz_model = scsi_ascii_inquiry_len(skdev->inq_product_id,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld strlen(skdev->inq_product_id));
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld sz_sn = scsi_ascii_inquiry_len(skdev->inq_serial_num,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld strlen(skdev->inq_serial_num));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta sz = sz_model + sz_sn + 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld (void) snprintf(skdev->devid_str, sizeof (skdev->devid_str),
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld "%.*s=%.*s", sz_model, skdev->inq_product_id, sz_sn,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld skdev->inq_serial_num);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rc = ddi_devid_init(skdev->dip, DEVID_SCSI_SERIAL, sz,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->devid_str, devid);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rc != DDI_SUCCESS)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s: devid_init FAILED", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rc);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_bd_attach, attach to blkdev driver
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * dip - device info structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: DDI_SUCCESS or DDI_FAILURE.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_bd_attach(dev_info_t *dip, skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rv;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->s_bdh = bd_alloc_handle(skdev, &skd_bd_ops,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &skd_64bit_io_dma_attr, KM_SLEEP);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->s_bdh == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!skd_bd_attach: FAILED");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rv = bd_attach_handle(dip, skdev->s_bdh);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rv != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!bd_attach_handle FAILED\n");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "bd_attach_handle OK\n");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->bd_attached++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rv);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_bd_detach, detach from the blkdev driver.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_bd_detach(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->bd_attached)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) bd_detach_handle(skdev->s_bdh);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta bd_free_handle(skdev->s_bdh);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_attach, attach sdk device driver
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: dip - device info structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * cmd - DDI attach argument (ATTACH, RESUME, etc.)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: DDI_SUCCESS or DDI_FAILURE.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int instance;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int nregs;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_device_t *skdev = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int inx;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta uint16_t cmd_reg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int progress = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta char name[MAXPATHLEN];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta off_t regsize;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta char pci_str[32];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta char fw_version[8];
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta instance = ddi_get_instance(dip);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_get_parent_data(dip);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (cmd) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case DDI_ATTACH:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case DDI_RESUME:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Re-enable timer */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start_timer(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_SUCCESS);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "sTec S1120 Driver v%s Instance: %d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta VERSIONSTR, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Check that hardware is installed in a DMA-capable slot
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (ddi_slaveonly(dip) == DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s%d: installed in a "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "slot that isn't DMA-capable slot", DRV_NAME, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * No support for high-level interrupts
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (ddi_intr_hilevel(dip, 0) != 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s%d: High level interrupt not supported",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DRV_NAME, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Allocate our per-device-instance structure
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (ddi_soft_state_zalloc(skd_state, instance) !=
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s%d: soft state zalloc failed ",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DRV_NAME, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta progress |= SKD_SOFT_STATE_ALLOCED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev = ddi_get_soft_state(skd_state, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s%d: Unable to get soft state structure",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DRV_NAME, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto skd_attach_failed;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) snprintf(skdev->name, sizeof (skdev->name),
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DRV_NAME "%d", instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->dip = dip;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->instance = instance;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_set_driver_private(dip, skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_pathname(dip, name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta for (inx = strlen(name); inx; inx--) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (name[inx] == ',') {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta name[inx] = '\0';
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (name[inx] == '@') {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->pathname = kmem_zalloc(strlen(name) + 1, KM_SLEEP);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) strlcpy(skdev->pathname, name, strlen(name) + 1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta progress |= SKD_PATHNAME_ALLOCED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->flags |= SKD_PATHNAME_ALLOCED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (pci_config_setup(dip, &skdev->pci_handle) != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s%d: pci_config_setup FAILED",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DRV_NAME, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto skd_attach_failed;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta progress |= SKD_CONFIG_SPACE_SETUP;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Save adapter path. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) ddi_dev_nregs(dip, &nregs);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * 0x0 Configuration Space
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * 0x1 I/O Space
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * 0x2 s1120 register space
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (ddi_dev_regsize(dip, 1, &regsize) != DDI_SUCCESS ||
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_regs_map_setup(dip, 1, &skdev->iobase, 0, regsize,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &dev_acc_attr, &skdev->iobase_handle) != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s%d: regs_map_setup(mem) failed",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DRV_NAME, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto skd_attach_failed;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta progress |= SKD_REGS_MAPPED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->iomap_iobase = skdev->iobase;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->iomap_handle = skdev->iobase_handle;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: PCI iobase=%ph, iomap=%ph, regnum=%d, "
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "regsize=%ld", skdev->name, (void *)skdev->iobase,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)skdev->iomap_iobase, 1, regsize);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (ddi_dev_regsize(dip, 2, &regsize) != DDI_SUCCESS ||
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_regs_map_setup(dip, 2, &skdev->dev_iobase, 0, regsize,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta &dev_acc_attr, &skdev->dev_handle) != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s%d: regs_map_setup(mem) failed",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DRV_NAME, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto skd_attach_failed;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->dev_memsize = (int)regsize;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: DEV iobase=%ph regsize=%d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, (void *)skdev->dev_iobase,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->dev_memsize);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta progress |= SKD_DEV_IOBASE_MAPPED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmd_reg = pci_config_get16(skdev->pci_handle, PCI_CONF_COMM);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmd_reg |= (PCI_COMM_ME | PCI_COMM_INTX_DISABLE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmd_reg &= ~PCI_COMM_PARITY_DETECT;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pci_config_put16(skdev->pci_handle, PCI_CONF_COMM, cmd_reg);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Get adapter PCI device information. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->vendor_id = pci_config_get16(skdev->pci_handle, PCI_CONF_VENID);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->device_id = pci_config_get16(skdev->pci_handle, PCI_CONF_DEVID);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: %x-%x card detected",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, skdev->vendor_id, skdev->device_id);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_get_properties(dip, skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) skd_init(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_construct(skdev, instance)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s: construct FAILED", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto skd_attach_failed;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta progress |= SKD_PROBED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta progress |= SKD_CONSTRUCTED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SIMPLEQ_INIT(&skdev->waitqueue);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Setup interrupt handler
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_setup_interrupts(skdev) != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s: Unable to add interrupt",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto skd_attach_failed;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta progress |= SKD_INTR_ADDED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->flags |= SKD_ATTACHED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->d_blkshift = 9;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta progress |= SKD_ATTACHED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start_device(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->progress = progress;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Give the board a chance to
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * complete its initialization.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->gendisk_on != 1)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) skd_wait_for_s1120(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->gendisk_on != 1) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!%s: s1120 failed to come ONLINE",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto skd_attach_failed;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_report_dev(dip);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_internal_skspcl(skdev, &skdev->internal_skspcl, INQUIRY);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->disks_initialized++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) strcpy(fw_version, "???");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) skd_pci_info(skdev, pci_str, sizeof (pci_str));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " sTec S1120 Driver(%s) version %s-b%s",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta DRV_NAME, DRV_VERSION, DRV_BUILD_ID);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " sTec S1120 %04x:%04x %s 64 bit",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->vendor_id, skdev->device_id, pci_str);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " sTec S1120 %s\n", skdev->pathname);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (*skdev->inq_serial_num)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " sTec S1120 serial#=%s",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->inq_serial_num);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (*skdev->inq_product_id &&
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *skdev->inq_product_rev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, " sTec S1120 prod ID=%s prod rev=%s",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->inq_product_id, skdev->inq_product_rev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: intr-type-cap: %d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, skdev->irq_type);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: max-scsi-reqs: %d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, skd_max_queue_depth);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: max-sgs-per-req: %d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, skd_sgs_per_request);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: max-scsi-req-per-msg: %d",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->name, skd_max_req_per_msg);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skd_bd_attach(dip, skdev) == DDI_FAILURE)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta goto skd_attach_failed;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_update_props(skdev, dip);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Enable timer */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start_timer(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->progress = progress;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->attached = 1;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_SUCCESS);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_attach_failed:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_dealloc_resources(dip, skdev, progress, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((skdev->flags & SKD_MUTEX_DESTROYED) == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_destroy_mutex(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_soft_state_free(skd_state, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!skd_attach FAILED: progress=%x", progress);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_halt
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_halt(skd_device_t *skdev)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "%s: halt/suspend ......", skdev->name);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_detach, detaches driver from the system.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: dip - device info structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: DDI_SUCCESS on successful detach otherwise DDI_FAILURE.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_buf_private_t *pbuf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_device_t *skdev;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int instance;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta timeout_id_t timer_id = NULL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta int rv1 = DDI_SUCCESS;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta struct skd_special_context *skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta instance = ddi_get_instance(dip);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev = ddi_get_soft_state(skd_state, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev == NULL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!detach failed: NULL skd state");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_CONT, "skd_detach(%d): entered", instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta switch (cmd) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case DDI_DETACH:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Test for packet cache inuse. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Stop command/event processing. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->flags |= (SKD_SUSPENDED | SKD_CMD_ABORT_TMO);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Disable driver timer if no adapters. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->skd_timer_timeout_id != 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta timer_id = skdev->skd_timer_timeout_id;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skd_timer_timeout_id = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (timer_id != 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) untimeout(timer_id);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#ifdef SKD_PM
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->power_level != LOW_POWER_LEVEL) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_halt(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->power_level = LOW_POWER_LEVEL;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta#endif
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skspcl = &skdev->internal_skspcl;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_send_internal_skspcl(skdev, skspcl, SYNCHRONIZE_CACHE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_stop_device(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Clear request queue.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta while (!SIMPLEQ_EMPTY(&skdev->waitqueue)) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf = skd_get_queued_pbuf(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_end_request_abnormal(skdev, pbuf, ECANCELED,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta SKD_IODONE_WNIOC);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta "detach: cancelled pbuf %p %ld <%s> %lld\n",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void *)pbuf, pbuf->x_xfer->x_nblks,
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (pbuf->dir & B_READ) ? "Read" : "Write",
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf->x_xfer->x_blkno);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_bd_detach(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_dealloc_resources(dip, skdev, skdev->progress, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if ((skdev->flags & SKD_MUTEX_DESTROYED) == 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_destroy_mutex(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_soft_state_free(skd_state, instance);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_exit();
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta case DDI_SUSPEND:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Block timer. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->flags |= SKD_SUSPENDED;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* Disable driver timer if last adapter. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->skd_timer_timeout_id != 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta timer_id = skdev->skd_timer_timeout_id;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->skd_timer_timeout_id = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ADAPTER_STATE_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (timer_id != 0) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) untimeout(timer_id);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta ddi_prop_remove_all(dip);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_halt(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta default:
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta rv1 = DDI_FAILURE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta break;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rv1 != DDI_SUCCESS) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta cmn_err(CE_WARN, "!skd_detach, failed, rv1=%x", rv1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta } else {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_CONT, "skd_detach: exiting");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (rv1 != DDI_SUCCESS)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (DDI_FAILURE);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (rv1);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_devid_init, calls skd_setup_devid to setup
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * the device's devid structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: arg - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * dip - dev_info structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * devid - devid structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/* ARGSUSED */ /* Upstream common source with other platforms. */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_devid_init(void *arg, dev_info_t *dip, ddi_devid_t *devid)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_device_t *skdev = arg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta (void) skd_setup_devid(skdev, devid);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_bd_driveinfo, retrieves device's info.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: drive - drive data structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * arg - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Nothing.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic void
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_bd_driveinfo(void *arg, bd_drive_t *drive)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_device_t *skdev = arg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta drive->d_qsize = (skdev->queue_depth_limit * 4) / 5;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta drive->d_maxxfer = SKD_DMA_MAXXFER;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta drive->d_removable = B_FALSE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta drive->d_hotpluggable = B_FALSE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta drive->d_target = 0;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta drive->d_lun = 0;
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld if (skdev->inquiry_is_valid != 0) {
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_vendor = skdev->inq_vendor_id;
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_vendor_len = strlen(drive->d_vendor);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_product = skdev->inq_product_id;
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_product_len = strlen(drive->d_product);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_serial = skdev->inq_serial_num;
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_serial_len = strlen(drive->d_serial);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_revision = skdev->inq_product_rev;
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_revision_len = strlen(drive->d_revision);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_bd_mediainfo, retrieves device media info.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: arg - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * media - container for media info.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Zero.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_bd_mediainfo(void *arg, bd_media_t *media)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_device_t *skdev = arg;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta media->m_nblks = skdev->Nblocks;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta media->m_blksize = 512;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta media->m_pblksize = 4096;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta media->m_readonly = B_FALSE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta media->m_solidstate = B_TRUE;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_rw, performs R/W requests for blkdev driver.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: skdev - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * xfer - tranfer structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * dir - I/O direction.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: EAGAIN if device is not online. EIO if blkdev wants us to
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * be a dump device (for now).
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Value returned by skd_start().
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_rw(skd_device_t *skdev, bd_xfer_t *xfer, int dir)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_buf_private_t *pbuf;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * The x_flags structure element is not defined in Oracle Solaris
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta /* We'll need to fix this in order to support dump on this device. */
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (xfer->x_flags & BD_XFER_POLL)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (EIO);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (skdev->state != SKD_DRVR_STATE_ONLINE) {
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta Dcmn_err(CE_NOTE, "Device - not ONLINE");
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_request_fn_not_online(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (EAGAIN);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta }
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf = kmem_zalloc(sizeof (skd_buf_private_t), KM_NOSLEEP);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta if (pbuf == NULL)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (ENOMEM);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_LOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf->dir = dir;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta pbuf->x_xfer = xfer;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_queue(skdev, pbuf);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skdev->ios_queued++;
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta WAITQ_UNLOCK(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta skd_start(skdev);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (0);
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_bd_read, performs blkdev read requests.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: arg - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * xfer - tranfer request structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Value return by skd_rw().
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_bd_read(void *arg, bd_xfer_t *xfer)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (skd_rw(arg, xfer, B_READ));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta/*
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Name: skd_bd_write, performs blkdev write requests.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Inputs: arg - device state structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * xfer - tranfer request structure.
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta * Returns: Value return by skd_rw().
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta *
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta */
f52228b83292315dabb975359cdcf9db662845b2Joe Betetastatic int
f52228b83292315dabb975359cdcf9db662845b2Joe Betetaskd_bd_write(void *arg, bd_xfer_t *xfer)
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta{
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta return (skd_rw(arg, xfer, B_WRITE));
f52228b83292315dabb975359cdcf9db662845b2Joe Beteta}