diff options
Diffstat (limited to 'sys/dev/mpt/mpt_freebsd.c')
-rw-r--r-- | sys/dev/mpt/mpt_freebsd.c | 1530 |
1 files changed, 0 insertions, 1530 deletions
diff --git a/sys/dev/mpt/mpt_freebsd.c b/sys/dev/mpt/mpt_freebsd.c deleted file mode 100644 index d7bb430..0000000 --- a/sys/dev/mpt/mpt_freebsd.c +++ /dev/null @@ -1,1530 +0,0 @@ -/*- - * FreeBSD/CAM specific routines for LSI '909 FC adapters. - * FreeBSD Version. - * - * Copyright (c) 2000, 2001 by Greg Ansley - * - * 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 immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * 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. - */ -/* - * Additional Copyright (c) 2002 by Matthew Jacob under same license. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <dev/mpt/mpt_freebsd.h> - -static void mpt_poll(struct cam_sim *); -static timeout_t mpttimeout; -static timeout_t mpttimeout2; -static void mpt_action(struct cam_sim *, union ccb *); -static int mpt_setwidth(mpt_softc_t *, int, int); -static int mpt_setsync(mpt_softc_t *, int, int, int); - -void -mpt_cam_attach(mpt_softc_t *mpt) -{ - struct cam_devq *devq; - struct cam_sim *sim; - int maxq; - - mpt->bus = 0; - maxq = (mpt->mpt_global_credits < MPT_MAX_REQUESTS(mpt))? - mpt->mpt_global_credits : MPT_MAX_REQUESTS(mpt); - - - /* - * Create the device queue for our SIM(s). - */ - - devq = cam_simq_alloc(maxq); - if (devq == NULL) { - return; - } - - /* - * Construct our SIM entry. - */ - sim = cam_sim_alloc(mpt_action, mpt_poll, "mpt", mpt, - mpt->unit, 1, maxq, devq); - if (sim == NULL) { - cam_simq_free(devq); - return; - } - - /* - * Register exactly the bus. - */ - - if (xpt_bus_register(sim, 0) != CAM_SUCCESS) { - cam_sim_free(sim, TRUE); - return; - } - - if (xpt_create_path(&mpt->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; - } - mpt->sim = sim; -} - -void -mpt_cam_detach(mpt_softc_t *mpt) -{ - if (mpt->sim != NULL) { - xpt_free_path(mpt->path); - xpt_bus_deregister(cam_sim_path(mpt->sim)); - cam_sim_free(mpt->sim, TRUE); - mpt->sim = NULL; - } -} - -/* This routine is used after a system crash to dump core onto the - * swap device. - */ -static void -mpt_poll(struct cam_sim *sim) -{ - mpt_softc_t *mpt = (mpt_softc_t *) cam_sim_softc(sim); - MPT_LOCK(mpt); - mpt_intr(mpt); - MPT_UNLOCK(mpt); -} - -/* - * This routine is called if the 9x9 does not return completion status - * for a command after a CAM specified time. - */ -static void -mpttimeout(void *arg) -{ - request_t *req; - union ccb *ccb = arg; - u_int32_t oseq; - mpt_softc_t *mpt; - - mpt = ccb->ccb_h.ccb_mpt_ptr; - MPT_LOCK(mpt); - req = ccb->ccb_h.ccb_req_ptr; - oseq = req->sequence; - mpt->timeouts++; - if (mpt_intr(mpt)) { - if (req->sequence != oseq) { - mpt_prt(mpt, "bullet missed in timeout"); - MPT_UNLOCK(mpt); - return; - } - mpt_prt(mpt, "bullet U-turned in timeout: got us"); - } - mpt_prt(mpt, - "time out on request index = 0x%02x sequence = 0x%08x", - req->index, req->sequence); - mpt_check_doorbell(mpt); - mpt_prt(mpt, "Status %08x; Mask %08x; Doorbell %08x", - mpt_read(mpt, MPT_OFFSET_INTR_STATUS), - mpt_read(mpt, MPT_OFFSET_INTR_MASK), - mpt_read(mpt, MPT_OFFSET_DOORBELL) ); - printf("request state %s\n", mpt_req_state(req->debug)); - if (ccb != req->ccb) { - printf("time out: ccb %p != req->ccb %p\n", - ccb,req->ccb); - } - mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf); - req->debug = REQ_TIMEOUT; - req->ccb = NULL; - req->link.sle_next = (void *) mpt; - (void) timeout(mpttimeout2, (caddr_t)req, hz / 10); - ccb->ccb_h.status = CAM_CMD_TIMEOUT; - ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - mpt->outofbeer = 0; - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - CAMLOCK_2_MPTLOCK(mpt); - MPT_UNLOCK(mpt); -} - -static void -mpttimeout2(void *arg) -{ - request_t *req = arg; - if (req->debug == REQ_TIMEOUT) { - mpt_softc_t *mpt = (mpt_softc_t *) req->link.sle_next; - MPT_LOCK(mpt); - mpt_free_request(mpt, req); - MPT_UNLOCK(mpt); - } -} - -/* - * Callback routine from "bus_dmamap_load" or in simple case called directly. - * - * Takes a list of physical segments and builds the SGL for SCSI IO command - * and forwards the commard to the IOC after one last check that CAM has not - * aborted the transaction. - */ -static void -mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) -{ - request_t *req; - union ccb *ccb; - mpt_softc_t *mpt; - MSG_SCSI_IO_REQUEST *mpt_req; - SGE_SIMPLE32 *se; - - req = (request_t *)arg; - ccb = req->ccb; - - mpt = ccb->ccb_h.ccb_mpt_ptr; - req = ccb->ccb_h.ccb_req_ptr; - mpt_req = req->req_vbuf; - - if (error == 0 && nseg > MPT_SGL_MAX) { - error = EFBIG; - } - - if (error != 0) { - if (error != EFBIG) - mpt_prt(mpt, "bus_dmamap_load returned %d", error); - if (ccb->ccb_h.status == CAM_REQ_INPROG) { - xpt_freeze_devq(ccb->ccb_h.path, 1); - ccb->ccb_h.status = CAM_DEV_QFRZN; - if (error == EFBIG) - ccb->ccb_h.status |= CAM_REQ_TOO_BIG; - else - ccb->ccb_h.status |= CAM_REQ_CMP_ERR; - } - ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - xpt_done(ccb); - CAMLOCK_2_MPTLOCK(mpt); - mpt_free_request(mpt, req); - MPTLOCK_2_CAMLOCK(mpt); - return; - } - - if (nseg > MPT_NSGL_FIRST(mpt)) { - int i, nleft = nseg; - u_int32_t flags; - bus_dmasync_op_t op; - SGE_CHAIN32 *ce; - - mpt_req->DataLength = ccb->csio.dxfer_len; - flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT; - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) - flags |= MPI_SGE_FLAGS_HOST_TO_IOC; - - se = (SGE_SIMPLE32 *) &mpt_req->SGL; - for (i = 0; i < MPT_NSGL_FIRST(mpt) - 1; i++, se++, dm_segs++) { - u_int32_t tf; - - bzero(se, sizeof (*se)); - se->Address = dm_segs->ds_addr; - MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len); - tf = flags; - if (i == MPT_NSGL_FIRST(mpt) - 2) { - tf |= MPI_SGE_FLAGS_LAST_ELEMENT; - } - MPI_pSGE_SET_FLAGS(se, tf); - nleft -= 1; - } - - /* - * Tell the IOC where to find the first chain element - */ - mpt_req->ChainOffset = ((char *)se - (char *)mpt_req) >> 2; - - /* - * Until we're finished with all segments... - */ - while (nleft) { - int ntodo; - /* - * Construct the chain element that point to the - * next segment. - */ - ce = (SGE_CHAIN32 *) se++; - if (nleft > MPT_NSGL(mpt)) { - ntodo = MPT_NSGL(mpt) - 1; - ce->NextChainOffset = (MPT_RQSL(mpt) - - sizeof (SGE_SIMPLE32)) >> 2; - ce->Length = MPT_NSGL(mpt) * - sizeof (SGE_SIMPLE32); - } else { - ntodo = nleft; - ce->NextChainOffset = 0; - ce->Length = ntodo * sizeof (SGE_SIMPLE32); - } - ce->Address = req->req_pbuf + - ((char *)se - (char *)mpt_req); - ce->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT; - for (i = 0; i < ntodo; i++, se++, dm_segs++) { - u_int32_t tf; - - bzero(se, sizeof (*se)); - se->Address = dm_segs->ds_addr; - MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len); - tf = flags; - if (i == ntodo - 1) { - tf |= MPI_SGE_FLAGS_LAST_ELEMENT; - if (ce->NextChainOffset == 0) { - tf |= - MPI_SGE_FLAGS_END_OF_LIST | - MPI_SGE_FLAGS_END_OF_BUFFER; - } - } - MPI_pSGE_SET_FLAGS(se, tf); - nleft -= 1; - } - - } - - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) - op = BUS_DMASYNC_PREREAD; - else - op = BUS_DMASYNC_PREWRITE; - if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) { - bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op); - } - } else if (nseg > 0) { - int i; - u_int32_t flags; - bus_dmasync_op_t op; - - mpt_req->DataLength = ccb->csio.dxfer_len; - flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT; - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) - flags |= MPI_SGE_FLAGS_HOST_TO_IOC; - - /* Copy the segments into our SG list */ - se = (SGE_SIMPLE32 *) &mpt_req->SGL; - for (i = 0; i < nseg; i++, se++, dm_segs++) { - u_int32_t tf; - - bzero(se, sizeof (*se)); - se->Address = dm_segs->ds_addr; - MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len); - tf = flags; - if (i == nseg - 1) { - tf |= - MPI_SGE_FLAGS_LAST_ELEMENT | - MPI_SGE_FLAGS_END_OF_BUFFER | - MPI_SGE_FLAGS_END_OF_LIST; - } - MPI_pSGE_SET_FLAGS(se, tf); - } - - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) - op = BUS_DMASYNC_PREREAD; - else - op = BUS_DMASYNC_PREWRITE; - if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) { - bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op); - } - } else { - se = (SGE_SIMPLE32 *) &mpt_req->SGL; - /* - * No data to transfer so we just make a single simple SGL - * with zero length. - */ - MPI_pSGE_SET_FLAGS(se, - (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | - MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST)); - } - - /* - * Last time we need to check if this CCB needs to be aborted. - */ - if (ccb->ccb_h.status != CAM_REQ_INPROG) { - if (nseg && (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) - bus_dmamap_unload(mpt->buffer_dmat, req->dmap); - CAMLOCK_2_MPTLOCK(mpt); - mpt_free_request(mpt, req); - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - return; - } - - ccb->ccb_h.status |= CAM_SIM_QUEUED; - MPTLOCK_2_CAMLOCK(mpt); - if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { - ccb->ccb_h.timeout_ch = - timeout(mpttimeout, (caddr_t)ccb, - (ccb->ccb_h.timeout * hz) / 1000); - } else { - callout_handle_init(&ccb->ccb_h.timeout_ch); - } - if (mpt->verbose > 1) - mpt_print_scsi_io_request(mpt_req); - mpt_send_cmd(mpt, req); - MPTLOCK_2_CAMLOCK(mpt); -} - -static void -mpt_start(union ccb *ccb) -{ - request_t *req; - struct mpt_softc *mpt; - MSG_SCSI_IO_REQUEST *mpt_req; - struct ccb_scsiio *csio = &ccb->csio; - struct ccb_hdr *ccbh = &ccb->ccb_h; - - /* Get the pointer for the physical addapter */ - mpt = ccb->ccb_h.ccb_mpt_ptr; - - CAMLOCK_2_MPTLOCK(mpt); - /* Get a request structure off the free list */ - if ((req = mpt_get_request(mpt)) == NULL) { - if (mpt->outofbeer == 0) { - mpt->outofbeer = 1; - xpt_freeze_simq(mpt->sim, 1); - if (mpt->verbose > 1) { - mpt_prt(mpt, "FREEZEQ"); - } - } - MPTLOCK_2_CAMLOCK(mpt); - ccb->ccb_h.status = CAM_REQUEUE_REQ; - xpt_done(ccb); - return; - } - MPTLOCK_2_CAMLOCK(mpt); - - /* Link the ccb and the request structure so we can find */ - /* the other knowing either the request or the ccb */ - req->ccb = ccb; - ccb->ccb_h.ccb_req_ptr = req; - - /* Now we build the command for the IOC */ - mpt_req = req->req_vbuf; - bzero(mpt_req, sizeof *mpt_req); - - mpt_req->Function = MPI_FUNCTION_SCSI_IO_REQUEST; - mpt_req->Bus = mpt->bus; - - mpt_req->SenseBufferLength = - (csio->sense_len < MPT_SENSE_SIZE) ? - csio->sense_len : MPT_SENSE_SIZE; - - /* We use the message context to find the request structure when we */ - /* Get the command competion interrupt from the FC IOC. */ - mpt_req->MsgContext = req->index; - - /* Which physical device to do the I/O on */ - mpt_req->TargetID = ccb->ccb_h.target_id; - mpt_req->LUN[1] = ccb->ccb_h.target_lun; - - /* Set the direction of the transfer */ - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) - mpt_req->Control = MPI_SCSIIO_CONTROL_READ; - else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) - mpt_req->Control = MPI_SCSIIO_CONTROL_WRITE; - else - mpt_req->Control = MPI_SCSIIO_CONTROL_NODATATRANSFER; - - if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) { - switch(ccb->csio.tag_action) { - case MSG_HEAD_OF_Q_TAG: - mpt_req->Control |= MPI_SCSIIO_CONTROL_HEADOFQ; - break; - case MSG_ACA_TASK: - mpt_req->Control |= MPI_SCSIIO_CONTROL_ACAQ; - break; - case MSG_ORDERED_Q_TAG: - mpt_req->Control |= MPI_SCSIIO_CONTROL_ORDEREDQ; - break; - case MSG_SIMPLE_Q_TAG: - default: - mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ; - break; - } - } else { - if (mpt->is_fc) - mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ; - else - mpt_req->Control |= MPI_SCSIIO_CONTROL_UNTAGGED; - } - - if (mpt->is_fc == 0) { - if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) { - mpt_req->Control |= MPI_SCSIIO_CONTROL_NO_DISCONNECT; - } - } - - /* Copy the scsi command block into place */ - if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) - bcopy(csio->cdb_io.cdb_ptr, mpt_req->CDB, csio->cdb_len); - else - bcopy(csio->cdb_io.cdb_bytes, mpt_req->CDB, csio->cdb_len); - - mpt_req->CDBLength = csio->cdb_len; - mpt_req->DataLength = csio->dxfer_len; - mpt_req->SenseBufferLowAddr = req->sense_pbuf; - - /* - * If we have any data to send with this command, - * map it into bus space. - */ - - if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { - /* - * We've been given a pointer to a single buffer. - */ - if ((ccbh->flags & CAM_DATA_PHYS) == 0) { - /* - * Virtual address that needs to translated into - * one or more physical pages. - */ - int error; - - error = bus_dmamap_load(mpt->buffer_dmat, - req->dmap, csio->data_ptr, csio->dxfer_len, - mpt_execute_req, req, 0); - if (error == EINPROGRESS) { - /* - * So as to maintain ordering, - * freeze the controller queue - * until our mapping is - * returned. - */ - xpt_freeze_simq(mpt->sim, 1); - ccbh->status |= CAM_RELEASE_SIMQ; - } - } else { - /* - * We have been given a pointer to single - * physical buffer. - */ - struct bus_dma_segment seg; - seg.ds_addr = - (bus_addr_t)(vm_offset_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - mpt_execute_req(req, &seg, 1, 0); - } - } else { - /* - * We have been given a list of addresses. - * These case could be easily done but they are not - * currently generated by the CAM subsystem so there - * is no point in wasting the time right now. - */ - struct bus_dma_segment *segs; - if ((ccbh->flags & CAM_SG_LIST_PHYS) == 0) { - mpt_execute_req(req, NULL, 0, EFAULT); - } else { - /* Just use the segments provided */ - segs = (struct bus_dma_segment *)csio->data_ptr; - mpt_execute_req(req, segs, csio->sglist_cnt, - (csio->sglist_cnt < MPT_SGL_MAX)? - 0 : EFBIG); - } - } - } else { - mpt_execute_req(req, NULL, 0, 0); - } -} - -static int -mpt_bus_reset(union ccb *ccb) -{ - int error; - request_t *req; - mpt_softc_t *mpt; - MSG_SCSI_TASK_MGMT *reset_req; - - /* Get the pointer for the physical adapter */ - mpt = ccb->ccb_h.ccb_mpt_ptr; - - /* Get a request structure off the free list */ - if ((req = mpt_get_request(mpt)) == NULL) { - return (CAM_REQUEUE_REQ); - } - - /* Link the ccb and the request structure so we can find */ - /* the other knowing either the request or the ccb */ - req->ccb = ccb; - ccb->ccb_h.ccb_req_ptr = req; - - reset_req = req->req_vbuf; - bzero(reset_req, sizeof *reset_req); - - reset_req->Function = MPI_FUNCTION_SCSI_TASK_MGMT; - reset_req->MsgContext = req->index; - reset_req->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; - if (mpt->is_fc) { - /* - * Should really be TARGET_RESET_OPTION - */ - reset_req->MsgFlags = - MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION; - } - /* Which physical device Reset */ - reset_req->TargetID = ccb->ccb_h.target_id; - reset_req->LUN[1] = ccb->ccb_h.target_lun; - - ccb->ccb_h.status |= CAM_SIM_QUEUED; - - error = mpt_send_handshake_cmd(mpt, - sizeof (MSG_SCSI_TASK_MGMT), reset_req); - if (error) { - mpt_prt(mpt, - "mpt_bus_reset: mpt_send_handshake return %d", error); - return (CAM_REQ_CMP_ERR); - } else { - return (CAM_REQ_CMP); - } -} - -/* - * Process an asynchronous event from the IOC. - */ -static void mpt_ctlop(mpt_softc_t *, void *, u_int32_t); -static void mpt_event_notify_reply(mpt_softc_t *mpt, MSG_EVENT_NOTIFY_REPLY *); - -static void -mpt_ctlop(mpt_softc_t *mpt, void *vmsg, u_int32_t reply) -{ - MSG_DEFAULT_REPLY *dmsg = vmsg; - - if (dmsg->Function == MPI_FUNCTION_EVENT_NOTIFICATION) { - mpt_event_notify_reply(mpt, vmsg); - mpt_free_reply(mpt, (reply << 1)); - } else if (dmsg->Function == MPI_FUNCTION_EVENT_ACK) { - mpt_free_reply(mpt, (reply << 1)); - } else if (dmsg->Function == MPI_FUNCTION_PORT_ENABLE) { - MSG_PORT_ENABLE_REPLY *msg = vmsg; - int index = msg->MsgContext & ~0x80000000; - if (mpt->verbose > 1) { - mpt_prt(mpt, "enable port reply idx %d", index); - } - if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) { - request_t *req = &mpt->request_pool[index]; - req->debug = REQ_DONE; - } - mpt_free_reply(mpt, (reply << 1)); - } else if (dmsg->Function == MPI_FUNCTION_CONFIG) { - MSG_CONFIG_REPLY *msg = vmsg; - int index = msg->MsgContext & ~0x80000000; - if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) { - request_t *req = &mpt->request_pool[index]; - req->debug = REQ_DONE; - req->sequence = reply; - } else { - mpt_free_reply(mpt, (reply << 1)); - } - } else { - mpt_prt(mpt, "unknown mpt_ctlop: %x", dmsg->Function); - } -} - -static void -mpt_event_notify_reply(mpt_softc_t *mpt, MSG_EVENT_NOTIFY_REPLY *msg) -{ - switch(msg->Event) { - case MPI_EVENT_LOG_DATA: - /* Some error occured that LSI wants logged */ - printf("\tEvtLogData: IOCLogInfo: 0x%08x\n", msg->IOCLogInfo); - printf("\tEvtLogData: Event Data:"); - { - int i; - for (i = 0; i < msg->EventDataLength; i++) { - printf(" %08x", msg->Data[i]); - } - } - printf("\n"); - break; - - case MPI_EVENT_UNIT_ATTENTION: - mpt_prt(mpt, "Bus: 0x%02x TargetID: 0x%02x", - (msg->Data[0] >> 8) & 0xff, msg->Data[0] & 0xff); - break; - - case MPI_EVENT_IOC_BUS_RESET: - /* We generated a bus reset */ - mpt_prt(mpt, "IOC Bus Reset Port: %d", - (msg->Data[0] >> 8) & 0xff); - break; - - case MPI_EVENT_EXT_BUS_RESET: - /* Someone else generated a bus reset */ - mpt_prt(mpt, "Ext Bus Reset"); - /* - * These replies don't return EventData like the MPI - * spec says they do - */ -/* xpt_async(AC_BUS_RESET, path, NULL); */ - break; - - case MPI_EVENT_RESCAN: - /* - * In general this means a device has been added - * to the loop. - */ - mpt_prt(mpt, "Rescan Port: %d", (msg->Data[0] >> 8) & 0xff); -/* xpt_async(AC_FOUND_DEVICE, path, NULL); */ - break; - - case MPI_EVENT_LINK_STATUS_CHANGE: - mpt_prt(mpt, "Port %d: LinkState: %s", - (msg->Data[1] >> 8) & 0xff, - ((msg->Data[0] & 0xff) == 0)? "Failed" : "Active"); - break; - - case MPI_EVENT_LOOP_STATE_CHANGE: - switch ((msg->Data[0] >> 16) & 0xff) { - case 0x01: - mpt_prt(mpt, - "Port 0x%x: FC LinkEvent: LIP(%02x,%02x) (Loop Initialization)\n", - (msg->Data[1] >> 8) & 0xff, - (msg->Data[0] >> 8) & 0xff, - (msg->Data[0] ) & 0xff); - switch ((msg->Data[0] >> 8) & 0xff) { - case 0xF7: - if ((msg->Data[0] & 0xff) == 0xF7) { - printf("Device needs AL_PA\n"); - } else { - printf("Device %02x doesn't like FC performance\n", - msg->Data[0] & 0xFF); - } - break; - case 0xF8: - if ((msg->Data[0] & 0xff) == 0xF7) { - printf("Device had loop failure at its receiver prior to acquiring AL_PA\n"); - } else { - printf("Device %02x detected loop failure at its receiver\n", - msg->Data[0] & 0xFF); - } - break; - default: - printf("Device %02x requests that device %02x reset itself\n", - msg->Data[0] & 0xFF, - (msg->Data[0] >> 8) & 0xFF); - break; - } - break; - case 0x02: - mpt_prt(mpt, "Port 0x%x: FC LinkEvent: LPE(%02x,%02x) (Loop Port Enable)", - (msg->Data[1] >> 8) & 0xff, /* Port */ - (msg->Data[0] >> 8) & 0xff, /* Character 3 */ - (msg->Data[0] ) & 0xff /* Character 4 */ - ); - break; - case 0x03: - mpt_prt(mpt, "Port 0x%x: FC LinkEvent: LPB(%02x,%02x) (Loop Port Bypass)", - (msg->Data[1] >> 8) & 0xff, /* Port */ - (msg->Data[0] >> 8) & 0xff, /* Character 3 */ - (msg->Data[0] ) & 0xff /* Character 4 */ - ); - break; - default: - mpt_prt(mpt, "Port 0x%x: FC LinkEvent: Unknown FC event (%02x %02x %02x)", - (msg->Data[1] >> 8) & 0xff, /* Port */ - (msg->Data[0] >> 16) & 0xff, /* Event */ - (msg->Data[0] >> 8) & 0xff, /* Character 3 */ - (msg->Data[0] ) & 0xff /* Character 4 */ - ); - } - break; - - case MPI_EVENT_LOGOUT: - mpt_prt(mpt, "FC Logout Port: %d N_PortID: %02x", - (msg->Data[1] >> 8) & 0xff, msg->Data[0]); - break; - case MPI_EVENT_EVENT_CHANGE: - /* This is just an acknowledgement of our - mpt_send_event_request */ - break; - default: - mpt_prt(mpt, "Unknown event 0x%x\n", msg->Event); - } - if (msg->AckRequired) { - MSG_EVENT_ACK *ackp; - request_t *req; - if ((req = mpt_get_request(mpt)) == NULL) { - panic("unable to get request to acknowledge notify"); - } - ackp = (MSG_EVENT_ACK *) req->req_vbuf; - bzero(ackp, sizeof *ackp); - ackp->Function = MPI_FUNCTION_EVENT_ACK; - ackp->Event = msg->Event; - ackp->EventContext = msg->EventContext; - ackp->MsgContext = req->index | 0x80000000; - mpt_check_doorbell(mpt); - mpt_send_cmd(mpt, req); - } -} - -void -mpt_done(mpt_softc_t *mpt, u_int32_t reply) -{ - int index; - request_t *req; - union ccb *ccb; - MSG_REQUEST_HEADER *mpt_req; - MSG_SCSI_IO_REPLY *mpt_reply; - - index = -1; /* Shutup the complier */ - - if ((reply & MPT_CONTEXT_REPLY) == 0) { - /* context reply */ - mpt_reply = NULL; - index = reply & MPT_CONTEXT_MASK; - } else { - unsigned *pReply; - - bus_dmamap_sync(mpt->reply_dmat, mpt->reply_dmap, - BUS_DMASYNC_POSTREAD); - /* address reply (Error) */ - mpt_reply = MPT_REPLY_PTOV(mpt, reply); - if (mpt->verbose > 1) { - pReply = (unsigned *) mpt_reply; - mpt_prt(mpt, "Address Reply (index %u)", - mpt_reply->MsgContext & 0xffff); - printf("%08x %08x %08x %08x\n", - pReply[0], pReply[1], pReply[2], pReply[3]); - printf("%08x %08x %08x %08x\n", - pReply[4], pReply[5], pReply[6], pReply[7]); - printf("%08x %08x %08x %08x\n\n", - pReply[8], pReply[9], pReply[10], pReply[11]); - } - index = mpt_reply->MsgContext; - } - - /* - * Address reply with MessageContext high bit set - * This is most likely a notify message so we try - * to process it then free it - */ - if ((index & 0x80000000) != 0) { - if (mpt_reply != NULL) { - mpt_ctlop(mpt, mpt_reply, reply); - } else { - mpt_prt(mpt, "mpt_done: index 0x%x, NULL reply", index); - } - return; - } - - /* Did we end up with a valid index into the table? */ - if (index < 0 || index >= MPT_MAX_REQUESTS(mpt)) { - mpt_prt(mpt, "mpt_done: invalid index (%x) in reply", index); - return; - } - - req = &mpt->request_pool[index]; - - /* Make sure memory hasn't been trashed */ - if (req->index != index) { - printf("mpt_done: corrupted request struct"); - return; - } - - /* Short cut for task management replys; nothing more for us to do */ - mpt_req = req->req_vbuf; - if (mpt_req->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { - if (mpt->verbose > 1) { - mpt_prt(mpt, "mpt_done: TASK MGMT"); - } - goto done; - } - - if (mpt_req->Function == MPI_FUNCTION_PORT_ENABLE) { - goto done; - } - - /* - * At this point it better be a SCSI IO command, but don't - * crash if it isn't - */ - if (mpt_req->Function != MPI_FUNCTION_SCSI_IO_REQUEST) { - goto done; - } - - /* Recover the CAM control block from the request structure */ - ccb = req->ccb; - - /* Can't have had a SCSI command with out a CAM control block */ - if (ccb == NULL || (ccb->ccb_h.status & CAM_SIM_QUEUED) == 0) { - mpt_prt(mpt, - "mpt_done: corrupted ccb, index = 0x%02x seq = 0x%08x", - req->index, req->sequence); - printf(" request state %s\nmpt_request:\n", - mpt_req_state(req->debug)); - mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf); - - if (mpt_reply != NULL) { - printf("\nmpt_done: reply:\n"); - mpt_print_reply(MPT_REPLY_PTOV(mpt, reply)); - } else { - printf("\nmpt_done: context reply: 0x%08x\n", reply); - } - goto done; - } - - untimeout(mpttimeout, ccb, ccb->ccb_h.timeout_ch); - - if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - bus_dmasync_op_t op; - - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { - op = BUS_DMASYNC_POSTREAD; - } else { - op = BUS_DMASYNC_POSTWRITE; - } - bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op); - bus_dmamap_unload(mpt->buffer_dmat, req->dmap); - } - ccb->csio.resid = 0; - - if (mpt_reply == NULL) { - /* Context reply; report that the command was successfull */ - ccb->ccb_h.status = CAM_REQ_CMP; - ccb->csio.scsi_status = SCSI_STATUS_OK; - ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - if (mpt->outofbeer) { - ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - mpt->outofbeer = 0; - if (mpt->verbose > 1) { - mpt_prt(mpt, "THAWQ"); - } - } - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - CAMLOCK_2_MPTLOCK(mpt); - goto done; - } - - ccb->csio.scsi_status = mpt_reply->SCSIStatus; - switch(mpt_reply->IOCStatus) { - case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: - ccb->ccb_h.status = CAM_DATA_RUN_ERR; - break; - - case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: - /* - * Yikes, Tagged queue full comes through this path! - * - * So we'll change it to a status error and anything - * that returns status should probably be a status - * error as well. - */ - ccb->csio.resid = - ccb->csio.dxfer_len - mpt_reply->TransferCount; - if (mpt_reply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) { - ccb->ccb_h.status = CAM_DATA_RUN_ERR; - break; - } - /* Fall through */ - case MPI_IOCSTATUS_SUCCESS: - case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: - switch (ccb->csio.scsi_status) { - case SCSI_STATUS_OK: - ccb->ccb_h.status = CAM_REQ_CMP; - break; - default: - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; - break; - } - break; - case MPI_IOCSTATUS_BUSY: - case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: - ccb->ccb_h.status = CAM_BUSY; - break; - - case MPI_IOCSTATUS_SCSI_INVALID_BUS: - case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: - case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: - ccb->ccb_h.status = CAM_DEV_NOT_THERE; - break; - - case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: - ccb->ccb_h.status = CAM_DATA_RUN_ERR; - break; - - case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: - case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: - ccb->ccb_h.status = CAM_UNCOR_PARITY; - break; - - case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: - ccb->ccb_h.status = CAM_REQ_CMP; - break; - - case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: - ccb->ccb_h.status = CAM_UA_TERMIO; - break; - - case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: - ccb->ccb_h.status = CAM_REQ_TERMIO; - break; - - case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: - ccb->ccb_h.status = CAM_SCSI_BUS_RESET; - break; - - default: - ccb->ccb_h.status = CAM_UNREC_HBA_ERROR; - break; - } - - if ((mpt_reply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) != 0) { - if (ccb->ccb_h.flags & (CAM_SENSE_PHYS | CAM_SENSE_PTR)) { - ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL; - } else { - ccb->ccb_h.status |= CAM_AUTOSNS_VALID; - ccb->csio.sense_resid = mpt_reply->SenseCount; - bcopy(req->sense_vbuf, &ccb->csio.sense_data, - ccb->csio.sense_len); - } - } else if (mpt_reply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { - ccb->ccb_h.status &= ~CAM_STATUS_MASK; - ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL; - } - - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { - ccb->ccb_h.status |= CAM_DEV_QFRZN; - xpt_freeze_devq(ccb->ccb_h.path, 1); - } - } - - - ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - if (mpt->outofbeer) { - ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - mpt->outofbeer = 0; - if (mpt->verbose > 1) { - mpt_prt(mpt, "THAWQ"); - } - } - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - CAMLOCK_2_MPTLOCK(mpt); - -done: - /* If IOC done with this request free it up */ - if (mpt_reply == NULL || (mpt_reply->MsgFlags & 0x80) == 0) - mpt_free_request(mpt, req); - - /* If address reply; give the buffer back to the IOC */ - if (mpt_reply != NULL) - mpt_free_reply(mpt, (reply << 1)); -} - -static void -mpt_action(struct cam_sim *sim, union ccb *ccb) -{ - int tgt, error; - mpt_softc_t *mpt; - struct ccb_trans_settings *cts; - - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mpt_action\n")); - - mpt = (mpt_softc_t *)cam_sim_softc(sim); - - ccb->ccb_h.ccb_mpt_ptr = mpt; - - switch (ccb->ccb_h.func_code) { - case XPT_RESET_BUS: - if (mpt->verbose > 1) - mpt_prt(mpt, "XPT_RESET_BUS"); - CAMLOCK_2_MPTLOCK(mpt); - error = mpt_bus_reset(ccb); - switch (error) { - case CAM_REQ_INPROG: - MPTLOCK_2_CAMLOCK(mpt); - break; - case CAM_REQUEUE_REQ: - if (mpt->outofbeer == 0) { - mpt->outofbeer = 1; - xpt_freeze_simq(sim, 1); - if (mpt->verbose > 1) { - mpt_prt(mpt, "FREEZEQ"); - } - } - ccb->ccb_h.status = CAM_REQUEUE_REQ; - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - break; - - case CAM_REQ_CMP: - ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - ccb->ccb_h.status |= CAM_REQ_CMP; - if (mpt->outofbeer) { - ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - mpt->outofbeer = 0; - if (mpt->verbose > 1) { - mpt_prt(mpt, "THAWQ"); - } - } - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - break; - - default: - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - } - break; - - case XPT_SCSI_IO: /* Execute the requested I/O operation */ - /* - * Do a couple of preliminary checks... - */ - if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { - if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) { - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - } - } - /* Max supported CDB length is 16 bytes */ - if (ccb->csio.cdb_len > - sizeof (((PTR_MSG_SCSI_IO_REQUEST)0)->CDB)) { - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - return; - } - ccb->csio.scsi_status = SCSI_STATUS_OK; - mpt_start(ccb); - break; - - case XPT_ABORT: - /* - * XXX: Need to implement - */ - ccb->ccb_h.status = CAM_UA_ABORT; - xpt_done(ccb); - break; - -#ifdef CAM_NEW_TRAN_CODE -#define IS_CURRENT_SETTINGS(c) (c->type == CTS_TYPE_CURRENT_SETTINGS) -#else -#define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS) -#endif -#define DP_DISC_ENABLE 0x1 -#define DP_DISC_DISABL 0x2 -#define DP_DISC (DP_DISC_ENABLE|DP_DISC_DISABL) - -#define DP_TQING_ENABLE 0x4 -#define DP_TQING_DISABL 0x8 -#define DP_TQING (DP_TQING_ENABLE|DP_TQING_DISABL) - -#define DP_WIDE 0x10 -#define DP_NARROW 0x20 -#define DP_WIDTH (DP_WIDE|DP_NARROW) - -#define DP_SYNC 0x40 - - case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */ - cts = &ccb->cts; - if (!IS_CURRENT_SETTINGS(cts)) { - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - } - tgt = cts->ccb_h.target_id; - if (mpt->is_fc == 0) { - u_int8_t dval = 0; - u_int period = 0, offset = 0; -#ifndef CAM_NEW_TRAN_CODE - if (cts->valid & CCB_TRANS_DISC_VALID) { - dval |= DP_DISC_ENABLE; - } - if (cts->valid & CCB_TRANS_TQ_VALID) { - dval |= DP_TQING_ENABLE; - } - if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) { - if (cts->bus_width) - dval |= DP_WIDE; - else - dval |= DP_NARROW; - } - /* - * Any SYNC RATE of nonzero and SYNC_OFFSET - * of nonzero will cause us to go to the - * selected (from NVRAM) maximum value for - * this device. At a later point, we'll - * allow finer control. - */ - if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) && - (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)) { - dval |= DP_SYNC; - period = cts->sync_period; - offset = cts->sync_offset; - } -#else - struct ccb_trans_settings_scsi *scsi = - &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = - &cts->xport_specific.spi; - - if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { - if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) - dval |= DP_DISC_ENABLE; - else - dval |= DP_DISC_DISABL; - } - - if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { - if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) - dval |= DP_TQING_ENABLE; - else - dval |= DP_TQING_DISABL; - } - - if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { - if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT) - dval |= DP_WIDE; - else - dval |= DP_NARROW; - } - - if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) && - (spi->valid & CTS_SPI_VALID_SYNC_RATE) && - (spi->sync_period && spi->sync_offset)) { - dval |= DP_SYNC; - period = spi->sync_period; - offset = spi->sync_offset; - } -#endif - CAMLOCK_2_MPTLOCK(mpt); - if (dval & DP_DISC_ENABLE) { - mpt->mpt_disc_enable |= (1 << tgt); - } else if (dval & DP_DISC_DISABL) { - mpt->mpt_disc_enable &= ~(1 << tgt); - } - if (dval & DP_TQING_ENABLE) { - mpt->mpt_tag_enable |= (1 << tgt); - } else if (dval & DP_TQING_DISABL) { - mpt->mpt_tag_enable &= ~(1 << tgt); - } - if (dval & DP_WIDTH) { - if (mpt_setwidth(mpt, tgt, dval & DP_WIDE)) { - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - break; - } - } - if (dval & DP_SYNC) { - if (mpt_setsync(mpt, tgt, period, offset)) { - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - break; - } - } - MPTLOCK_2_CAMLOCK(mpt); - if (mpt->verbose > 1) { - mpt_prt(mpt, - "SET tgt %d flags %x period %x off %x", - tgt, dval, period, offset); - } - } - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - - case XPT_GET_TRAN_SETTINGS: - cts = &ccb->cts; - tgt = cts->ccb_h.target_id; - if (mpt->is_fc) { -#ifndef CAM_NEW_TRAN_CODE - /* - * a lot of normal SCSI things don't make sense. - */ - cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB; - cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; - /* - * How do you measure the width of a high - * speed serial bus? Well, in bytes. - * - * Offset and period make no sense, though, so we set - * (above) a 'base' transfer speed to be gigabit. - */ - cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; -#else - struct ccb_trans_settings_fc *fc = - &cts->xport_specific.fc; - - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_FC; - cts->transport_version = 0; - - fc->valid = CTS_FC_VALID_SPEED; - fc->bitrate = 100000; /* XXX: Need for 2Gb/s */ - /* XXX: need a port database for each target */ -#endif - } else { -#ifdef CAM_NEW_TRAN_CODE - struct ccb_trans_settings_scsi *scsi = - &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = - &cts->xport_specific.spi; -#endif - u_int8_t dval, pval, oval; - - /* - * We aren't going off of Port PAGE2 params for - * tagged queuing or disconnect capabilities - * for current settings. For goal settings, - * we assert all capabilities- we've had some - * problems with reading NVRAM data. - */ - if (IS_CURRENT_SETTINGS(cts)) { - CONFIG_PAGE_SCSI_DEVICE_0 tmp; - dval = 0; - - tmp = mpt->mpt_dev_page0[tgt]; - CAMLOCK_2_MPTLOCK(mpt); - if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) { - mpt_prt(mpt, - "cannot get target %d DP0", tgt); - } else { - if (mpt->verbose > 1) { - mpt_prt(mpt, - "SPI Tgt %d Page 0: NParms %x Information %x", - tgt, - tmp.NegotiatedParameters, - tmp.Information); - } - } - MPTLOCK_2_CAMLOCK(mpt); - - if (tmp.NegotiatedParameters & - MPI_SCSIDEVPAGE0_NP_WIDE) - dval |= DP_WIDE; - - if (mpt->mpt_disc_enable & (1 << tgt)) { - dval |= DP_DISC_ENABLE; - } - if (mpt->mpt_tag_enable & (1 << tgt)) { - dval |= DP_TQING_ENABLE; - } - oval = (tmp.NegotiatedParameters >> 16) & 0xff; - pval = (tmp.NegotiatedParameters >> 8) & 0xff; - } else { - /* - * XXX: Fix wrt NVRAM someday. Attempts - * XXX: to read port page2 device data - * XXX: just returns zero in these areas. - */ - dval = DP_WIDE|DP_DISC|DP_TQING; - oval = (mpt->mpt_port_page0.Capabilities >> 16); - pval = (mpt->mpt_port_page0.Capabilities >> 8); - } -#ifndef CAM_NEW_TRAN_CODE - cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); - if (dval & DP_DISC_ENABLE) { - cts->flags |= CCB_TRANS_DISC_ENB; - } - if (dval & DP_TQING_ENABLE) { - cts->flags |= CCB_TRANS_TAG_ENB; - } - if (dval & DP_WIDE) { - cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; - } else { - cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; - } - cts->valid = CCB_TRANS_BUS_WIDTH_VALID | - CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; - if (oval) { - cts->sync_period = pval; - cts->sync_offset = oval; - cts->valid |= - CCB_TRANS_SYNC_RATE_VALID | - CCB_TRANS_SYNC_OFFSET_VALID; - } -#else - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_SPI; - cts->transport_version = 2; - - scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; - spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; - if (dval & DP_DISC_ENABLE) { - spi->flags |= CTS_SPI_FLAGS_DISC_ENB; - } - if (dval & DP_TQING_ENABLE) { - scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; - } - if (oval && pval) { - spi->sync_offset = oval; - spi->sync_period = pval; - spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; - spi->valid |= CTS_SPI_VALID_SYNC_RATE; - } - spi->valid |= CTS_SPI_VALID_BUS_WIDTH; - if (dval & DP_WIDE) { - spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; - } else { - spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; - } - if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { - scsi->valid = CTS_SCSI_VALID_TQ; - spi->valid |= CTS_SPI_VALID_DISC; - } else { - scsi->valid = 0; - } -#endif - if (mpt->verbose > 1) { - mpt_prt(mpt, - "GET %s tgt %d flags %x period %x off %x", - IS_CURRENT_SETTINGS(cts)? "ACTIVE" : - "NVRAM", tgt, dval, pval, oval); - } - } - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - - case XPT_CALC_GEOMETRY: - { - struct ccb_calc_geometry *ccg; - - ccg = &ccb->ccg; - if (ccg->block_size == 0) { - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - } - - cam_calc_geometry(ccg, /*extended*/1); - xpt_done(ccb); - break; - } - case XPT_PATH_INQ: /* Path routing inquiry */ - { - struct ccb_pathinq *cpi = &ccb->cpi; - - cpi->version_num = 1; - cpi->target_sprt = 0; - cpi->hba_eng_cnt = 0; - cpi->max_lun = 7; - cpi->bus_id = cam_sim_bus(sim); - if (mpt->is_fc) { - cpi->max_target = 255; - cpi->hba_misc = PIM_NOBUSRESET; - cpi->initiator_id = cpi->max_target + 1; - cpi->base_transfer_speed = 100000; - cpi->hba_inquiry = PI_TAG_ABLE; - } else { - cpi->initiator_id = mpt->mpt_ini_id; - cpi->base_transfer_speed = 3300; - cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; - cpi->hba_misc = 0; - cpi->max_target = 15; - } - - strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "LSI", HBA_IDLEN); - strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - default: - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - } -} - -static int -mpt_setwidth(mpt_softc_t *mpt, int tgt, int onoff) -{ - CONFIG_PAGE_SCSI_DEVICE_1 tmp; - tmp = mpt->mpt_dev_page1[tgt]; - if (onoff) { - tmp.RequestedParameters |= MPI_SCSIDEVPAGE1_RP_WIDE; - } else { - tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_WIDE; - } - if (mpt_write_cfg_page(mpt, tgt, &tmp.Header)) { - return (-1); - } - if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) { - return (-1); - } - mpt->mpt_dev_page1[tgt] = tmp; - if (mpt->verbose > 1) { - mpt_prt(mpt, - "SPI Target %d Page 1: RequestedParameters %x Config %x", - tgt, mpt->mpt_dev_page1[tgt].RequestedParameters, - mpt->mpt_dev_page1[tgt].Configuration); - } - return (0); -} - -static int -mpt_setsync(mpt_softc_t *mpt, int tgt, int period, int offset) -{ - CONFIG_PAGE_SCSI_DEVICE_1 tmp; - tmp = mpt->mpt_dev_page1[tgt]; - tmp.RequestedParameters &= - ~MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK; - tmp.RequestedParameters &= - ~MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK; - tmp.RequestedParameters &= - ~MPI_SCSIDEVPAGE1_RP_DT; - tmp.RequestedParameters &= - ~MPI_SCSIDEVPAGE1_RP_QAS; - tmp.RequestedParameters &= - ~MPI_SCSIDEVPAGE1_RP_IU; - /* - * XXX: For now, we're ignoring specific settings - */ - if (period && offset) { - int factor, offset, np; - factor = (mpt->mpt_port_page0.Capabilities >> 8) & 0xff; - offset = (mpt->mpt_port_page0.Capabilities >> 16) & 0xff; - np = 0; - if (factor < 0x9) { - np |= MPI_SCSIDEVPAGE1_RP_QAS; - np |= MPI_SCSIDEVPAGE1_RP_IU; - } - if (factor < 0xa) { - np |= MPI_SCSIDEVPAGE1_RP_DT; - } - np |= (factor << 8) | (offset << 16); - tmp.RequestedParameters |= np; - } - if (mpt_write_cfg_page(mpt, tgt, &tmp.Header)) { - return (-1); - } - if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) { - return (-1); - } - mpt->mpt_dev_page1[tgt] = tmp; - if (mpt->verbose > 1) { - mpt_prt(mpt, - "SPI Target %d Page 1: RParams %x Config %x", - tgt, mpt->mpt_dev_page1[tgt].RequestedParameters, - mpt->mpt_dev_page1[tgt].Configuration); - } - return (0); -} |