summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/pkgdefs/SUNWaac/Makefile6
-rw-r--r--usr/src/pkgdefs/SUNWaac/depend31
-rw-r--r--usr/src/pkgdefs/SUNWaac/pkginfo.tmpl6
-rw-r--r--usr/src/pkgdefs/SUNWaac/prototype_com7
-rw-r--r--usr/src/pkgdefs/common_files/depend9
-rw-r--r--usr/src/pkgdefs/common_files/i.aacconf76
-rw-r--r--usr/src/tools/scripts/bfu.sh1
-rw-r--r--usr/src/uts/common/io/aac/README18
-rw-r--r--usr/src/uts/common/io/aac/aac.c1569
-rw-r--r--usr/src/uts/common/io/aac/aac.conf35
-rw-r--r--usr/src/uts/common/io/aac/aac.h77
-rw-r--r--usr/src/uts/common/io/aac/aac_ioctl.c25
-rw-r--r--usr/src/uts/common/io/aac/aac_ioctl.h6
-rw-r--r--usr/src/uts/common/io/aac/aac_regs.h48
-rw-r--r--usr/src/uts/common/io/warlock/aac.wlcmd7
15 files changed, 1646 insertions, 275 deletions
diff --git a/usr/src/pkgdefs/SUNWaac/Makefile b/usr/src/pkgdefs/SUNWaac/Makefile
index 7e91bc33f8..17c7b091bb 100644
--- a/usr/src/pkgdefs/SUNWaac/Makefile
+++ b/usr/src/pkgdefs/SUNWaac/Makefile
@@ -2,17 +2,17 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
include ../Makefile.com
LICENSEFILES += ../../uts/common/io/aac/THIRDPARTYLICENSE
CDDL=
+DATAFILES += depend i.aacconf
+
.KEEP_STATE:
-all: $(FILES) depend postinstall postremove
+all: $(FILES) postinstall postremove
install: all pkg
include ../Makefile.targ
diff --git a/usr/src/pkgdefs/SUNWaac/depend b/usr/src/pkgdefs/SUNWaac/depend
deleted file mode 100644
index 175a6b29bc..0000000000
--- a/usr/src/pkgdefs/SUNWaac/depend
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-# This package information file defines software dependencies associated
-# with the pkg. You can define three types of pkg dependencies with this file:
-# P indicates a prerequisite for installation
-# I indicates an incompatible package
-# R indicates a reverse dependency
-# <pkg.abbr> see pkginfo(4), PKG parameter
-# <name> see pkginfo(4), NAME parameter
-# <version> see pkginfo(4), VERSION parameter
-# <arch> see pkginfo(4), ARCH parameter
-# <type> <pkg.abbr> <name>
-# (<arch>)<version>
-# (<arch>)<version>
-# ...
-# <type> <pkg.abbr> <name>
-# ...
-
-P SUNWcar Core Architecture, (Root)
-P SUNWcakr Core Solaris Kernel Architecture (Root)
-P SUNWkvm Core Architecture, (Kvm)
-P SUNWcsr Core Solaris, (Root)
-P SUNWckr Core Solaris Kernel (Root)
-P SUNWcnetr Core Solaris Network Infrastructure (Root)
-P SUNWcsu Core Solaris, (Usr)
-P SUNWcsd Core Solaris Devices
-P SUNWcsl Core Solaris Libraries
diff --git a/usr/src/pkgdefs/SUNWaac/pkginfo.tmpl b/usr/src/pkgdefs/SUNWaac/pkginfo.tmpl
index 0eab167b1d..f9907ab4a7 100644
--- a/usr/src/pkgdefs/SUNWaac/pkginfo.tmpl
+++ b/usr/src/pkgdefs/SUNWaac/pkginfo.tmpl
@@ -1,9 +1,7 @@
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
PKG=SUNWaac
NAME=Adaptec AdvanceRaid Controller SCSI HBA Driver
@@ -17,7 +15,7 @@ MAXINST="1000"
CATEGORY=system
VENDOR="Sun Microsystems, Inc."
DESC="Adaptec AdvanceRaid Controller SCSI HBA Driver"
-CLASSES="none"
+CLASSES="none aacconf"
HOTLINE="Please contact your local service provider"
EMAIL=""
BASEDIR=/
diff --git a/usr/src/pkgdefs/SUNWaac/prototype_com b/usr/src/pkgdefs/SUNWaac/prototype_com
index 094b3925a0..f6c8cc7ce8 100644
--- a/usr/src/pkgdefs/SUNWaac/prototype_com
+++ b/usr/src/pkgdefs/SUNWaac/prototype_com
@@ -20,11 +20,9 @@
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
#
# This required package information file contains a list of package contents.
@@ -44,8 +42,9 @@ i copyright
i depend
i postinstall
i postremove
+i i.aacconf
# Adaptec AdvanceRaid Controller Driver
d none kernel 0755 root sys
d none kernel/drv 0755 root sys
-f none kernel/drv/aac.conf 0644 root sys
+e aacconf kernel/drv/aac.conf 0644 root sys
diff --git a/usr/src/pkgdefs/common_files/depend b/usr/src/pkgdefs/common_files/depend
index f180d109ca..4d7c829f2e 100644
--- a/usr/src/pkgdefs/common_files/depend
+++ b/usr/src/pkgdefs/common_files/depend
@@ -1,13 +1,12 @@
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -22,8 +21,6 @@
#
# CDDL HEADER END
#
-# ident "%Z%%M% %I% %E% SMI"
-#
# This package information file defines software dependencies associated
# with the pkg. You can define three types of pkg dependencies with this file:
# P indicates a prerequisite for installation
diff --git a/usr/src/pkgdefs/common_files/i.aacconf b/usr/src/pkgdefs/common_files/i.aacconf
new file mode 100644
index 0000000000..c3970cee24
--- /dev/null
+++ b/usr/src/pkgdefs/common_files/i.aacconf
@@ -0,0 +1,76 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+# Get parameter value from old aac.conf file.
+# Syntax: file parameter-name
+getval()
+{
+ # Strip all instances of ';' putval() will add exactly one.
+ sed -n "/^[ ]*[^#]/s/.*$2[ ]*=[ ]*\([^ ;]*\).*/\1/p" $1 \
+ | head -1
+}
+
+# Put old parameter value into new aac.conf file.
+# Syntax: file parameter-name value
+putval()
+{
+ # If new parameter-value pair, append it to the file.
+ grep "^[ ]*$2" $1 >/dev/null
+ if [ $? -eq 0 ]; then
+ sed "/^[ ]*[^#]/s/\($2[ ]*=[ ]*\)[^ ]*/\1$3;/" \
+ $1 > /tmp/tmp.$$
+ mv /tmp/tmp.$$ $1
+ else
+ echo "$2=$3;" >>$1
+ fi
+}
+
+if read src dest; then
+ if [ ! -f $dest ]; then
+ # no existing version, just copy in new one
+ cp $src $dest
+ else
+ #
+ # upgrading solaris
+ # Save existing values of the following parameters.
+ # Copy new aac.conf over current configuration file.
+ # Restore saved parameters in the new aac.conf file.
+ #
+ legacy_name_enable=`getval $dest legacy-name-enable`
+ nondasd_enable=`getval $dest nondasd-enable`
+
+ cp $src $dest
+
+ if [ -z "$legacy_name_enable" ]; then
+ legacy_name_enable='"yes"'
+ fi
+ putval $dest legacy-name-enable $legacy_name_enable
+ if [ -z "$nondasd_enable" ]; then
+ nondasd_enable='"no"'
+ fi
+ putval $dest nondasd-enable $nondasd_enable
+ fi
+fi
+exit 0
diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh
index 2499421002..1062eab786 100644
--- a/usr/src/tools/scripts/bfu.sh
+++ b/usr/src/tools/scripts/bfu.sh
@@ -213,6 +213,7 @@ global_zone_only_files="
etc/security/tsol/devalloc_defaults
etc/system
etc/zones/index
+ kernel/drv/aac.conf
kernel/drv/elxl.conf
kernel/drv/md.conf
kernel/drv/options.conf
diff --git a/usr/src/uts/common/io/aac/README b/usr/src/uts/common/io/aac/README
index c4b47284bd..6af40491bd 100644
--- a/usr/src/uts/common/io/aac/README
+++ b/usr/src/uts/common/io/aac/README
@@ -23,8 +23,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-
aac driver 2.0
================
The Solaris aac driver enhancement updates the Solaris aac 1.6 driver
@@ -69,7 +67,7 @@ SPARC platform support is added in this release:
now uses DDI compliant functions to access the device's IO and memory
spaces for DMA transfers.
-aac driver 2.2.23
+aac driver 2.2.3
==================
MSI interrupts supporting is added in this release:
Instead of supporting fixed interrupt only, the driver added the MSI
@@ -77,3 +75,17 @@ MSI interrupts supporting is added in this release:
driver has replaced all legacy interrupt ddi interfaces callings by
the according ddi_intr_* ones.
+aac driver 2.2.5
+==================
+Two new features are included in this release:
+One is Non-DASD support:
+ The driver now supports non-DASD(Non Direct Access Storage Device).
+ This means you can use cdroms and other non-DASD devices with
+ your aac card. Before trying it, make sure your card's firmware support
+ non-DASD access. For some cards, you may need to explicitly enable it
+ through aac BIOS. Make sure nondasd-enable property in aac.conf is
+ switched on.
+The other is FIB dump:
+ The driver now supports FIB contents dumping for driver debugging. To
+ enable it, you need to set AAC_DEBUG and the appropriate flags in
+ aac_debug_fib_flags.
diff --git a/usr/src/uts/common/io/aac/aac.c b/usr/src/uts/common/io/aac/aac.c
index b636a3a5d6..10ea80a60e 100644
--- a/usr/src/uts/common/io/aac/aac.c
+++ b/usr/src/uts/common/io/aac/aac.c
@@ -4,8 +4,8 @@
*/
/*
- * Copyright 2005-06 Adaptec, Inc.
- * Copyright (c) 2005-06 Adaptec Inc., Achim Leubner
+ * Copyright 2005-08 Adaptec, Inc.
+ * Copyright (c) 2005-08 Adaptec Inc., Achim Leubner
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2001 Scott Long
* Copyright (c) 2000 BSDi
@@ -32,8 +32,6 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/modctl.h>
#include <sys/conf.h>
#include <sys/cmn_err.h>
@@ -72,9 +70,20 @@
#define AAC_SCSA_MINOR(x) ((x) & TRAN_MINOR_MASK)
#define AAC_IS_SCSA_NODE(x) ((x) == DEVCTL_MINOR || (x) == SCSI_MINOR)
+#define SD2TRAN(sd) ((sd)->sd_address.a_hba_tran)
#define AAC_TRAN2SOFTS(tran) ((struct aac_softstate *)(tran)->tran_hba_private)
#define AAC_DIP2TRAN(dip) ((scsi_hba_tran_t *)ddi_get_driver_private(dip))
#define AAC_DIP2SOFTS(dip) (AAC_TRAN2SOFTS(AAC_DIP2TRAN(dip)))
+#define SD2AAC(sd) (AAC_TRAN2SOFTS(SD2TRAN(sd)))
+#define AAC_PD(t) ((t) - AAC_MAX_LD)
+#define AAC_DEV(softs, t) (((t) < AAC_MAX_LD) ? \
+ &(softs)->containers[(t)].dev : \
+ ((t) < AAC_MAX_DEV(softs)) ? \
+ &(softs)->nondasds[AAC_PD(t)].dev : NULL)
+#define AAC_DEVCFG_BEGIN(softs, tgt) \
+ aac_devcfg((softs), (tgt), 1)
+#define AAC_DEVCFG_END(softs, tgt) \
+ aac_devcfg((softs), (tgt), 0)
#define PKT2AC(pkt) ((struct aac_cmd *)(pkt)->pkt_ha_private)
#define AAC_BUSYWAIT(cond, timeout /* in millisecond */) { \
if (!(cond)) { \
@@ -112,6 +121,16 @@
#define AAC_VPD_ID_LENGTH 3
#define AAC_VPD_ID_DATA 4
+#define AAC_SCSI_RPTLUNS_HEAD_SIZE 0x08
+#define AAC_SCSI_RPTLUNS_ADDR_SIZE 0x08
+#define AAC_SCSI_RPTLUNS_ADDR_MASK 0xC0
+/* 00b - peripheral device addressing method */
+#define AAC_SCSI_RPTLUNS_ADDR_PERIPHERAL 0x00
+/* 01b - flat space addressing method */
+#define AAC_SCSI_RPTLUNS_ADDR_FLAT_SPACE 0x40
+/* 10b - logical unit addressing method */
+#define AAC_SCSI_RPTLUNS_ADDR_LOGICAL_UNIT 0x80
+
/* Return the size of FIB with data part type data_type */
#define AAC_FIB_SIZEOF(data_type) \
(sizeof (struct aac_fib_header) + sizeof (data_type))
@@ -190,13 +209,18 @@
#define AAC_THROTTLE_DRAIN -1
#define AAC_QUIESCE_TICK 1 /* 1 second */
-#define AAC_QUIESCE_TIMEOUT 60 /* 60 seconds */
+#define AAC_QUIESCE_TIMEOUT 180 /* 180 seconds */
#define AAC_DEFAULT_TICK 10 /* 10 seconds */
#define AAC_SYNC_TICK (30*60) /* 30 minutes */
/* Poll time for aac_do_poll_io() */
#define AAC_POLL_TIME 60 /* 60 seconds */
+/* IOP reset */
+#define AAC_IOP_RESET_SUCCEED 0 /* IOP reset succeed */
+#define AAC_IOP_RESET_FAILED -1 /* IOP reset failed */
+#define AAC_IOP_RESET_ABNORMAL -2 /* Reset operation abnormal */
+
/*
* Hardware access functions
*/
@@ -289,14 +313,14 @@ int aac_do_io(struct aac_softstate *, struct aac_cmd *);
static int aac_do_poll_io(struct aac_softstate *, struct aac_cmd *);
static int aac_do_sync_io(struct aac_softstate *, struct aac_cmd *);
static int aac_send_command(struct aac_softstate *, struct aac_slot *);
-static void aac_cmd_timeout(struct aac_softstate *);
+static void aac_cmd_timeout(struct aac_softstate *, struct aac_cmd *);
static int aac_dma_sync_ac(struct aac_cmd *);
static int aac_shutdown(struct aac_softstate *);
static int aac_reset_adapter(struct aac_softstate *);
static int aac_do_quiesce(struct aac_softstate *softs);
static int aac_do_unquiesce(struct aac_softstate *softs);
static void aac_unhold_bus(struct aac_softstate *, int);
-static void aac_set_throttle(struct aac_softstate *, struct aac_container *,
+static void aac_set_throttle(struct aac_softstate *, struct aac_device *,
int, int);
/*
@@ -327,6 +351,14 @@ int aac_check_acc_handle(ddi_acc_handle_t);
int aac_check_dma_handle(ddi_dma_handle_t);
void aac_fm_ereport(struct aac_softstate *, char *);
+/*
+ * Auto enumeration functions
+ */
+static dev_info_t *aac_find_child(struct aac_softstate *, uint16_t, uint8_t);
+static int aac_tran_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t,
+ void *, dev_info_t **);
+static int aac_dr_event(struct aac_softstate *, int, int, int);
+
#ifdef DEBUG
/*
* UART debug output support
@@ -363,6 +395,14 @@ uint32_t aac_debug_flags =
/* AACDB_FLAGS_FIB | */
/* AACDB_FLAGS_IOCTL | */
0;
+uint32_t aac_debug_fib_flags =
+/* AACDB_FLAGS_FIB_RW | */
+/* AACDB_FLAGS_FIB_IOCTL | */
+/* AACDB_FLAGS_FIB_SRB | */
+/* AACDB_FLAGS_FIB_SYNC | */
+/* AACDB_FLAGS_FIB_HEADER | */
+/* AACDB_FLAGS_FIB_TIMEOUT | */
+0;
#endif /* DEBUG */
@@ -569,8 +609,7 @@ static struct aac_interface aac_rkt_interface = {
ddi_device_acc_attr_t aac_acc_attr = {
DDI_DEVICE_ATTR_V0,
DDI_STRUCTURE_LE_ACC,
- DDI_STRICTORDER_ACC,
- DDI_FLAGERR_ACC
+ DDI_STRICTORDER_ACC
};
static struct {
@@ -602,7 +641,14 @@ static ddi_dma_attr_t aac_dma_attr = {
0xffffffffull, /* segment boundary */
1, /* s/g list length */
AAC_BLK_SIZE, /* granularity of device */
- DDI_DMA_FLAGERR /* DMA transfer flags */
+ 0 /* DMA transfer flags */
+};
+
+struct aac_drinfo {
+ struct aac_softstate *softs;
+ int tgt;
+ int lun;
+ int event;
};
static int aac_tick = AAC_DEFAULT_TICK; /* tick for the internal timer */
@@ -629,6 +675,8 @@ _NOTE(SCHEME_PROTECTS_DATA("unique per aac_fib", aac_blockread aac_blockwrite \
aac_sg_table aac_srb))
_NOTE(SCHEME_PROTECTS_DATA("unique to sync fib and cdb", scsi_inquiry))
_NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
+_NOTE(SCHEME_PROTECTS_DATA("unique to dr event", aac_drinfo))
+_NOTE(SCHEME_PROTECTS_DATA("unique to scsi_transport", buf))
int
_init(void)
@@ -703,6 +751,7 @@ aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
int instance, i;
struct aac_softstate *softs = NULL;
int attach_state = 0;
+ char *data;
int intr_types;
DBCALLED(NULL, 1);
@@ -730,11 +779,16 @@ aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
softs->devinfo_p = dip;
softs->buf_dma_attr = softs->addr_dma_attr = aac_dma_attr;
softs->addr_dma_attr.dma_attr_granular = 1;
+ softs->acc_attr = aac_acc_attr;
softs->card = AAC_UNKNOWN_CARD;
#ifdef DEBUG
softs->debug_flags = aac_debug_flags;
+ softs->debug_fib_flags = aac_debug_fib_flags;
#endif
+ /* Initialize FMA */
+ aac_fm_init(softs);
+
/* Check the card type */
if (aac_check_card_type(softs) == AACERR) {
AACDB_PRINT(softs, CE_WARN, "Card not supported");
@@ -743,20 +797,10 @@ aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
/* We have found the right card and everything is OK */
attach_state |= AAC_ATTACH_CARD_DETECTED;
- /*
- * Initialize FMA
- */
- softs->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, softs->devinfo_p,
- DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
- DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
- DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
-
- aac_fm_init(softs);
-
/* Map PCI mem space */
if (ddi_regs_map_setup(dip, 1,
(caddr_t *)&softs->pci_mem_base_vaddr, 0,
- softs->map_size_min, &aac_acc_attr,
+ softs->map_size_min, &softs->acc_attr,
&softs->pci_mem_handle) != DDI_SUCCESS)
goto error;
@@ -809,6 +853,17 @@ aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
DDI_INTR_PRI(softs->intr_pri));
attach_state |= AAC_ATTACH_KMUTEX_INITED;
+ /* Check for legacy device naming support */
+ softs->legacy = 1; /* default to use legacy name */
+ if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
+ "legacy-name-enable", &data) == DDI_SUCCESS)) {
+ if (strcmp(data, "no") == 0) {
+ AACDB_PRINT(softs, CE_NOTE, "legacy-name disabled");
+ softs->legacy = 0;
+ }
+ ddi_prop_free(data);
+ }
+
/*
* Everything has been set up till now,
* we will do some common attach.
@@ -866,6 +921,13 @@ aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
goto error;
}
+ /* Create a taskq for dealing with dr events */
+ if ((softs->taskq = ddi_taskq_create(dip, "aac_dr_taskq", 1,
+ TASKQ_DEFAULTPRI, 0)) == NULL) {
+ AACDB_PRINT(softs, CE_WARN, "ddi_taskq_create failed");
+ goto error;
+ }
+
aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
softs->state = AAC_STATE_RUN;
@@ -880,6 +942,8 @@ aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
return (DDI_SUCCESS);
error:
+ if (softs && softs->taskq)
+ ddi_taskq_destroy(softs->taskq);
if (attach_state & AAC_ATTACH_CREATE_SCSI)
ddi_remove_minor_node(dip, "scsi");
if (attach_state & AAC_ATTACH_CREATE_DEVCTL)
@@ -938,6 +1002,8 @@ aac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
mutex_enter(&softs->io_lock);
softs->timeout_id = 0;
+ ddi_taskq_destroy(softs->taskq);
+
ddi_remove_minor_node(dip, "aac");
ddi_remove_minor_node(dip, "scsi");
ddi_remove_minor_node(dip, "devctl");
@@ -1028,12 +1094,12 @@ static void
aac_set_arq_data(struct scsi_pkt *pkt, uchar_t key,
uchar_t add_code, uchar_t qual_code, uint64_t info)
{
- struct scsi_arq_status *arqstat;
+ struct scsi_arq_status *arqstat = (void *)(pkt->pkt_scbp);
- pkt->pkt_state |= STATE_GOT_STATUS | STATE_ARQ_DONE;
+ *pkt->pkt_scbp = STATUS_CHECK; /* CHECK CONDITION */
+ pkt->pkt_state |= STATE_ARQ_DONE;
- arqstat = (void *)(pkt->pkt_scbp);
- arqstat->sts_status.sts_chk = 1; /* CHECK CONDITION */
+ *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD;
arqstat->sts_rqpkt_reason = CMD_CMPLT;
arqstat->sts_rqpkt_resid = 0;
arqstat->sts_rqpkt_state =
@@ -1103,7 +1169,9 @@ aac_set_arq_data_hwerr(struct aac_cmd *acp)
static void
aac_set_arq_data_reset(struct aac_softstate *softs, struct aac_cmd *acp)
{
- struct aac_container *dvp = acp->dvp;
+ struct aac_container *dvp = (struct aac_container *)acp->dvp;
+
+ ASSERT(dvp->dev.type == AAC_DEV_LD);
if (dvp->reset) {
dvp->reset = 0;
@@ -1140,7 +1208,7 @@ aac_send_command(struct aac_softstate *softs, struct aac_slot *slotp)
static void
aac_end_io(struct aac_softstate *softs, struct aac_cmd *acp)
{
- struct aac_container *dvp = acp->dvp;
+ struct aac_device *dvp = acp->dvp;
int q = AAC_CMDQ(acp);
if (acp->slotp) { /* outstanding cmd */
@@ -1183,7 +1251,12 @@ aac_handle_io(struct aac_softstate *softs, int index)
slotp = &softs->io_slot[index];
ASSERT(slotp->index == index);
acp = slotp->acp;
- ASSERT(acp != NULL && acp->slotp == slotp);
+
+ if (acp == NULL || acp->slotp != slotp) {
+ cmn_err(CE_WARN,
+ "Firmware error: invalid slot index received from FW");
+ return;
+ }
acp->flags |= AAC_CMD_CMPLT;
(void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU);
@@ -1239,7 +1312,7 @@ aac_process_intr_new(struct aac_softstate *softs)
index = AAC_OUTB_GET(softs);
if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
- return (DDI_INTR_UNCLAIMED);
+ return (0);
}
if (index != 0xfffffffful) {
do {
@@ -1388,8 +1461,7 @@ aac_process_intr_old(struct aac_softstate *softs)
if (fib_xfer_state & AAC_FIBSTATE_FROMADAP) {
ddi_put32(acc, &fibp0->Header.XferState,
fib_xfer_state | AAC_FIBSTATE_DONEHOST);
- ddi_put32(acc, (void *)&fibp0->data[0],
- ST_OK);
+ ddi_put32(acc, (void *)&fibp0->data[0], ST_OK);
if (fib_size0 > AAC_FIB_SIZE)
ddi_put16(acc, &fibp0->Header.Size,
AAC_FIB_SIZE);
@@ -1646,8 +1718,6 @@ aac_set_pkt_reason(struct aac_softstate *softs, struct aac_cmd *acp,
#ifndef __lock_lint
_NOTE(ARGUNUSED(softs))
#endif
- AACDB_PRINT(softs, CE_NOTE, "acp=0x%p, reason=%x, stat=%x",
- (void *)acp, reason, stat);
if (acp->pkt->pkt_reason == CMD_CMPLT)
acp->pkt->pkt_reason = reason;
acp->pkt->pkt_statistics |= stat;
@@ -1664,7 +1734,7 @@ aac_soft_callback(struct aac_softstate *softs, struct aac_cmd *acp)
acp->flags |= AAC_CMD_CMPLT;
acp->pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | \
- STATE_SENT_CMD;
+ STATE_SENT_CMD | STATE_GOT_STATUS;
if (acp->pkt->pkt_state & STATE_XFERRED_DATA)
acp->pkt->pkt_resid = 0;
@@ -1695,6 +1765,8 @@ aac_ld_complete(struct aac_softstate *softs, struct aac_cmd *acp)
ASSERT(!(acp->flags & AAC_CMD_SYNC));
ASSERT(!(acp->flags & AAC_CMD_NO_CB));
+ acp->pkt->pkt_state |= STATE_GOT_STATUS;
+
/*
* block_read/write has a similar response header, use blockread
* response for both.
@@ -1710,6 +1782,182 @@ aac_ld_complete(struct aac_softstate *softs, struct aac_cmd *acp)
}
/*
+ * Handle completed phys. device IO command
+ */
+static void
+aac_pd_complete(struct aac_softstate *softs, struct aac_cmd *acp)
+{
+ ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
+ struct aac_fib *fibp = acp->slotp->fibp;
+ struct scsi_pkt *pkt = acp->pkt;
+ struct aac_srb_reply *resp;
+ uint32_t resp_status;
+
+ ASSERT(!(acp->flags & AAC_CMD_SYNC));
+ ASSERT(!(acp->flags & AAC_CMD_NO_CB));
+
+ resp = (struct aac_srb_reply *)&fibp->data[0];
+ resp_status = ddi_get32(acc, &resp->status);
+
+ /* First check FIB status */
+ if (resp_status == ST_OK) {
+ uint32_t scsi_status;
+ uint32_t srb_status;
+ uint32_t data_xfer_length;
+
+ scsi_status = ddi_get32(acc, &resp->scsi_status);
+ srb_status = ddi_get32(acc, &resp->srb_status);
+ data_xfer_length = ddi_get32(acc, &resp->data_xfer_length);
+
+ *pkt->pkt_scbp = (uint8_t)scsi_status;
+ pkt->pkt_state |= STATE_GOT_STATUS;
+ if (scsi_status == STATUS_GOOD) {
+ uchar_t cmd = ((union scsi_cdb *)(void *)
+ (pkt->pkt_cdbp))->scc_cmd;
+
+ /* Next check SRB status */
+ switch (srb_status & 0x3f) {
+ case SRB_STATUS_DATA_OVERRUN:
+ AACDB_PRINT(softs, CE_NOTE, "DATA_OVERRUN: " \
+ "scmd=%d, xfer=%d, buflen=%d",
+ (uint32_t)cmd, data_xfer_length,
+ acp->bcount);
+
+ switch (cmd) {
+ case SCMD_READ:
+ case SCMD_WRITE:
+ case SCMD_READ_G1:
+ case SCMD_WRITE_G1:
+ case SCMD_READ_G4:
+ case SCMD_WRITE_G4:
+ case SCMD_READ_G5:
+ case SCMD_WRITE_G5:
+ aac_set_pkt_reason(softs, acp,
+ CMD_DATA_OVR, 0);
+ break;
+ }
+ /*FALLTHRU*/
+ case SRB_STATUS_ERROR_RECOVERY:
+ case SRB_STATUS_PENDING:
+ case SRB_STATUS_SUCCESS:
+ /*
+ * pkt_resid should only be calculated if the
+ * status is ERROR_RECOVERY/PENDING/SUCCESS/
+ * OVERRUN/UNDERRUN
+ */
+ if (data_xfer_length) {
+ pkt->pkt_state |= STATE_XFERRED_DATA;
+ pkt->pkt_resid = acp->bcount - \
+ data_xfer_length;
+ ASSERT(pkt->pkt_resid >= 0);
+ }
+ break;
+ case SRB_STATUS_ABORTED:
+ AACDB_PRINT(softs, CE_NOTE,
+ "SRB_STATUS_ABORTED, xfer=%d, resid=%d",
+ data_xfer_length, pkt->pkt_resid);
+ aac_set_pkt_reason(softs, acp, CMD_ABORTED,
+ STAT_ABORTED);
+ break;
+ case SRB_STATUS_ABORT_FAILED:
+ AACDB_PRINT(softs, CE_NOTE,
+ "SRB_STATUS_ABORT_FAILED, xfer=%d, " \
+ "resid=%d", data_xfer_length,
+ pkt->pkt_resid);
+ aac_set_pkt_reason(softs, acp, CMD_ABORT_FAIL,
+ 0);
+ break;
+ case SRB_STATUS_PARITY_ERROR:
+ AACDB_PRINT(softs, CE_NOTE,
+ "SRB_STATUS_PARITY_ERROR, xfer=%d, " \
+ "resid=%d", data_xfer_length,
+ pkt->pkt_resid);
+ aac_set_pkt_reason(softs, acp, CMD_PER_FAIL, 0);
+ break;
+ case SRB_STATUS_NO_DEVICE:
+ case SRB_STATUS_INVALID_PATH_ID:
+ case SRB_STATUS_INVALID_TARGET_ID:
+ case SRB_STATUS_INVALID_LUN:
+ case SRB_STATUS_SELECTION_TIMEOUT:
+#ifdef DEBUG
+ if (AAC_DEV_IS_VALID(acp->dvp)) {
+ AACDB_PRINT(softs, CE_NOTE,
+ "SRB_STATUS_NO_DEVICE(%d), " \
+ "xfer=%d, resid=%d ",
+ srb_status & 0x3f,
+ data_xfer_length, pkt->pkt_resid);
+ }
+#endif
+ aac_set_pkt_reason(softs, acp, CMD_DEV_GONE, 0);
+ break;
+ case SRB_STATUS_COMMAND_TIMEOUT:
+ case SRB_STATUS_TIMEOUT:
+ AACDB_PRINT(softs, CE_NOTE,
+ "SRB_STATUS_COMMAND_TIMEOUT, xfer=%d, " \
+ "resid=%d", data_xfer_length,
+ pkt->pkt_resid);
+ aac_set_pkt_reason(softs, acp, CMD_TIMEOUT,
+ STAT_TIMEOUT);
+ break;
+ case SRB_STATUS_BUS_RESET:
+ AACDB_PRINT(softs, CE_NOTE,
+ "SRB_STATUS_BUS_RESET, xfer=%d, " \
+ "resid=%d", data_xfer_length,
+ pkt->pkt_resid);
+ aac_set_pkt_reason(softs, acp, CMD_RESET,
+ STAT_BUS_RESET);
+ break;
+ default:
+ AACDB_PRINT(softs, CE_NOTE, "srb_status=%d, " \
+ "xfer=%d, resid=%d", srb_status & 0x3f,
+ data_xfer_length, pkt->pkt_resid);
+ aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0);
+ break;
+ }
+ } else if (scsi_status == STATUS_CHECK) {
+ /* CHECK CONDITION */
+ struct scsi_arq_status *arqstat =
+ (void *)(pkt->pkt_scbp);
+ uint32_t sense_data_size;
+
+ pkt->pkt_state |= STATE_ARQ_DONE;
+
+ *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD;
+ arqstat->sts_rqpkt_reason = CMD_CMPLT;
+ arqstat->sts_rqpkt_resid = 0;
+ arqstat->sts_rqpkt_state =
+ STATE_GOT_BUS |
+ STATE_GOT_TARGET |
+ STATE_SENT_CMD |
+ STATE_XFERRED_DATA;
+ arqstat->sts_rqpkt_statistics = 0;
+
+ sense_data_size = ddi_get32(acc,
+ &resp->sense_data_size);
+ ASSERT(sense_data_size <= AAC_SENSE_BUFFERSIZE);
+ AACDB_PRINT(softs, CE_NOTE,
+ "CHECK CONDITION: sense len=%d, xfer len=%d",
+ sense_data_size, data_xfer_length);
+
+ if (sense_data_size > SENSE_LENGTH)
+ sense_data_size = SENSE_LENGTH;
+ ddi_rep_get8(acc, (uint8_t *)&arqstat->sts_sensedata,
+ (uint8_t *)resp->sense_data, sense_data_size,
+ DDI_DEV_AUTOINCR);
+ } else {
+ AACDB_PRINT(softs, CE_WARN, "invaild scsi status: " \
+ "scsi_status=%d, srb_status=%d",
+ scsi_status, srb_status);
+ aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0);
+ }
+ } else {
+ AACDB_PRINT(softs, CE_NOTE, "SRB failed: fib status %d",
+ resp_status);
+ aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0);
+ }
+}
+
+/*
* Handle completed IOCTL command
*/
/*ARGSUSED*/
@@ -1749,6 +1997,8 @@ aac_synccache_complete(struct aac_softstate *softs, struct aac_cmd *acp)
ASSERT(!(acp->flags & AAC_CMD_SYNC));
+ acp->pkt->pkt_state |= STATE_GOT_STATUS;
+
resp = (struct aac_synchronize_reply *)&slotp->fibp->data[0];
status = ddi_get32(acc, &resp->Status);
if (status != CT_OK)
@@ -1877,7 +2127,7 @@ aac_check_firmware(struct aac_softstate *softs)
uint32_t options;
uint32_t atu_size;
ddi_acc_handle_t pci_handle;
- uint8_t *pci_mbr;
+ uint8_t *data;
uint32_t max_fibs;
uint32_t max_fib_size;
uint32_t sg_tablesize;
@@ -1944,6 +2194,18 @@ aac_check_firmware(struct aac_softstate *softs)
AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array size");
}
+ if (options & AAC_SUPPORTED_NONDASD) {
+ if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, softs->devinfo_p, 0,
+ "nondasd-enable", (char **)&data) == DDI_SUCCESS)) {
+ if (strcmp((char *)data, "yes") == 0) {
+ AACDB_PRINT(softs, CE_NOTE,
+ "!Enable Non-DASD access");
+ softs->flags |= AAC_FLAGS_NONDASD;
+ }
+ ddi_prop_free(data);
+ }
+ }
+
/* Read preferred settings */
max_fib_size = 0;
if ((aac_sync_mbcommand(softs, AAC_MONKER_GETCOMMPREF,
@@ -1960,13 +2222,14 @@ aac_check_firmware(struct aac_softstate *softs)
/* Enable new comm. and rawio at the same time */
if ((softs->support_opt & AAC_SUPPORTED_NEW_COMM) &&
(max_fib_size != 0)) {
+ /* read out and save PCI MBR */
if ((atu_size > softs->map_size) &&
(ddi_regs_map_setup(softs->devinfo_p, 1,
- (caddr_t *)&pci_mbr, 0, atu_size, &aac_acc_attr,
+ (caddr_t *)&data, 0, atu_size, &softs->acc_attr,
&pci_handle) == DDI_SUCCESS)) {
ddi_regs_map_free(&softs->pci_mem_handle);
softs->pci_mem_handle = pci_handle;
- softs->pci_mem_base_vaddr = pci_mbr;
+ softs->pci_mem_base_vaddr = data;
softs->map_size = atu_size;
}
if (atu_size == softs->map_size) {
@@ -2026,7 +2289,7 @@ aac_check_firmware(struct aac_softstate *softs)
softs->buf_dma_attr.dma_attr_count_max =
softs->buf_dma_attr.dma_attr_maxxfer - 1;
- /* Setup FIB operations for logical devices */
+ /* Setup FIB operations */
if (softs->flags & AAC_FLAGS_RAW_IO)
softs->aac_cmd_fib = aac_cmd_fib_rawio;
else if (softs->flags & AAC_FLAGS_SG_64BIT)
@@ -2150,6 +2413,61 @@ aac_get_adapter_info(struct aac_softstate *softs,
return (AACOK);
}
+static int
+aac_get_bus_info(struct aac_softstate *softs, uint32_t *bus_max,
+ uint32_t *tgt_max)
+{
+ ddi_acc_handle_t acc = softs->sync_slot.fib_acc_handle;
+ struct aac_fib *fibp = softs->sync_slot.fibp;
+ struct aac_ctcfg *c_cmd;
+ struct aac_ctcfg_resp *c_resp;
+ uint32_t scsi_method_id;
+ struct aac_bus_info *cmd;
+ struct aac_bus_info_response *resp;
+ int rval;
+
+ /* Detect MethodId */
+ c_cmd = (struct aac_ctcfg *)&fibp->data[0];
+ ddi_put32(acc, &c_cmd->Command, VM_ContainerConfig);
+ ddi_put32(acc, &c_cmd->cmd, CT_GET_SCSI_METHOD);
+ ddi_put32(acc, &c_cmd->param, 0);
+ rval = aac_sync_fib(softs, ContainerCommand,
+ AAC_FIB_SIZEOF(struct aac_ctcfg));
+ c_resp = (struct aac_ctcfg_resp *)&fibp->data[0];
+ if (rval != AACOK || ddi_get32(acc, &c_resp->Status) != 0) {
+ AACDB_PRINT(softs, CE_WARN,
+ "VM_ContainerConfig command fail");
+ return (AACERR);
+ }
+ scsi_method_id = ddi_get32(acc, &c_resp->param);
+
+ /* Detect phys. bus count and max. target id first */
+ cmd = (struct aac_bus_info *)&fibp->data[0];
+ ddi_put32(acc, &cmd->Command, VM_Ioctl);
+ ddi_put32(acc, &cmd->ObjType, FT_DRIVE); /* physical drive */
+ ddi_put32(acc, &cmd->MethodId, scsi_method_id);
+ ddi_put32(acc, &cmd->ObjectId, 0);
+ ddi_put32(acc, &cmd->CtlCmd, GetBusInfo);
+ /*
+ * For VM_Ioctl, the firmware uses the Header.Size filled from the
+ * driver as the size to be returned. Therefore the driver has to use
+ * sizeof (struct aac_bus_info_response) because it is greater than
+ * sizeof (struct aac_bus_info).
+ */
+ rval = aac_sync_fib(softs, ContainerCommand,
+ AAC_FIB_SIZEOF(struct aac_bus_info_response));
+ resp = (struct aac_bus_info_response *)cmd;
+
+ /* Scan all coordinates with INQUIRY */
+ if ((rval != AACOK) || (ddi_get32(acc, &resp->Status) != 0)) {
+ AACDB_PRINT(softs, CE_WARN, "GetBusInfo command fail");
+ return (AACERR);
+ }
+ *bus_max = ddi_get32(acc, &resp->BusCount);
+ *tgt_max = ddi_get32(acc, &resp->TargetsPerBus);
+ return (AACOK);
+}
+
/*
* The following function comes from Adaptec:
*
@@ -2397,14 +2715,52 @@ aac_common_attach(struct aac_softstate *softs)
goto error;
}
- /* Setup containers */
- bzero(softs->containers, sizeof (struct aac_container) * AAC_MAX_LD);
- softs->container_count = 0;
+ /* Setup containers (logical devices) */
if (aac_probe_containers(softs) != AACOK) {
cmn_err(CE_CONT, "?Fatal error: get container info error");
goto error;
}
+ /* Setup phys. devices */
+ if (softs->flags & AAC_FLAGS_NONDASD) {
+ uint32_t bus_max, tgt_max;
+ uint32_t bus, tgt;
+ int index;
+
+ if (aac_get_bus_info(softs, &bus_max, &tgt_max) != AACOK) {
+ cmn_err(CE_CONT, "?Fatal error: get bus info error");
+ goto error;
+ }
+ AACDB_PRINT(softs, CE_NOTE, "bus_max=%d, tgt_max=%d",
+ bus_max, tgt_max);
+ if (bus_max != softs->bus_max || tgt_max != softs->tgt_max) {
+ if (softs->state & AAC_STATE_RESET) {
+ cmn_err(CE_WARN,
+ "?Fatal error: bus map changed");
+ goto error;
+ }
+ softs->bus_max = bus_max;
+ softs->tgt_max = tgt_max;
+ if (softs->nondasds) {
+ kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \
+ sizeof (struct aac_nondasd));
+ }
+ softs->nondasds = kmem_zalloc(AAC_MAX_PD(softs) * \
+ sizeof (struct aac_nondasd), KM_SLEEP);
+
+ index = 0;
+ for (bus = 0; bus < softs->bus_max; bus++) {
+ for (tgt = 0; tgt < softs->tgt_max; tgt++) {
+ struct aac_nondasd *dvp =
+ &softs->nondasds[index++];
+ dvp->dev.type = AAC_DEV_PD;
+ dvp->bus = bus;
+ dvp->tid = tgt;
+ }
+ }
+ }
+ }
+
/* Check dma & acc handles allocated in attach */
if (aac_check_dma_handle(softs->comm_space_dma_handle) != DDI_SUCCESS) {
ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
@@ -2426,10 +2782,14 @@ aac_common_attach(struct aac_softstate *softs)
}
return (AACOK);
-
error:
if (softs->state & AAC_STATE_RESET)
return (AACERR);
+ if (softs->nondasds) {
+ kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \
+ sizeof (struct aac_nondasd));
+ softs->nondasds = NULL;
+ }
if (softs->total_fibs > 0)
aac_destroy_fibs(softs);
if (softs->total_slots > 0)
@@ -2449,6 +2809,11 @@ aac_common_detach(struct aac_softstate *softs)
(void) aac_shutdown(softs);
+ if (softs->nondasds) {
+ kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \
+ sizeof (struct aac_nondasd));
+ softs->nondasds = NULL;
+ }
aac_destroy_fibs(softs);
aac_destroy_slots(softs);
aac_free_comm_space(softs);
@@ -2527,6 +2892,8 @@ aac_sync_fib(struct aac_softstate *softs, uint16_t cmd, uint16_t fibsize)
if (slotp->acp == NULL)
aac_cmd_fib_header(softs, slotp, cmd, fibsize);
+ AACDB_PRINT_FIB(softs, &softs->sync_slot);
+
(void) ddi_dma_sync(dma, offsetof(struct aac_comm_space, sync_fib),
fibsize, DDI_DMA_SYNC_FORDEV);
@@ -2839,20 +3206,15 @@ aac_probe_container(struct aac_softstate *softs, uint32_t cid)
return (AACERR);
if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE) {
- if (dvp->valid) {
+ if (AAC_DEV_IS_VALID(&dvp->dev)) {
AACDB_PRINT(softs, CE_NOTE,
">>> Container %d deleted", cid);
- dvp->valid = 0;
+ dvp->dev.flags &= ~AAC_DFLAG_VALID;
+ (void) aac_dr_event(softs, dvp->cid, -1,
+ AAC_EVT_OFFLINE);
}
} else {
size = AAC_MIR_SIZE(softs, acc, mir);
- AACDB_PRINT(softs, CE_NOTE, "Container #%d found: " \
- "size=0x%x.%08x, type=%d, name=%s",
- cid,
- ddi_get32(acc, &mir->MntObj.CapacityHigh),
- ddi_get32(acc, &mir->MntObj.Capacity),
- ddi_get32(acc, &mir->MntObj.VolType),
- mir->MntObj.FileSystemName);
/* Get container UID */
if (aac_get_container_uid(softs, cid, &uid) == AACERR) {
@@ -2862,7 +3224,7 @@ aac_probe_container(struct aac_softstate *softs, uint32_t cid)
}
AACDB_PRINT(softs, CE_CONT, "uid=0x%08x", uid);
- if (dvp->valid) {
+ if (AAC_DEV_IS_VALID(&dvp->dev)) {
if (dvp->uid != uid) {
AACDB_PRINT(softs, CE_WARN,
">>> Container %u uid changed to %d",
@@ -2877,14 +3239,23 @@ aac_probe_container(struct aac_softstate *softs, uint32_t cid)
}
} else { /* Init new container */
AACDB_PRINT(softs, CE_NOTE,
- ">>> Container %d added", cid);
- dvp->valid = 1;
+ ">>> Container %d added: " \
+ "size=0x%x.%08x, type=%d, name=%s",
+ cid,
+ ddi_get32(acc, &mir->MntObj.CapacityHigh),
+ ddi_get32(acc, &mir->MntObj.Capacity),
+ ddi_get32(acc, &mir->MntObj.VolType),
+ mir->MntObj.FileSystemName);
+ dvp->dev.flags |= AAC_DFLAG_VALID;
+ dvp->dev.type = AAC_DEV_LD;
dvp->cid = cid;
dvp->uid = uid;
dvp->size = size;
dvp->locked = 0;
dvp->deleted = 0;
+ (void) aac_dr_event(softs, dvp->cid, -1,
+ AAC_EVT_ONLINE);
}
}
return (AACOK);
@@ -2892,7 +3263,7 @@ aac_probe_container(struct aac_softstate *softs, uint32_t cid)
/*
* Do a rescan of all the possible containers and update the container list
- * with newly online/offline containers.
+ * with newly online/offline containers, and prepare for autoconfiguration.
*/
static int
aac_probe_containers(struct aac_softstate *softs)
@@ -2912,11 +3283,13 @@ aac_probe_containers(struct aac_softstate *softs)
for (dvp = &softs->containers[count];
dvp < &softs->containers[softs->container_count]; dvp++) {
- if (dvp->valid == 0)
+ if (!AAC_DEV_IS_VALID(&dvp->dev))
continue;
AACDB_PRINT(softs, CE_NOTE, ">>> Container %d deleted",
dvp->cid);
- dvp->valid = 0;
+ dvp->dev.flags &= ~AAC_DFLAG_VALID;
+ (void) aac_dr_event(softs, dvp->cid, -1,
+ AAC_EVT_OFFLINE);
}
}
softs->container_count = count;
@@ -2945,7 +3318,7 @@ aac_alloc_comm_space(struct aac_softstate *softs)
if (ddi_dma_mem_alloc(
softs->comm_space_dma_handle,
sizeof (struct aac_comm_space),
- &aac_acc_attr,
+ &softs->acc_attr,
DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
DDI_DMA_SLEEP,
NULL,
@@ -3179,8 +3552,11 @@ static uchar_t *
aac_lun_serialno(struct aac_softstate *softs, int tgt, uchar_t *buf)
{
int i, d;
- uint32_t uid = softs->containers[tgt].uid;
+ uint32_t uid;
+
+ ASSERT(tgt >= 0 && tgt < AAC_MAX_LD);
+ uid = softs->containers[tgt].uid;
for (i = 7; i >= 0; i--) {
d = uid & 0xf;
buf[i] = d > 9 ? 'A' + (d - 0xa) : '0' + d;
@@ -3457,6 +3833,24 @@ finish:
kmem_free(sense_data, sdata_size);
}
+static int
+aac_name_node(dev_info_t *dip, char *name, int len)
+{
+ int tgt, lun;
+
+ tgt = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
+ DDI_PROP_DONTPASS, "target", -1);
+ if (tgt == -1)
+ return (DDI_FAILURE);
+ lun = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
+ DDI_PROP_DONTPASS, "lun", -1);
+ if (lun == -1)
+ return (DDI_FAILURE);
+
+ (void) snprintf(name, len, "%x,%x", tgt, lun);
+ return (DDI_SUCCESS);
+}
+
/*ARGSUSED*/
static int
aac_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
@@ -3466,34 +3860,84 @@ aac_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
#if defined(DEBUG) || defined(__lock_lint)
int ctl = ddi_get_instance(softs->devinfo_p);
#endif
- int tgt = sd->sd_address.a_target;
- int lun = sd->sd_address.a_lun;
- struct aac_container *dvp;
+ uint16_t tgt = sd->sd_address.a_target;
+ uint8_t lun = sd->sd_address.a_lun;
+ struct aac_device *dvp;
DBCALLED(softs, 2);
- if ((0 > tgt) || (tgt >= AAC_MAX_LD)) {
- AACDB_PRINT(softs, CE_NOTE,
- "aac_tran_tgt_init: c%t%dL%d out", ctl, tgt, lun);
+ if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
+ /*
+ * If no persistent node exist, we don't allow .conf node
+ * to be created.
+ */
+ if (aac_find_child(softs, tgt, lun) != NULL) {
+ if (ndi_merge_node(tgt_dip, aac_name_node) !=
+ DDI_SUCCESS)
+ /* Create this .conf node */
+ return (DDI_SUCCESS);
+ }
return (DDI_FAILURE);
}
/*
- * Only support container that has been detected and valid
+ * Only support container/phys. device that has been
+ * detected and valid
*/
mutex_enter(&softs->io_lock);
- dvp = &softs->containers[tgt];
- if (dvp->valid && lun == 0) {
- AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%t%dL%d ok",
- ctl, tgt, lun);
- mutex_exit(&softs->io_lock);
- return (DDI_SUCCESS);
- } else {
- AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%t%dL%d",
- ctl, tgt, lun);
+ if (tgt >= AAC_MAX_DEV(softs)) {
+ AACDB_PRINT_TRAN(softs,
+ "aac_tran_tgt_init: c%dt%dL%d out", ctl, tgt, lun);
mutex_exit(&softs->io_lock);
return (DDI_FAILURE);
}
+
+ if (tgt < AAC_MAX_LD) {
+ dvp = (struct aac_device *)&softs->containers[tgt];
+ if (lun != 0 || !AAC_DEV_IS_VALID(dvp)) {
+ AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%dt%dL%d",
+ ctl, tgt, lun);
+ mutex_exit(&softs->io_lock);
+ return (DDI_FAILURE);
+ }
+ /*
+ * Save the tgt_dip for the given target if one doesn't exist
+ * already. Dip's for non-existance tgt's will be cleared in
+ * tgt_free.
+ */
+ if (softs->containers[tgt].dev.dip == NULL &&
+ strcmp(ddi_driver_name(sd->sd_dev), "sd") == 0)
+ softs->containers[tgt].dev.dip = tgt_dip;
+ } else {
+ dvp = (struct aac_device *)&softs->nondasds[AAC_PD(tgt)];
+ }
+
+ AACDB_PRINT(softs, CE_NOTE,
+ "aac_tran_tgt_init: c%dt%dL%d ok (%s)", ctl, tgt, lun,
+ (dvp->type == AAC_DEV_PD) ? "pd" : "ld");
+ mutex_exit(&softs->io_lock);
+ return (DDI_SUCCESS);
+}
+
+static void
+aac_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
+ scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
+{
+#ifndef __lock_lint
+ _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran))
+#endif
+
+ struct aac_softstate *softs = SD2AAC(sd);
+ int tgt = sd->sd_address.a_target;
+
+ mutex_enter(&softs->io_lock);
+ if (tgt < AAC_MAX_LD) {
+ if (softs->containers[tgt].dev.dip == tgt_dip)
+ softs->containers[tgt].dev.dip = NULL;
+ } else {
+ softs->nondasds[AAC_PD(tgt)].dev.flags &= ~AAC_DFLAG_VALID;
+ }
+ mutex_exit(&softs->io_lock);
}
/*
@@ -3535,20 +3979,27 @@ aac_abort_iocmd(struct aac_softstate *softs, struct aac_cmd *acp,
* Phys. drives are treated as logical ones
* during error recovery.
*/
- if (softs->flags & AAC_STATE_RESET)
+ if (acp->slotp) { /* outstanding cmd */
+ acp->pkt->pkt_state |= STATE_GOT_STATUS;
aac_set_arq_data_reset(softs, acp);
+ }
switch (reason) {
case CMD_TIMEOUT:
+ AACDB_PRINT(softs, CE_NOTE, "CMD_TIMEOUT: acp=0x%p",
+ acp);
aac_set_pkt_reason(softs, acp, CMD_TIMEOUT,
STAT_TIMEOUT | STAT_BUS_RESET);
break;
case CMD_RESET:
/* aac support only RESET_ALL */
+ AACDB_PRINT(softs, CE_NOTE, "CMD_RESET: acp=0x%p", acp);
aac_set_pkt_reason(softs, acp, CMD_RESET,
STAT_BUS_RESET);
break;
case CMD_ABORTED:
+ AACDB_PRINT(softs, CE_NOTE, "CMD_ABORTED: acp=0x%p",
+ acp);
aac_set_pkt_reason(softs, acp, CMD_ABORTED,
STAT_ABORTED);
break;
@@ -3585,7 +4036,7 @@ aac_abort_iocmds(struct aac_softstate *softs, int iocmd, struct scsi_pkt *pkt,
struct aac_cmd *acp;
for (i = 0; i < AAC_MAX_LD; i++) {
- if (softs->containers[i].valid)
+ if (AAC_DEV_IS_VALID(&softs->containers[i].dev))
softs->containers[i].reset = 1;
}
while ((acp = softs->q_busy.q_head) != NULL)
@@ -3616,6 +4067,7 @@ aac_check_drain(void *arg)
mutex_enter(&softs->io_lock);
if (softs->ndrains) {
+ softs->drain_timeid = 0;
/*
* If both ASYNC and SYNC bus throttle are held,
* wake up threads only when both are drained out.
@@ -3640,6 +4092,7 @@ static void
aac_start_drain(struct aac_softstate *softs)
{
if (softs->ndrains == 0) {
+ ASSERT(softs->drain_timeid == 0);
softs->drain_timeid = timeout(aac_check_drain, softs,
AAC_QUIESCE_TICK * drv_usectohz(1000000));
}
@@ -3680,7 +4133,7 @@ aac_reset_adapter(struct aac_softstate *softs)
{
int health;
uint32_t status;
- int rval = AACERR;
+ int rval = AAC_IOP_RESET_FAILED;
DBCALLED(softs, 1);
@@ -3747,8 +4200,14 @@ aac_reset_adapter(struct aac_softstate *softs)
(void) aac_sync_fib(softs, ContainerCommand,
AAC_FIB_SIZEOF(struct aac_pause_command));
- ddi_fm_service_impact(softs->devinfo_p,
- DDI_SERVICE_LOST);
+ if (aac_check_adapter_health(softs) != 0)
+ ddi_fm_service_impact(softs->devinfo_p,
+ DDI_SERVICE_LOST);
+ else
+ /*
+ * IOP reset not supported or IOP not reseted
+ */
+ rval = AAC_IOP_RESET_ABNORMAL;
goto finish;
}
}
@@ -3761,7 +4220,7 @@ aac_reset_adapter(struct aac_softstate *softs)
if (aac_common_attach(softs) != AACOK)
goto finish;
- rval = AACOK;
+ rval = AAC_IOP_RESET_SUCCEED;
finish:
AAC_ENABLE_INTR(softs);
@@ -3769,7 +4228,7 @@ finish:
}
static void
-aac_set_throttle(struct aac_softstate *softs, struct aac_container *dvp, int q,
+aac_set_throttle(struct aac_softstate *softs, struct aac_device *dvp, int q,
int throttle)
{
/*
@@ -3791,8 +4250,11 @@ aac_hold_bus(struct aac_softstate *softs, int iocmds)
if (iocmds & (1 << q)) {
softs->bus_throttle[q] = 0;
for (i = 0; i < AAC_MAX_LD; i++)
- aac_set_throttle(softs, &softs->containers[i],
- q, 0);
+ aac_set_throttle(softs,
+ &softs->containers[i].dev, q, 0);
+ for (i = 0; i < AAC_MAX_PD(softs); i++)
+ aac_set_throttle(softs,
+ &softs->nondasds[i].dev, q, 0);
}
}
}
@@ -3814,7 +4276,11 @@ aac_unhold_bus(struct aac_softstate *softs, int iocmds)
continue;
softs->bus_throttle[q] = softs->total_slots;
for (i = 0; i < AAC_MAX_LD; i++)
- aac_set_throttle(softs, &softs->containers[i],
+ aac_set_throttle(softs,
+ &softs->containers[i].dev,
+ q, softs->total_slots);
+ for (i = 0; i < AAC_MAX_PD(softs); i++)
+ aac_set_throttle(softs, &softs->nondasds[i].dev,
q, softs->total_slots);
}
}
@@ -3833,8 +4299,14 @@ aac_do_reset(struct aac_softstate *softs)
* Hold off new io commands and wait all outstanding io
* commands to complete.
*/
- if (health == 0 && (softs->bus_ncmds[AAC_CMDQ_SYNC] ||
- softs->bus_ncmds[AAC_CMDQ_ASYNC])) {
+ if (health == 0) {
+ int sync_cmds = softs->bus_ncmds[AAC_CMDQ_SYNC];
+ int async_cmds = softs->bus_ncmds[AAC_CMDQ_ASYNC];
+
+ if (sync_cmds == 0 && async_cmds == 0) {
+ rval = AAC_IOP_RESET_SUCCEED;
+ goto finish;
+ }
/*
* Give the adapter up to AAC_QUIESCE_TIMEOUT more seconds
* to complete the outstanding io commands
@@ -3856,20 +4328,28 @@ aac_do_reset(struct aac_softstate *softs)
timeout--;
}
aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
+
+ if (softs->bus_ncmds[AAC_CMDQ_SYNC] == 0 &&
+ softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) {
+ /* Cmds drained out */
+ rval = AAC_IOP_RESET_SUCCEED;
+ goto finish;
+ } else if (softs->bus_ncmds[AAC_CMDQ_SYNC] < sync_cmds ||
+ softs->bus_ncmds[AAC_CMDQ_ASYNC] < async_cmds) {
+ /* Cmds not drained out, adapter overloaded */
+ rval = AAC_IOP_RESET_ABNORMAL;
+ goto finish;
+ }
}
/*
- * If a longer waiting time still can't drain all outstanding io
+ * If a longer waiting time still can't drain any outstanding io
* commands, do IOP reset.
*/
- if (softs->bus_ncmds[AAC_CMDQ_SYNC] ||
- softs->bus_ncmds[AAC_CMDQ_ASYNC]) {
- if ((rval = aac_reset_adapter(softs)) != AACOK)
- softs->state |= AAC_STATE_DEAD;
- } else {
- rval = AACOK;
- }
+ if ((rval = aac_reset_adapter(softs)) == AAC_IOP_RESET_FAILED)
+ softs->state |= AAC_STATE_DEAD;
+finish:
softs->state &= ~AAC_STATE_RESET;
return (rval);
}
@@ -3888,19 +4368,23 @@ aac_tran_reset(struct scsi_address *ap, int level)
}
mutex_enter(&softs->io_lock);
- rval = (aac_do_reset(softs) == AACOK) ? 1 : 0;
- if (rval == 1 && !ddi_in_panic()) {
+ switch (rval = aac_do_reset(softs)) {
+ case AAC_IOP_RESET_SUCCEED:
aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING | AAC_IOCMD_ASYNC,
NULL, CMD_RESET);
aac_start_waiting_io(softs);
- } else {
- /* Abort IOCTL cmds when system panic or adapter dead */
+ break;
+ case AAC_IOP_RESET_FAILED:
+ /* Abort IOCTL cmds when adapter is dead */
aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_RESET);
+ break;
+ case AAC_IOP_RESET_ABNORMAL:
+ aac_start_waiting_io(softs);
}
mutex_exit(&softs->io_lock);
aac_drain_comp_q(softs);
- return (rval);
+ return (rval == 0);
}
static int
@@ -3966,7 +4450,7 @@ aac_tran_start_ld(struct aac_softstate *softs, struct aac_cmd *acp)
struct buf *bp;
int rval;
- dvp = acp->dvp;
+ dvp = (struct aac_container *)acp->dvp;
pkt = acp->pkt;
cdbp = (void *)pkt->pkt_cdbp;
bp = acp->bp;
@@ -4047,6 +4531,11 @@ aac_tran_start_ld(struct aac_softstate *softs, struct aac_cmd *acp)
acp->blkno = GETG0ADDR(cdbp);
goto do_io;
+ case SCMD_READ_G5: /* read_12 */
+ case SCMD_WRITE_G5: /* write_12 */
+ acp->blkno = GETG5ADDR(cdbp);
+ goto do_io;
+
case SCMD_READ_G1: /* read_10 */
case SCMD_WRITE_G1: /* write_10 */
acp->blkno = (uint32_t)GETG1ADDR(cdbp);
@@ -4145,7 +4634,7 @@ aac_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt)
{
struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
struct aac_cmd *acp = PKT2AC(pkt);
- struct aac_container *dvp = acp->dvp;
+ struct aac_device *dvp = acp->dvp;
int rval;
DBCALLED(softs, 2);
@@ -4159,10 +4648,13 @@ aac_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt)
acp->timeout = acp->pkt->pkt_time;
if (pkt->pkt_flags & FLAG_NOINTR)
acp->flags |= AAC_CMD_NO_INTR;
+#ifdef DEBUG
+ acp->fib_flags = AACDB_FLAGS_FIB_SCMD;
+#endif
pkt->pkt_reason = CMD_CMPLT;
pkt->pkt_state = 0;
pkt->pkt_statistics = 0;
- *pkt->pkt_scbp = 0; /* clear arq scsi_status */
+ *pkt->pkt_scbp = STATUS_GOOD; /* clear arq scsi_status */
if (acp->flags & AAC_CMD_DMA_VALID) {
pkt->pkt_resid = acp->bcount;
@@ -4180,14 +4672,31 @@ aac_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt)
mutex_enter(&softs->io_lock);
AACDB_PRINT_SCMD(softs, acp);
- if (dvp->valid && ap->a_lun == 0 && !(softs->state & AAC_STATE_DEAD)) {
- rval = aac_tran_start_ld(softs, acp);
+ if ((dvp->flags & (AAC_DFLAG_VALID | AAC_DFLAG_CONFIGURING)) &&
+ !(softs->state & AAC_STATE_DEAD)) {
+ if (dvp->type == AAC_DEV_LD) {
+ if (ap->a_lun == 0)
+ rval = aac_tran_start_ld(softs, acp);
+ else
+ goto error;
+ } else {
+ rval = aac_do_io(softs, acp);
+ }
} else {
- AACDB_PRINT(softs, CE_WARN,
- "Cannot send cmd to target t%dL%d: %s",
- ap->a_target, ap->a_lun,
- (softs->state & AAC_STATE_DEAD) ?
- "adapter dead" : "target invalid");
+error:
+#ifdef DEBUG
+ if (!(softs->state & AAC_STATE_DEAD)) {
+ AACDB_PRINT_TRAN(softs,
+ "Cannot send cmd to target t%dL%d: %s",
+ ap->a_target, ap->a_lun,
+ "target invalid");
+ } else {
+ AACDB_PRINT(softs, CE_WARN,
+ "Cannot send cmd to target t%dL%d: %s",
+ ap->a_target, ap->a_lun,
+ "adapter dead");
+ }
+#endif
rval = TRAN_FATAL_ERROR;
}
mutex_exit(&softs->io_lock);
@@ -4198,7 +4707,7 @@ static int
aac_tran_getcap(struct scsi_address *ap, char *cap, int whom)
{
struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
- struct aac_container *dvp;
+ struct aac_device *dvp;
int rval;
DBCALLED(softs, 2);
@@ -4211,10 +4720,10 @@ aac_tran_getcap(struct scsi_address *ap, char *cap, int whom)
}
mutex_enter(&softs->io_lock);
- dvp = &softs->containers[ap->a_target];
- if (!dvp->valid || (ap->a_lun != 0)) {
+ dvp = AAC_DEV(softs, ap->a_target);
+ if (dvp == NULL || !AAC_DEV_IS_VALID(dvp)) {
mutex_exit(&softs->io_lock);
- AACDB_PRINT(softs, CE_WARN, "Bad target t%dL%d to getcap",
+ AACDB_PRINT_TRAN(softs, "Bad target t%dL%d to getcap",
ap->a_target, ap->a_lun);
return (-1);
}
@@ -4246,7 +4755,7 @@ static int
aac_tran_setcap(struct scsi_address *ap, char *cap, int value, int whom)
{
struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
- struct aac_container *dvp;
+ struct aac_device *dvp;
int rval;
DBCALLED(softs, 2);
@@ -4259,10 +4768,10 @@ aac_tran_setcap(struct scsi_address *ap, char *cap, int value, int whom)
}
mutex_enter(&softs->io_lock);
- dvp = &softs->containers[ap->a_target];
- if (!dvp->valid || (ap->a_lun != 0)) {
+ dvp = AAC_DEV(softs, ap->a_target);
+ if (dvp == NULL || !AAC_DEV_IS_VALID(dvp)) {
mutex_exit(&softs->io_lock);
- AACDB_PRINT(softs, CE_WARN, "Bad target t%dL%d to setcap",
+ AACDB_PRINT_TRAN(softs, "Bad target t%dL%d to setcap",
ap->a_target, ap->a_lun);
return (-1);
}
@@ -4326,10 +4835,10 @@ aac_cmd_dma_alloc(struct aac_softstate *softs, struct aac_cmd *acp,
goto get_dma_cookies;
AACDB_PRINT(softs, CE_WARN,
"ddi_dma_getwin() fail %d", rval);
- return (NULL);
+ return (AACERR);
}
AACDB_PRINT(softs, CE_WARN, "Nothing to transfer");
- return (NULL);
+ return (AACERR);
}
/* We need to transfer data, so we alloc DMA resources for this pkt */
@@ -4385,7 +4894,7 @@ aac_cmd_dma_alloc(struct aac_softstate *softs, struct aac_cmd *acp,
rval = ddi_dma_mem_alloc(acp->buf_dma_handle,
AAC_ROUNDUP(bp->b_bcount, AAC_DMA_ALIGN),
- &aac_acc_attr, DDI_DMA_STREAMING,
+ &softs->acc_attr, DDI_DMA_STREAMING,
cb, arg, &acp->abp, &bufsz, &acp->abh);
if (rval != DDI_SUCCESS) {
@@ -4505,14 +5014,22 @@ get_dma_cookies:
if (acp->pkt) {
/* Return remaining byte count */
- acp->pkt->pkt_resid = bp->b_bcount - acp->total_xfer;
-
+ if (acp->total_xfer <= bp->b_bcount) {
+ acp->pkt->pkt_resid = bp->b_bcount - \
+ acp->total_xfer;
+ } else {
+ /*
+ * Allocated DMA size is greater than the buf
+ * size of bp. This is caused by devices like
+ * tape. we have extra bytes allocated, but
+ * the packet residual has to stay correct.
+ */
+ acp->pkt->pkt_resid = 0;
+ }
AACDB_PRINT_TRAN(softs,
"bp=0x%p, xfered=%d/%d, resid=%d",
(void *)bp->b_un.b_addr, (int)acp->total_xfer,
(int)bp->b_bcount, (int)acp->pkt->pkt_resid);
-
- ASSERT(acp->pkt->pkt_resid >= 0);
}
}
return (AACOK);
@@ -4548,9 +5065,17 @@ aac_tran_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
acp->pkt = pkt;
acp->cmdlen = cmdlen;
- acp->dvp = &softs->containers[ap->a_target];
- acp->aac_cmd_fib = softs->aac_cmd_fib;
- acp->ac_comp = aac_ld_complete;
+ if (ap->a_target < AAC_MAX_LD) {
+ acp->dvp = &softs->containers[ap->a_target].dev;
+ acp->aac_cmd_fib = softs->aac_cmd_fib;
+ acp->ac_comp = aac_ld_complete;
+ } else {
+ _NOTE(ASSUMING_PROTECTED(softs->nondasds))
+
+ acp->dvp = &softs->nondasds[AAC_PD(ap->a_target)].dev;
+ acp->aac_cmd_fib = softs->aac_cmd_fib_scsi;
+ acp->ac_comp = aac_pd_complete;
+ }
} else {
acp = PKT2AC(pkt);
new_acp = NULL;
@@ -4673,6 +5198,7 @@ aac_hba_setup(struct aac_softstate *softs)
return (AACERR);
hba_tran->tran_hba_private = softs;
hba_tran->tran_tgt_init = aac_tran_tgt_init;
+ hba_tran->tran_tgt_free = aac_tran_tgt_free;
hba_tran->tran_tgt_probe = scsi_hba_probe;
hba_tran->tran_start = aac_tran_start;
hba_tran->tran_getcap = aac_tran_getcap;
@@ -4685,6 +5211,7 @@ aac_hba_setup(struct aac_softstate *softs)
hba_tran->tran_dmafree = aac_tran_dmafree;
hba_tran->tran_quiesce = aac_tran_quiesce;
hba_tran->tran_unquiesce = aac_tran_unquiesce;
+ hba_tran->tran_bus_config = aac_tran_bus_config;
rval = scsi_hba_attach_setup(softs->devinfo_p, &softs->buf_dma_attr,
hba_tran, 0);
if (rval != DDI_SUCCESS) {
@@ -4693,6 +5220,7 @@ aac_hba_setup(struct aac_softstate *softs)
return (AACERR);
}
+ softs->hba_tran = hba_tran;
return (AACOK);
}
@@ -4913,18 +5441,32 @@ aac_cmd_fib_srb(struct aac_cmd *acp)
struct aac_slot *slotp = acp->slotp;
ddi_acc_handle_t acc = slotp->fib_acc_handle;
struct aac_srb *srb = (struct aac_srb *)&slotp->fibp->data[0];
- struct aac_srb *srb0 = (struct aac_srb *)&acp->fibp->data[0];
+ uint8_t *cdb;
ddi_put32(acc, &srb->function, SRBF_ExecuteScsi);
ddi_put32(acc, &srb->retry_limit, 0);
ddi_put32(acc, &srb->cdb_size, acp->cmdlen);
ddi_put32(acc, &srb->timeout, 0); /* use driver timeout */
+ if (acp->fibp == NULL) {
+ if (acp->flags & AAC_CMD_BUF_READ)
+ ddi_put32(acc, &srb->flags, SRB_DataIn);
+ else if (acp->flags & AAC_CMD_BUF_WRITE)
+ ddi_put32(acc, &srb->flags, SRB_DataOut);
+ ddi_put32(acc, &srb->channel,
+ ((struct aac_nondasd *)acp->dvp)->bus);
+ ddi_put32(acc, &srb->id, ((struct aac_nondasd *)acp->dvp)->tid);
+ ddi_put32(acc, &srb->lun, 0);
+ cdb = acp->pkt->pkt_cdbp;
+ } else {
+ struct aac_srb *srb0 = (struct aac_srb *)&acp->fibp->data[0];
- ddi_put32(acc, &srb->flags, srb0->flags);
- ddi_put32(acc, &srb->channel, srb0->channel);
- ddi_put32(acc, &srb->id, srb0->id);
- ddi_put32(acc, &srb->lun, srb0->lun);
- ddi_rep_put8(acc, srb0->cdb, srb->cdb, acp->cmdlen, DDI_DEV_AUTOINCR);
+ ddi_put32(acc, &srb->flags, srb0->flags);
+ ddi_put32(acc, &srb->channel, srb0->channel);
+ ddi_put32(acc, &srb->id, srb0->id);
+ ddi_put32(acc, &srb->lun, srb0->lun);
+ cdb = srb0->cdb;
+ }
+ ddi_rep_put8(acc, cdb, srb->cdb, acp->cmdlen, DDI_DEV_AUTOINCR);
}
static void
@@ -5003,7 +5545,7 @@ aac_cmd_slot_bind(struct aac_softstate *softs, struct aac_cmd *acp)
static int
aac_bind_io(struct aac_softstate *softs, struct aac_cmd *acp)
{
- struct aac_container *dvp = acp->dvp;
+ struct aac_device *dvp = acp->dvp;
int q = AAC_CMDQ(acp);
if (dvp) {
@@ -5044,6 +5586,8 @@ aac_start_io(struct aac_softstate *softs, struct aac_cmd *acp)
softs->bus_ncmds[q]++;
aac_cmd_enqueue(&softs->q_busy, acp);
+ AACDB_PRINT_FIB(softs, slotp);
+
if (softs->flags & AAC_FLAGS_NEW_COMM) {
rval = aac_send_command(softs, slotp);
} else {
@@ -5180,7 +5724,7 @@ aac_alloc_fib(struct aac_softstate *softs, struct aac_slot *slotp)
if (ddi_dma_mem_alloc(
slotp->fib_dma_handle,
softs->aac_max_fib_size,
- &aac_acc_attr,
+ &softs->acc_attr,
DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
DDI_DMA_SLEEP,
NULL,
@@ -5371,7 +5915,7 @@ aac_do_poll_io(struct aac_softstate *softs, struct aac_cmd *acp)
AAC_BUSYWAIT((intr_handler(softs) != AAC_DB_RESPONSE_READY), i);
if (i == 0)
- aac_cmd_timeout(softs);
+ aac_cmd_timeout(softs, acp);
}
ddi_trigger_softintr(softs->softint_id);
@@ -5463,7 +6007,7 @@ aac_handle_aif(struct aac_softstate *softs, struct aac_fib *fibp)
switch (en_type) {
case AifDenMorphComplete:
case AifDenVolumeExtendComplete:
- if (softs->containers[cid].valid)
+ if (AAC_DEV_IS_VALID(&softs->containers[cid].dev))
softs->devcfg_wait_on = AifEnConfigChange;
break;
}
@@ -5511,8 +6055,10 @@ aac_handle_aif(struct aac_softstate *softs, struct aac_fib *fibp)
break;
}
- if (devcfg_needed)
+ if (devcfg_needed) {
+ softs->devcfg_wait_on = 0;
(void) aac_probe_containers(softs);
+ }
/* Modify AIF contexts */
current = softs->aifq_idx;
@@ -5541,9 +6087,16 @@ aac_handle_aif(struct aac_softstate *softs, struct aac_fib *fibp)
/*
* Timeout recovery
*/
+/*ARGSUSED*/
static void
-aac_cmd_timeout(struct aac_softstate *softs)
+aac_cmd_timeout(struct aac_softstate *softs, struct aac_cmd *acp)
{
+#ifdef DEBUG
+ acp->fib_flags |= AACDB_FLAGS_FIB_TIMEOUT;
+ AACDB_PRINT(softs, CE_WARN, "acp %p timed out", acp);
+ AACDB_PRINT_FIB(softs, acp->slotp);
+#endif
+
/*
* Besides the firmware in unhealthy state, an overloaded
* adapter may also incur pkt timeout.
@@ -5553,14 +6106,17 @@ aac_cmd_timeout(struct aac_softstate *softs)
* while being required longer completion times should be
* tolerated.
*/
- if (aac_do_reset(softs) == AACOK) {
- aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING, NULL,
- CMD_RESET);
+ switch (aac_do_reset(softs)) {
+ case AAC_IOP_RESET_SUCCEED:
+ aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING, NULL, CMD_RESET);
aac_start_waiting_io(softs);
- } else {
+ break;
+ case AAC_IOP_RESET_FAILED:
/* Abort all waiting cmds when adapter is dead */
- aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL,
- CMD_TIMEOUT);
+ aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_TIMEOUT);
+ break;
+ case AAC_IOP_RESET_ABNORMAL:
+ aac_start_waiting_io(softs);
}
}
@@ -5594,7 +6150,7 @@ aac_daemon(void *arg)
for (acp = softs->q_busy.q_head; acp; acp = acp->next) {
if (acp->timeout) {
if (acp->timeout <= aac_timebase) {
- aac_cmd_timeout(softs);
+ aac_cmd_timeout(softs, acp);
ddi_trigger_softintr(softs->softint_id);
}
break;
@@ -5776,12 +6332,17 @@ aac_fm_init(struct aac_softstate *softs)
*/
ddi_iblock_cookie_t fm_ibc;
+ softs->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, softs->devinfo_p,
+ DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
+ DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
+ DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
+
/* Only register with IO Fault Services if we have some capability */
if (softs->fm_capabilities) {
/* Adjust access and dma attributes for FMA */
- aac_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
- softs->buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
- softs->addr_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
+ softs->acc_attr.devacc_attr_access |= DDI_FLAGERR_ACC;
+ softs->addr_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
+ softs->buf_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
/*
* Register capabilities with IO Fault Services.
@@ -5806,11 +6367,6 @@ aac_fm_init(struct aac_softstate *softs)
ddi_fm_handler_register(softs->devinfo_p,
aac_fm_error_cb, (void *) softs);
}
- } else {
- /* Clear FMA if no capabilities */
- aac_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
- softs->buf_dma_attr.dma_attr_flags = 0;
- softs->addr_dma_attr.dma_attr_flags = 0;
}
}
@@ -5840,6 +6396,11 @@ aac_fm_fini(struct aac_softstate *softs)
/* Unregister from IO Fault Services */
ddi_fm_fini(softs->devinfo_p);
+
+ /* Adjust access and dma attributes for FMA */
+ softs->acc_attr.devacc_attr_access &= ~DDI_FLAGERR_ACC;
+ softs->addr_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
+ softs->buf_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
}
}
@@ -5875,6 +6436,489 @@ aac_fm_ereport(struct aac_softstate *softs, char *detail)
}
}
+/*
+ * Autoconfiguration support
+ */
+static int
+aac_parse_devname(char *devnm, int *tgt, int *lun)
+{
+ char devbuf[SCSI_MAXNAMELEN];
+ char *addr;
+ char *p, *tp, *lp;
+ long num;
+
+ /* Parse dev name and address */
+ (void) strcpy(devbuf, devnm);
+ addr = "";
+ for (p = devbuf; *p != '\0'; p++) {
+ if (*p == '@') {
+ addr = p + 1;
+ *p = '\0';
+ } else if (*p == ':') {
+ *p = '\0';
+ break;
+ }
+ }
+
+ /* Parse taget and lun */
+ for (p = tp = addr, lp = NULL; *p != '\0'; p++) {
+ if (*p == ',') {
+ lp = p + 1;
+ *p = '\0';
+ break;
+ }
+ }
+ if (tgt && tp) {
+ if (ddi_strtol(tp, NULL, 0x10, &num))
+ return (AACERR);
+ *tgt = (int)num;
+ }
+ if (lun && lp) {
+ if (ddi_strtol(lp, NULL, 0x10, &num))
+ return (AACERR);
+ *lun = (int)num;
+ }
+ return (AACOK);
+}
+
+static dev_info_t *
+aac_find_child(struct aac_softstate *softs, uint16_t tgt, uint8_t lun)
+{
+ dev_info_t *child = NULL;
+ char addr[SCSI_MAXNAMELEN];
+ char tmp[MAXNAMELEN];
+
+ if (tgt < AAC_MAX_LD) {
+ if (lun == 0) {
+ struct aac_device *dvp = &softs->containers[tgt].dev;
+
+ child = dvp->dip;
+ }
+ } else {
+ (void) sprintf(addr, "%x,%x", tgt, lun);
+ for (child = ddi_get_child(softs->devinfo_p);
+ child; child = ddi_get_next_sibling(child)) {
+ /* We don't care about non-persistent node */
+ if (ndi_dev_is_persistent_node(child) == 0)
+ continue;
+
+ if (aac_name_node(child, tmp, MAXNAMELEN) !=
+ DDI_SUCCESS)
+ continue;
+ if (strcmp(addr, tmp) == 0)
+ break;
+ }
+ }
+ return (child);
+}
+
+static int
+aac_config_child(struct aac_softstate *softs, struct scsi_device *sd,
+ dev_info_t **dipp)
+{
+ char *nodename = NULL;
+ char **compatible = NULL;
+ int ncompatible = 0;
+ char *childname;
+ dev_info_t *ldip = NULL;
+ int tgt = sd->sd_address.a_target;
+ int lun = sd->sd_address.a_lun;
+ int dtype = sd->sd_inq->inq_dtype & DTYPE_MASK;
+ int rval;
+
+ DBCALLED(softs, 2);
+
+ scsi_hba_nodename_compatible_get(sd->sd_inq, NULL, dtype,
+ NULL, &nodename, &compatible, &ncompatible);
+ if (nodename == NULL) {
+ AACDB_PRINT(softs, CE_WARN,
+ "found no comptible driver for t%dL%d", tgt, lun);
+ rval = NDI_FAILURE;
+ goto finish;
+ }
+ childname = (softs->legacy && dtype == DTYPE_DIRECT) ? "sd" : nodename;
+
+ /* Create dev node */
+ rval = ndi_devi_alloc(softs->devinfo_p, childname, DEVI_SID_NODEID,
+ &ldip);
+ if (rval == NDI_SUCCESS) {
+ if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "target", tgt)
+ != DDI_PROP_SUCCESS) {
+ AACDB_PRINT(softs, CE_WARN, "unable to create "
+ "property for t%dL%d (target)", tgt, lun);
+ rval = NDI_FAILURE;
+ goto finish;
+ }
+ if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "lun", lun)
+ != DDI_PROP_SUCCESS) {
+ AACDB_PRINT(softs, CE_WARN, "unable to create "
+ "property for t%dL%d (lun)", tgt, lun);
+ rval = NDI_FAILURE;
+ goto finish;
+ }
+ if (ndi_prop_update_string_array(DDI_DEV_T_NONE, ldip,
+ "compatible", compatible, ncompatible)
+ != DDI_PROP_SUCCESS) {
+ AACDB_PRINT(softs, CE_WARN, "unable to create "
+ "property for t%dL%d (compatible)", tgt, lun);
+ rval = NDI_FAILURE;
+ goto finish;
+ }
+
+ rval = ndi_devi_online(ldip, NDI_ONLINE_ATTACH);
+ if (rval != NDI_SUCCESS) {
+ AACDB_PRINT(softs, CE_WARN, "unable to online t%dL%d",
+ tgt, lun);
+ ndi_prop_remove_all(ldip);
+ (void) ndi_devi_free(ldip);
+ }
+ }
+finish:
+ if (dipp)
+ *dipp = ldip;
+
+ scsi_hba_nodename_compatible_free(nodename, compatible);
+ return (rval);
+}
+
+/*ARGSUSED*/
+static int
+aac_probe_lun(struct aac_softstate *softs, struct scsi_device *sd)
+{
+ int tgt = sd->sd_address.a_target;
+ int lun = sd->sd_address.a_lun;
+
+ DBCALLED(softs, 2);
+
+ if (tgt < AAC_MAX_LD) {
+ int rval;
+
+ if (lun == 0) {
+ mutex_enter(&softs->io_lock);
+ rval = aac_probe_container(softs, tgt);
+ mutex_exit(&softs->io_lock);
+ if (rval == AACOK) {
+ if (scsi_hba_probe(sd, NULL) ==
+ SCSIPROBE_EXISTS)
+ return (NDI_SUCCESS);
+ }
+ }
+ return (NDI_FAILURE);
+ } else {
+ int dtype;
+
+ if (scsi_hba_probe(sd, NULL) != SCSIPROBE_EXISTS)
+ return (NDI_FAILURE);
+
+ dtype = sd->sd_inq->inq_dtype & DTYPE_MASK;
+
+ AACDB_PRINT(softs, CE_NOTE,
+ "Phys. device found: tgt %d dtype %d: %s",
+ tgt, dtype, sd->sd_inq->inq_vid);
+
+ /* Only non-DASD exposed */
+ if (dtype != DTYPE_RODIRECT /* CDROM */ &&
+ dtype != DTYPE_SEQUENTIAL /* TAPE */ &&
+ dtype != DTYPE_ESI /* SES */)
+ return (NDI_FAILURE);
+
+ AACDB_PRINT(softs, CE_NOTE, "non-DASD %d found", tgt);
+ mutex_enter(&softs->io_lock);
+ softs->nondasds[AAC_PD(tgt)].dev.flags |= AAC_DFLAG_VALID;
+ mutex_exit(&softs->io_lock);
+ return (NDI_SUCCESS);
+ }
+}
+
+static int
+aac_config_lun(struct aac_softstate *softs, uint16_t tgt, uint8_t lun,
+ dev_info_t **ldip)
+{
+ struct scsi_device sd;
+ dev_info_t *child;
+ int rval;
+
+ DBCALLED(softs, 2);
+
+ if ((child = aac_find_child(softs, tgt, lun)) != NULL) {
+ if (ldip)
+ *ldip = child;
+ return (NDI_SUCCESS);
+ }
+
+ bzero(&sd, sizeof (struct scsi_device));
+ sd.sd_address.a_hba_tran = softs->hba_tran;
+ sd.sd_address.a_target = (uint16_t)tgt;
+ sd.sd_address.a_lun = (uint8_t)lun;
+ if ((rval = aac_probe_lun(softs, &sd)) == NDI_SUCCESS)
+ rval = aac_config_child(softs, &sd, ldip);
+ scsi_unprobe(&sd);
+ return (rval);
+}
+
+static int
+aac_config_tgt(struct aac_softstate *softs, int tgt)
+{
+ struct scsi_address ap;
+ struct buf *bp = NULL;
+ int buf_len = AAC_SCSI_RPTLUNS_HEAD_SIZE + AAC_SCSI_RPTLUNS_ADDR_SIZE;
+ int list_len = 0;
+ int lun_total = 0;
+ dev_info_t *ldip;
+ int i;
+
+ ap.a_hba_tran = softs->hba_tran;
+ ap.a_target = (uint16_t)tgt;
+ ap.a_lun = 0;
+
+ for (i = 0; i < 2; i++) {
+ struct scsi_pkt *pkt;
+ uchar_t *cdb;
+ uchar_t *p;
+ uint32_t data;
+
+ if (bp == NULL) {
+ if ((bp = scsi_alloc_consistent_buf(&ap, NULL,
+ buf_len, B_READ, NULL_FUNC, NULL)) == NULL)
+ return (AACERR);
+ }
+ if ((pkt = scsi_init_pkt(&ap, NULL, bp, CDB_GROUP5,
+ sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT,
+ NULL, NULL)) == NULL) {
+ scsi_free_consistent_buf(bp);
+ return (AACERR);
+ }
+ cdb = pkt->pkt_cdbp;
+ bzero(cdb, CDB_GROUP5);
+ cdb[0] = SCMD_REPORT_LUNS;
+
+ /* Convert buffer len from local to LE_32 */
+ data = buf_len;
+ for (p = &cdb[9]; p > &cdb[5]; p--) {
+ *p = data & 0xff;
+ data >>= 8;
+ }
+
+ if (scsi_poll(pkt) < 0 ||
+ ((struct scsi_status *)pkt->pkt_scbp)->sts_chk) {
+ scsi_destroy_pkt(pkt);
+ break;
+ }
+
+ /* Convert list_len from LE_32 to local */
+ for (p = (uchar_t *)bp->b_un.b_addr;
+ p < (uchar_t *)bp->b_un.b_addr + 4; p++) {
+ data <<= 8;
+ data |= *p;
+ }
+ list_len = data;
+ if (buf_len < list_len + AAC_SCSI_RPTLUNS_HEAD_SIZE) {
+ scsi_free_consistent_buf(bp);
+ bp = NULL;
+ buf_len = list_len + AAC_SCSI_RPTLUNS_HEAD_SIZE;
+ }
+ scsi_destroy_pkt(pkt);
+ }
+ if (i >= 2) {
+ uint8_t *buf = (uint8_t *)(bp->b_un.b_addr +
+ AAC_SCSI_RPTLUNS_HEAD_SIZE);
+
+ for (i = 0; i < (list_len / AAC_SCSI_RPTLUNS_ADDR_SIZE); i++) {
+ uint16_t lun;
+
+ /* Determine report luns addressing type */
+ switch (buf[0] & AAC_SCSI_RPTLUNS_ADDR_MASK) {
+ /*
+ * Vendors in the field have been found to be
+ * concatenating bus/target/lun to equal the
+ * complete lun value instead of switching to
+ * flat space addressing
+ */
+ case AAC_SCSI_RPTLUNS_ADDR_PERIPHERAL:
+ case AAC_SCSI_RPTLUNS_ADDR_LOGICAL_UNIT:
+ case AAC_SCSI_RPTLUNS_ADDR_FLAT_SPACE:
+ lun = ((buf[0] & 0x3f) << 8) | buf[1];
+ if (lun > UINT8_MAX) {
+ AACDB_PRINT(softs, CE_WARN,
+ "abnormal lun number: %d", lun);
+ break;
+ }
+ if (aac_config_lun(softs, tgt, lun, &ldip) ==
+ NDI_SUCCESS)
+ lun_total++;
+ break;
+ }
+
+ buf += AAC_SCSI_RPTLUNS_ADDR_SIZE;
+ }
+ } else {
+ /* The target may do not support SCMD_REPORT_LUNS. */
+ if (aac_config_lun(softs, tgt, 0, &ldip) == NDI_SUCCESS)
+ lun_total++;
+ }
+ scsi_free_consistent_buf(bp);
+ return (lun_total);
+}
+
+static void
+aac_devcfg(struct aac_softstate *softs, int tgt, int en)
+{
+ struct aac_device *dvp;
+
+ mutex_enter(&softs->io_lock);
+ dvp = AAC_DEV(softs, tgt);
+ if (en)
+ dvp->flags |= AAC_DFLAG_CONFIGURING;
+ else
+ dvp->flags &= ~AAC_DFLAG_CONFIGURING;
+ mutex_exit(&softs->io_lock);
+}
+
+static int
+aac_tran_bus_config(dev_info_t *parent, uint_t flags, ddi_bus_config_op_t op,
+ void *arg, dev_info_t **childp)
+{
+ struct aac_softstate *softs;
+ int circ = 0;
+ int rval;
+
+ if ((softs = ddi_get_soft_state(aac_softstatep,
+ ddi_get_instance(parent))) == NULL)
+ return (NDI_FAILURE);
+
+ /* Commands for bus config should be blocked as the bus is quiesced */
+ mutex_enter(&softs->io_lock);
+ if (softs->state & AAC_STATE_QUIESCED) {
+ AACDB_PRINT(softs, CE_NOTE,
+ "bus_config abroted because bus is quiesced");
+ mutex_exit(&softs->io_lock);
+ return (NDI_FAILURE);
+ }
+ mutex_exit(&softs->io_lock);
+
+ DBCALLED(softs, 1);
+
+ /* Hold the nexus across the bus_config */
+ ndi_devi_enter(parent, &circ);
+ switch (op) {
+ case BUS_CONFIG_ONE: {
+ int tgt, lun;
+
+ if (aac_parse_devname(arg, &tgt, &lun) != AACOK) {
+ rval = NDI_FAILURE;
+ break;
+ }
+
+ AAC_DEVCFG_BEGIN(softs, tgt);
+ rval = aac_config_lun(softs, tgt, lun, childp);
+ AAC_DEVCFG_END(softs, tgt);
+ break;
+ }
+
+ case BUS_CONFIG_DRIVER:
+ case BUS_CONFIG_ALL: {
+ uint32_t bus, tgt;
+ int index, total;
+
+ for (tgt = 0; tgt < AAC_MAX_LD; tgt++) {
+ AAC_DEVCFG_BEGIN(softs, tgt);
+ (void) aac_config_lun(softs, tgt, 0, NULL);
+ AAC_DEVCFG_END(softs, tgt);
+ }
+
+ /* Config the non-DASD devices connected to the card */
+ total = 0;
+ index = AAC_MAX_LD;
+ for (bus = 0; bus < softs->bus_max; bus++) {
+ AACDB_PRINT(softs, CE_NOTE, "bus %d:", bus);
+ for (tgt = 0; tgt < softs->tgt_max; tgt++, index++) {
+ AAC_DEVCFG_BEGIN(softs, index);
+ if (aac_config_tgt(softs, index))
+ total++;
+ AAC_DEVCFG_END(softs, index);
+ }
+ }
+ AACDB_PRINT(softs, CE_CONT,
+ "?Total %d phys. device(s) found", total);
+ rval = NDI_SUCCESS;
+ break;
+ }
+ }
+
+ if (rval == NDI_SUCCESS)
+ rval = ndi_busop_bus_config(parent, flags, op, arg, childp, 0);
+ ndi_devi_exit(parent, circ);
+ return (rval);
+}
+
+static void
+aac_handle_dr(struct aac_drinfo *drp)
+{
+ struct aac_softstate *softs = drp->softs;
+ struct aac_device *dvp;
+ dev_info_t *dip;
+ int valid;
+ int circ1 = 0;
+
+ DBCALLED(softs, 1);
+
+ /* Hold the nexus across the bus_config */
+ mutex_enter(&softs->io_lock);
+ dvp = AAC_DEV(softs, drp->tgt);
+ valid = AAC_DEV_IS_VALID(dvp);
+ dip = dvp->dip;
+ mutex_exit(&softs->io_lock);
+
+ switch (drp->event) {
+ case AAC_EVT_ONLINE:
+ case AAC_EVT_OFFLINE:
+ /* Device onlined */
+ if (dip == NULL && valid) {
+ ndi_devi_enter(softs->devinfo_p, &circ1);
+ (void) aac_config_lun(softs, drp->tgt, 0, NULL);
+ AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d onlined",
+ softs->instance, drp->tgt, drp->lun);
+ ndi_devi_exit(softs->devinfo_p, circ1);
+ }
+ /* Device offlined */
+ if (dip && !valid) {
+ mutex_enter(&softs->io_lock);
+ (void) aac_do_reset(softs);
+ mutex_exit(&softs->io_lock);
+
+ (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
+ AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d offlined",
+ softs->instance, drp->tgt, drp->lun);
+ }
+ break;
+ }
+ kmem_free(drp, sizeof (struct aac_drinfo));
+}
+
+static int
+aac_dr_event(struct aac_softstate *softs, int tgt, int lun, int event)
+{
+ struct aac_drinfo *drp;
+
+ DBCALLED(softs, 1);
+
+ if (softs->taskq == NULL ||
+ (drp = kmem_zalloc(sizeof (struct aac_drinfo), KM_NOSLEEP)) == NULL)
+ return (AACERR);
+
+ drp->softs = softs;
+ drp->tgt = tgt;
+ drp->lun = lun;
+ drp->event = event;
+ if ((ddi_taskq_dispatch(softs->taskq, (void (*)(void *))aac_handle_dr,
+ drp, DDI_NOSLEEP)) != DDI_SUCCESS) {
+ AACDB_PRINT(softs, CE_WARN, "DR task start failed");
+ kmem_free(drp, sizeof (struct aac_drinfo));
+ return (AACERR);
+ }
+ return (AACOK);
+}
+
#ifdef DEBUG
/* -------------------------debug aid functions-------------------------- */
@@ -6503,6 +7547,7 @@ aac_print_scmd(struct aac_softstate *softs, struct aac_cmd *acp)
{
struct scsi_pkt *pkt = acp->pkt;
struct scsi_address *ap = &pkt->pkt_address;
+ int is_pd = 0;
int ctl = ddi_get_instance(softs->devinfo_p);
int tgt = ap->a_target;
int lun = ap->a_lun;
@@ -6510,11 +7555,18 @@ aac_print_scmd(struct aac_softstate *softs, struct aac_cmd *acp)
uchar_t cmd = cdbp->scc_cmd;
char *desc;
+ if (tgt >= AAC_MAX_LD) {
+ is_pd = 1;
+ ctl = ((struct aac_nondasd *)acp->dvp)->bus;
+ tgt = ((struct aac_nondasd *)acp->dvp)->tid;
+ lun = 0;
+ }
+
if ((desc = aac_cmd_name(cmd,
(struct aac_key_strings *)scsi_cmds)) == NULL) {
aac_printf(softs, CE_NOTE,
- "SCMD> Unknown(0x%2x) --> c%dt%dL%d",
- cmd, ctl, tgt, lun);
+ "SCMD> Unknown(0x%2x) --> c%dt%dL%d %s",
+ cmd, ctl, tgt, lun, is_pd ? "(pd)" : "");
return;
}
@@ -6522,85 +7574,228 @@ aac_print_scmd(struct aac_softstate *softs, struct aac_cmd *acp)
case SCMD_READ:
case SCMD_WRITE:
aac_printf(softs, CE_NOTE,
- "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d",
+ "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s",
desc, GETG0ADDR(cdbp), GETG0COUNT(cdbp),
(acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
- ctl, tgt, lun);
+ ctl, tgt, lun, is_pd ? "(pd)" : "");
break;
case SCMD_READ_G1:
case SCMD_WRITE_G1:
aac_printf(softs, CE_NOTE,
- "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d",
+ "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s",
desc, GETG1ADDR(cdbp), GETG1COUNT(cdbp),
(acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
- ctl, tgt, lun);
+ ctl, tgt, lun, is_pd ? "(pd)" : "");
break;
case SCMD_READ_G4:
case SCMD_WRITE_G4:
aac_printf(softs, CE_NOTE,
- "SCMD> %s 0x%x.%08x[%d] %s --> c%dt%dL%d",
+ "SCMD> %s 0x%x.%08x[%d] %s --> c%dt%dL%d %s",
desc, GETG4ADDR(cdbp), GETG4ADDRTL(cdbp),
GETG4COUNT(cdbp),
(acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
- ctl, tgt, lun);
+ ctl, tgt, lun, is_pd ? "(pd)" : "");
+ break;
+ case SCMD_READ_G5:
+ case SCMD_WRITE_G5:
+ aac_printf(softs, CE_NOTE,
+ "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s",
+ desc, GETG5ADDR(cdbp), GETG5COUNT(cdbp),
+ (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
+ ctl, tgt, lun, is_pd ? "(pd)" : "");
break;
default:
- aac_printf(softs, CE_NOTE, "SCMD> %s --> c%dt%dL%d",
- desc, ctl, tgt, lun);
+ aac_printf(softs, CE_NOTE, "SCMD> %s --> c%dt%dL%d %s",
+ desc, ctl, tgt, lun, is_pd ? "(pd)" : "");
}
}
void
-aac_print_fib(struct aac_softstate *softs, struct aac_fib *fibp)
+aac_print_fib(struct aac_softstate *softs, struct aac_slot *slotp)
{
+ struct aac_cmd *acp = slotp->acp;
+ struct aac_fib *fibp = slotp->fibp;
+ ddi_acc_handle_t acc = slotp->fib_acc_handle;
uint16_t fib_size;
- int32_t fib_cmd, sub_cmd;
+ uint32_t fib_cmd, sub_cmd;
char *cmdstr, *subcmdstr;
- struct aac_Container *pContainer;
+ char *caller;
+ int i;
+
+ if (acp) {
+ if (!(softs->debug_fib_flags & acp->fib_flags))
+ return;
+ if (acp->fib_flags & AACDB_FLAGS_FIB_SCMD)
+ caller = "SCMD";
+ else if (acp->fib_flags & AACDB_FLAGS_FIB_IOCTL)
+ caller = "IOCTL";
+ else if (acp->fib_flags & AACDB_FLAGS_FIB_SRB)
+ caller = "SRB";
+ else
+ return;
+ } else {
+ if (!(softs->debug_fib_flags & AACDB_FLAGS_FIB_SYNC))
+ return;
+ caller = "SYNC";
+ }
- fib_cmd = LE_16(fibp->Header.Command);
+ fib_cmd = ddi_get16(acc, &fibp->Header.Command);
cmdstr = aac_cmd_name(fib_cmd, aac_fib_cmds);
- sub_cmd = -1;
+ sub_cmd = (uint32_t)-1;
subcmdstr = NULL;
+ /* Print FIB header */
+ if (softs->debug_fib_flags & AACDB_FLAGS_FIB_HEADER) {
+ aac_printf(softs, CE_NOTE, "FIB> from %s", caller);
+ aac_printf(softs, CE_NOTE, " XferState %d",
+ ddi_get32(acc, &fibp->Header.XferState));
+ aac_printf(softs, CE_NOTE, " Command %d",
+ ddi_get16(acc, &fibp->Header.Command));
+ aac_printf(softs, CE_NOTE, " StructType %d",
+ ddi_get8(acc, &fibp->Header.StructType));
+ aac_printf(softs, CE_NOTE, " Flags 0x%x",
+ ddi_get8(acc, &fibp->Header.Flags));
+ aac_printf(softs, CE_NOTE, " Size %d",
+ ddi_get16(acc, &fibp->Header.Size));
+ aac_printf(softs, CE_NOTE, " SenderSize %d",
+ ddi_get16(acc, &fibp->Header.SenderSize));
+ aac_printf(softs, CE_NOTE, " SenderAddr 0x%x",
+ ddi_get32(acc, &fibp->Header.SenderFibAddress));
+ aac_printf(softs, CE_NOTE, " RcvrAddr 0x%x",
+ ddi_get32(acc, &fibp->Header.ReceiverFibAddress));
+ aac_printf(softs, CE_NOTE, " SenderData 0x%x",
+ ddi_get32(acc, &fibp->Header.SenderData));
+ }
+
+ /* Print FIB data */
switch (fib_cmd) {
case ContainerCommand:
- pContainer = (struct aac_Container *)fibp->data;
- sub_cmd = LE_32(pContainer->Command);
+ sub_cmd = ddi_get32(acc,
+ (void *)&(((uint32_t *)(void *)&fibp->data[0])[0]));
subcmdstr = aac_cmd_name(sub_cmd, aac_ctvm_subcmds);
if (subcmdstr == NULL)
break;
- fib_cmd = sub_cmd;
- cmdstr = subcmdstr;
- sub_cmd = -1;
- subcmdstr = NULL;
- switch (pContainer->Command) {
- case VM_ContainerConfig:
- sub_cmd = LE_32(pContainer->CTCommand.command);
+ switch (sub_cmd) {
+ case VM_ContainerConfig: {
+ struct aac_Container *pContainer =
+ (struct aac_Container *)fibp->data;
+
+ fib_cmd = sub_cmd;
+ cmdstr = subcmdstr;
+ sub_cmd = (uint32_t)-1;
+ subcmdstr = NULL;
+
+ sub_cmd = ddi_get32(acc,
+ &pContainer->CTCommand.command);
subcmdstr = aac_cmd_name(sub_cmd, aac_ct_subcmds);
if (subcmdstr == NULL)
break;
aac_printf(softs, CE_NOTE, "FIB> %s (0x%x, 0x%x, 0x%x)",
subcmdstr,
- LE_32(pContainer->CTCommand.param[0]),
- LE_32(pContainer->CTCommand.param[1]),
- LE_32(pContainer->CTCommand.param[2]));
+ ddi_get32(acc, &pContainer->CTCommand.param[0]),
+ ddi_get32(acc, &pContainer->CTCommand.param[1]),
+ ddi_get32(acc, &pContainer->CTCommand.param[2]));
return;
+ }
+
case VM_Ioctl:
- sub_cmd = LE_32(((int32_t *)(void *)pContainer)[4]);
+ fib_cmd = sub_cmd;
+ cmdstr = subcmdstr;
+ sub_cmd = (uint32_t)-1;
+ subcmdstr = NULL;
+
+ sub_cmd = ddi_get32(acc,
+ (void *)&(((uint32_t *)(void *)&fibp->data[0])[4]));
subcmdstr = aac_cmd_name(sub_cmd, aac_ioctl_subcmds);
break;
+
+ case VM_CtBlockRead:
+ case VM_CtBlockWrite: {
+ struct aac_blockread *br =
+ (struct aac_blockread *)fibp->data;
+ struct aac_sg_table *sg = &br->SgMap;
+ uint32_t sgcount = ddi_get32(acc, &sg->SgCount);
+
+ aac_printf(softs, CE_NOTE,
+ "FIB> %s Container %d 0x%x/%d", subcmdstr,
+ ddi_get32(acc, &br->ContainerId),
+ ddi_get32(acc, &br->BlockNumber),
+ ddi_get32(acc, &br->ByteCount));
+ for (i = 0; i < sgcount; i++)
+ aac_printf(softs, CE_NOTE,
+ " %d: 0x%08x/%d", i,
+ ddi_get32(acc, &sg->SgEntry[i].SgAddress),
+ ddi_get32(acc, &sg->SgEntry[i]. \
+ SgByteCount));
+ return;
+ }
}
break;
+ case ContainerCommand64: {
+ struct aac_blockread64 *br =
+ (struct aac_blockread64 *)fibp->data;
+ struct aac_sg_table64 *sg = &br->SgMap64;
+ uint32_t sgcount = ddi_get32(acc, &sg->SgCount);
+ uint64_t sgaddr;
+
+ sub_cmd = br->Command;
+ subcmdstr = NULL;
+ if (sub_cmd == VM_CtHostRead64)
+ subcmdstr = "VM_CtHostRead64";
+ else if (sub_cmd == VM_CtHostWrite64)
+ subcmdstr = "VM_CtHostWrite64";
+ else
+ break;
+
+ aac_printf(softs, CE_NOTE,
+ "FIB> %s Container %d 0x%x/%d", subcmdstr,
+ ddi_get16(acc, &br->ContainerId),
+ ddi_get32(acc, &br->BlockNumber),
+ ddi_get16(acc, &br->SectorCount));
+ for (i = 0; i < sgcount; i++) {
+ sgaddr = ddi_get64(acc,
+ &sg->SgEntry64[i].SgAddress);
+ aac_printf(softs, CE_NOTE,
+ " %d: 0x%08x.%08x/%d", i,
+ AAC_MS32(sgaddr), AAC_LS32(sgaddr),
+ ddi_get32(acc, &sg->SgEntry64[i]. \
+ SgByteCount));
+ }
+ return;
+ }
+
+ case RawIo: {
+ struct aac_raw_io *io = (struct aac_raw_io *)fibp->data;
+ struct aac_sg_tableraw *sg = &io->SgMapRaw;
+ uint32_t sgcount = ddi_get32(acc, &sg->SgCount);
+ uint64_t sgaddr;
+
+ aac_printf(softs, CE_NOTE,
+ "FIB> RawIo Container %d 0x%llx/%d 0x%x",
+ ddi_get16(acc, &io->ContainerId),
+ ddi_get64(acc, &io->BlockNumber),
+ ddi_get32(acc, &io->ByteCount),
+ ddi_get16(acc, &io->Flags));
+ for (i = 0; i < sgcount; i++) {
+ sgaddr = ddi_get64(acc, &sg->SgEntryRaw[i].SgAddress);
+ aac_printf(softs, CE_NOTE, " %d: 0x%08x.%08x/%d", i,
+ AAC_MS32(sgaddr), AAC_LS32(sgaddr),
+ ddi_get32(acc, &sg->SgEntryRaw[i].SgByteCount));
+ }
+ return;
+ }
+
case ClusterCommand:
- sub_cmd = LE_32(((int32_t *)(void *)fibp->data)[0]);
+ sub_cmd = ddi_get32(acc,
+ (void *)&(((uint32_t *)(void *)fibp->data)[0]));
subcmdstr = aac_cmd_name(sub_cmd, aac_cl_subcmds);
break;
case AifRequest:
- sub_cmd = LE_32(((int32_t *)(void *)fibp->data)[0]);
+ sub_cmd = ddi_get32(acc,
+ (void *)&(((uint32_t *)(void *)fibp->data)[0]));
subcmdstr = aac_cmd_name(sub_cmd, aac_aif_subcmds);
break;
@@ -6608,11 +7803,11 @@ aac_print_fib(struct aac_softstate *softs, struct aac_fib *fibp)
break;
}
- fib_size = LE_16(fibp->Header.Size);
+ fib_size = ddi_get16(acc, &(fibp->Header.Size));
if (subcmdstr)
aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d",
subcmdstr, fib_size);
- else if (cmdstr && sub_cmd == -1)
+ else if (cmdstr && sub_cmd == (uint32_t)-1)
aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d",
cmdstr, fib_size);
else if (cmdstr)
diff --git a/usr/src/uts/common/io/aac/aac.conf b/usr/src/uts/common/io/aac/aac.conf
index 4cd7a4be6e..dfc88968d1 100644
--- a/usr/src/uts/common/io/aac/aac.conf
+++ b/usr/src/uts/common/io/aac/aac.conf
@@ -1,8 +1,27 @@
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
#
-# ident "%Z%%M% %I% %E% SMI"
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
#
#
@@ -10,3 +29,13 @@
#
# global definitions
+#
+# non-DASD device support property
+#
+nondasd-enable="no";
+
+#
+# legacy target name support property
+# Do NOT edit this property, or system may not boot.
+#
+legacy-name-enable="no";
diff --git a/usr/src/uts/common/io/aac/aac.h b/usr/src/uts/common/io/aac/aac.h
index 75aa5d2c22..d5a9f2494a 100644
--- a/usr/src/uts/common/io/aac/aac.h
+++ b/usr/src/uts/common/io/aac/aac.h
@@ -38,8 +38,6 @@
#ifndef _AAC_H_
#define _AAC_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -57,7 +55,7 @@ extern "C" {
#define AAC_DRIVER_MAJOR_VERSION 2
#define AAC_DRIVER_MINOR_VERSION 2
-#define AAC_DRIVER_BUGFIX_LEVEL 4
+#define AAC_DRIVER_BUGFIX_LEVEL 5
#define AAC_DRIVER_TYPE AAC_TYPE_RELEASE
#define STR(s) # s
@@ -96,7 +94,7 @@ extern "C" {
#define AAC_IMMEDIATE_TIMEOUT 60 /* seconds */
#endif
#define AAC_FWUP_TIMEOUT 180 /* wait up to 3 minutes */
-#define AAC_IOCTL_TIMEOUT 180 /* wait up to 3 minutes */
+#define AAC_IOCTL_TIMEOUT 900 /* wait up to 15 minutes */
/* Adapter hardware interface types */
#define AAC_HWIF_UNKNOWN 0
@@ -151,17 +149,48 @@ struct aac_card_type {
char *desc; /* ASCII data for INQUIRY command product id */
};
+/* Device types */
+#define AAC_DEV_LD 0 /* logical device */
+#define AAC_DEV_PD 1 /* physical device */
+
+/* DR events */
+#define AAC_EVT_NONE 0
+#define AAC_EVT_ONLINE 1
+#define AAC_EVT_OFFLINE 2
+
+/* Device flags */
+#define AAC_DFLAG_VALID (1 << 0)
+#define AAC_DFLAG_CONFIGURING (1 << 1)
+
+#define AAC_DEV_IS_VALID(dvp) ((dvp)->flags & AAC_DFLAG_VALID)
+
+struct aac_device {
+ int flags;
+
+ uint8_t type;
+ dev_info_t *dip;
+ int ncmds[AAC_CMDQ_NUM]; /* outstanding cmds of the device */
+ int throttle[AAC_CMDQ_NUM]; /* hold IO cmds for the device */
+};
+
/* Array description */
struct aac_container {
- uint8_t valid;
+ struct aac_device dev;
+
uint32_t cid; /* container id */
uint32_t uid; /* container uid */
uint64_t size; /* in block */
uint8_t locked;
uint8_t deleted;
- uint8_t reset; /* container is being reseted */
- int ncmds[AAC_CMDQ_NUM]; /* outstanding cmds of the device */
- int throttle[AAC_CMDQ_NUM]; /* hold IO cmds for the device */
+ uint8_t reset; /* container is being reseted */
+};
+
+/* Non-DASD phys. device descrption, eg. CDROM or tape */
+struct aac_nondasd {
+ struct aac_device dev;
+
+ uint32_t bus;
+ uint32_t tid;
};
/*
@@ -214,6 +243,7 @@ struct aac_slot {
#define AAC_FLAGS_LBA_64BIT (1 << 7) /* 64-bit LBA supported */
#define AAC_FLAGS_17SG (1 << 8) /* quirk: 17 scatter gather maximum */
#define AAC_FLAGS_34SG (1 << 9) /* quirk: 34 scatter gather maximum */
+#define AAC_FLAGS_NONDASD (1 << 10) /* non-DASD device supported */
struct aac_softstate;
struct aac_interface {
@@ -252,13 +282,16 @@ struct aac_softstate {
int flags; /* firmware features enabled */
int instance;
dev_info_t *devinfo_p;
+ scsi_hba_tran_t *hba_tran;
int slen;
+ int legacy; /* legacy device naming */
/* DMA attributes */
ddi_dma_attr_t buf_dma_attr;
ddi_dma_attr_t addr_dma_attr;
/* PCI spaces */
+ ddi_device_acc_attr_t acc_attr;
ddi_acc_handle_t pci_mem_handle;
uint8_t *pci_mem_base_vaddr;
uint32_t pci_mem_base_paddr;
@@ -293,6 +326,9 @@ struct aac_softstate {
struct aac_container containers[AAC_MAX_LD];
int container_count; /* max container id + 1 */
+ struct aac_nondasd *nondasds;
+ uint32_t bus_max; /* max FW buses exposed */
+ uint32_t tgt_max; /* max FW target per bus */
/*
* Command queues
@@ -330,6 +366,7 @@ struct aac_softstate {
int devcfg_wait_on; /* AIF event waited for rescan */
int fm_capabilities;
+ ddi_taskq_t *taskq;
/* MSI specific fields */
ddi_intr_handle_t *htable; /* For array of interrupts */
@@ -341,6 +378,7 @@ struct aac_softstate {
#ifdef DEBUG
/* UART trace printf variables */
uint32_t debug_flags; /* debug print flags bitmap */
+ uint32_t debug_fib_flags; /* debug FIB print flags bitmap */
uint32_t debug_fw_flags; /* FW debug flags */
uint32_t debug_buf_offset; /* offset from DPMEM start */
uint32_t debug_buf_size; /* FW debug buffer size in bytes */
@@ -356,7 +394,7 @@ struct aac_softstate {
_NOTE(SCHEME_PROTECTS_DATA("stable data", aac_softstate::{flags slen \
buf_dma_attr pci_mem_handle pci_mem_base_vaddr \
comm_space_acc_handle comm_space_dma_handle aac_max_fib_size \
- aac_sg_tablesize aac_cmd_fib aac_cmd_fib_scsi debug_flags}))
+ aac_sg_tablesize aac_cmd_fib aac_cmd_fib_scsi debug_flags bus_max tgt_max}))
/*
* Scatter-gather list structure defined by HBA hardware
@@ -422,11 +460,15 @@ struct aac_cmd {
void (*ac_comp)(struct aac_softstate *, struct aac_cmd *);
struct aac_slot *slotp; /* slot used by this command */
- struct aac_container *dvp; /* target device */
+ struct aac_device *dvp; /* target device */
/* FIB for this IO command */
int fib_size; /* size of the FIB xferred to/from the card */
struct aac_fib *fibp;
+
+#ifdef DEBUG
+ uint32_t fib_flags;
+#endif
};
#ifdef DEBUG
@@ -444,10 +486,23 @@ struct aac_cmd {
#define AACDB_FLAGS_FIB 0x00000200
#define AACDB_FLAGS_IOCTL 0x00000400
+/*
+ * Flags for FIB print
+ */
+/* FIB sources */
+#define AACDB_FLAGS_FIB_SCMD 0x00000001
+#define AACDB_FLAGS_FIB_IOCTL 0x00000002
+#define AACDB_FLAGS_FIB_SRB 0x00000004
+#define AACDB_FLAGS_FIB_SYNC 0x00000008
+/* FIB components */
+#define AACDB_FLAGS_FIB_HEADER 0x00000010
+/* FIB states */
+#define AACDB_FLAGS_FIB_TIMEOUT 0x00000100
+
extern uint32_t aac_debug_flags;
extern int aac_dbflag_on(struct aac_softstate *, int);
extern void aac_printf(struct aac_softstate *, uint_t, const char *, ...);
-extern void aac_print_fib(struct aac_softstate *, struct aac_fib *);
+extern void aac_print_fib(struct aac_softstate *, struct aac_slot *);
#define AACDB_PRINT(s, lev, ...) { \
if (aac_dbflag_on((s), AACDB_FLAGS_MISC)) \
diff --git a/usr/src/uts/common/io/aac/aac_ioctl.c b/usr/src/uts/common/io/aac/aac_ioctl.c
index 5dcfa602a7..26e3a58431 100644
--- a/usr/src/uts/common/io/aac/aac_ioctl.c
+++ b/usr/src/uts/common/io/aac/aac_ioctl.c
@@ -32,8 +32,6 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/modctl.h>
#include <sys/conf.h>
#include <sys/cmn_err.h>
@@ -261,10 +259,14 @@ aac_ioctl_send_fib(struct aac_softstate *softs, intptr_t arg, int mode)
acp->fib_size = fib_size;
fibp->Header.Size = LE_16(fib_size);
- AACDB_PRINT_FIB(softs, fibp);
-
/* Process FIB */
if (fib_command == TakeABreakPt) {
+#ifdef DEBUG
+ if (aac_dbflag_on(softs, AACDB_FLAGS_FIB) &&
+ (softs->debug_fib_flags & AACDB_FLAGS_FIB_IOCTL))
+ aac_printf(softs, CE_NOTE, "FIB> TakeABreakPt, sz=%d",
+ fib_size);
+#endif
(void) aac_sync_mbcommand(softs, AAC_BREAKPOINT_REQ,
0, 0, 0, 0, NULL);
fibp->Header.XferState = LE_32(0);
@@ -275,6 +277,9 @@ aac_ioctl_send_fib(struct aac_softstate *softs, intptr_t arg, int mode)
acp->timeout = AAC_IOCTL_TIMEOUT;
acp->aac_cmd_fib = aac_cmd_fib_copy;
+#ifdef DEBUG
+ acp->fib_flags = AACDB_FLAGS_FIB_IOCTL;
+#endif
if ((rval = aac_send_fib(softs, acp)) != 0)
goto finish;
}
@@ -573,10 +578,10 @@ aac_send_raw_srb(struct aac_softstate *softs, dev_t dev, intptr_t arg, int mode)
bp = ddi_umem_iosetup(cookie, (uintptr_t)usge->addr - \
(uintptr_t)addrlo, usge->bcount, direct, dev, 0, NULL,
- DDI_UMEM_SLEEP);
+ DDI_UMEM_NOSLEEP);
if (bp == NULL) {
AACDB_PRINT(softs, CE_NOTE, "ddi_umem_iosetup failed");
- rval = EFAULT;
+ rval = ENOMEM;
goto finish;
}
if (aac_cmd_dma_alloc(softs, &usge->acp, bp, 0, NULL_FUNC,
@@ -612,8 +617,10 @@ send_fib:
acp->timeout = srb->timeout;
/* Send FIB command */
- AACDB_PRINT_FIB(softs, fibp);
acp->aac_cmd_fib = softs->aac_cmd_fib_scsi;
+#ifdef DEBUG
+ acp->fib_flags = AACDB_FLAGS_FIB_SRB;
+#endif
if ((rval = aac_send_fib(softs, acp)) != 0)
goto finish;
@@ -694,7 +701,7 @@ aac_query_disk(struct aac_softstate *softs, intptr_t arg, int mode)
mutex_enter(&softs->io_lock);
dvp = &softs->containers[qdisk->container_no];
- qdisk->valid = dvp->valid;
+ qdisk->valid = AAC_DEV_IS_VALID(&dvp->dev);
qdisk->locked = dvp->locked;
qdisk->deleted = dvp->deleted;
mutex_exit(&softs->io_lock);
@@ -727,7 +734,7 @@ aac_delete_disk(struct aac_softstate *softs, intptr_t arg, int mode)
* a container, rather we rely on an AIF coming from the
* controller.
*/
- if (dvp->valid) {
+ if (AAC_DEV_IS_VALID(&dvp->dev)) {
if (dvp->locked)
rval = EBUSY;
}
diff --git a/usr/src/uts/common/io/aac/aac_ioctl.h b/usr/src/uts/common/io/aac/aac_ioctl.h
index 9f88df64de..7c6f19955a 100644
--- a/usr/src/uts/common/io/aac/aac_ioctl.h
+++ b/usr/src/uts/common/io/aac/aac_ioctl.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,8 +38,6 @@
#ifndef _AAC_IOCTL_H_
#define _AAC_IOCTL_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -137,7 +135,7 @@ struct aac_features {
*
* Normally the packed structures are defined in a way that if the initial
* member is aligned, then the following members will also be aligned. So
- * we need only to make the packed structure, ie. the first member, is
+ * we need only to make sure the packed structure, ie. the first member, is
* aligned to satisfy alignment requirement.
*/
union aac_revision_align {
diff --git a/usr/src/uts/common/io/aac/aac_regs.h b/usr/src/uts/common/io/aac/aac_regs.h
index 1a831fc0ab..c510b16fac 100644
--- a/usr/src/uts/common/io/aac/aac_regs.h
+++ b/usr/src/uts/common/io/aac/aac_regs.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,8 +38,6 @@
#ifndef __AAC_REGS_H__
#define __AAC_REGS_H__
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -103,6 +101,8 @@ extern "C" {
#define AAC_RESP_DATA_FORMAT 2
#define AAC_MAX_LD 64 /* max number of logical disks */
+#define AAC_MAX_PD(s) ((s)->bus_max * (s)->tgt_max)
+#define AAC_MAX_DEV(s) (AAC_MAX_LD + AAC_MAX_PD((s)))
#define AAC_BLK_SIZE AAC_SECTOR_SIZE
#define AAC_DMA_ALIGN 4
#define AAC_DMA_ALIGN_MASK (AAC_DMA_ALIGN - 1)
@@ -378,6 +378,30 @@ struct aac_mntinforesp {
struct aac_mntobj MntObj;
};
+/*
+ * Structures used to access physical drives
+ */
+struct aac_bus_info {
+ uint32_t Command; /* VM_Ioctl */
+ uint32_t ObjType; /* FT_DRIVE */
+ uint32_t MethodId; /* 1 = SCSI Layer */
+ uint32_t ObjectId; /* Handle */
+ uint32_t CtlCmd; /* GetBusInfo */
+};
+
+struct aac_bus_info_response {
+ uint32_t Status; /* ST_OK */
+ uint32_t ObjType;
+ uint32_t MethodId; /* unused */
+ uint32_t ObjectId; /* unused */
+ uint32_t CtlCmd; /* unused */
+ uint32_t ProbeComplete;
+ uint32_t BusCount;
+ uint32_t TargetsPerBus;
+ uint8_t InitiatorBusId[10];
+ uint8_t BusValid[10];
+};
+
#define CT_FIB_PARAMS 6
#define MAX_FIB_PARAMS 10
#define CT_PACKET_SIZE \
@@ -938,6 +962,21 @@ struct aac_close_command {
uint32_t ContainerId;
};
+/*
+ * Container Config Command
+ */
+struct aac_ctcfg {
+ uint32_t Command;
+ uint32_t cmd;
+ uint32_t param;
+};
+
+struct aac_ctcfg_resp {
+ uint32_t Status;
+ uint32_t resp;
+ uint32_t param;
+};
+
/* Write 'stability' options */
#define CSTABLE 1
#define CUNSTABLE 2
@@ -1465,8 +1504,7 @@ struct aac_srb_reply
uint32_t scsi_status;
uint32_t data_xfer_length;
uint32_t sense_data_size;
- uint8_t sense_data[AAC_SENSE_BUFFERSIZE]; /* Can this be */
- /* SCSI_SENSE_BUFFERSIZE */
+ uint8_t sense_data[AAC_SENSE_BUFFERSIZE];
};
/*
diff --git a/usr/src/uts/common/io/warlock/aac.wlcmd b/usr/src/uts/common/io/warlock/aac.wlcmd
index 2aa4017b5f..69e9cdfe98 100644
--- a/usr/src/uts/common/io/warlock/aac.wlcmd
+++ b/usr/src/uts/common/io/warlock/aac.wlcmd
@@ -20,12 +20,9 @@
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
-
one aac_softstate
add aac_softstate::aac_if.aif_get_fwstatus target \
@@ -48,7 +45,7 @@ add aac_softstate::aac_cmd_fib_scsi target \
aac_cmd_fib_scsi32 \
aac_cmd_fib_scsi64
-root aac_intr_old aac_intr_new aac_fm_error_cb
+root aac_intr_old aac_intr_new aac_fm_error_cb aac_handle_dr aac_name_node
add scsi_pkt::pkt_comp target \
aac_tran_destroy_pkt \