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