diff options
-rw-r--r-- | sys/amd64/conf/GENERIC | 1 | ||||
-rw-r--r-- | sys/conf/NOTES | 1 | ||||
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/dev/aac/aac.c | 137 | ||||
-rw-r--r-- | sys/dev/aac/aac_cam.c | 591 | ||||
-rw-r--r-- | sys/dev/aac/aac_cam.h | 34 | ||||
-rw-r--r-- | sys/dev/aac/aac_disk.c | 2 | ||||
-rw-r--r-- | sys/dev/aac/aac_pci.c | 69 | ||||
-rw-r--r-- | sys/dev/aac/aacreg.h | 186 | ||||
-rw-r--r-- | sys/dev/aac/aacvar.h | 11 | ||||
-rw-r--r-- | sys/i386/conf/GENERIC | 1 | ||||
-rw-r--r-- | sys/modules/aac/Makefile | 3 |
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 |