aic7xxx_osm.c revision 66717
165942Sgibbs/* 265942Sgibbs * Bus independent FreeBSD shim for the aic7xxx based adaptec SCSI controllers 365942Sgibbs * 465942Sgibbs * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000 Justin T. Gibbs. 565942Sgibbs * All rights reserved. 665942Sgibbs * 765942Sgibbs * Redistribution and use in source and binary forms, with or without 865942Sgibbs * modification, are permitted provided that the following conditions 965942Sgibbs * are met: 1065942Sgibbs * 1. Redistributions of source code must retain the above copyright 1165942Sgibbs * notice, this list of conditions, and the following disclaimer, 1265942Sgibbs * without modification. 1365942Sgibbs * 2. The name of the author may not be used to endorse or promote products 1465942Sgibbs * derived from this software without specific prior written permission. 1565942Sgibbs * 1665942Sgibbs * Alternatively, this software may be distributed under the terms of the 1765942Sgibbs * GNU Public License ("GPL"). 1865942Sgibbs * 1965942Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2065942Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2165942Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2265942Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2365942Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2465942Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2565942Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2665942Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2765942Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2865942Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2965942Sgibbs * SUCH DAMAGE. 3065942Sgibbs * 3165942Sgibbs * $Id$ 3265942Sgibbs * 3365942Sgibbs * $FreeBSD: head/sys/dev/aic7xxx/aic7xxx_osm.c 66717 2000-10-06 04:01:06Z gibbs $ 3465942Sgibbs */ 3565942Sgibbs 3665942Sgibbs#include <dev/aic7xxx/aic7xxx_freebsd.h> 3765942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h> 3865942Sgibbs 3965942Sgibbs#include <sys/eventhandler.h> 4065942Sgibbs 4165942Sgibbs#ifndef AHC_TMODE_ENABLE 4265942Sgibbs#define AHC_TMODE_ENABLE 0 4365942Sgibbs#endif 4465942Sgibbs 4565942Sgibbs#define ccb_scb_ptr spriv_ptr0 4665942Sgibbs#define ccb_ahc_ptr spriv_ptr1 4765942Sgibbs 4865942Sgibbs#ifdef AHC_DEBUG 4965942Sgibbsstatic int ahc_debug = AHC_DEBUG; 5065942Sgibbs#endif 5165942Sgibbs 5265942Sgibbsstatic void ahc_freebsd_intr(void *arg); 5365942Sgibbs 5465942Sgibbs#if UNUSED 5565942Sgibbsstatic void ahc_dump_targcmd(struct target_cmd *cmd); 5665942Sgibbs#endif 5765942Sgibbsstatic void ahc_action(struct cam_sim *sim, union ccb *ccb); 5865942Sgibbsstatic void ahc_get_tran_settings(struct ahc_softc *ahc, 5965942Sgibbs int our_id, char channel, 6065942Sgibbs struct ccb_trans_settings *cts); 6165942Sgibbsstatic void ahc_async(void *callback_arg, uint32_t code, 6265942Sgibbs struct cam_path *path, void *arg); 6365942Sgibbsstatic void ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, 6465942Sgibbs int nsegments, int error); 6565942Sgibbsstatic void ahc_poll(struct cam_sim *sim); 6665942Sgibbsstatic void ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, 6765942Sgibbs struct ccb_scsiio *csio, struct scb *scb); 6865942Sgibbsstatic void ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, 6965942Sgibbs union ccb *ccb); 7065942Sgibbsstatic int ahc_create_path(struct ahc_softc *ahc, 7166269Sgibbs char channel, u_int target, u_int lun, 7265942Sgibbs struct cam_path **path); 7365942Sgibbs 7465942Sgibbsstatic void ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb); 7565942Sgibbs 7665942Sgibbsstatic int 7766269Sgibbsahc_create_path(struct ahc_softc *ahc, char channel, u_int target, 7866269Sgibbs u_int lun, struct cam_path **path) 7965942Sgibbs{ 8065942Sgibbs path_id_t path_id; 8165942Sgibbs 8266269Sgibbs if (channel == 'B') 8365942Sgibbs path_id = cam_sim_path(ahc->platform_data->sim_b); 8465942Sgibbs else 8565942Sgibbs path_id = cam_sim_path(ahc->platform_data->sim); 8665942Sgibbs 8765942Sgibbs return (xpt_create_path(path, /*periph*/NULL, 8866269Sgibbs path_id, target, lun)); 8965942Sgibbs} 9065942Sgibbs 9165942Sgibbs/* 9265942Sgibbs * Attach all the sub-devices we can find 9365942Sgibbs */ 9465942Sgibbsint 9565942Sgibbsahc_attach(struct ahc_softc *ahc) 9665942Sgibbs{ 9765942Sgibbs char ahc_info[256]; 9865942Sgibbs struct ccb_setasync csa; 9965942Sgibbs struct cam_devq *devq; 10065942Sgibbs int bus_id; 10165942Sgibbs int bus_id2; 10265942Sgibbs struct cam_sim *sim; 10365942Sgibbs struct cam_sim *sim2; 10465942Sgibbs struct cam_path *path; 10565942Sgibbs struct cam_path *path2; 10665942Sgibbs long s; 10765942Sgibbs int count; 10865942Sgibbs int error; 10965942Sgibbs 11065942Sgibbs count = 0; 11165942Sgibbs sim = NULL; 11265942Sgibbs sim2 = NULL; 11365942Sgibbs 11465942Sgibbs ahc_controller_info(ahc, ahc_info); 11565942Sgibbs printf("%s\n", ahc_info); 11665942Sgibbs ahc_lock(ahc, &s); 11765942Sgibbs /* Hook up our interrupt handler */ 11865942Sgibbs if ((error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq, 11965942Sgibbs INTR_TYPE_CAM, ahc_freebsd_intr, ahc, 12065942Sgibbs &ahc->platform_data->ih)) != 0) { 12165942Sgibbs device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n", 12265942Sgibbs error); 12365942Sgibbs goto fail; 12465942Sgibbs } 12565942Sgibbs 12665942Sgibbs /* 12765942Sgibbs * Attach secondary channel first if the user has 12865942Sgibbs * declared it the primary channel. 12965942Sgibbs */ 13065942Sgibbs if ((ahc->flags & AHC_CHANNEL_B_PRIMARY) != 0) { 13165942Sgibbs bus_id = 1; 13265942Sgibbs bus_id2 = 0; 13365942Sgibbs } else { 13465942Sgibbs bus_id = 0; 13565942Sgibbs bus_id2 = 1; 13665942Sgibbs } 13765942Sgibbs 13865942Sgibbs /* 13965942Sgibbs * Create the device queue for our SIM(s). 14065942Sgibbs */ 14166647Sgibbs devq = cam_simq_alloc(AHC_SCB_MAX - 1); 14265942Sgibbs if (devq == NULL) 14365942Sgibbs goto fail; 14465942Sgibbs 14565942Sgibbs /* 14665942Sgibbs * Construct our first channel SIM entry 14765942Sgibbs */ 14866104Sgibbs sim = cam_sim_alloc(ahc_action, ahc_poll, "ahc", ahc, 14966104Sgibbs device_get_unit(ahc->dev_softc), 15066647Sgibbs 1, AHC_SCB_MAX - 1, devq); 15165942Sgibbs if (sim == NULL) { 15265942Sgibbs cam_simq_free(devq); 15365942Sgibbs goto fail; 15465942Sgibbs } 15565942Sgibbs 15665942Sgibbs if (xpt_bus_register(sim, bus_id) != CAM_SUCCESS) { 15765942Sgibbs cam_sim_free(sim, /*free_devq*/TRUE); 15865942Sgibbs sim = NULL; 15965942Sgibbs goto fail; 16065942Sgibbs } 16165942Sgibbs 16265942Sgibbs if (xpt_create_path(&path, /*periph*/NULL, 16365942Sgibbs cam_sim_path(sim), CAM_TARGET_WILDCARD, 16465942Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 16565942Sgibbs xpt_bus_deregister(cam_sim_path(sim)); 16665942Sgibbs cam_sim_free(sim, /*free_devq*/TRUE); 16765942Sgibbs sim = NULL; 16865942Sgibbs goto fail; 16965942Sgibbs } 17065942Sgibbs 17165942Sgibbs xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); 17265942Sgibbs csa.ccb_h.func_code = XPT_SASYNC_CB; 17365942Sgibbs csa.event_enable = AC_LOST_DEVICE; 17465942Sgibbs csa.callback = ahc_async; 17565942Sgibbs csa.callback_arg = sim; 17665942Sgibbs xpt_action((union ccb *)&csa); 17765942Sgibbs count++; 17865942Sgibbs 17965942Sgibbs if (ahc->features & AHC_TWIN) { 18065942Sgibbs sim2 = cam_sim_alloc(ahc_action, ahc_poll, "ahc", 18166104Sgibbs ahc, device_get_unit(ahc->dev_softc), 1, 18266647Sgibbs AHC_SCB_MAX - 1, devq); 18365942Sgibbs 18465942Sgibbs if (sim2 == NULL) { 18565942Sgibbs printf("ahc_attach: Unable to attach second " 18665942Sgibbs "bus due to resource shortage"); 18765942Sgibbs goto fail; 18865942Sgibbs } 18965942Sgibbs 19065942Sgibbs if (xpt_bus_register(sim2, bus_id2) != CAM_SUCCESS) { 19165942Sgibbs printf("ahc_attach: Unable to attach second " 19265942Sgibbs "bus due to resource shortage"); 19365942Sgibbs /* 19465942Sgibbs * We do not want to destroy the device queue 19565942Sgibbs * because the first bus is using it. 19665942Sgibbs */ 19765942Sgibbs cam_sim_free(sim2, /*free_devq*/FALSE); 19865942Sgibbs goto fail; 19965942Sgibbs } 20065942Sgibbs 20165942Sgibbs if (xpt_create_path(&path2, /*periph*/NULL, 20265942Sgibbs cam_sim_path(sim2), 20365942Sgibbs CAM_TARGET_WILDCARD, 20465942Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 20565942Sgibbs xpt_bus_deregister(cam_sim_path(sim2)); 20665942Sgibbs cam_sim_free(sim2, /*free_devq*/FALSE); 20765942Sgibbs sim2 = NULL; 20865942Sgibbs goto fail; 20965942Sgibbs } 21065942Sgibbs xpt_setup_ccb(&csa.ccb_h, path2, /*priority*/5); 21165942Sgibbs csa.ccb_h.func_code = XPT_SASYNC_CB; 21265942Sgibbs csa.event_enable = AC_LOST_DEVICE; 21365942Sgibbs csa.callback = ahc_async; 21465942Sgibbs csa.callback_arg = sim2; 21565942Sgibbs xpt_action((union ccb *)&csa); 21665942Sgibbs count++; 21765942Sgibbs } 21865942Sgibbs 21965942Sgibbsfail: 22065942Sgibbs if ((ahc->flags & AHC_CHANNEL_B_PRIMARY) != 0) { 22165942Sgibbs ahc->platform_data->sim_b = sim; 22265942Sgibbs ahc->platform_data->path_b = path; 22365942Sgibbs ahc->platform_data->sim = sim2; 22465942Sgibbs ahc->platform_data->path = path2; 22565942Sgibbs } else { 22665942Sgibbs ahc->platform_data->sim = sim; 22765942Sgibbs ahc->platform_data->path = path; 22865942Sgibbs ahc->platform_data->sim_b = sim2; 22965942Sgibbs ahc->platform_data->path_b = path2; 23065942Sgibbs } 23165942Sgibbs ahc_unlock(ahc, &s); 23265942Sgibbs 23365942Sgibbs if (count != 0) 23465942Sgibbs /* We have to wait until after any system dumps... */ 23565942Sgibbs EVENTHANDLER_REGISTER(shutdown_final, ahc_shutdown, 23665942Sgibbs ahc, SHUTDOWN_PRI_DEFAULT); 23765942Sgibbs 23865942Sgibbs return (count); 23965942Sgibbs} 24065942Sgibbs 24165942Sgibbs/* 24265942Sgibbs * Catch an interrupt from the adapter 24365942Sgibbs */ 24465942Sgibbsvoid 24565942Sgibbsahc_freebsd_intr(void *arg) 24665942Sgibbs{ 24765942Sgibbs struct ahc_softc *ahc; 24865942Sgibbs 24965942Sgibbs ahc = (struct ahc_softc *)arg; 25065942Sgibbs ahc_intr(ahc); 25165942Sgibbs} 25265942Sgibbs 25365942Sgibbs/* 25465942Sgibbs * We have an scb which has been processed by the 25565942Sgibbs * adaptor, now we look to see how the operation 25665942Sgibbs * went. 25765942Sgibbs */ 25865942Sgibbsvoid 25965942Sgibbsahc_done(struct ahc_softc *ahc, struct scb *scb) 26065942Sgibbs{ 26165942Sgibbs union ccb *ccb; 26265942Sgibbs 26365942Sgibbs CAM_DEBUG(scb->io_ctx->ccb_h.path, CAM_DEBUG_TRACE, 26465942Sgibbs ("ahc_done - scb %d\n", scb->hscb->tag)); 26565942Sgibbs 26665942Sgibbs ccb = scb->io_ctx; 26765942Sgibbs LIST_REMOVE(scb, pending_links); 26865942Sgibbs if (ccb->ccb_h.func_code == XPT_SCSI_IO 26965942Sgibbs && ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0 27065942Sgibbs || ccb->csio.tag_action == CAM_TAG_ACTION_NONE) 27165942Sgibbs && (ahc->features & AHC_SCB_BTT) == 0) { 27265942Sgibbs struct scb_tailq *untagged_q; 27365942Sgibbs 27465942Sgibbs untagged_q = &ahc->untagged_queues[ccb->ccb_h.target_id]; 27565942Sgibbs TAILQ_REMOVE(untagged_q, scb, links.tqe); 27665942Sgibbs ahc_run_untagged_queue(ahc, untagged_q); 27765942Sgibbs } 27865942Sgibbs 27965942Sgibbs untimeout(ahc_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch); 28065942Sgibbs 28165942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 28265942Sgibbs bus_dmasync_op_t op; 28365942Sgibbs 28465942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 28565942Sgibbs op = BUS_DMASYNC_POSTREAD; 28665942Sgibbs else 28765942Sgibbs op = BUS_DMASYNC_POSTWRITE; 28865942Sgibbs bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op); 28965942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); 29065942Sgibbs } 29165942Sgibbs 29265942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 29365942Sgibbs if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) 29465942Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 29565942Sgibbs ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 29665942Sgibbs ahc_free_scb(ahc, scb); 29765942Sgibbs xpt_done(ccb); 29865942Sgibbs return; 29965942Sgibbs } 30065942Sgibbs 30165942Sgibbs /* 30265942Sgibbs * If the recovery SCB completes, we have to be 30365942Sgibbs * out of our timeout. 30465942Sgibbs */ 30565942Sgibbs if ((scb->flags & SCB_RECOVERY_SCB) != 0) { 30665942Sgibbs struct scb *list_scb; 30765942Sgibbs 30865942Sgibbs /* 30965942Sgibbs * We were able to complete the command successfully, 31065942Sgibbs * so reinstate the timeouts for all other pending 31165942Sgibbs * commands. 31265942Sgibbs */ 31365942Sgibbs LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { 31465942Sgibbs union ccb *ccb; 31565942Sgibbs 31665942Sgibbs ccb = list_scb->io_ctx; 31765942Sgibbs ccb->ccb_h.timeout_ch = 31865942Sgibbs timeout(ahc_timeout, list_scb, 31965942Sgibbs (ccb->ccb_h.timeout * hz)/1000); 32065942Sgibbs } 32165942Sgibbs 32265942Sgibbs /* 32365942Sgibbs * Ensure that we didn't put a second instance of this 32465942Sgibbs * SCB into the QINFIFO. 32565942Sgibbs */ 32665942Sgibbs ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb), 32765942Sgibbs SCB_GET_CHANNEL(ahc, scb), 32865942Sgibbs SCB_GET_LUN(scb), scb->hscb->tag, 32965942Sgibbs ROLE_INITIATOR, /*status*/0, 33065942Sgibbs SEARCH_REMOVE); 33165942Sgibbs if (ahc_get_transaction_status(scb) == CAM_BDR_SENT 33265942Sgibbs || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) 33365942Sgibbs ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); 33465942Sgibbs ahc_print_path(ahc, scb); 33565942Sgibbs printf("no longer in timeout, status = %x\n", 33665942Sgibbs ccb->ccb_h.status); 33765942Sgibbs } 33865942Sgibbs 33965942Sgibbs /* Don't clobber any existing error state */ 34065942Sgibbs if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) { 34165942Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 34265942Sgibbs } else if ((scb->flags & SCB_SENSE) != 0) { 34365942Sgibbs /* 34465942Sgibbs * We performed autosense retrieval. 34565942Sgibbs * 34665942Sgibbs * Zero any sense not transferred by the 34765942Sgibbs * device. The SCSI spec mandates that any 34865942Sgibbs * untransfered data should be assumed to be 34965942Sgibbs * zero. Complete the 'bounce' of sense information 35065942Sgibbs * through buffers accessible via bus-space by 35165942Sgibbs * copying it into the clients csio. 35265942Sgibbs */ 35365942Sgibbs memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data)); 35465942Sgibbs memcpy(&ccb->csio.sense_data, 35565942Sgibbs &ahc->scb_data->sense[scb->hscb->tag], 35665942Sgibbs (scb->sg_list->len & AHC_SG_LEN_MASK) 35765942Sgibbs - ccb->csio.sense_resid); 35865942Sgibbs scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID; 35965942Sgibbs } 36065942Sgibbs ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 36165942Sgibbs ahc_free_scb(ahc, scb); 36265942Sgibbs xpt_done(ccb); 36365942Sgibbs} 36465942Sgibbs 36565942Sgibbsstatic void 36665942Sgibbsahc_action(struct cam_sim *sim, union ccb *ccb) 36765942Sgibbs{ 36865942Sgibbs struct ahc_softc *ahc; 36965942Sgibbs struct tmode_lstate *lstate; 37065942Sgibbs u_int target_id; 37165942Sgibbs u_int our_id; 37265942Sgibbs long s; 37365942Sgibbs 37465942Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahc_action\n")); 37565942Sgibbs 37665942Sgibbs ahc = (struct ahc_softc *)cam_sim_softc(sim); 37765942Sgibbs 37865942Sgibbs target_id = ccb->ccb_h.target_id; 37965942Sgibbs our_id = SIM_SCSI_ID(ahc, sim); 38065942Sgibbs 38165942Sgibbs switch (ccb->ccb_h.func_code) { 38265942Sgibbs /* Common cases first */ 38365942Sgibbs case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 38465942Sgibbs case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/ 38565942Sgibbs { 38665942Sgibbs struct tmode_tstate *tstate; 38765942Sgibbs cam_status status; 38865942Sgibbs 38965942Sgibbs status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, 39065942Sgibbs &lstate, TRUE); 39165942Sgibbs 39265942Sgibbs if (status != CAM_REQ_CMP) { 39365942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 39465942Sgibbs /* Response from the black hole device */ 39565942Sgibbs tstate = NULL; 39665942Sgibbs lstate = ahc->black_hole; 39765942Sgibbs } else { 39865942Sgibbs ccb->ccb_h.status = status; 39965942Sgibbs xpt_done(ccb); 40065942Sgibbs break; 40165942Sgibbs } 40265942Sgibbs } 40365942Sgibbs if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { 40465942Sgibbs 40565942Sgibbs ahc_lock(ahc, &s); 40665942Sgibbs SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h, 40765942Sgibbs sim_links.sle); 40865942Sgibbs ccb->ccb_h.status = CAM_REQ_INPROG; 40965942Sgibbs if ((ahc->flags & AHC_TQINFIFO_BLOCKED) != 0) 41065942Sgibbs ahc_run_tqinfifo(ahc, /*paused*/FALSE); 41165942Sgibbs ahc_unlock(ahc, &s); 41265942Sgibbs break; 41365942Sgibbs } 41465942Sgibbs 41565942Sgibbs /* 41665942Sgibbs * The target_id represents the target we attempt to 41765942Sgibbs * select. In target mode, this is the initiator of 41865942Sgibbs * the original command. 41965942Sgibbs */ 42065942Sgibbs our_id = target_id; 42165942Sgibbs target_id = ccb->csio.init_id; 42265942Sgibbs /* FALLTHROUGH */ 42365942Sgibbs } 42465942Sgibbs case XPT_SCSI_IO: /* Execute the requested I/O operation */ 42565942Sgibbs case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 42665942Sgibbs { 42766717Sgibbs struct scb *scb; 42866717Sgibbs struct hardware_scb *hscb; 42965942Sgibbs 43065942Sgibbs /* 43165942Sgibbs * get an scb to use. 43265942Sgibbs */ 43366717Sgibbs ahc_lock(ahc, &s); 43465942Sgibbs if ((scb = ahc_get_scb(ahc)) == NULL) { 43565942Sgibbs 43665942Sgibbs ahc->flags |= AHC_RESOURCE_SHORTAGE; 43765942Sgibbs ahc_unlock(ahc, &s); 43865942Sgibbs xpt_freeze_simq(sim, /*count*/1); 43966510Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 44065942Sgibbs xpt_done(ccb); 44165942Sgibbs return; 44265942Sgibbs } 44366717Sgibbs ahc_unlock(ahc, &s); 44465942Sgibbs 44565942Sgibbs hscb = scb->hscb; 44665942Sgibbs 44765942Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, 44865942Sgibbs ("start scb(%p)\n", scb)); 44965942Sgibbs scb->io_ctx = ccb; 45065942Sgibbs /* 45165942Sgibbs * So we can find the SCB when an abort is requested 45265942Sgibbs */ 45365942Sgibbs ccb->ccb_h.ccb_scb_ptr = scb; 45465942Sgibbs ccb->ccb_h.ccb_ahc_ptr = ahc; 45565942Sgibbs 45665942Sgibbs /* 45765942Sgibbs * Put all the arguments for the xfer in the scb 45865942Sgibbs */ 45965942Sgibbs hscb->control = 0; 46065942Sgibbs hscb->scsiid = BUILD_SCSIID(ahc, sim, target_id, our_id); 46165942Sgibbs hscb->lun = ccb->ccb_h.target_lun; 46265942Sgibbs if (ccb->ccb_h.func_code == XPT_RESET_DEV) { 46365942Sgibbs hscb->cdb_len = 0; 46465942Sgibbs scb->flags |= SCB_DEVICE_RESET; 46565942Sgibbs hscb->control |= MK_MESSAGE; 46665942Sgibbs ahc_execute_scb(scb, NULL, 0, 0); 46765942Sgibbs } else { 46865942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 46965942Sgibbs struct target_data *tdata; 47065942Sgibbs 47165942Sgibbs tdata = &hscb->shared_data.tdata; 47265942Sgibbs if (ahc->pending_device == lstate) { 47365942Sgibbs scb->flags |= SCB_TARGET_IMMEDIATE; 47465942Sgibbs ahc->pending_device = NULL; 47565942Sgibbs } 47665942Sgibbs hscb->control |= TARGET_SCB; 47765942Sgibbs tdata->target_phases = IDENTIFY_SEEN; 47865942Sgibbs if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { 47965942Sgibbs tdata->target_phases |= SPHASE_PENDING; 48065942Sgibbs tdata->scsi_status = 48165942Sgibbs ccb->csio.scsi_status; 48265942Sgibbs } 48365942Sgibbs tdata->initiator_tag = ccb->csio.tag_id; 48465942Sgibbs } 48565942Sgibbs if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) 48665942Sgibbs hscb->control |= ccb->csio.tag_action; 48765942Sgibbs 48865942Sgibbs ahc_setup_data(ahc, sim, &ccb->csio, scb); 48965942Sgibbs } 49065942Sgibbs break; 49165942Sgibbs } 49265942Sgibbs case XPT_NOTIFY_ACK: 49365942Sgibbs case XPT_IMMED_NOTIFY: 49465942Sgibbs { 49565942Sgibbs struct tmode_tstate *tstate; 49665942Sgibbs struct tmode_lstate *lstate; 49765942Sgibbs cam_status status; 49865942Sgibbs 49965942Sgibbs status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, 50065942Sgibbs &lstate, TRUE); 50165942Sgibbs 50265942Sgibbs if (status != CAM_REQ_CMP) { 50365942Sgibbs ccb->ccb_h.status = status; 50465942Sgibbs xpt_done(ccb); 50565942Sgibbs break; 50665942Sgibbs } 50765942Sgibbs SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h, 50865942Sgibbs sim_links.sle); 50965942Sgibbs ccb->ccb_h.status = CAM_REQ_INPROG; 51065942Sgibbs ahc_send_lstate_events(ahc, lstate); 51165942Sgibbs break; 51265942Sgibbs } 51365942Sgibbs case XPT_EN_LUN: /* Enable LUN as a target */ 51465942Sgibbs ahc_handle_en_lun(ahc, sim, ccb); 51565942Sgibbs xpt_done(ccb); 51665942Sgibbs break; 51765942Sgibbs case XPT_ABORT: /* Abort the specified CCB */ 51865942Sgibbs { 51965942Sgibbs ahc_abort_ccb(ahc, sim, ccb); 52065942Sgibbs break; 52165942Sgibbs } 52265942Sgibbs case XPT_SET_TRAN_SETTINGS: 52365942Sgibbs { 52465942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 52565942Sgibbs struct ahc_devinfo devinfo; 52665942Sgibbs struct ccb_trans_settings *cts; 52765942Sgibbs struct ccb_trans_settings_scsi *scsi; 52865942Sgibbs struct ccb_trans_settings_spi *spi; 52965942Sgibbs struct ahc_initiator_tinfo *tinfo; 53065942Sgibbs struct tmode_tstate *tstate; 53165942Sgibbs uint16_t *discenable; 53265942Sgibbs uint16_t *tagenable; 53365942Sgibbs u_int update_type; 53465942Sgibbs 53565942Sgibbs cts = &ccb->cts; 53665942Sgibbs scsi = &cts->proto_specific.scsi; 53765942Sgibbs spi = &cts->xport_specific.spi; 53865942Sgibbs ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), 53965942Sgibbs cts->ccb_h.target_id, 54065942Sgibbs cts->ccb_h.target_lun, 54165942Sgibbs SIM_CHANNEL(ahc, sim), 54265942Sgibbs ROLE_UNKNOWN); 54365942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, 54465942Sgibbs devinfo.our_scsiid, 54565942Sgibbs devinfo.target, &tstate); 54665942Sgibbs update_type = 0; 54765942Sgibbs if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 54865942Sgibbs update_type |= AHC_TRANS_GOAL; 54965942Sgibbs discenable = &tstate->discenable; 55065942Sgibbs tagenable = &tstate->tagenable; 55165942Sgibbs tinfo->current.protocol_version = 55265942Sgibbs cts->protocol_version; 55365942Sgibbs tinfo->current.transport_version = 55465942Sgibbs cts->transport_version; 55565942Sgibbs tinfo->goal.protocol_version = 55665942Sgibbs cts->protocol_version; 55765942Sgibbs tinfo->goal.transport_version = 55865942Sgibbs cts->transport_version; 55965942Sgibbs } else if (cts->type == CTS_TYPE_USER_SETTINGS) { 56065942Sgibbs update_type |= AHC_TRANS_USER; 56165942Sgibbs discenable = &ahc->user_discenable; 56265942Sgibbs tagenable = &ahc->user_tagenable; 56365942Sgibbs tinfo->user.protocol_version = 56465942Sgibbs cts->protocol_version; 56565942Sgibbs tinfo->user.transport_version = 56665942Sgibbs cts->transport_version; 56765942Sgibbs } else { 56865942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 56965942Sgibbs xpt_done(ccb); 57065942Sgibbs break; 57165942Sgibbs } 57265942Sgibbs 57365942Sgibbs ahc_lock(ahc, &s); 57465942Sgibbs 57565942Sgibbs if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { 57665942Sgibbs if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) 57765942Sgibbs *discenable |= devinfo.target_mask; 57865942Sgibbs else 57965942Sgibbs *discenable &= ~devinfo.target_mask; 58065942Sgibbs } 58165942Sgibbs 58265942Sgibbs if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 58365942Sgibbs if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) 58465942Sgibbs *tagenable |= devinfo.target_mask; 58565942Sgibbs else 58665942Sgibbs *tagenable &= ~devinfo.target_mask; 58765942Sgibbs } 58865942Sgibbs 58965942Sgibbs if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { 59065942Sgibbs ahc_validate_width(ahc, &spi->bus_width); 59165942Sgibbs ahc_set_width(ahc, &devinfo, spi->bus_width, 59265942Sgibbs update_type, /*paused*/FALSE); 59365942Sgibbs } 59465942Sgibbs 59565942Sgibbs if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) { 59665942Sgibbs if (update_type == AHC_TRANS_USER) 59765942Sgibbs spi->ppr_options = tinfo->user.ppr_options; 59865942Sgibbs else 59965942Sgibbs spi->ppr_options = tinfo->goal.ppr_options; 60065942Sgibbs } 60165942Sgibbs 60265942Sgibbs if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) { 60365942Sgibbs if (update_type == AHC_TRANS_USER) 60465942Sgibbs spi->sync_offset = tinfo->user.offset; 60565942Sgibbs else 60665942Sgibbs spi->sync_offset = tinfo->goal.offset; 60765942Sgibbs } 60865942Sgibbs 60965942Sgibbs if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 61065942Sgibbs if (update_type == AHC_TRANS_USER) 61165942Sgibbs spi->sync_period = tinfo->user.period; 61265942Sgibbs else 61365942Sgibbs spi->sync_period = tinfo->goal.period; 61465942Sgibbs } 61565942Sgibbs 61665942Sgibbs if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) 61765942Sgibbs || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) { 61865942Sgibbs struct ahc_syncrate *syncrate; 61965942Sgibbs u_int maxsync; 62065942Sgibbs 62165942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 62265942Sgibbs maxsync = AHC_SYNCRATE_DT; 62365942Sgibbs else if ((ahc->features & AHC_ULTRA) != 0) 62465942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 62565942Sgibbs else 62665942Sgibbs maxsync = AHC_SYNCRATE_FAST; 62765942Sgibbs 62865942Sgibbs syncrate = ahc_find_syncrate(ahc, &spi->sync_period, 62965942Sgibbs &spi->ppr_options, 63065942Sgibbs maxsync); 63165942Sgibbs ahc_validate_offset(ahc, syncrate, &spi->sync_offset, 63265942Sgibbs spi->bus_width); 63365942Sgibbs 63465942Sgibbs /* We use a period of 0 to represent async */ 63565942Sgibbs if (spi->sync_offset == 0) { 63665942Sgibbs spi->sync_period = 0; 63765942Sgibbs spi->ppr_options = 0; 63865942Sgibbs } 63965942Sgibbs 64065942Sgibbs ahc_set_syncrate(ahc, &devinfo, syncrate, 64165942Sgibbs spi->sync_period, spi->sync_offset, 64265942Sgibbs spi->ppr_options, update_type, 64365942Sgibbs /*paused*/FALSE); 64465942Sgibbs } 64565942Sgibbs ahc_unlock(ahc, &s); 64665942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 64765942Sgibbs xpt_done(ccb); 64865942Sgibbs#else 64965942Sgibbs struct ahc_devinfo devinfo; 65065942Sgibbs struct ccb_trans_settings *cts; 65165942Sgibbs struct ahc_initiator_tinfo *tinfo; 65265942Sgibbs struct tmode_tstate *tstate; 65365942Sgibbs uint16_t *discenable; 65465942Sgibbs uint16_t *tagenable; 65565942Sgibbs u_int update_type; 65665942Sgibbs long s; 65765942Sgibbs 65865942Sgibbs cts = &ccb->cts; 65965942Sgibbs ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), 66065942Sgibbs cts->ccb_h.target_id, 66165942Sgibbs cts->ccb_h.target_lun, 66265942Sgibbs SIM_CHANNEL(ahc, sim), 66365942Sgibbs ROLE_UNKNOWN); 66465942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, 66565942Sgibbs devinfo.our_scsiid, 66665942Sgibbs devinfo.target, &tstate); 66765942Sgibbs update_type = 0; 66865942Sgibbs if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) { 66965942Sgibbs update_type |= AHC_TRANS_GOAL; 67065942Sgibbs discenable = &tstate->discenable; 67165942Sgibbs tagenable = &tstate->tagenable; 67265942Sgibbs } else if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { 67365942Sgibbs update_type |= AHC_TRANS_USER; 67465942Sgibbs discenable = &ahc->user_discenable; 67565942Sgibbs tagenable = &ahc->user_tagenable; 67665942Sgibbs } else { 67765942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 67865942Sgibbs xpt_done(ccb); 67965942Sgibbs break; 68065942Sgibbs } 68165942Sgibbs 68265942Sgibbs ahc_lock(ahc, &s); 68365942Sgibbs 68465942Sgibbs if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) { 68565942Sgibbs if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) 68665942Sgibbs *discenable |= devinfo.target_mask; 68765942Sgibbs else 68865942Sgibbs *discenable &= ~devinfo.target_mask; 68965942Sgibbs } 69065942Sgibbs 69165942Sgibbs if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) { 69265942Sgibbs if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) 69365942Sgibbs *tagenable |= devinfo.target_mask; 69465942Sgibbs else 69565942Sgibbs *tagenable &= ~devinfo.target_mask; 69665942Sgibbs } 69765942Sgibbs 69865942Sgibbs if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0) { 69965942Sgibbs ahc_validate_width(ahc, &cts->bus_width); 70065942Sgibbs ahc_set_width(ahc, &devinfo, cts->bus_width, 70165942Sgibbs update_type, /*paused*/FALSE); 70265942Sgibbs } 70365942Sgibbs 70465942Sgibbs if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0) { 70565942Sgibbs if (update_type == AHC_TRANS_USER) 70665942Sgibbs cts->sync_offset = tinfo->user.offset; 70765942Sgibbs else 70865942Sgibbs cts->sync_offset = tinfo->goal.offset; 70965942Sgibbs } 71065942Sgibbs 71165942Sgibbs if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) == 0) { 71265942Sgibbs if (update_type == AHC_TRANS_USER) 71365942Sgibbs cts->sync_period = tinfo->user.period; 71465942Sgibbs else 71565942Sgibbs cts->sync_period = tinfo->goal.period; 71665942Sgibbs } 71765942Sgibbs 71865942Sgibbs if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) 71965942Sgibbs || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) { 72065942Sgibbs struct ahc_syncrate *syncrate; 72165942Sgibbs u_int ppr_options; 72265942Sgibbs u_int maxsync; 72365942Sgibbs 72465942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 72565942Sgibbs maxsync = AHC_SYNCRATE_DT; 72665942Sgibbs else if ((ahc->features & AHC_ULTRA) != 0) 72765942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 72865942Sgibbs else 72965942Sgibbs maxsync = AHC_SYNCRATE_FAST; 73065942Sgibbs 73165942Sgibbs ppr_options = 0; 73265942Sgibbs if (cts->sync_period <= 9) 73365942Sgibbs ppr_options = MSG_EXT_PPR_DT_REQ; 73465942Sgibbs 73565942Sgibbs syncrate = ahc_find_syncrate(ahc, &cts->sync_period, 73665942Sgibbs &ppr_options, 73765942Sgibbs maxsync); 73865942Sgibbs ahc_validate_offset(ahc, syncrate, &cts->sync_offset, 73965942Sgibbs MSG_EXT_WDTR_BUS_8_BIT); 74065942Sgibbs 74165942Sgibbs /* We use a period of 0 to represent async */ 74265942Sgibbs if (cts->sync_offset == 0) { 74365942Sgibbs cts->sync_period = 0; 74465942Sgibbs ppr_options = 0; 74565942Sgibbs } 74665942Sgibbs 74765942Sgibbs if (ppr_options == MSG_EXT_PPR_DT_REQ 74865942Sgibbs && tinfo->user.transport_version >= 3) { 74965942Sgibbs tinfo->goal.transport_version = 75065942Sgibbs tinfo->user.transport_version; 75165942Sgibbs tinfo->current.transport_version = 75265942Sgibbs tinfo->user.transport_version; 75365942Sgibbs } 75465942Sgibbs 75565942Sgibbs ahc_set_syncrate(ahc, &devinfo, syncrate, 75665942Sgibbs cts->sync_period, cts->sync_offset, 75765942Sgibbs ppr_options, update_type, 75865942Sgibbs /*paused*/FALSE); 75965942Sgibbs } 76065942Sgibbs ahc_unlock(ahc, &s); 76165942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 76265942Sgibbs xpt_done(ccb); 76365942Sgibbs#endif 76465942Sgibbs break; 76565942Sgibbs } 76665942Sgibbs case XPT_GET_TRAN_SETTINGS: 76765942Sgibbs /* Get default/user set transfer settings for the target */ 76865942Sgibbs { 76965942Sgibbs 77065942Sgibbs ahc_lock(ahc, &s); 77165942Sgibbs ahc_get_tran_settings(ahc, SIM_SCSI_ID(ahc, sim), 77265942Sgibbs SIM_CHANNEL(ahc, sim), &ccb->cts); 77365942Sgibbs ahc_unlock(ahc, &s); 77465942Sgibbs xpt_done(ccb); 77565942Sgibbs break; 77665942Sgibbs } 77765942Sgibbs case XPT_CALC_GEOMETRY: 77865942Sgibbs { 77965942Sgibbs struct ccb_calc_geometry *ccg; 78065942Sgibbs uint32_t size_mb; 78165942Sgibbs uint32_t secs_per_cylinder; 78265942Sgibbs int extended; 78365942Sgibbs 78465942Sgibbs ccg = &ccb->ccg; 78565942Sgibbs size_mb = ccg->volume_size 78665942Sgibbs / ((1024L * 1024L) / ccg->block_size); 78765942Sgibbs extended = SIM_IS_SCSIBUS_B(ahc, sim) 78865942Sgibbs ? ahc->flags & AHC_EXTENDED_TRANS_B 78965942Sgibbs : ahc->flags & AHC_EXTENDED_TRANS_A; 79065942Sgibbs 79165942Sgibbs if (size_mb > 1024 && extended) { 79265942Sgibbs ccg->heads = 255; 79365942Sgibbs ccg->secs_per_track = 63; 79465942Sgibbs } else { 79565942Sgibbs ccg->heads = 64; 79665942Sgibbs ccg->secs_per_track = 32; 79765942Sgibbs } 79865942Sgibbs secs_per_cylinder = ccg->heads * ccg->secs_per_track; 79965942Sgibbs ccg->cylinders = ccg->volume_size / secs_per_cylinder; 80065942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 80165942Sgibbs xpt_done(ccb); 80265942Sgibbs break; 80365942Sgibbs } 80465942Sgibbs case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 80565942Sgibbs { 80665942Sgibbs int found; 80765942Sgibbs 80865942Sgibbs ahc_lock(ahc, &s); 80965942Sgibbs found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim), 81065942Sgibbs /*initiate reset*/TRUE); 81165942Sgibbs ahc_unlock(ahc, &s); 81265942Sgibbs if (bootverbose) { 81365942Sgibbs xpt_print_path(SIM_PATH(ahc, sim)); 81465942Sgibbs printf("SCSI bus reset delivered. " 81565942Sgibbs "%d SCBs aborted.\n", found); 81665942Sgibbs } 81765942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 81865942Sgibbs xpt_done(ccb); 81965942Sgibbs break; 82065942Sgibbs } 82165942Sgibbs case XPT_TERM_IO: /* Terminate the I/O process */ 82265942Sgibbs /* XXX Implement */ 82365942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 82465942Sgibbs xpt_done(ccb); 82565942Sgibbs break; 82665942Sgibbs case XPT_PATH_INQ: /* Path routing inquiry */ 82765942Sgibbs { 82865942Sgibbs struct ccb_pathinq *cpi = &ccb->cpi; 82965942Sgibbs 83065942Sgibbs cpi->version_num = 1; /* XXX??? */ 83165942Sgibbs cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; 83265942Sgibbs if ((ahc->features & AHC_WIDE) != 0) 83365942Sgibbs cpi->hba_inquiry |= PI_WIDE_16; 83465942Sgibbs if ((ahc->flags & AHC_TARGETMODE) != 0) { 83565942Sgibbs cpi->target_sprt = PIT_PROCESSOR 83665942Sgibbs | PIT_DISCONNECT 83765942Sgibbs | PIT_TERM_IO; 83865942Sgibbs } else { 83965942Sgibbs cpi->target_sprt = 0; 84065942Sgibbs } 84165942Sgibbs cpi->hba_misc = (ahc->flags & AHC_INITIATORMODE) 84265942Sgibbs ? 0 : PIM_NOINITIATOR; 84365942Sgibbs cpi->hba_eng_cnt = 0; 84465942Sgibbs cpi->max_target = (ahc->features & AHC_WIDE) ? 15 : 7; 84565942Sgibbs cpi->max_lun = 64; 84665942Sgibbs if (SIM_IS_SCSIBUS_B(ahc, sim)) { 84765942Sgibbs cpi->initiator_id = ahc->our_id_b; 84865942Sgibbs if ((ahc->flags & AHC_RESET_BUS_B) == 0) 84965942Sgibbs cpi->hba_misc |= PIM_NOBUSRESET; 85065942Sgibbs } else { 85165942Sgibbs cpi->initiator_id = ahc->our_id; 85265942Sgibbs if ((ahc->flags & AHC_RESET_BUS_A) == 0) 85365942Sgibbs cpi->hba_misc |= PIM_NOBUSRESET; 85465942Sgibbs } 85565942Sgibbs cpi->bus_id = cam_sim_bus(sim); 85665942Sgibbs cpi->base_transfer_speed = 3300; 85765942Sgibbs strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 85865942Sgibbs strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); 85965942Sgibbs strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 86065942Sgibbs cpi->unit_number = cam_sim_unit(sim); 86165942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 86265942Sgibbs cpi->protocol = PROTO_SCSI; 86365942Sgibbs cpi->protocol_version = SCSI_REV_2; 86465942Sgibbs cpi->transport = XPORT_SPI; 86565942Sgibbs cpi->transport_version = 2; 86665942Sgibbs cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_ST; 86765942Sgibbs if ((ahc->features & AHC_DT) != 0) { 86865942Sgibbs cpi->transport_version = 3; 86965942Sgibbs cpi->xport_specific.spi.ppr_options = 87065942Sgibbs SID_SPI_CLOCK_DT_ST; 87165942Sgibbs } 87265942Sgibbs#endif 87365942Sgibbs cpi->ccb_h.status = CAM_REQ_CMP; 87465942Sgibbs xpt_done(ccb); 87565942Sgibbs break; 87665942Sgibbs } 87765942Sgibbs default: 87865942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 87965942Sgibbs xpt_done(ccb); 88065942Sgibbs break; 88165942Sgibbs } 88265942Sgibbs} 88365942Sgibbs 88465942Sgibbsstatic void 88565942Sgibbsahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel, 88665942Sgibbs struct ccb_trans_settings *cts) 88765942Sgibbs{ 88865942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 88965942Sgibbs struct ahc_devinfo devinfo; 89065942Sgibbs struct ccb_trans_settings_scsi *scsi; 89165942Sgibbs struct ccb_trans_settings_spi *spi; 89265942Sgibbs struct ahc_initiator_tinfo *targ_info; 89365942Sgibbs struct tmode_tstate *tstate; 89465942Sgibbs struct ahc_transinfo *tinfo; 89565942Sgibbs 89665942Sgibbs scsi = &cts->proto_specific.scsi; 89765942Sgibbs spi = &cts->xport_specific.spi; 89865942Sgibbs ahc_compile_devinfo(&devinfo, our_id, 89965942Sgibbs cts->ccb_h.target_id, 90065942Sgibbs cts->ccb_h.target_lun, 90165942Sgibbs channel, ROLE_UNKNOWN); 90265942Sgibbs targ_info = ahc_fetch_transinfo(ahc, devinfo.channel, 90365942Sgibbs devinfo.our_scsiid, 90465942Sgibbs devinfo.target, &tstate); 90565942Sgibbs 90665942Sgibbs if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 90765942Sgibbs tinfo = &targ_info->current; 90865942Sgibbs else 90965942Sgibbs tinfo = &targ_info->user; 91065942Sgibbs 91165942Sgibbs scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 91265942Sgibbs spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 91365942Sgibbs if (cts->type == CTS_TYPE_USER_SETTINGS) { 91465942Sgibbs if ((ahc->user_discenable & devinfo.target_mask) != 0) 91565942Sgibbs spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 91665942Sgibbs 91765942Sgibbs if ((ahc->user_tagenable & devinfo.target_mask) != 0) 91865942Sgibbs scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 91965942Sgibbs } else { 92065942Sgibbs if ((tstate->discenable & devinfo.target_mask) != 0) 92165942Sgibbs spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 92265942Sgibbs 92365942Sgibbs if ((tstate->tagenable & devinfo.target_mask) != 0) 92465942Sgibbs scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 92565942Sgibbs } 92665942Sgibbs cts->protocol_version = tinfo->protocol_version; 92765942Sgibbs cts->transport_version = tinfo->transport_version; 92865942Sgibbs 92965942Sgibbs spi->sync_period = tinfo->period; 93065942Sgibbs spi->sync_offset = tinfo->offset; 93165942Sgibbs spi->bus_width = tinfo->width; 93265942Sgibbs spi->ppr_options = tinfo->ppr_options; 93365942Sgibbs 93465942Sgibbs cts->protocol = PROTO_SCSI; 93565942Sgibbs cts->transport = XPORT_SPI; 93665942Sgibbs spi->valid = CTS_SPI_VALID_SYNC_RATE 93765942Sgibbs | CTS_SPI_VALID_SYNC_OFFSET 93865942Sgibbs | CTS_SPI_VALID_BUS_WIDTH 93965942Sgibbs | CTS_SPI_VALID_PPR_OPTIONS; 94065942Sgibbs 94166717Sgibbs if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 94266717Sgibbs scsi->valid = CTS_SCSI_VALID_TQ; 94366717Sgibbs spi->valid |= CTS_SPI_VALID_DISC; 94466717Sgibbs } else { 94566717Sgibbs scsi->valid = 0; 94666717Sgibbs } 94766717Sgibbs 94865942Sgibbs cts->ccb_h.status = CAM_REQ_CMP; 94965942Sgibbs#else 95065942Sgibbs struct ahc_devinfo devinfo; 95165942Sgibbs struct ahc_initiator_tinfo *targ_info; 95265942Sgibbs struct tmode_tstate *tstate; 95365942Sgibbs struct ahc_transinfo *tinfo; 95465942Sgibbs long s; 95565942Sgibbs 95665942Sgibbs ahc_compile_devinfo(&devinfo, our_id, 95765942Sgibbs cts->ccb_h.target_id, 95865942Sgibbs cts->ccb_h.target_lun, 95965942Sgibbs channel, ROLE_UNKNOWN); 96065942Sgibbs targ_info = ahc_fetch_transinfo(ahc, devinfo.channel, 96165942Sgibbs devinfo.our_scsiid, 96265942Sgibbs devinfo.target, &tstate); 96365942Sgibbs 96465942Sgibbs if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) 96565942Sgibbs tinfo = &targ_info->current; 96665942Sgibbs else 96765942Sgibbs tinfo = &targ_info->user; 96865942Sgibbs 96965942Sgibbs ahc_lock(ahc, &s); 97065942Sgibbs 97165942Sgibbs cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); 97265942Sgibbs if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) { 97365942Sgibbs if ((ahc->user_discenable & devinfo.target_mask) != 0) 97465942Sgibbs cts->flags |= CCB_TRANS_DISC_ENB; 97565942Sgibbs 97665942Sgibbs if ((ahc->user_tagenable & devinfo.target_mask) != 0) 97765942Sgibbs cts->flags |= CCB_TRANS_TAG_ENB; 97865942Sgibbs } else { 97965942Sgibbs if ((tstate->discenable & devinfo.target_mask) != 0) 98065942Sgibbs cts->flags |= CCB_TRANS_DISC_ENB; 98165942Sgibbs 98265942Sgibbs if ((tstate->tagenable & devinfo.target_mask) != 0) 98365942Sgibbs cts->flags |= CCB_TRANS_TAG_ENB; 98465942Sgibbs } 98565942Sgibbs cts->sync_period = tinfo->period; 98665942Sgibbs cts->sync_offset = tinfo->offset; 98765942Sgibbs cts->bus_width = tinfo->width; 98865942Sgibbs 98965942Sgibbs ahc_unlock(ahc, &s); 99065942Sgibbs 99165942Sgibbs cts->valid = CCB_TRANS_SYNC_RATE_VALID 99265942Sgibbs | CCB_TRANS_SYNC_OFFSET_VALID 99366717Sgibbs | CCB_TRANS_BUS_WIDTH_VALID; 99465942Sgibbs 99566717Sgibbs if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) 99666717Sgibbs cts->valid |= CCB_TRANS_DISC_VALID|CCB_TRANS_TQ_VALID; 99766717Sgibbs 99865942Sgibbs cts->ccb_h.status = CAM_REQ_CMP; 99965942Sgibbs#endif 100065942Sgibbs} 100165942Sgibbs 100265942Sgibbsstatic void 100365942Sgibbsahc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) 100465942Sgibbs{ 100565942Sgibbs struct ahc_softc *ahc; 100665942Sgibbs struct cam_sim *sim; 100765942Sgibbs 100865942Sgibbs sim = (struct cam_sim *)callback_arg; 100965942Sgibbs ahc = (struct ahc_softc *)cam_sim_softc(sim); 101065942Sgibbs switch (code) { 101165942Sgibbs case AC_LOST_DEVICE: 101265942Sgibbs { 101365942Sgibbs struct ahc_devinfo devinfo; 101465942Sgibbs long s; 101565942Sgibbs 101665942Sgibbs ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), 101765942Sgibbs xpt_path_target_id(path), 101865942Sgibbs xpt_path_lun_id(path), 101965942Sgibbs SIM_CHANNEL(ahc, sim), 102065942Sgibbs ROLE_UNKNOWN); 102165942Sgibbs 102265942Sgibbs /* 102365942Sgibbs * Revert to async/narrow transfers 102465942Sgibbs * for the next device. 102565942Sgibbs */ 102665942Sgibbs ahc_lock(ahc, &s); 102765942Sgibbs ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, 102865942Sgibbs AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE); 102965942Sgibbs ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL, 103065942Sgibbs /*period*/0, /*offset*/0, /*ppr_options*/0, 103165942Sgibbs AHC_TRANS_GOAL|AHC_TRANS_CUR, 103265942Sgibbs /*paused*/FALSE); 103365942Sgibbs ahc_unlock(ahc, &s); 103465942Sgibbs break; 103565942Sgibbs } 103665942Sgibbs default: 103765942Sgibbs break; 103865942Sgibbs } 103965942Sgibbs} 104065942Sgibbs 104165942Sgibbsstatic void 104265942Sgibbsahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, 104365942Sgibbs int error) 104465942Sgibbs{ 104566717Sgibbs struct scb *scb; 104666717Sgibbs union ccb *ccb; 104766717Sgibbs struct ahc_softc *ahc; 104866717Sgibbs struct ahc_initiator_tinfo *tinfo; 104966717Sgibbs struct tmode_tstate *tstate; 105066717Sgibbs u_int mask; 105166717Sgibbs long s; 105265942Sgibbs 105365942Sgibbs scb = (struct scb *)arg; 105465942Sgibbs ccb = scb->io_ctx; 105565942Sgibbs ahc = (struct ahc_softc *)ccb->ccb_h.ccb_ahc_ptr; 105665942Sgibbs 105765942Sgibbs if (error != 0) { 105865942Sgibbs if (error == EFBIG) 105965942Sgibbs ahc_set_transaction_status(scb, CAM_REQ_TOO_BIG); 106065942Sgibbs else 106165942Sgibbs ahc_set_transaction_status(scb, CAM_REQ_CMP_ERR); 106265942Sgibbs if (nsegments != 0) 106365942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); 106466647Sgibbs ahc_lock(ahc, &s); 106565942Sgibbs ahc_free_scb(ahc, scb); 106666647Sgibbs ahc_unlock(ahc, &s); 106765942Sgibbs xpt_done(ccb); 106865942Sgibbs return; 106965942Sgibbs } 107065942Sgibbs if (nsegments != 0) { 107165942Sgibbs struct ahc_dma_seg *sg; 107265942Sgibbs bus_dma_segment_t *end_seg; 107365942Sgibbs bus_dmasync_op_t op; 107465942Sgibbs 107565942Sgibbs end_seg = dm_segs + nsegments; 107665942Sgibbs 107765942Sgibbs /* Copy the segments into our SG list */ 107865942Sgibbs sg = scb->sg_list; 107965942Sgibbs while (dm_segs < end_seg) { 108065942Sgibbs sg->addr = dm_segs->ds_addr; 108165942Sgibbs/* XXX Add in the 5th byte of the address later. */ 108265942Sgibbs sg->len = dm_segs->ds_len; 108365942Sgibbs sg++; 108465942Sgibbs dm_segs++; 108565942Sgibbs } 108665942Sgibbs 108765942Sgibbs /* 108865942Sgibbs * Note where to find the SG entries in bus space. 108965942Sgibbs * We also set the full residual flag which the 109065942Sgibbs * sequencer will clear as soon as a data transfer 109165942Sgibbs * occurs. 109265942Sgibbs */ 109365942Sgibbs scb->hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; 109465942Sgibbs 109565942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 109665942Sgibbs op = BUS_DMASYNC_PREREAD; 109765942Sgibbs else 109865942Sgibbs op = BUS_DMASYNC_PREWRITE; 109965942Sgibbs 110065942Sgibbs bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op); 110165942Sgibbs 110265942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 110365942Sgibbs struct target_data *tdata; 110465942Sgibbs 110565942Sgibbs tdata = &scb->hscb->shared_data.tdata; 110665942Sgibbs tdata->target_phases |= DPHASE_PENDING; 110765942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 110865942Sgibbs tdata->data_phase = P_DATAOUT; 110965942Sgibbs else 111065942Sgibbs tdata->data_phase = P_DATAIN; 111165942Sgibbs 111265942Sgibbs /* 111365942Sgibbs * If the transfer is of an odd length and in the 111465942Sgibbs * "in" direction (scsi->HostBus), then it may 111565942Sgibbs * trigger a bug in the 'WideODD' feature of 111665942Sgibbs * non-Ultra2 chips. Force the total data-length 111765942Sgibbs * to be even by adding an extra, 1 byte, SG, 111865942Sgibbs * element. We do this even if we are not currently 111965942Sgibbs * negotiated wide as negotiation could occur before 112065942Sgibbs * this command is executed. 112165942Sgibbs */ 112265942Sgibbs if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0 112365942Sgibbs && (ccb->csio.dxfer_len & 0x1) != 0 112465942Sgibbs && (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 112565942Sgibbs 112665942Sgibbs nsegments++; 112765942Sgibbs if (nsegments > AHC_NSEG) { 112865942Sgibbs 112965942Sgibbs ahc_set_transaction_status(scb, 113065942Sgibbs CAM_REQ_TOO_BIG); 113165942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, 113265942Sgibbs scb->dmamap); 113366647Sgibbs ahc_lock(ahc, &s); 113465942Sgibbs ahc_free_scb(ahc, scb); 113566647Sgibbs ahc_unlock(ahc, &s); 113665942Sgibbs xpt_done(ccb); 113765942Sgibbs return; 113865942Sgibbs } 113965942Sgibbs sg->addr = ahc->dma_bug_buf; 114065942Sgibbs sg->len = 1; 114165942Sgibbs sg++; 114265942Sgibbs } 114365942Sgibbs } 114465942Sgibbs sg--; 114565942Sgibbs sg->len |= AHC_DMA_LAST_SEG; 114665942Sgibbs 114765942Sgibbs /* Copy the first SG into the "current" data pointer area */ 114865942Sgibbs scb->hscb->dataptr = scb->sg_list->addr; 114965942Sgibbs scb->hscb->datacnt = scb->sg_list->len; 115065942Sgibbs } else { 115165942Sgibbs scb->hscb->sgptr = SG_LIST_NULL; 115265942Sgibbs scb->hscb->dataptr = 0; 115365942Sgibbs scb->hscb->datacnt = 0; 115465942Sgibbs } 115565942Sgibbs 115665942Sgibbs scb->sg_count = nsegments; 115765942Sgibbs 115865942Sgibbs ahc_lock(ahc, &s); 115965942Sgibbs 116065942Sgibbs /* 116165942Sgibbs * Last time we need to check if this SCB needs to 116265942Sgibbs * be aborted. 116365942Sgibbs */ 116465942Sgibbs if (ahc_get_transaction_status(scb) != CAM_REQ_INPROG) { 116565942Sgibbs if (nsegments != 0) 116665942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, 116765942Sgibbs scb->dmamap); 116865942Sgibbs ahc_free_scb(ahc, scb); 116966647Sgibbs ahc_unlock(ahc, &s); 117065942Sgibbs xpt_done(ccb); 117165942Sgibbs return; 117265942Sgibbs } 117365942Sgibbs 117466717Sgibbs tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid), 117566717Sgibbs SCSIID_OUR_ID(scb->hscb->scsiid), 117666717Sgibbs ccb->ccb_h.target_id, &tstate); 117766717Sgibbs 117866717Sgibbs mask = SCB_GET_TARGET_MASK(ahc, scb); 117966717Sgibbs scb->hscb->scsirate = tinfo->scsirate; 118066717Sgibbs scb->hscb->scsioffset = tinfo->current.offset; 118166717Sgibbs if ((tstate->ultraenb & mask) != 0) 118266717Sgibbs scb->hscb->control |= ULTRAENB; 118366717Sgibbs 118466717Sgibbs if ((tstate->discenable & mask) != 0 118566717Sgibbs && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0) 118666717Sgibbs scb->hscb->control |= DISCENB; 118766717Sgibbs 118866717Sgibbs if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0 118966717Sgibbs && (tinfo->current.width != 0 || tinfo->current.period != 0)) { 119066717Sgibbs scb->flags |= SCB_NEGOTIATE; 119166717Sgibbs scb->hscb->control |= MK_MESSAGE; 119266717Sgibbs } 119366717Sgibbs 119465942Sgibbs LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); 119565942Sgibbs 119665942Sgibbs ccb->ccb_h.status |= CAM_SIM_QUEUED; 119765942Sgibbs 119865942Sgibbs if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { 119965942Sgibbs if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) 120065942Sgibbs ccb->ccb_h.timeout = 5 * 1000; 120165942Sgibbs ccb->ccb_h.timeout_ch = 120265942Sgibbs timeout(ahc_timeout, (caddr_t)scb, 120365942Sgibbs (ccb->ccb_h.timeout * hz) / 1000); 120465942Sgibbs } 120565942Sgibbs 120665942Sgibbs /* 120765942Sgibbs * We only allow one untagged transaction 120865942Sgibbs * per target in the initiator role unless 120965942Sgibbs * we are storing a full busy target *lun* 121065942Sgibbs * table in SCB space. 121165942Sgibbs */ 121265942Sgibbs if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0 121365942Sgibbs && (ahc->features & AHC_SCB_BTT) == 0) { 121465942Sgibbs struct scb_tailq *untagged_q; 121565942Sgibbs 121665942Sgibbs untagged_q = &(ahc->untagged_queues[ccb->ccb_h.target_id]); 121765942Sgibbs TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); 121865942Sgibbs if (TAILQ_FIRST(untagged_q) != scb) { 121965942Sgibbs ahc_unlock(ahc, &s); 122065942Sgibbs return; 122165942Sgibbs } 122265942Sgibbs } 122365942Sgibbs scb->flags |= SCB_ACTIVE; 122465942Sgibbs 122565942Sgibbs if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { 122665942Sgibbs pause_sequencer(ahc); 122765942Sgibbs if ((ahc->flags & AHC_PAGESCBS) == 0) 122865942Sgibbs ahc_outb(ahc, SCBPTR, scb->hscb->tag); 122965942Sgibbs ahc_outb(ahc, SCB_TAG, scb->hscb->tag); 123065942Sgibbs ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP); 123165942Sgibbs unpause_sequencer(ahc); 123265942Sgibbs } else { 123365942Sgibbs ahc_queue_scb(ahc, scb); 123465942Sgibbs } 123565942Sgibbs 123665942Sgibbs ahc_unlock(ahc, &s); 123765942Sgibbs} 123865942Sgibbs 123965942Sgibbsstatic void 124065942Sgibbsahc_poll(struct cam_sim *sim) 124165942Sgibbs{ 124265942Sgibbs ahc_intr(cam_sim_softc(sim)); 124365942Sgibbs} 124465942Sgibbs 124565942Sgibbsstatic void 124665942Sgibbsahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, 124765942Sgibbs struct ccb_scsiio *csio, struct scb *scb) 124865942Sgibbs{ 124965942Sgibbs struct hardware_scb *hscb; 125065942Sgibbs struct ccb_hdr *ccb_h; 125165942Sgibbs 125265942Sgibbs hscb = scb->hscb; 125365942Sgibbs ccb_h = &csio->ccb_h; 125465942Sgibbs 125565942Sgibbs if (ccb_h->func_code == XPT_SCSI_IO) { 125665942Sgibbs hscb->cdb_len = csio->cdb_len; 125765942Sgibbs if ((ccb_h->flags & CAM_CDB_POINTER) != 0) { 125865942Sgibbs 125965942Sgibbs if (hscb->cdb_len > sizeof(hscb->cdb32) 126065942Sgibbs || (ccb_h->flags & CAM_CDB_PHYS) != 0) { 126166647Sgibbs u_long s; 126266647Sgibbs 126365942Sgibbs ahc_set_transaction_status(scb, 126465942Sgibbs CAM_REQ_INVALID); 126566647Sgibbs ahc_lock(ahc, &s); 126665942Sgibbs ahc_free_scb(ahc, scb); 126766647Sgibbs ahc_unlock(ahc, &s); 126866647Sgibbs xpt_done((union ccb *)csio); 126965942Sgibbs return; 127065942Sgibbs } 127165942Sgibbs if (hscb->cdb_len > 12) { 127265942Sgibbs memcpy(hscb->cdb32, 127365942Sgibbs csio->cdb_io.cdb_ptr, 127465942Sgibbs hscb->cdb_len); 127565942Sgibbs hscb->shared_data.cdb_ptr = scb->cdb32_busaddr; 127665942Sgibbs } else { 127765942Sgibbs memcpy(hscb->shared_data.cdb, 127865942Sgibbs csio->cdb_io.cdb_ptr, 127965942Sgibbs hscb->cdb_len); 128065942Sgibbs } 128165942Sgibbs } else { 128265942Sgibbs if (hscb->cdb_len > 12) { 128365942Sgibbs memcpy(hscb->cdb32, csio->cdb_io.cdb_bytes, 128465942Sgibbs hscb->cdb_len); 128565942Sgibbs hscb->shared_data.cdb_ptr = scb->cdb32_busaddr; 128665942Sgibbs } else { 128765942Sgibbs memcpy(hscb->shared_data.cdb, 128865942Sgibbs csio->cdb_io.cdb_bytes, 128965942Sgibbs hscb->cdb_len); 129065942Sgibbs } 129165942Sgibbs } 129265942Sgibbs } 129365942Sgibbs 129465942Sgibbs /* Only use S/G if there is a transfer */ 129565942Sgibbs if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 129665942Sgibbs if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { 129765942Sgibbs /* We've been given a pointer to a single buffer */ 129865942Sgibbs if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { 129965942Sgibbs int s; 130065942Sgibbs int error; 130165942Sgibbs 130265942Sgibbs s = splsoftvm(); 130365942Sgibbs error = bus_dmamap_load(ahc->buffer_dmat, 130465942Sgibbs scb->dmamap, 130565942Sgibbs csio->data_ptr, 130665942Sgibbs csio->dxfer_len, 130765942Sgibbs ahc_execute_scb, 130865942Sgibbs scb, /*flags*/0); 130965942Sgibbs if (error == EINPROGRESS) { 131065942Sgibbs /* 131165942Sgibbs * So as to maintain ordering, 131265942Sgibbs * freeze the controller queue 131365942Sgibbs * until our mapping is 131465942Sgibbs * returned. 131565942Sgibbs */ 131665942Sgibbs xpt_freeze_simq(sim, 131765942Sgibbs /*count*/1); 131865942Sgibbs scb->io_ctx->ccb_h.status |= 131965942Sgibbs CAM_RELEASE_SIMQ; 132065942Sgibbs } 132165942Sgibbs splx(s); 132265942Sgibbs } else { 132365942Sgibbs struct bus_dma_segment seg; 132465942Sgibbs 132565942Sgibbs /* Pointer to physical buffer */ 132665942Sgibbs if (csio->dxfer_len > AHC_MAXTRANSFER_SIZE) 132765942Sgibbs panic("ahc_setup_data - Transfer size " 132865942Sgibbs "larger than can device max"); 132965942Sgibbs 133065942Sgibbs seg.ds_addr = (bus_addr_t)csio->data_ptr; 133165942Sgibbs seg.ds_len = csio->dxfer_len; 133265942Sgibbs ahc_execute_scb(scb, &seg, 1, 0); 133365942Sgibbs } 133465942Sgibbs } else { 133565942Sgibbs struct bus_dma_segment *segs; 133665942Sgibbs 133765942Sgibbs if ((ccb_h->flags & CAM_DATA_PHYS) != 0) 133865942Sgibbs panic("ahc_setup_data - Physical segment " 133965942Sgibbs "pointers unsupported"); 134065942Sgibbs 134165942Sgibbs if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) 134265942Sgibbs panic("ahc_setup_data - Virtual segment " 134365942Sgibbs "addresses unsupported"); 134465942Sgibbs 134565942Sgibbs /* Just use the segments provided */ 134665942Sgibbs segs = (struct bus_dma_segment *)csio->data_ptr; 134765942Sgibbs ahc_execute_scb(scb, segs, csio->sglist_cnt, 0); 134865942Sgibbs } 134965942Sgibbs } else { 135065942Sgibbs ahc_execute_scb(scb, NULL, 0, 0); 135165942Sgibbs } 135265942Sgibbs} 135365942Sgibbs 135465942Sgibbsstatic void 135565942Sgibbsahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb) { 135665942Sgibbs 135765942Sgibbs if ((scb->flags & SCB_RECOVERY_SCB) == 0) { 135865942Sgibbs struct scb *list_scb; 135965942Sgibbs 136065942Sgibbs scb->flags |= SCB_RECOVERY_SCB; 136165942Sgibbs 136265942Sgibbs /* 136365942Sgibbs * Take all queued, but not sent SCBs out of the equation. 136465942Sgibbs * Also ensure that no new CCBs are queued to us while we 136565942Sgibbs * try to fix this problem. 136665942Sgibbs */ 136765942Sgibbs if ((scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 136865942Sgibbs xpt_freeze_simq(SCB_GET_SIM(ahc, scb), /*count*/1); 136965942Sgibbs scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; 137065942Sgibbs } 137165942Sgibbs 137265942Sgibbs /* 137365942Sgibbs * Go through all of our pending SCBs and remove 137465942Sgibbs * any scheduled timeouts for them. We will reschedule 137565942Sgibbs * them after we've successfully fixed this problem. 137665942Sgibbs */ 137765942Sgibbs LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { 137865942Sgibbs union ccb *ccb; 137965942Sgibbs 138065942Sgibbs ccb = list_scb->io_ctx; 138165942Sgibbs untimeout(ahc_timeout, list_scb, ccb->ccb_h.timeout_ch); 138265942Sgibbs } 138365942Sgibbs } 138465942Sgibbs} 138565942Sgibbs 138665942Sgibbsvoid 138765942Sgibbsahc_timeout(void *arg) 138865942Sgibbs{ 138965942Sgibbs struct scb *scb; 139065942Sgibbs struct ahc_softc *ahc; 139165942Sgibbs long s; 139265942Sgibbs int found; 139365942Sgibbs u_int last_phase; 139465942Sgibbs int target; 139565942Sgibbs int lun; 139665942Sgibbs int i; 139765942Sgibbs char channel; 139865942Sgibbs 139965942Sgibbs scb = (struct scb *)arg; 140065942Sgibbs ahc = (struct ahc_softc *)scb->io_ctx->ccb_h.ccb_ahc_ptr; 140165942Sgibbs 140265942Sgibbs ahc_lock(ahc, &s); 140365942Sgibbs 140465942Sgibbs /* 140565942Sgibbs * Ensure that the card doesn't do anything 140665942Sgibbs * behind our back. Also make sure that we 140765942Sgibbs * didn't "just" miss an interrupt that would 140865942Sgibbs * affect this timeout. 140965942Sgibbs */ 141065942Sgibbs do { 141165942Sgibbs ahc_intr(ahc); 141265942Sgibbs pause_sequencer(ahc); 141365942Sgibbs } while (ahc_inb(ahc, INTSTAT) & INT_PEND); 141465942Sgibbs 141565942Sgibbs ahc_print_path(ahc, scb); 141665942Sgibbs if ((scb->flags & SCB_ACTIVE) == 0) { 141765942Sgibbs /* Previous timeout took care of me already */ 141865942Sgibbs printf("Timedout SCB %d handled by another timeout\n", 141965942Sgibbs scb->hscb->tag); 142065942Sgibbs unpause_sequencer(ahc); 142165942Sgibbs ahc_unlock(ahc, &s); 142265942Sgibbs return; 142365942Sgibbs } 142465942Sgibbs 142565942Sgibbs target = SCB_GET_TARGET(ahc, scb); 142665942Sgibbs channel = SCB_GET_CHANNEL(ahc, scb); 142765942Sgibbs lun = SCB_GET_LUN(scb); 142865942Sgibbs 142965942Sgibbs printf("SCB 0x%x - timed out ", scb->hscb->tag); 143065942Sgibbs /* 143165942Sgibbs * Take a snapshot of the bus state and print out 143265942Sgibbs * some information so we can track down driver bugs. 143365942Sgibbs */ 143465942Sgibbs last_phase = ahc_inb(ahc, LASTPHASE); 143565942Sgibbs 143665942Sgibbs for (i = 0; i < num_phases; i++) { 143765942Sgibbs if (last_phase == phase_table[i].phase) 143865942Sgibbs break; 143965942Sgibbs } 144065942Sgibbs printf("%s", phase_table[i].phasemsg); 144165942Sgibbs 144265942Sgibbs printf(", SEQADDR == 0x%x\n", 144365942Sgibbs ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); 144465942Sgibbs 144565942Sgibbs if (scb->sg_count > 0) { 144665942Sgibbs for (i = 0; i < scb->sg_count; i++) { 144765942Sgibbs printf("sg[%d] - Addr 0x%x : Length %d\n", 144865942Sgibbs i, 144965942Sgibbs scb->sg_list[i].addr, 145065942Sgibbs scb->sg_list[i].len); 145165942Sgibbs } 145265942Sgibbs } 145365942Sgibbs if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { 145465942Sgibbs /* 145565942Sgibbs * Been down this road before. 145665942Sgibbs * Do a full bus reset. 145765942Sgibbs */ 145865942Sgibbsbus_reset: 145965942Sgibbs ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); 146065942Sgibbs found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE); 146165942Sgibbs printf("%s: Issued Channel %c Bus Reset. " 146265942Sgibbs "%d SCBs aborted\n", ahc_name(ahc), channel, found); 146365942Sgibbs } else { 146465942Sgibbs /* 146565942Sgibbs * If we are a target, transition to bus free and report 146665942Sgibbs * the timeout. 146765942Sgibbs * 146865942Sgibbs * The target/initiator that is holding up the bus may not 146965942Sgibbs * be the same as the one that triggered this timeout 147065942Sgibbs * (different commands have different timeout lengths). 147165942Sgibbs * If the bus is idle and we are actiing as the initiator 147265942Sgibbs * for this request, queue a BDR message to the timed out 147365942Sgibbs * target. Otherwise, if the timed out transaction is 147465942Sgibbs * active: 147565942Sgibbs * Initiator transaction: 147665942Sgibbs * Stuff the message buffer with a BDR message and assert 147765942Sgibbs * ATN in the hopes that the target will let go of the bus 147865942Sgibbs * and go to the mesgout phase. If this fails, we'll 147965942Sgibbs * get another timeout 2 seconds later which will attempt 148065942Sgibbs * a bus reset. 148165942Sgibbs * 148265942Sgibbs * Target transaction: 148365942Sgibbs * Transition to BUS FREE and report the error. 148465942Sgibbs * It's good to be the target! 148565942Sgibbs */ 148665942Sgibbs u_int active_scb_index; 148765942Sgibbs 148865942Sgibbs active_scb_index = ahc_inb(ahc, SCB_TAG); 148965942Sgibbs 149065942Sgibbs if (last_phase != P_BUSFREE 149165942Sgibbs && (active_scb_index < ahc->scb_data->numscbs)) { 149265942Sgibbs struct scb *active_scb; 149365942Sgibbs 149465942Sgibbs /* 149565942Sgibbs * If the active SCB is not from our device, 149665942Sgibbs * assume that another device is hogging the bus 149765942Sgibbs * and wait for it's timeout to expire before 149865942Sgibbs * taking additional action. 149965942Sgibbs */ 150065942Sgibbs active_scb = &ahc->scb_data->scbarray[active_scb_index]; 150165942Sgibbs if (active_scb->hscb->scsiid != scb->hscb->scsiid 150265942Sgibbs || active_scb->hscb->lun != scb->hscb->lun) { 150365942Sgibbs struct ccb_hdr *ccbh; 150465942Sgibbs u_int newtimeout; 150565942Sgibbs 150665942Sgibbs ahc_print_path(ahc, scb); 150765942Sgibbs printf("Other SCB Timeout%s", 150865942Sgibbs (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 150965942Sgibbs ? " again\n" : "\n"); 151065942Sgibbs scb->flags |= SCB_OTHERTCL_TIMEOUT; 151165942Sgibbs newtimeout = 151265942Sgibbs MAX(active_scb->io_ctx->ccb_h.timeout, 151365942Sgibbs scb->io_ctx->ccb_h.timeout); 151465942Sgibbs ccbh = &scb->io_ctx->ccb_h; 151565942Sgibbs scb->io_ctx->ccb_h.timeout_ch = 151665942Sgibbs timeout(ahc_timeout, scb, 151765942Sgibbs (newtimeout * hz) / 1000); 151865942Sgibbs ahc_unlock(ahc, &s); 151965942Sgibbs return; 152065942Sgibbs } 152165942Sgibbs 152265942Sgibbs /* It's us */ 152365942Sgibbs if ((scb->hscb->control & TARGET_SCB) != 0) { 152465942Sgibbs 152565942Sgibbs /* 152665942Sgibbs * Send back any queued up transactions 152765942Sgibbs * and properly record the error condition. 152865942Sgibbs */ 152965942Sgibbs ahc_freeze_devq(ahc, scb); 153065942Sgibbs ahc_set_transaction_status(scb, 153165942Sgibbs CAM_CMD_TIMEOUT); 153265942Sgibbs ahc_freeze_scb(scb); 153365942Sgibbs ahc_done(ahc, scb); 153465942Sgibbs 153565942Sgibbs /* Will clear us from the bus */ 153665942Sgibbs restart_sequencer(ahc); 153766717Sgibbs ahc_unlock(ahc, &s); 153865942Sgibbs return; 153965942Sgibbs } 154065942Sgibbs 154165942Sgibbs ahc_set_recoveryscb(ahc, active_scb); 154265942Sgibbs ahc_outb(ahc, MSG_OUT, MSG_BUS_DEV_RESET); 154365942Sgibbs ahc_outb(ahc, SCSISIGO, last_phase|ATNO); 154465942Sgibbs ahc_print_path(ahc, active_scb); 154565942Sgibbs printf("BDR message in message buffer\n"); 154665942Sgibbs active_scb->flags |= SCB_DEVICE_RESET; 154765942Sgibbs active_scb->io_ctx->ccb_h.timeout_ch = 154865942Sgibbs timeout(ahc_timeout, (caddr_t)active_scb, 2 * hz); 154965942Sgibbs unpause_sequencer(ahc); 155065942Sgibbs } else { 155165942Sgibbs int disconnected; 155265942Sgibbs 155365942Sgibbs /* XXX Shouldn't panic. Just punt instead */ 155465942Sgibbs if ((scb->hscb->control & TARGET_SCB) != 0) 155565942Sgibbs panic("Timed-out target SCB but bus idle"); 155665942Sgibbs 155765942Sgibbs if (last_phase != P_BUSFREE 155865942Sgibbs && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) { 155965942Sgibbs /* XXX What happened to the SCB? */ 156065942Sgibbs /* Hung target selection. Goto busfree */ 156165942Sgibbs printf("%s: Hung target selection\n", 156265942Sgibbs ahc_name(ahc)); 156365942Sgibbs restart_sequencer(ahc); 156466717Sgibbs ahc_unlock(ahc, &s); 156565942Sgibbs return; 156665942Sgibbs } 156765942Sgibbs 156865942Sgibbs if (ahc_search_qinfifo(ahc, target, channel, lun, 156965942Sgibbs scb->hscb->tag, ROLE_INITIATOR, 157065942Sgibbs /*status*/0, SEARCH_COUNT) > 0) { 157165942Sgibbs disconnected = FALSE; 157265942Sgibbs } else { 157365942Sgibbs disconnected = TRUE; 157465942Sgibbs } 157565942Sgibbs 157665942Sgibbs if (disconnected) { 157765942Sgibbs u_int active_scb; 157865942Sgibbs 157965942Sgibbs ahc_set_recoveryscb(ahc, scb); 158065942Sgibbs /* 158165942Sgibbs * Simply set the MK_MESSAGE control bit. 158265942Sgibbs */ 158365942Sgibbs scb->hscb->control |= MK_MESSAGE; 158465942Sgibbs scb->flags |= SCB_QUEUED_MSG 158565942Sgibbs | SCB_DEVICE_RESET; 158665942Sgibbs 158765942Sgibbs /* 158865942Sgibbs * Mark the cached copy of this SCB in the 158965942Sgibbs * disconnected list too, so that a reconnect 159065942Sgibbs * at this point causes a BDR or abort. 159165942Sgibbs */ 159265942Sgibbs active_scb = ahc_inb(ahc, SCBPTR); 159365942Sgibbs if (ahc_search_disc_list(ahc, target, 159465942Sgibbs channel, lun, 159565942Sgibbs scb->hscb->tag, 159665942Sgibbs /*stop_on_first*/TRUE, 159765942Sgibbs /*remove*/FALSE, 159865942Sgibbs /*save_state*/FALSE)) { 159965942Sgibbs u_int scb_control; 160065942Sgibbs 160165942Sgibbs scb_control = ahc_inb(ahc, SCB_CONTROL); 160265942Sgibbs scb_control |= MK_MESSAGE; 160365942Sgibbs ahc_outb(ahc, SCB_CONTROL, scb_control); 160465942Sgibbs } 160565942Sgibbs ahc_outb(ahc, SCBPTR, active_scb); 160665942Sgibbs 160765942Sgibbs /* 160865942Sgibbs * Actually re-queue this SCB in case we can 160965942Sgibbs * select the device before it reconnects. 161065942Sgibbs * Clear out any entries in the QINFIFO first 161165942Sgibbs * so we are the next SCB for this target 161265942Sgibbs * to run. 161365942Sgibbs */ 161465942Sgibbs ahc_search_qinfifo(ahc, 161565942Sgibbs SCB_GET_TARGET(ahc, scb), 161665942Sgibbs channel, SCB_GET_LUN(scb), 161765942Sgibbs SCB_LIST_NULL, 161865942Sgibbs ROLE_INITIATOR, 161965942Sgibbs CAM_REQUEUE_REQ, 162065942Sgibbs SEARCH_COMPLETE); 162165942Sgibbs ahc_print_path(ahc, scb); 162265942Sgibbs printf("Queuing a BDR SCB\n"); 162365942Sgibbs ahc->qinfifo[ahc->qinfifonext++] = 162465942Sgibbs scb->hscb->tag; 162565942Sgibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 162665942Sgibbs ahc_outb(ahc, HNSCB_QOFF, 162765942Sgibbs ahc->qinfifonext); 162865942Sgibbs } else { 162965942Sgibbs ahc_outb(ahc, KERNEL_QINPOS, 163065942Sgibbs ahc->qinfifonext); 163165942Sgibbs } 163265942Sgibbs scb->io_ctx->ccb_h.timeout_ch = 163365942Sgibbs timeout(ahc_timeout, (caddr_t)scb, 2 * hz); 163465942Sgibbs unpause_sequencer(ahc); 163565942Sgibbs } else { 163665942Sgibbs /* Go "immediatly" to the bus reset */ 163765942Sgibbs /* This shouldn't happen */ 163865942Sgibbs ahc_set_recoveryscb(ahc, scb); 163965942Sgibbs ahc_print_path(ahc, scb); 164065942Sgibbs printf("SCB %d: Immediate reset. " 164165942Sgibbs "Flags = 0x%x\n", scb->hscb->tag, 164265942Sgibbs scb->flags); 164365942Sgibbs goto bus_reset; 164465942Sgibbs } 164565942Sgibbs } 164665942Sgibbs } 164765942Sgibbs ahc_unlock(ahc, &s); 164865942Sgibbs} 164965942Sgibbs 165065942Sgibbsstatic void 165165942Sgibbsahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) 165265942Sgibbs{ 165365942Sgibbs union ccb *abort_ccb; 165465942Sgibbs 165565942Sgibbs abort_ccb = ccb->cab.abort_ccb; 165665942Sgibbs switch (abort_ccb->ccb_h.func_code) { 165765942Sgibbs case XPT_ACCEPT_TARGET_IO: 165865942Sgibbs case XPT_IMMED_NOTIFY: 165965942Sgibbs case XPT_CONT_TARGET_IO: 166065942Sgibbs { 166165942Sgibbs struct tmode_tstate *tstate; 166265942Sgibbs struct tmode_lstate *lstate; 166365942Sgibbs struct ccb_hdr_slist *list; 166465942Sgibbs cam_status status; 166565942Sgibbs 166665942Sgibbs status = ahc_find_tmode_devs(ahc, sim, abort_ccb, &tstate, 166765942Sgibbs &lstate, TRUE); 166865942Sgibbs 166965942Sgibbs if (status != CAM_REQ_CMP) { 167065942Sgibbs ccb->ccb_h.status = status; 167165942Sgibbs break; 167265942Sgibbs } 167365942Sgibbs 167465942Sgibbs if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) 167565942Sgibbs list = &lstate->accept_tios; 167665942Sgibbs else if (abort_ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) 167765942Sgibbs list = &lstate->immed_notifies; 167865942Sgibbs else 167965942Sgibbs list = NULL; 168065942Sgibbs 168165942Sgibbs if (list != NULL) { 168265942Sgibbs struct ccb_hdr *curelm; 168365942Sgibbs int found; 168465942Sgibbs 168565942Sgibbs curelm = SLIST_FIRST(list); 168665942Sgibbs found = 0; 168765942Sgibbs if (curelm == &abort_ccb->ccb_h) { 168865942Sgibbs found = 1; 168965942Sgibbs SLIST_REMOVE_HEAD(list, sim_links.sle); 169065942Sgibbs } else { 169165942Sgibbs while(curelm != NULL) { 169265942Sgibbs struct ccb_hdr *nextelm; 169365942Sgibbs 169465942Sgibbs nextelm = 169565942Sgibbs SLIST_NEXT(curelm, sim_links.sle); 169665942Sgibbs 169765942Sgibbs if (nextelm == &abort_ccb->ccb_h) { 169865942Sgibbs found = 1; 169965942Sgibbs SLIST_NEXT(curelm, 170065942Sgibbs sim_links.sle) = 170165942Sgibbs SLIST_NEXT(nextelm, 170265942Sgibbs sim_links.sle); 170365942Sgibbs break; 170465942Sgibbs } 170565942Sgibbs curelm = nextelm; 170665942Sgibbs } 170765942Sgibbs } 170865942Sgibbs 170965942Sgibbs if (found) { 171065942Sgibbs abort_ccb->ccb_h.status = CAM_REQ_ABORTED; 171165942Sgibbs xpt_done(abort_ccb); 171265942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 171365942Sgibbs } else { 171465942Sgibbs printf("Not found\n"); 171565942Sgibbs ccb->ccb_h.status = CAM_PATH_INVALID; 171665942Sgibbs } 171765942Sgibbs break; 171865942Sgibbs } 171965942Sgibbs /* FALLTHROUGH */ 172065942Sgibbs } 172165942Sgibbs case XPT_SCSI_IO: 172265942Sgibbs /* XXX Fully implement the hard ones */ 172365942Sgibbs ccb->ccb_h.status = CAM_UA_ABORT; 172465942Sgibbs break; 172565942Sgibbs default: 172665942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 172765942Sgibbs break; 172865942Sgibbs } 172965942Sgibbs xpt_done(ccb); 173065942Sgibbs} 173165942Sgibbs 173265942Sgibbsvoid 173366269Sgibbsahc_send_async(struct ahc_softc *ahc, char channel, u_int target, 173466269Sgibbs u_int lun, ac_code code) 173565942Sgibbs{ 173665942Sgibbs struct ccb_trans_settings cts; 173765942Sgibbs struct cam_path *path; 173865942Sgibbs void *arg; 173965942Sgibbs int error; 174065942Sgibbs 174165942Sgibbs arg = NULL; 174266269Sgibbs error = ahc_create_path(ahc, channel, target, lun, &path); 174365942Sgibbs 174465942Sgibbs if (error != CAM_REQ_CMP) 174565942Sgibbs return; 174665942Sgibbs 174765942Sgibbs switch (code) { 174865942Sgibbs case AC_TRANSFER_NEG: 174965942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 175065942Sgibbs cts.type = CTS_TYPE_CURRENT_SETTINGS; 175165942Sgibbs#else 175265942Sgibbs cts.flags = CCB_TRANS_CURRENT_SETTINGS; 175365942Sgibbs#endif 175465942Sgibbs cts.ccb_h.path = path; 175566269Sgibbs cts.ccb_h.target_id = target; 175666269Sgibbs cts.ccb_h.target_lun = lun; 175766269Sgibbs ahc_get_tran_settings(ahc, channel == 'A' ? ahc->our_id 175866269Sgibbs : ahc->our_id_b, 175966269Sgibbs channel, &cts); 176065942Sgibbs arg = &cts; 176165942Sgibbs break; 176265942Sgibbs case AC_SENT_BDR: 176365942Sgibbs case AC_BUS_RESET: 176465942Sgibbs break; 176565942Sgibbs default: 176665942Sgibbs panic("ahc_send_async: Unexpected async event"); 176765942Sgibbs } 176865942Sgibbs xpt_async(code, path, arg); 176965942Sgibbs} 177065942Sgibbs 177165942Sgibbsvoid 177265942Sgibbsahc_platform_set_tags(struct ahc_softc *ahc, 177365942Sgibbs struct ahc_devinfo *devinfo, int enable) 177465942Sgibbs{ 177565942Sgibbs} 177665942Sgibbs 177765942Sgibbsint 177865942Sgibbsahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) 177965942Sgibbs{ 178065942Sgibbs ahc->platform_data = 178165942Sgibbs malloc(sizeof(struct ahc_platform_data), M_DEVBUF, M_NOWAIT); 178265942Sgibbs if (ahc->platform_data == NULL) 178365942Sgibbs return (ENOMEM); 178465942Sgibbs memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); 178565942Sgibbs return (0); 178665942Sgibbs} 178765942Sgibbs 178865942Sgibbsvoid 178965942Sgibbsahc_platform_free(struct ahc_softc *ahc) 179065942Sgibbs{ 179165942Sgibbs if (ahc->platform_data != NULL) { 179265942Sgibbs if (ahc->platform_data->regs != NULL) 179365942Sgibbs bus_release_resource(ahc->dev_softc, 179465942Sgibbs ahc->platform_data->regs_res_type, 179565942Sgibbs ahc->platform_data->regs_res_id, 179665942Sgibbs ahc->platform_data->regs); 179765942Sgibbs 179865942Sgibbs if (ahc->platform_data->irq != NULL) 179965942Sgibbs bus_release_resource(ahc->dev_softc, 180065942Sgibbs ahc->platform_data->irq_res_type, 180165942Sgibbs 0, ahc->platform_data->irq); 180265942Sgibbs 180365942Sgibbs free(ahc->platform_data, M_DEVBUF); 180465942Sgibbs } 180565942Sgibbs} 180665942Sgibbs 180765942Sgibbsint 180865942Sgibbsahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc) 180965942Sgibbs{ 181065942Sgibbs /* We don't sort softcs under FreeBSD so report equal always */ 181165942Sgibbs return (0); 181265942Sgibbs} 181365942Sgibbs 181465942Sgibbs#if UNUSED 181565942Sgibbsstatic void 181665942Sgibbsahc_dump_targcmd(struct target_cmd *cmd) 181765942Sgibbs{ 181865942Sgibbs uint8_t *byte; 181965942Sgibbs uint8_t *last_byte; 182065942Sgibbs int i; 182165942Sgibbs 182265942Sgibbs byte = &cmd->initiator_channel; 182365942Sgibbs /* Debugging info for received commands */ 182465942Sgibbs last_byte = &cmd[1].initiator_channel; 182565942Sgibbs 182665942Sgibbs i = 0; 182765942Sgibbs while (byte < last_byte) { 182865942Sgibbs if (i == 0) 182965942Sgibbs printf("\t"); 183065942Sgibbs printf("%#x", *byte++); 183165942Sgibbs i++; 183265942Sgibbs if (i == 8) { 183365942Sgibbs printf("\n"); 183465942Sgibbs i = 0; 183565942Sgibbs } else { 183665942Sgibbs printf(", "); 183765942Sgibbs } 183865942Sgibbs } 183965942Sgibbs} 184065942Sgibbs#endif 1841