summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/conf/GENERIC1
-rw-r--r--sys/conf/NOTES1
-rw-r--r--sys/conf/files1
-rw-r--r--sys/dev/aac/aac.c137
-rw-r--r--sys/dev/aac/aac_cam.c591
-rw-r--r--sys/dev/aac/aac_cam.h34
-rw-r--r--sys/dev/aac/aac_disk.c2
-rw-r--r--sys/dev/aac/aac_pci.c69
-rw-r--r--sys/dev/aac/aacreg.h186
-rw-r--r--sys/dev/aac/aacvar.h11
-rw-r--r--sys/i386/conf/GENERIC1
-rw-r--r--sys/modules/aac/Makefile3
12 files changed, 989 insertions, 48 deletions
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 6a2eafd..15a2b17 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -115,6 +115,7 @@ device ses # SCSI Environmental Services (and SAF-TE)
# RAID controllers
device aac # Adaptec FSA RAID
+device aacp # SCSI passthrough for aac (requires CAM)
device amr # AMI MegaRAID
device ida # Compaq Smart RAID
device mlx # Mylex DAC960 family
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index a84076c..b10bd54 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1288,6 +1288,7 @@ device mly
# support).
#
device aac
+device aacp # SCSI Passthrough interface (optional)
#
# Compaq Smart RAID, Mylex DAC960 and AMI MegaRAID controllers. Only
diff --git a/sys/conf/files b/sys/conf/files
index c069d46..030b9af 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -196,6 +196,7 @@ dev/aac/aac.c optional aac
dev/aac/aac_debug.c optional aac
dev/aac/aac_disk.c optional aac
dev/aac/aac_pci.c optional aac pci
+dev/aac/aac_cam.c optional aacp aac
dev/acpica/acpi.c optional acpica
dev/acpica/acpica_support.c optional acpica
dev/acpica/acpi_acad.c optional acpica nowerror
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
index a9c6ea3..cd2e8ab 100644
--- a/sys/dev/aac/aac.c
+++ b/sys/dev/aac/aac.c
@@ -70,13 +70,14 @@
#include <dev/aac/aac_ioctl.h>
#include <dev/aac/aacvar.h>
#include <dev/aac/aac_tables.h>
+#include <dev/aac/aac_cam.h>
static void aac_startup(void *arg);
static void aac_add_container(struct aac_softc *sc,
struct aac_mntinforesp *mir, int f);
+static void aac_get_bus_info(struct aac_softc *sc);
/* Command Processing */
-static void aac_startio(struct aac_softc *sc);
static void aac_timeout(struct aac_softc *sc);
static int aac_start(struct aac_command *cm);
static void aac_complete(void *context, int pending);
@@ -87,9 +88,6 @@ static void aac_host_command(struct aac_softc *sc);
static void aac_host_response(struct aac_softc *sc);
/* Command Buffer Management */
-static int aac_alloc_command(struct aac_softc *sc,
- struct aac_command **cmp);
-static void aac_release_command(struct aac_command *cm);
static void aac_map_command_helper(void *arg, bus_dma_segment_t *segs,
int nseg, int error);
static int aac_alloc_commands(struct aac_softc *sc);
@@ -327,6 +325,10 @@ aac_attach(struct aac_softc *sc)
SHUTDOWN_PRI_DEFAULT)) == NULL)
device_printf(sc->aac_dev, "shutdown event registration failed\n");
+ /* Register with CAM for the non-DASD devices */
+ if (!(sc->quirks & AAC_QUIRK_NOCAM))
+ aac_get_bus_info(sc);
+
return(0);
}
@@ -349,7 +351,7 @@ aac_startup(void *arg)
/* disconnect ourselves from the intrhook chain */
config_intrhook_disestablish(&sc->aac_ich);
- aac_get_sync_fib(sc, &fib, 0);
+ aac_alloc_sync_fib(sc, &fib, 0);
mi = (struct aac_mntinfo *)&fib->data[0];
/* loop over possible containers */
@@ -409,7 +411,7 @@ aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f)
mir->MntTable[0].FileSystemName,
mir->MntTable[0].Capacity, mir->MntTable[0].VolType);
- if ((child = device_add_child(sc->aac_dev, NULL, -1)) == NULL)
+ if ((child = device_add_child(sc->aac_dev, "aacd", -1)) == NULL)
device_printf(sc->aac_dev, "device_add_child failed\n");
else
device_set_ivars(child, co);
@@ -545,7 +547,7 @@ aac_shutdown(device_t dev)
*/
device_printf(sc->aac_dev, "shutting down controller...");
- aac_get_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
+ aac_alloc_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
cc = (struct aac_close_command *)&fib->data[0];
cc->Command = VM_CloseAll;
@@ -669,7 +671,7 @@ aac_intr(void *arg)
/*
* Start as much queued I/O as possible on the controller
*/
-static void
+void
aac_startio(struct aac_softc *sc)
{
struct aac_command *cm;
@@ -781,7 +783,7 @@ aac_host_command(struct aac_softc *sc)
/* XXX Compute the Size field? */
size = fib->Header.Size;
if (size > sizeof(struct aac_fib)) {
- size = sizeof(struct aac_fib);
+ size = sizeof(struct aac_fib);
fib->Header.Size = size;
}
/*
@@ -1041,7 +1043,7 @@ aac_wait_command(struct aac_command *cm, int timeout)
/*
* Allocate a command.
*/
-static int
+int
aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp)
{
struct aac_command *cm;
@@ -1058,7 +1060,7 @@ aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp)
/*
* Release a command back to the freelist.
*/
-static void
+void
aac_release_command(struct aac_command *cm)
{
debug_called(3);
@@ -1330,8 +1332,8 @@ aac_init(struct aac_softc *sc)
* Create DMA tag for the common structure and allocate it.
*/
if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */
- 1, 0, /* algnmnt, boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
+ 1, 0, /* algnmnt, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
sizeof(struct aac_common), /* maxsize */
@@ -1350,7 +1352,7 @@ aac_init(struct aac_softc *sc)
}
bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap,
sc->aac_common, sizeof(*sc->aac_common), aac_common_map,
- sc, 0);
+ sc, 0);
bzero(sc->aac_common, sizeof(*sc->aac_common));
/*
@@ -1515,7 +1517,7 @@ aac_sync_command(struct aac_softc *sc, u_int32_t command,
* Grab the sync fib area.
*/
int
-aac_get_sync_fib(struct aac_softc *sc, struct aac_fib **fib, int flags)
+aac_alloc_sync_fib(struct aac_softc *sc, struct aac_fib **fib, int flags)
{
/*
@@ -2070,11 +2072,12 @@ aac_describe_controller(struct aac_softc *sc)
debug_called(2);
- aac_get_sync_fib(sc, &fib, 0);
+ aac_alloc_sync_fib(sc, &fib, 0);
fib->data[0] = 0;
if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) {
device_printf(sc->aac_dev, "RequestAdapterInfo failed\n");
+ aac_release_sync_fib(sc);
return;
}
info = (struct aac_adapter_info *)&fib->data[0];
@@ -2093,6 +2096,8 @@ aac_describe_controller(struct aac_softc *sc)
info->KernelRevision.external.comp.dash,
info->KernelRevision.buildNumber,
(u_int32_t)(info->SerialNumber & 0xffffff));
+
+ aac_release_sync_fib(sc);
}
/*
@@ -2366,7 +2371,7 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
* doesn't tell us anything else! Re-enumerate the
* containers and sort things out.
*/
- aac_get_sync_fib(sc, &fib, 0);
+ aac_alloc_sync_fib(sc, &fib, 0);
mi = (struct aac_mntinfo *)&fib->data[0];
mi->Command = VM_NameServe;
mi->MntType = FT_FILESYS;
@@ -2697,3 +2702,101 @@ aac_query_disk(struct aac_softc *sc, caddr_t uptr)
return (error);
}
+static void
+aac_get_bus_info(struct aac_softc *sc)
+{
+ struct aac_fib *fib;
+ struct aac_ctcfg *c_cmd;
+ struct aac_ctcfg_resp *c_resp;
+ struct aac_vmioctl *vmi;
+ struct aac_vmi_businf_resp *vmi_resp;
+ struct aac_getbusinf businfo;
+ struct aac_cam_inf *caminf;
+ device_t child;
+ int i, found, error;
+
+ aac_alloc_sync_fib(sc, &fib, 0);
+ c_cmd = (struct aac_ctcfg *)&fib->data[0];
+
+ c_cmd->Command = VM_ContainerConfig;
+ c_cmd->cmd = CT_GET_SCSI_METHOD;
+ c_cmd->param = 0;
+
+ error = aac_sync_fib(sc, ContainerCommand, 0, fib,
+ sizeof(struct aac_ctcfg));
+ if (error) {
+ device_printf(sc->aac_dev, "Error %d sending "
+ "VM_ContainerConfig command\n", error);
+ aac_release_sync_fib(sc);
+ return;
+ }
+
+ c_resp = (struct aac_ctcfg_resp *)&fib->data[0];
+ if (c_resp->Status != ST_OK) {
+ device_printf(sc->aac_dev, "VM_ContainerConfig returned 0x%x\n",
+ c_resp->Status);
+ aac_release_sync_fib(sc);
+ return;
+ }
+
+ sc->scsi_method_id = c_resp->param;
+
+ vmi = (struct aac_vmioctl *)&fib->data[0];
+ vmi->Command = VM_Ioctl;
+ vmi->ObjType = FT_DRIVE;
+ vmi->MethId = sc->scsi_method_id;
+ vmi->ObjId = 0;
+ vmi->IoctlCmd = GetBusInfo;
+
+ error = aac_sync_fib(sc, ContainerCommand, 0, fib,
+ sizeof(struct aac_vmioctl));
+ if (error) {
+ device_printf(sc->aac_dev, "Error %d sending VMIoctl command\n",
+ error);
+ aac_release_sync_fib(sc);
+ return;
+ }
+
+ vmi_resp = (struct aac_vmi_businf_resp *)&fib->data[0];
+ if (vmi_resp->Status != ST_OK) {
+ device_printf(sc->aac_dev, "VM_Ioctl returned %d\n",
+ vmi_resp->Status);
+ aac_release_sync_fib(sc);
+ return;
+ }
+
+ bcopy(&vmi_resp->BusInf, &businfo, sizeof(struct aac_getbusinf));
+ aac_release_sync_fib(sc);
+
+ found = 0;
+ for (i = 0; i < businfo.BusCount; i++) {
+ if (businfo.BusValid[i] != AAC_BUS_VALID)
+ continue;
+
+ MALLOC(caminf, struct aac_cam_inf *,
+ sizeof(struct aac_cam_inf), M_AACBUF, M_NOWAIT | M_ZERO);
+ if (caminf == NULL)
+ continue;
+
+ child = device_add_child(sc->aac_dev, "aacp", -1);
+ if (child == NULL) {
+ device_printf(sc->aac_dev, "device_add_child failed\n");
+ continue;
+ }
+
+ caminf->TargetsPerBus = businfo.TargetsPerBus;
+ caminf->BusNumber = i;
+ caminf->InitiatorBusId = businfo.InitiatorBusId[i];
+ caminf->aac_sc = sc;
+
+ device_set_ivars(child, caminf);
+ device_set_desc(child, "SCSI Passthrough Bus");
+
+ found = 1;
+ }
+
+ if (found)
+ bus_generic_attach(sc->aac_dev);
+
+ return;
+}
diff --git a/sys/dev/aac/aac_cam.c b/sys/dev/aac/aac_cam.c
new file mode 100644
index 0000000..6ec390c
--- /dev/null
+++ b/sys/dev/aac/aac_cam.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2002 Adaptec, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * CAM front-end for communicating with non-DASD devices
+ */
+
+#include "opt_aac.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_sim.h>
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_message.h>
+
+#include <dev/aac/aac_compat.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/devicestat.h>
+#include <sys/disk.h>
+
+#include <machine/md_var.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/aac/aacreg.h>
+#include <dev/aac/aac_ioctl.h>
+#include <dev/aac/aacvar.h>
+#include <dev/aac/aac_cam.h>
+
+struct aac_cam {
+ device_t dev;
+ struct aac_cam_inf *inf;
+ u_int32_t scsi_method_id;
+ int bus;
+ struct cam_sim *sim;
+ struct cam_path *path;
+};
+
+static int aac_cam_probe(device_t dev);
+static int aac_cam_attach(device_t dev);
+static int aac_cam_detach(device_t dev);
+static void aac_cam_action(struct cam_sim *, union ccb *);
+static void aac_cam_poll(struct cam_sim *);
+static void aac_cam_complete(struct aac_command *);
+static u_int32_t aac_cam_reset_bus(struct cam_sim *, union ccb *);
+static u_int32_t aac_cam_abort_ccb(struct cam_sim *, union ccb *);
+static u_int32_t aac_cam_term_io(struct cam_sim *, union ccb *);
+static int aac_cam_get_tran_settings(struct aac_softc *, struct ccb_trans_settings *, u_int32_t);
+
+static devclass_t aac_pass_devclass;
+
+static device_method_t aac_pass_methods[] = {
+ DEVMETHOD(device_probe, aac_cam_probe),
+ DEVMETHOD(device_attach, aac_cam_attach),
+ DEVMETHOD(device_detach, aac_cam_detach),
+ { 0, 0 }
+};
+
+static driver_t aac_pass_driver = {
+ "aacp",
+ aac_pass_methods,
+ sizeof(struct aac_cam)
+};
+
+DRIVER_MODULE(aacp, aac, aac_pass_driver, aac_pass_devclass, 0, 0);
+MODULE_DEPEND(aacp, cam, 1, 1, 1);
+
+MALLOC_DEFINE(M_AACCAM, "aaccam", "AAC CAM info");
+
+static int
+aac_cam_probe(device_t dev)
+{
+
+ debug_called(2);
+
+ return (0);
+}
+
+static int
+aac_cam_detach(device_t dev)
+{
+
+ return (0);
+}
+
+/*
+ * Register the driver as a CAM SIM
+ */
+static int
+aac_cam_attach(device_t dev)
+{
+ struct cam_devq *devq;
+ struct cam_sim *sim;
+ struct cam_path *path;
+ struct aac_cam *camsc;
+ struct aac_cam_inf *inf;
+
+ debug_called(1);
+
+ camsc = (struct aac_cam *)device_get_softc(dev);
+ inf = (struct aac_cam_inf *)device_get_ivars(dev);
+ camsc->inf = inf;
+
+ devq = cam_simq_alloc(inf->TargetsPerBus);
+ if (devq == NULL)
+ return (EIO);
+
+ sim = cam_sim_alloc(aac_cam_action, aac_cam_poll, "aacp", camsc,
+ device_get_unit(dev), 1, 1, devq);
+ if (sim == NULL) {
+ cam_simq_free(devq);
+ return (EIO);
+ }
+
+ if (xpt_bus_register(sim, 0) != CAM_SUCCESS) {
+ cam_sim_free(sim, TRUE);
+ return (EIO);
+ }
+
+ if (xpt_create_path(&path, NULL, cam_sim_path(sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_bus_deregister(cam_sim_path(sim));
+ cam_sim_free(sim, TRUE);
+ return (EIO);
+ }
+
+ camsc->sim = sim;
+ camsc->path = path;
+ camsc->bus = cam_sim_bus(sim);
+
+ return (0);
+}
+
+static void
+aac_cam_action(struct cam_sim *sim, union ccb *ccb)
+{
+ struct aac_cam *camsc;
+ struct aac_softc *sc;
+ struct aac_srb32 *srb;
+ struct aac_fib *fib;
+ struct aac_command *cm;
+
+ debug_called(2);
+
+ camsc = (struct aac_cam *)cam_sim_softc(sim);
+ sc = camsc->inf->aac_sc;
+
+ /* Synchronous ops, and ops that don't require communication with the
+ * controller */
+ switch(ccb->ccb_h.func_code) {
+ case XPT_SCSI_IO:
+ case XPT_RESET_DEV:
+ /* These are handled down below */
+ break;
+ case XPT_CALC_GEOMETRY:
+ {
+ struct ccb_calc_geometry *ccg;
+ u_int32_t size_mb;
+ u_int32_t secs_per_cylinder;
+
+ ccg = &ccb->ccg;
+ size_mb = ccg->volume_size /
+ ((1024L * 1024L) / ccg->block_size);
+ if (size_mb >= (2 * 1024)) { /* 2GB */
+ ccg->heads = 255;
+ ccg->secs_per_track = 63;
+ } else if (size_mb >= (1 * 1024)) { /* 1GB */
+ ccg->heads = 128;
+ ccg->secs_per_track = 32;
+ } else {
+ ccg->heads = 64;
+ ccg->secs_per_track = 32;
+ }
+ secs_per_cylinder = ccg->heads * ccg->secs_per_track;
+ ccg->cylinders = ccg->volume_size / secs_per_cylinder;
+
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+ return;
+ }
+ case XPT_PATH_INQ:
+ {
+ struct ccb_pathinq *cpi = &ccb->cpi;
+
+ cpi->version_num = 1;
+ cpi->hba_inquiry = PI_WIDE_16;
+ cpi->target_sprt = 0;
+ cpi->hba_misc = 0;
+ cpi->hba_eng_cnt = 0;
+ cpi->max_target = camsc->inf->TargetsPerBus;
+ cpi->max_lun = 8; /* Per the controller spec */
+ cpi->initiator_id = camsc->inf->InitiatorBusId;
+ cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
+ strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+ strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
+ strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+ cpi->unit_number = cam_sim_unit(sim);
+
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+ return;
+ }
+ case XPT_GET_TRAN_SETTINGS:
+ {
+ u_int32_t handle;
+
+ handle = AAC_BTL_TO_HANDLE(cam_sim_bus(sim),
+ ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
+ ccb->ccb_h.status = aac_cam_get_tran_settings(sc, &ccb->cts,
+ handle);
+ xpt_done(ccb);
+ return;
+ }
+ case XPT_SET_TRAN_SETTINGS:
+ ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
+ xpt_done(ccb);
+ return;
+ case XPT_RESET_BUS:
+ if (!(sc->quirks & AAC_QUIRK_CAM_NORESET)) {
+ ccb->ccb_h.status = aac_cam_reset_bus(sim, ccb);
+ } else {
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ }
+ xpt_done(ccb);
+ return;
+ case XPT_ABORT:
+ ccb->ccb_h.status = aac_cam_abort_ccb(sim, ccb);
+ xpt_done(ccb);
+ return;
+ case XPT_TERM_IO:
+ ccb->ccb_h.status = aac_cam_term_io(sim, ccb);
+ xpt_done(ccb);
+ return;
+ default:
+ device_printf(sc->aac_dev, "Unsupported command 0x%x\n",
+ ccb->ccb_h.func_code);
+ ccb->ccb_h.status = CAM_PROVIDE_FAIL;
+ xpt_done(ccb);
+ return;
+ }
+
+ /* Async ops that require communcation with the controller */
+
+ if (aac_alloc_command(sc, &cm)) {
+ xpt_freeze_simq(sim, 1);
+ ccb->ccb_h.status = CAM_REQUEUE_REQ;
+ xpt_done(ccb);
+ return;
+ }
+
+ fib = cm->cm_fib;
+ srb = (struct aac_srb32 *)&fib->data[0];
+ cm->cm_datalen = 0;
+
+ switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
+ case CAM_DIR_IN:
+ srb->flags = AAC_SRB_FLAGS_DATA_IN;
+ cm->cm_flags |= AAC_CMD_DATAIN;
+ break;
+ case CAM_DIR_OUT:
+ srb->flags = AAC_SRB_FLAGS_DATA_OUT;
+ cm->cm_flags |= AAC_CMD_DATAOUT;
+ break;
+ case CAM_DIR_NONE:
+ srb->flags = AAC_SRB_FLAGS_NO_DATA_XFER;
+ break;
+ default:
+ srb->flags = AAC_SRB_FLAGS_UNSPECIFIED_DIRECTION;
+ cm->cm_flags |= AAC_CMD_DATAIN | AAC_CMD_DATAOUT;
+ break;
+ }
+
+ switch(ccb->ccb_h.func_code) {
+ case XPT_SCSI_IO:
+ {
+ struct ccb_scsiio *csio = &ccb->csio;
+
+ srb->function = AAC_SRB_FUNC_EXECUTE_SCSI;
+
+ /*
+ * Copy the CDB into the SRB. It's only 6-16 bytes,
+ * so a copy is not too expensive.
+ */
+ srb->cdb_len = csio->cdb_len;
+ if (ccb->ccb_h.flags & CAM_CDB_POINTER)
+ bcopy(csio->cdb_io.cdb_ptr, (u_int8_t *)&srb->cdb[0],
+ srb->cdb_len);
+ else
+ bcopy(csio->cdb_io.cdb_bytes, (u_int8_t *)&srb->cdb[0],
+ srb->cdb_len);
+
+ /* Map the s/g list. XXX 32bit addresses only! */
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+ if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
+ srb->data_len = csio->dxfer_len;
+ if (ccb->ccb_h.flags & CAM_DATA_PHYS) {
+ srb->sg_map32.SgCount = 1;
+ srb->sg_map32.SgEntry[0].SgAddress =
+ (u_int32_t)csio->data_ptr;
+ srb->sg_map32.SgEntry[0].SgByteCount =
+ csio->dxfer_len;
+ } else {
+ /*
+ * Arrange things so that the S/G
+ * map will get set up automagically
+ */
+ cm->cm_data = (void *)csio->data_ptr;
+ cm->cm_datalen = csio->dxfer_len;
+ cm->cm_sgtable = &srb->sg_map32;
+ }
+ } else {
+ /* XXX Need to handle multiple s/g elements */
+ panic("aac_cam: multiple s/g elements");
+ }
+ } else {
+ srb->sg_map32.SgCount = 0;
+ srb->sg_map32.SgEntry[0].SgByteCount = 0;
+ srb->data_len = 0;
+ }
+
+ break;
+ }
+ case XPT_RESET_DEV:
+ if (!(sc->quirks & AAC_QUIRK_CAM_NORESET)) {
+ srb->function = AAC_SRB_FUNC_RESET_DEVICE;
+ break;
+ } else {
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+ return;
+ }
+ default:
+ break;
+ }
+
+ srb->bus = cam_sim_bus(sim); /* Bus number relative to the card */
+ srb->target = ccb->ccb_h.target_id;
+ srb->lun = ccb->ccb_h.target_lun;
+ srb->timeout = ccb->ccb_h.timeout; /* XXX */
+ srb->retry_limit = 0;
+
+ cm->cm_complete = aac_cam_complete;
+ cm->cm_private = ccb;
+ cm->cm_timestamp = time_second;
+ cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
+
+ fib->Header.XferState =
+ AAC_FIBSTATE_HOSTOWNED |
+ AAC_FIBSTATE_INITIALISED |
+ AAC_FIBSTATE_FROMHOST |
+ AAC_FIBSTATE_REXPECTED |
+ AAC_FIBSTATE_NORM;
+ fib->Header.Command = ScsiPortCommand;
+ fib->Header.Size = sizeof(struct aac_fib_header) +
+ sizeof(struct aac_srb32);
+
+ aac_enqueue_ready(cm);
+ aac_startio(cm->cm_sc);
+
+ return;
+}
+
+static void
+aac_cam_poll(struct cam_sim *sim)
+{
+ /*
+ * Pinging the interrupt routine isn't very safe, nor is it
+ * really necessary. Do nothing.
+ */
+}
+
+static void
+aac_cam_complete(struct aac_command *cm)
+{
+ union ccb *ccb;
+ struct aac_srb_response *srbr;
+ struct aac_softc *sc;
+
+ debug_called(2);
+
+ sc = cm->cm_sc;
+ ccb = cm->cm_private;
+ srbr = (struct aac_srb_response *)&cm->cm_fib->data[0];
+
+ if (srbr->fib_status != 0) {
+ device_printf(sc->aac_dev, "Passthru FIB failed!\n");
+ ccb->ccb_h.status = CAM_REQ_ABORTED;
+ } else {
+ /*
+ * The SRB error codes just happen to match the CAM error
+ * codes. How convienient!
+ */
+ ccb->ccb_h.status = srbr->srb_status;
+
+ /* Take care of SCSI_IO ops. */
+ if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
+ u_int8_t command, device;
+
+ ccb->csio.scsi_status = srbr->scsi_status;
+
+ /* Take care of autosense */
+ if (srbr->sense_len) {
+ int sense_len, scsi_sense_len;
+
+ scsi_sense_len = sizeof(struct scsi_sense_data);
+ bzero(&ccb->csio.sense_data, scsi_sense_len);
+ sense_len = (srbr->sense_len >
+ scsi_sense_len) ? scsi_sense_len :
+ srbr->sense_len;
+ bcopy(&srbr->sense[0], &ccb->csio.sense_data,
+ srbr->sense_len);
+ ccb->csio.sense_len = sense_len;
+ ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
+ scsi_sense_print(&ccb->csio);
+ }
+
+ /* If this is an inquiry command, fake things out */
+ if (ccb->ccb_h.flags & CAM_CDB_POINTER)
+ command = ccb->csio.cdb_io.cdb_ptr[0];
+ else
+ command = ccb->csio.cdb_io.cdb_bytes[0];
+
+ if ((command == INQUIRY) &&
+ (ccb->ccb_h.status == CAM_REQ_CMP)) {
+ device = ccb->csio.data_ptr[0] & 0x1f;
+ /*
+ * We want DASD and PROC devices to only be
+ * visible through the pass device.
+ */
+ if ((device == T_DIRECT) ||
+ (device == T_PROCESSOR) ||
+ (sc->quirks & AAC_QUIRK_CAM_PASSONLY))
+ ccb->csio.data_ptr[0] =
+ ((device & 0xe0) | T_NODEVICE);
+ }
+ }
+ }
+
+ aac_release_command(cm);
+
+ xpt_done(ccb);
+
+ return;
+}
+
+static u_int32_t
+aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb)
+{
+ struct aac_fib *fib;
+ struct aac_softc *sc;
+ struct aac_cam *camsc;
+ struct aac_vmioctl *vmi;
+ struct aac_resetbus *rbc;
+ int e;
+
+ camsc = (struct aac_cam *)cam_sim_softc(sim);
+ sc = camsc->inf->aac_sc;
+
+ if (sc == NULL) {
+ printf("Null sc?\n");
+ return (CAM_REQ_ABORTED);
+ }
+
+ aac_alloc_sync_fib(sc, &fib, 0);
+
+ vmi = (struct aac_vmioctl *)&fib->data[0];
+ vmi->Command = VM_Ioctl;
+ vmi->ObjType = FT_DRIVE;
+ vmi->MethId = sc->scsi_method_id;
+ vmi->ObjId = 0;
+ vmi->IoctlCmd = ResetBus;
+
+ rbc = (struct aac_resetbus *)&vmi->IoctlBuf[0];
+ rbc->BusNumber = cam_sim_bus(sim);
+
+ e = aac_sync_fib(sc, ContainerCommand, 0, fib,
+ sizeof(struct aac_vmioctl));
+ if (e) {
+ device_printf(sc->aac_dev, "Error 0x%x sending passthrough\n",
+ e);
+ aac_release_sync_fib(sc);
+ return (CAM_REQ_ABORTED);
+ }
+
+ aac_release_sync_fib(sc);
+ return (CAM_REQ_CMP);
+}
+
+static u_int32_t
+aac_cam_abort_ccb(struct cam_sim *sim, union ccb *ccb)
+{
+ return (CAM_UA_ABORT);
+}
+
+static u_int32_t
+aac_cam_term_io(struct cam_sim *sim, union ccb *ccb)
+{
+ return (CAM_UA_TERMIO);
+}
+
+static int
+aac_cam_get_tran_settings(struct aac_softc *sc, struct ccb_trans_settings *cts, u_int32_t handle)
+{
+ struct aac_fib *fib;
+ struct aac_vmioctl *vmi;
+ struct aac_vmi_devinfo_resp *vmi_resp;
+ int error;
+
+ aac_alloc_sync_fib(sc, &fib, 0);
+ vmi = (struct aac_vmioctl *)&fib->data[0];
+
+ vmi->Command = VM_Ioctl;
+ vmi->ObjType = FT_DRIVE;
+ vmi->MethId = sc->scsi_method_id;
+ vmi->ObjId = handle;
+ vmi->IoctlCmd = GetDeviceProbeInfo;
+
+ error = aac_sync_fib(sc, ContainerCommand, 0, fib,
+ sizeof(struct aac_vmioctl));
+ if (error) {
+ device_printf(sc->aac_dev, "Error %d sending VMIoctl command\n",
+ error);
+ aac_release_sync_fib(sc);
+ return (CAM_REQ_INVALID);
+ }
+
+ vmi_resp = (struct aac_vmi_devinfo_resp *)&fib->data[0];
+ if (vmi_resp->Status != ST_OK) {
+ device_printf(sc->aac_dev, "VM_Ioctl returned %d\n",
+ vmi_resp->Status);
+ aac_release_sync_fib(sc);
+ return (CAM_REQ_CMP_ERR);
+ }
+
+ cts->bus_width = ((vmi_resp->Inquiry7 & 0x60) >> 5);
+ if (vmi_resp->ScsiRate) {
+ cts->sync_period =
+ scsi_calc_syncparam((10000 / vmi_resp->ScsiRate));
+ cts->sync_offset = vmi_resp->ScsiOffset;
+ } else {
+ cts->sync_period = 0;
+ cts->sync_offset = 0;
+ }
+ cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
+ cts->valid = CCB_TRANS_DISC_VALID |
+ CCB_TRANS_SYNC_RATE_VALID |
+ CCB_TRANS_SYNC_OFFSET_VALID |
+ CCB_TRANS_BUS_WIDTH_VALID |
+ CCB_TRANS_TQ_VALID;
+
+ aac_release_sync_fib(sc);
+ return (CAM_REQ_CMP);
+}
diff --git a/sys/dev/aac/aac_cam.h b/sys/dev/aac/aac_cam.h
new file mode 100644
index 0000000..b06caeb
--- /dev/null
+++ b/sys/dev/aac/aac_cam.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2002 Adaptec, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+struct aac_cam_inf {
+ int TargetsPerBus;
+ int BusNumber;
+ int InitiatorBusId;
+ struct aac_softc *aac_sc;
+};
diff --git a/sys/dev/aac/aac_disk.c b/sys/dev/aac/aac_disk.c
index 7aeb37d..000d841 100644
--- a/sys/dev/aac/aac_disk.c
+++ b/sys/dev/aac/aac_disk.c
@@ -269,7 +269,7 @@ aac_disk_dump(dev_t dev, void *virtual, vm_offset_t physical, off_t offset, size
}
}
- aac_get_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
+ aac_alloc_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
bw = (struct aac_blockwrite *)&fib->data[0];
while (length > 0) {
diff --git a/sys/dev/aac/aac_pci.c b/sys/dev/aac/aac_pci.c
index f19bf3d..85d4001 100644
--- a/sys/dev/aac/aac_pci.c
+++ b/sys/dev/aac/aac_pci.c
@@ -90,30 +90,44 @@ struct aac_ident
u_int16_t subvendor;
u_int16_t subdevice;
int hwif;
+ int quirks;
char *desc;
} aac_identifiers[] = {
- {0x1028, 0x0001, 0x1028, 0x0001, AAC_HWIF_I960RX, "Dell PERC 2/Si"},
- {0x1028, 0x0002, 0x1028, 0x0002, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
- {0x1028, 0x0003, 0x1028, 0x0003, AAC_HWIF_I960RX, "Dell PERC 3/Si"},
- {0x1028, 0x0004, 0x1028, 0x00d0, AAC_HWIF_I960RX, "Dell PERC 3/Si"},
- {0x1028, 0x0002, 0x1028, 0x00d1, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
- {0x1028, 0x0002, 0x1028, 0x00d9, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
- {0x1028, 0x0008, 0x1028, 0x00cf, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
- {0x1028, 0x000a, 0x1028, 0x0106, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
- {0x1028, 0x000a, 0x1028, 0x011b, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
- {0x1028, 0x000a, 0x1028, 0x0121, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
- {0x1011, 0x0046, 0x9005, 0x0364, AAC_HWIF_STRONGARM, "Adaptec AAC-364"},
- {0x1011, 0x0046, 0x9005, 0x0365, AAC_HWIF_STRONGARM,
- "Adaptec SCSI RAID 5400S"},
- {0x1011, 0x0046, 0x9005, 0x1364, AAC_HWIF_STRONGARM, "Dell PERC 2/QC"},
- {0x1011, 0x0046, 0x103c, 0x10c2, AAC_HWIF_STRONGARM, "HP NetRaid-4M"},
- {0x9005, 0x0285, 0x9005, 0x0285, AAC_HWIF_I960RX,
+ {0x1028, 0x0001, 0x1028, 0x0001, AAC_HWIF_I960RX, AAC_QUIRK_NOCAM,
+ "Dell PERC 2/Si"},
+ {0x1028, 0x0002, 0x1028, 0x0002, AAC_HWIF_I960RX, AAC_QUIRK_NOCAM,
+ "Dell PERC 3/Di"},
+ {0x1028, 0x0003, 0x1028, 0x0003, AAC_HWIF_I960RX, AAC_QUIRK_NOCAM,
+ "Dell PERC 3/Si"},
+ {0x1028, 0x0004, 0x1028, 0x00d0, AAC_HWIF_I960RX, AAC_QUIRK_NOCAM,
+ "Dell PERC 3/Si"},
+ {0x1028, 0x0002, 0x1028, 0x00d1, AAC_HWIF_I960RX, AAC_QUIRK_NOCAM,
+ "Dell PERC 3/Di"},
+ {0x1028, 0x0002, 0x1028, 0x00d9, AAC_HWIF_I960RX, AAC_QUIRK_NOCAM,
+ "Dell PERC 3/Di"},
+ {0x1028, 0x0008, 0x1028, 0x00cf, AAC_HWIF_I960RX, AAC_QUIRK_NOCAM,
+ "Dell PERC 3/Di"},
+ {0x1028, 0x000a, 0x1028, 0x0106, AAC_HWIF_I960RX, AAC_QUIRK_NOCAM,
+ "Dell PERC 3/Di"},
+ {0x1028, 0x000a, 0x1028, 0x011b, AAC_HWIF_I960RX, AAC_QUIRK_NOCAM,
+ "Dell PERC 3/Di"},
+ {0x1028, 0x000a, 0x1028, 0x0121, AAC_HWIF_I960RX, AAC_QUIRK_NOCAM,
+ "Dell PERC 3/Di"},
+ {0x1011, 0x0046, 0x9005, 0x0364, AAC_HWIF_STRONGARM, AAC_QUIRK_NOCAM,
+ "Adaptec AAC-364"},
+ {0x1011, 0x0046, 0x9005, 0x0365, AAC_HWIF_STRONGARM, 0,
+ "Adaptec SCSI RAID 5400S"},
+ {0x1011, 0x0046, 0x9005, 0x1364, AAC_HWIF_STRONGARM, AAC_QUIRK_NOCAM |
+ AAC_QUIRK_PERC2QC, "Dell PERC 2/QC"},
+ {0x1011, 0x0046, 0x103c, 0x10c2, AAC_HWIF_STRONGARM,
+ AAC_QUIRK_CAM_NORESET, "HP NetRaid-4M"},
+ {0x9005, 0x0285, 0x9005, 0x0285, AAC_HWIF_I960RX, 0,
"Adaptec SCSI RAID 2200S"},
- {0x9005, 0x0285, 0x9005, 0x0287, AAC_HWIF_I960RX,
+ {0x9005, 0x0285, 0x9005, 0x0287, AAC_HWIF_I960RX, 0,
"Adaptec SCSI RAID 2200S"},
- {0x9005, 0x0285, 0x9005, 0x0286, AAC_HWIF_I960RX,
+ {0x9005, 0x0285, 0x9005, 0x0286, AAC_HWIF_I960RX, 0,
"Adaptec SCSI RAID 2120S"},
- {0, 0, 0, 0, 0, 0}
+ {0, 0, 0, 0, 0, 0, 0}
};
/*
@@ -266,7 +280,7 @@ aac_pci_attach(device_t dev)
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
0, /* flags */
&sc->aac_fib_dmat)) {
- device_printf(sc->aac_dev, "can't allocate FIB DMA tag\n");
+ device_printf(sc->aac_dev, "can't allocate FIB DMA tag\n");;
goto out;
}
@@ -277,7 +291,9 @@ aac_pci_attach(device_t dev)
sc->aac_hwif = AAC_HWIF_UNKNOWN;
for (i = 0; aac_identifiers[i].vendor != 0; i++) {
if ((aac_identifiers[i].vendor == pci_get_vendor(dev)) &&
- (aac_identifiers[i].device == pci_get_device(dev))) {
+ (aac_identifiers[i].device == pci_get_device(dev)) &&
+ (aac_identifiers[i].subvendor == pci_get_subvendor(dev)) &&
+ (aac_identifiers[i].subdevice == pci_get_subdevice(dev))) {
sc->aac_hwif = aac_identifiers[i].hwif;
switch(sc->aac_hwif) {
case AAC_HWIF_I960RX:
@@ -294,6 +310,10 @@ aac_pci_attach(device_t dev)
sc->aac_if = aac_fa_interface;
break;
}
+
+ /* Set up quirks */
+ sc->quirks = aac_identifiers[i].quirks;
+
break;
}
}
@@ -305,13 +325,6 @@ aac_pci_attach(device_t dev)
/*
- * Check for quirky hardware
- */
- if (pci_get_subdevice(dev) == 0x1364 &&
- pci_get_subvendor(dev) == 0x9005)
- sc->quirks |= AAC_QUIRK_PERC2QC;
-
- /*
* Do bus-independent initialisation.
*/
error = aac_attach(sc);
diff --git a/sys/dev/aac/aacreg.h b/sys/dev/aac/aacreg.h
index 2a954df..c360ba2 100644
--- a/sys/dev/aac/aacreg.h
+++ b/sys/dev/aac/aacreg.h
@@ -1002,6 +1002,105 @@ struct aac_closecommand {
} __attribute__ ((packed));
/*
+ * Container Config Command
+ */
+#define CT_GET_SCSI_METHOD 64
+struct aac_ctcfg {
+ AAC_VMCommand Command;
+ u_int32_t cmd;
+ u_int32_t param;
+} __attribute__ ((packed));
+
+struct aac_ctcfg_resp {
+ AAC_FSAStatus Status;
+ u_int32_t resp;
+ u_int32_t param;
+} __attribute__ ((packed));
+
+/*
+ * 'Ioctl' commads
+ */
+#define AAC_SCSI_MAX_PORTS 10
+#define AAC_BUS_NO_EXIST 0
+#define AAC_BUS_VALID 1
+#define AAC_BUS_FAULTED 2
+#define AAC_BUS_DISABLED 3
+#define GetBusInfo 0x9
+
+struct aac_getbusinf {
+ u_int32_t ProbeComplete;
+ u_int32_t BusCount;
+ u_int32_t TargetsPerBus;
+ u_int8_t InitiatorBusId[AAC_SCSI_MAX_PORTS];
+ u_int8_t BusValid[AAC_SCSI_MAX_PORTS];
+} __attribute__ ((packed));
+
+struct aac_vmioctl {
+ AAC_VMCommand Command;
+ AAC_FType ObjType;
+ u_int32_t MethId;
+ u_int32_t ObjId;
+ u_int32_t IoctlCmd;
+ u_int32_t IoctlBuf[1]; /* Placeholder? */
+} __attribute__ ((packed));
+
+struct aac_vmi_businf_resp {
+ AAC_FSAStatus Status;
+ AAC_FType ObjType;
+ u_int32_t MethId;
+ u_int32_t ObjId;
+ u_int32_t IoctlCmd;
+ struct aac_getbusinf BusInf;
+} __attribute__ ((packed));
+
+#define AAC_BTL_TO_HANDLE(b, t, l) \
+ (((b & 0x3f) << 7) | ((l & 0x7) << 4) | (t & 0xf))
+#define GetDeviceProbeInfo 0x5
+
+struct aac_vmi_devinfo_resp {
+ AAC_FSAStatus Status;
+ AAC_FType ObjType;
+ u_int32_t MethId;
+ u_int32_t ObjId;
+ u_int32_t IoctlCmd;
+ u_int8_t VendorId[8];
+ u_int8_t ProductId[16];
+ u_int8_t ProductRev[4];
+ u_int32_t Inquiry7;
+ u_int32_t align1;
+ u_int32_t Inquiry0;
+ u_int32_t align2;
+ u_int32_t Inquiry1;
+ u_int32_t align3;
+ u_int32_t reserved[2];
+ u_int8_t VendorSpecific[20];
+ u_int32_t Smart:1;
+ u_int32_t AAC_Managed:1;
+ u_int32_t align4;
+ u_int32_t reserved2:6;
+ u_int32_t Bus;
+ u_int32_t Target;
+ u_int32_t Lun;
+ u_int32_t ultraEnable:1,
+ disconnectEnable:1,
+ fast20EnabledW:1,
+ scamDevice:1,
+ scamTolerant:1,
+ setForSync:1,
+ setForWide:1,
+ syncDevice:1,
+ wideDevice:1,
+ reserved1:7,
+ ScsiRate:8,
+ ScsiOffset:8;
+}; /* Do not pack */
+
+#define ResetBus 0x16
+struct aac_resetbus {
+ u_int32_t BusNumber;
+};
+
+/*
* Write 'stability' options.
*/
typedef enum {
@@ -1062,6 +1161,93 @@ struct aac_close_command {
};
/*
+ * SCSI Passthrough structures
+ */
+struct aac_srb32 {
+ u_int32_t function;
+ u_int32_t bus;
+ u_int32_t target;
+ u_int32_t lun;
+ u_int32_t timeout;
+ u_int32_t flags;
+ u_int32_t data_len;
+ u_int32_t retry_limit;
+ u_int32_t cdb_len;
+ u_int8_t cdb[16];
+ struct aac_sg_table sg_map32;
+};
+
+enum {
+ AAC_SRB_FUNC_EXECUTE_SCSI = 0x00,
+ AAC_SRB_FUNC_CLAIM_DEVICE,
+ AAC_SRB_FUNC_IO_CONTROL,
+ AAC_SRB_FUNC_RECEIVE_EVENT,
+ AAC_SRB_FUNC_RELEASE_QUEUE,
+ AAC_SRB_FUNC_ATTACH_DEVICE,
+ AAC_SRB_FUNC_RELEASE_DEVICE,
+ AAC_SRB_FUNC_SHUTDOWN,
+ AAC_SRB_FUNC_FLUSH,
+ AAC_SRB_FUNC_ABORT_COMMAND = 0x10,
+ AAC_SRB_FUNC_RELEASE_RECOVERY,
+ AAC_SRB_FUNC_RESET_BUS,
+ AAC_SRB_FUNC_RESET_DEVICE,
+ AAC_SRB_FUNC_TERMINATE_IO,
+ AAC_SRB_FUNC_FLUSH_QUEUE,
+ AAC_SRB_FUNC_REMOVE_DEVICE,
+ AAC_SRB_FUNC_DOMAIN_VALIDATION
+};
+
+#define AAC_SRB_FLAGS_NO_DATA_XFER 0x0000
+#define AAC_SRB_FLAGS_DISABLE_DISCONNECT 0x0004
+#define AAC_SRB_FLAGS_DISABLE_SYNC_TRANSFER 0x0008
+#define AAC_SRB_FLAGS_BYPASS_FROZEN_QUEUE 0x0010
+#define AAC_SRB_FLAGS_DISABLE_AUTOSENSE 0x0020
+#define AAC_SRB_FLAGS_DATA_IN 0x0040
+#define AAC_SRB_FLAGS_DATA_OUT 0x0080
+#define AAC_SRB_FLAGS_UNSPECIFIED_DIRECTION \
+ (AAC_SRB_FLAGS_DATA_IN | AAC_SRB_FLAGS_DATA_OUT)
+
+#define AAC_HOST_SENSE_DATA_MAX 30
+
+struct aac_srb_response {
+ u_int32_t fib_status;
+ u_int32_t srb_status;
+ u_int32_t scsi_status;
+ u_int32_t data_len;
+ u_int32_t sense_len;
+ u_int8_t sense[AAC_HOST_SENSE_DATA_MAX];
+};
+
+enum {
+ AAC_SRB_STS_PENDING = 0x00,
+ AAC_SRB_STS_SUCCESS,
+ AAC_SRB_STS_ABORTED,
+ AAC_SRB_STS_ABORT_FAILED,
+ AAC_SRB_STS_ERROR,
+ AAC_SRB_STS_BUSY,
+ AAC_SRB_STS_INVALID_REQUEST,
+ AAC_SRB_STS_INVALID_PATH_ID,
+ AAC_SRB_STS_NO_DEVICE,
+ AAC_SRB_STS_TIMEOUT,
+ AAC_SRB_STS_SELECTION_TIMEOUT,
+ AAC_SRB_STS_COMMAND_TIMEOUT,
+ AAC_SRB_STS_MESSAGE_REJECTED = 0x0D,
+ AAC_SRB_STS_BUS_RESET,
+ AAC_SRB_STS_PARITY_ERROR,
+ AAC_SRB_STS_REQUEST_SENSE_FAILED,
+ AAC_SRB_STS_NO_HBA,
+ AAC_SRB_STS_DATA_OVERRUN,
+ AAC_SRB_STS_UNEXPECTED_BUS_FREE,
+ AAC_SRB_STS_PHASE_SEQUENCE_FAILURE,
+ AAC_SRB_STS_BAD_SRB_BLOCK_LENGTH,
+ AAC_SRB_STS_REQUEST_FLUSHED,
+ AAC_SRB_STS_INVALID_LUN = 0x20,
+ AAC_SRB_STS_INVALID_TARGET_ID,
+ AAC_SRB_STS_BAD_FUNCTION,
+ AAC_SRB_STS_ERROR_RECOVERY
+};
+
+/*
* Register set for adapters based on the Falcon bridge and PPC core
*/
diff --git a/sys/dev/aac/aacvar.h b/sys/dev/aac/aacvar.h
index e4b870e..30d5535 100644
--- a/sys/dev/aac/aacvar.h
+++ b/sys/dev/aac/aacvar.h
@@ -362,6 +362,11 @@ struct aac_softc
#define AAC_AIFFLAGS_EXITED (1 << 3)
u_int32_t quirks;
#define AAC_QUIRK_PERC2QC (1 << 0)
+#define AAC_QUIRK_NOCAM (1 << 1) /* No SCSI passthrough */
+#define AAC_QUIRK_CAM_NORESET (1 << 2) /* Fake SCSI resets */
+#define AAC_QUIRK_CAM_PASSONLY (1 << 3) /* Only create pass devices */
+
+ u_int32_t scsi_method_id;
};
@@ -377,7 +382,11 @@ extern int aac_resume(device_t dev);
extern void aac_intr(void *arg);
extern void aac_submit_bio(struct bio *bp);
extern void aac_biodone(struct bio *bp);
-extern int aac_get_sync_fib(struct aac_softc *sc,
+extern void aac_startio(struct aac_softc *sc);
+extern int aac_alloc_command(struct aac_softc *sc,
+ struct aac_command **cmp);
+extern void aac_release_command(struct aac_command *cm);
+extern int aac_alloc_sync_fib(struct aac_softc *sc,
struct aac_fib **fib, int flags);
extern void aac_release_sync_fib(struct aac_softc *sc);
extern int aac_sync_fib(struct aac_softc *sc, u_int32_t command,
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index 6a2eafd..15a2b17 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -115,6 +115,7 @@ device ses # SCSI Environmental Services (and SAF-TE)
# RAID controllers
device aac # Adaptec FSA RAID
+device aacp # SCSI passthrough for aac (requires CAM)
device amr # AMI MegaRAID
device ida # Compaq Smart RAID
device mlx # Mylex DAC960 family
diff --git a/sys/modules/aac/Makefile b/sys/modules/aac/Makefile
index 08409e0..7e1a351 100644
--- a/sys/modules/aac/Makefile
+++ b/sys/modules/aac/Makefile
@@ -3,7 +3,8 @@
.PATH: ${.CURDIR}/../../dev/aac
KMOD= aac
-SRCS= aac.c aac_pci.c aac_disk.c opt_aac.h
+SRCS= aac.c aac_pci.c aac_disk.c aac_cam.c
+SRCS+= opt_scsi.h opt_cam.h opt_aac.h
SRCS+= device_if.h bus_if.h pci_if.h
CFLAGS+= -DAAC_COMPAT_LINUX
OpenPOWER on IntegriCloud