aic7xxx_osm.c revision 68402
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 68402 2000-11-06 20:05:38Z 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 if (ahc_get_transaction_status(scb) == CAM_BDR_SENT 32065942Sgibbs || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) 32165942Sgibbs ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); 32265942Sgibbs ahc_print_path(ahc, scb); 32365942Sgibbs printf("no longer in timeout, status = %x\n", 32465942Sgibbs ccb->ccb_h.status); 32565942Sgibbs } 32665942Sgibbs 32765942Sgibbs /* Don't clobber any existing error state */ 32865942Sgibbs if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) { 32965942Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 33065942Sgibbs } else if ((scb->flags & SCB_SENSE) != 0) { 33165942Sgibbs /* 33265942Sgibbs * We performed autosense retrieval. 33365942Sgibbs * 33465942Sgibbs * Zero any sense not transferred by the 33565942Sgibbs * device. The SCSI spec mandates that any 33665942Sgibbs * untransfered data should be assumed to be 33765942Sgibbs * zero. Complete the 'bounce' of sense information 33865942Sgibbs * through buffers accessible via bus-space by 33965942Sgibbs * copying it into the clients csio. 34065942Sgibbs */ 34165942Sgibbs memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data)); 34265942Sgibbs memcpy(&ccb->csio.sense_data, 34365942Sgibbs &ahc->scb_data->sense[scb->hscb->tag], 34465942Sgibbs (scb->sg_list->len & AHC_SG_LEN_MASK) 34565942Sgibbs - ccb->csio.sense_resid); 34665942Sgibbs scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID; 34765942Sgibbs } 34865942Sgibbs ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 34965942Sgibbs ahc_free_scb(ahc, scb); 35065942Sgibbs xpt_done(ccb); 35165942Sgibbs} 35265942Sgibbs 35365942Sgibbsstatic void 35465942Sgibbsahc_action(struct cam_sim *sim, union ccb *ccb) 35565942Sgibbs{ 35665942Sgibbs struct ahc_softc *ahc; 35765942Sgibbs struct tmode_lstate *lstate; 35865942Sgibbs u_int target_id; 35965942Sgibbs u_int our_id; 36065942Sgibbs long s; 36165942Sgibbs 36265942Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahc_action\n")); 36365942Sgibbs 36465942Sgibbs ahc = (struct ahc_softc *)cam_sim_softc(sim); 36565942Sgibbs 36665942Sgibbs target_id = ccb->ccb_h.target_id; 36765942Sgibbs our_id = SIM_SCSI_ID(ahc, sim); 36865942Sgibbs 36965942Sgibbs switch (ccb->ccb_h.func_code) { 37065942Sgibbs /* Common cases first */ 37165942Sgibbs case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 37265942Sgibbs case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/ 37365942Sgibbs { 37465942Sgibbs struct tmode_tstate *tstate; 37565942Sgibbs cam_status status; 37665942Sgibbs 37765942Sgibbs status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, 37865942Sgibbs &lstate, TRUE); 37965942Sgibbs 38065942Sgibbs if (status != CAM_REQ_CMP) { 38165942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 38265942Sgibbs /* Response from the black hole device */ 38365942Sgibbs tstate = NULL; 38465942Sgibbs lstate = ahc->black_hole; 38565942Sgibbs } else { 38665942Sgibbs ccb->ccb_h.status = status; 38765942Sgibbs xpt_done(ccb); 38865942Sgibbs break; 38965942Sgibbs } 39065942Sgibbs } 39165942Sgibbs if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { 39265942Sgibbs 39365942Sgibbs ahc_lock(ahc, &s); 39465942Sgibbs SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h, 39565942Sgibbs sim_links.sle); 39665942Sgibbs ccb->ccb_h.status = CAM_REQ_INPROG; 39765942Sgibbs if ((ahc->flags & AHC_TQINFIFO_BLOCKED) != 0) 39865942Sgibbs ahc_run_tqinfifo(ahc, /*paused*/FALSE); 39965942Sgibbs ahc_unlock(ahc, &s); 40065942Sgibbs break; 40165942Sgibbs } 40265942Sgibbs 40365942Sgibbs /* 40465942Sgibbs * The target_id represents the target we attempt to 40565942Sgibbs * select. In target mode, this is the initiator of 40665942Sgibbs * the original command. 40765942Sgibbs */ 40865942Sgibbs our_id = target_id; 40965942Sgibbs target_id = ccb->csio.init_id; 41065942Sgibbs /* FALLTHROUGH */ 41165942Sgibbs } 41265942Sgibbs case XPT_SCSI_IO: /* Execute the requested I/O operation */ 41365942Sgibbs case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 41465942Sgibbs { 41566717Sgibbs struct scb *scb; 41666717Sgibbs struct hardware_scb *hscb; 41765942Sgibbs 41868087Sgibbs if ((ahc->flags & AHC_INITIATORROLE) == 0 41968087Sgibbs && (ccb->ccb_h.func_code == XPT_SCSI_IO 42068087Sgibbs || ccb->ccb_h.func_code == XPT_RESET_DEV)) { 42168087Sgibbs ccb->ccb_h.status = CAM_PROVIDE_FAIL; 42268087Sgibbs xpt_done(ccb); 42368087Sgibbs } 42468087Sgibbs 42565942Sgibbs /* 42665942Sgibbs * get an scb to use. 42765942Sgibbs */ 42866717Sgibbs ahc_lock(ahc, &s); 42965942Sgibbs if ((scb = ahc_get_scb(ahc)) == NULL) { 43065942Sgibbs 43166891Sgibbs xpt_freeze_simq(sim, /*count*/1); 43265942Sgibbs ahc->flags |= AHC_RESOURCE_SHORTAGE; 43365942Sgibbs ahc_unlock(ahc, &s); 43466510Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 43565942Sgibbs xpt_done(ccb); 43665942Sgibbs return; 43765942Sgibbs } 43866717Sgibbs ahc_unlock(ahc, &s); 43965942Sgibbs 44065942Sgibbs hscb = scb->hscb; 44165942Sgibbs 44265942Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, 44365942Sgibbs ("start scb(%p)\n", scb)); 44465942Sgibbs scb->io_ctx = ccb; 44565942Sgibbs /* 44665942Sgibbs * So we can find the SCB when an abort is requested 44765942Sgibbs */ 44865942Sgibbs ccb->ccb_h.ccb_scb_ptr = scb; 44965942Sgibbs 45065942Sgibbs /* 45165942Sgibbs * Put all the arguments for the xfer in the scb 45265942Sgibbs */ 45365942Sgibbs hscb->control = 0; 45465942Sgibbs hscb->scsiid = BUILD_SCSIID(ahc, sim, target_id, our_id); 45565942Sgibbs hscb->lun = ccb->ccb_h.target_lun; 45665942Sgibbs if (ccb->ccb_h.func_code == XPT_RESET_DEV) { 45765942Sgibbs hscb->cdb_len = 0; 45865942Sgibbs scb->flags |= SCB_DEVICE_RESET; 45965942Sgibbs hscb->control |= MK_MESSAGE; 46065942Sgibbs ahc_execute_scb(scb, NULL, 0, 0); 46165942Sgibbs } else { 46265942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 46365942Sgibbs struct target_data *tdata; 46465942Sgibbs 46565942Sgibbs tdata = &hscb->shared_data.tdata; 46665942Sgibbs if (ahc->pending_device == lstate) { 46765942Sgibbs scb->flags |= SCB_TARGET_IMMEDIATE; 46865942Sgibbs ahc->pending_device = NULL; 46965942Sgibbs } 47065942Sgibbs hscb->control |= TARGET_SCB; 47165942Sgibbs tdata->target_phases = IDENTIFY_SEEN; 47265942Sgibbs if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { 47365942Sgibbs tdata->target_phases |= SPHASE_PENDING; 47465942Sgibbs tdata->scsi_status = 47565942Sgibbs ccb->csio.scsi_status; 47665942Sgibbs } 47765942Sgibbs tdata->initiator_tag = ccb->csio.tag_id; 47865942Sgibbs } 47965942Sgibbs if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) 48065942Sgibbs hscb->control |= ccb->csio.tag_action; 48165942Sgibbs 48265942Sgibbs ahc_setup_data(ahc, sim, &ccb->csio, scb); 48365942Sgibbs } 48465942Sgibbs break; 48565942Sgibbs } 48665942Sgibbs case XPT_NOTIFY_ACK: 48765942Sgibbs case XPT_IMMED_NOTIFY: 48865942Sgibbs { 48965942Sgibbs struct tmode_tstate *tstate; 49065942Sgibbs struct tmode_lstate *lstate; 49165942Sgibbs cam_status status; 49265942Sgibbs 49365942Sgibbs status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, 49465942Sgibbs &lstate, TRUE); 49565942Sgibbs 49665942Sgibbs if (status != CAM_REQ_CMP) { 49765942Sgibbs ccb->ccb_h.status = status; 49865942Sgibbs xpt_done(ccb); 49965942Sgibbs break; 50065942Sgibbs } 50165942Sgibbs SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h, 50265942Sgibbs sim_links.sle); 50365942Sgibbs ccb->ccb_h.status = CAM_REQ_INPROG; 50465942Sgibbs ahc_send_lstate_events(ahc, lstate); 50565942Sgibbs break; 50665942Sgibbs } 50765942Sgibbs case XPT_EN_LUN: /* Enable LUN as a target */ 50865942Sgibbs ahc_handle_en_lun(ahc, sim, ccb); 50965942Sgibbs xpt_done(ccb); 51065942Sgibbs break; 51165942Sgibbs case XPT_ABORT: /* Abort the specified CCB */ 51265942Sgibbs { 51365942Sgibbs ahc_abort_ccb(ahc, sim, ccb); 51465942Sgibbs break; 51565942Sgibbs } 51665942Sgibbs case XPT_SET_TRAN_SETTINGS: 51765942Sgibbs { 51865942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 51965942Sgibbs struct ahc_devinfo devinfo; 52065942Sgibbs struct ccb_trans_settings *cts; 52165942Sgibbs struct ccb_trans_settings_scsi *scsi; 52265942Sgibbs struct ccb_trans_settings_spi *spi; 52365942Sgibbs struct ahc_initiator_tinfo *tinfo; 52465942Sgibbs struct tmode_tstate *tstate; 52565942Sgibbs uint16_t *discenable; 52665942Sgibbs uint16_t *tagenable; 52765942Sgibbs u_int update_type; 52865942Sgibbs 52965942Sgibbs cts = &ccb->cts; 53065942Sgibbs scsi = &cts->proto_specific.scsi; 53165942Sgibbs spi = &cts->xport_specific.spi; 53265942Sgibbs ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), 53365942Sgibbs cts->ccb_h.target_id, 53465942Sgibbs cts->ccb_h.target_lun, 53565942Sgibbs SIM_CHANNEL(ahc, sim), 53665942Sgibbs ROLE_UNKNOWN); 53765942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, 53865942Sgibbs devinfo.our_scsiid, 53965942Sgibbs devinfo.target, &tstate); 54065942Sgibbs update_type = 0; 54165942Sgibbs if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 54265942Sgibbs update_type |= AHC_TRANS_GOAL; 54365942Sgibbs discenable = &tstate->discenable; 54465942Sgibbs tagenable = &tstate->tagenable; 54565942Sgibbs tinfo->current.protocol_version = 54665942Sgibbs cts->protocol_version; 54765942Sgibbs tinfo->current.transport_version = 54865942Sgibbs cts->transport_version; 54965942Sgibbs tinfo->goal.protocol_version = 55065942Sgibbs cts->protocol_version; 55165942Sgibbs tinfo->goal.transport_version = 55265942Sgibbs cts->transport_version; 55365942Sgibbs } else if (cts->type == CTS_TYPE_USER_SETTINGS) { 55465942Sgibbs update_type |= AHC_TRANS_USER; 55565942Sgibbs discenable = &ahc->user_discenable; 55665942Sgibbs tagenable = &ahc->user_tagenable; 55765942Sgibbs tinfo->user.protocol_version = 55865942Sgibbs cts->protocol_version; 55965942Sgibbs tinfo->user.transport_version = 56065942Sgibbs cts->transport_version; 56165942Sgibbs } else { 56265942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 56365942Sgibbs xpt_done(ccb); 56465942Sgibbs break; 56565942Sgibbs } 56665942Sgibbs 56765942Sgibbs ahc_lock(ahc, &s); 56865942Sgibbs 56965942Sgibbs if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { 57065942Sgibbs if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) 57165942Sgibbs *discenable |= devinfo.target_mask; 57265942Sgibbs else 57365942Sgibbs *discenable &= ~devinfo.target_mask; 57465942Sgibbs } 57565942Sgibbs 57665942Sgibbs if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 57765942Sgibbs if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) 57865942Sgibbs *tagenable |= devinfo.target_mask; 57965942Sgibbs else 58065942Sgibbs *tagenable &= ~devinfo.target_mask; 58165942Sgibbs } 58265942Sgibbs 58365942Sgibbs if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { 58468087Sgibbs ahc_validate_width(ahc, /*tinfo limit*/NULL, 58568087Sgibbs &spi->bus_width, ROLE_UNKNOWN); 58665942Sgibbs ahc_set_width(ahc, &devinfo, spi->bus_width, 58765942Sgibbs update_type, /*paused*/FALSE); 58865942Sgibbs } 58965942Sgibbs 59065942Sgibbs if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) { 59165942Sgibbs if (update_type == AHC_TRANS_USER) 59265942Sgibbs spi->ppr_options = tinfo->user.ppr_options; 59365942Sgibbs else 59465942Sgibbs spi->ppr_options = tinfo->goal.ppr_options; 59565942Sgibbs } 59665942Sgibbs 59765942Sgibbs if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) { 59865942Sgibbs if (update_type == AHC_TRANS_USER) 59965942Sgibbs spi->sync_offset = tinfo->user.offset; 60065942Sgibbs else 60165942Sgibbs spi->sync_offset = tinfo->goal.offset; 60265942Sgibbs } 60365942Sgibbs 60465942Sgibbs if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 60565942Sgibbs if (update_type == AHC_TRANS_USER) 60665942Sgibbs spi->sync_period = tinfo->user.period; 60765942Sgibbs else 60865942Sgibbs spi->sync_period = tinfo->goal.period; 60965942Sgibbs } 61065942Sgibbs 61165942Sgibbs if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) 61265942Sgibbs || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) { 61365942Sgibbs struct ahc_syncrate *syncrate; 61465942Sgibbs u_int maxsync; 61565942Sgibbs 61665942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 61765942Sgibbs maxsync = AHC_SYNCRATE_DT; 61865942Sgibbs else if ((ahc->features & AHC_ULTRA) != 0) 61965942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 62065942Sgibbs else 62165942Sgibbs maxsync = AHC_SYNCRATE_FAST; 62265942Sgibbs 62365942Sgibbs syncrate = ahc_find_syncrate(ahc, &spi->sync_period, 62465942Sgibbs &spi->ppr_options, 62565942Sgibbs maxsync); 62668087Sgibbs ahc_validate_offset(ahc, /*tinfo limit*/NULL, 62768087Sgibbs syncrate, &spi->sync_offset, 62868087Sgibbs spi->bus_width, ROLE_UNKNOWN); 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) { 69568087Sgibbs ahc_validate_width(ahc, /*tinfo limit*/NULL, 69668087Sgibbs &cts->bus_width, ROLE_UNKNOWN); 69765942Sgibbs ahc_set_width(ahc, &devinfo, cts->bus_width, 69865942Sgibbs update_type, /*paused*/FALSE); 69965942Sgibbs } 70065942Sgibbs 70165942Sgibbs if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0) { 70265942Sgibbs if (update_type == AHC_TRANS_USER) 70365942Sgibbs cts->sync_offset = tinfo->user.offset; 70465942Sgibbs else 70565942Sgibbs cts->sync_offset = tinfo->goal.offset; 70665942Sgibbs } 70765942Sgibbs 70865942Sgibbs if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) == 0) { 70965942Sgibbs if (update_type == AHC_TRANS_USER) 71065942Sgibbs cts->sync_period = tinfo->user.period; 71165942Sgibbs else 71265942Sgibbs cts->sync_period = tinfo->goal.period; 71365942Sgibbs } 71465942Sgibbs 71565942Sgibbs if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) 71665942Sgibbs || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) { 71765942Sgibbs struct ahc_syncrate *syncrate; 71865942Sgibbs u_int ppr_options; 71965942Sgibbs u_int maxsync; 72065942Sgibbs 72165942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 72265942Sgibbs maxsync = AHC_SYNCRATE_DT; 72365942Sgibbs else if ((ahc->features & AHC_ULTRA) != 0) 72465942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 72565942Sgibbs else 72665942Sgibbs maxsync = AHC_SYNCRATE_FAST; 72765942Sgibbs 72865942Sgibbs ppr_options = 0; 72965942Sgibbs if (cts->sync_period <= 9) 73065942Sgibbs ppr_options = MSG_EXT_PPR_DT_REQ; 73165942Sgibbs 73265942Sgibbs syncrate = ahc_find_syncrate(ahc, &cts->sync_period, 73365942Sgibbs &ppr_options, 73465942Sgibbs maxsync); 73568087Sgibbs ahc_validate_offset(ahc, /*tinfo limit*/NULL, 73668087Sgibbs syncrate, &cts->sync_offset, 73768087Sgibbs MSG_EXT_WDTR_BUS_8_BIT, 73868087Sgibbs ROLE_UNKNOWN); 73965942Sgibbs 74065942Sgibbs /* We use a period of 0 to represent async */ 74165942Sgibbs if (cts->sync_offset == 0) { 74265942Sgibbs cts->sync_period = 0; 74365942Sgibbs ppr_options = 0; 74465942Sgibbs } 74565942Sgibbs 74665942Sgibbs if (ppr_options == MSG_EXT_PPR_DT_REQ 74765942Sgibbs && tinfo->user.transport_version >= 3) { 74865942Sgibbs tinfo->goal.transport_version = 74965942Sgibbs tinfo->user.transport_version; 75065942Sgibbs tinfo->current.transport_version = 75165942Sgibbs tinfo->user.transport_version; 75265942Sgibbs } 75365942Sgibbs 75465942Sgibbs ahc_set_syncrate(ahc, &devinfo, syncrate, 75565942Sgibbs cts->sync_period, cts->sync_offset, 75665942Sgibbs ppr_options, update_type, 75765942Sgibbs /*paused*/FALSE); 75865942Sgibbs } 75965942Sgibbs ahc_unlock(ahc, &s); 76065942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 76165942Sgibbs xpt_done(ccb); 76265942Sgibbs#endif 76365942Sgibbs break; 76465942Sgibbs } 76565942Sgibbs case XPT_GET_TRAN_SETTINGS: 76665942Sgibbs /* Get default/user set transfer settings for the target */ 76765942Sgibbs { 76865942Sgibbs 76965942Sgibbs ahc_lock(ahc, &s); 77065942Sgibbs ahc_get_tran_settings(ahc, SIM_SCSI_ID(ahc, sim), 77165942Sgibbs SIM_CHANNEL(ahc, sim), &ccb->cts); 77265942Sgibbs ahc_unlock(ahc, &s); 77365942Sgibbs xpt_done(ccb); 77465942Sgibbs break; 77565942Sgibbs } 77665942Sgibbs case XPT_CALC_GEOMETRY: 77765942Sgibbs { 77865942Sgibbs struct ccb_calc_geometry *ccg; 77965942Sgibbs uint32_t size_mb; 78065942Sgibbs uint32_t secs_per_cylinder; 78165942Sgibbs int extended; 78265942Sgibbs 78365942Sgibbs ccg = &ccb->ccg; 78465942Sgibbs size_mb = ccg->volume_size 78565942Sgibbs / ((1024L * 1024L) / ccg->block_size); 78665942Sgibbs extended = SIM_IS_SCSIBUS_B(ahc, sim) 78765942Sgibbs ? ahc->flags & AHC_EXTENDED_TRANS_B 78865942Sgibbs : ahc->flags & AHC_EXTENDED_TRANS_A; 78965942Sgibbs 79065942Sgibbs if (size_mb > 1024 && extended) { 79165942Sgibbs ccg->heads = 255; 79265942Sgibbs ccg->secs_per_track = 63; 79365942Sgibbs } else { 79465942Sgibbs ccg->heads = 64; 79565942Sgibbs ccg->secs_per_track = 32; 79665942Sgibbs } 79765942Sgibbs secs_per_cylinder = ccg->heads * ccg->secs_per_track; 79865942Sgibbs ccg->cylinders = ccg->volume_size / secs_per_cylinder; 79965942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 80065942Sgibbs xpt_done(ccb); 80165942Sgibbs break; 80265942Sgibbs } 80365942Sgibbs case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 80465942Sgibbs { 80565942Sgibbs int found; 80665942Sgibbs 80765942Sgibbs ahc_lock(ahc, &s); 80865942Sgibbs found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim), 80965942Sgibbs /*initiate reset*/TRUE); 81065942Sgibbs ahc_unlock(ahc, &s); 81165942Sgibbs if (bootverbose) { 81265942Sgibbs xpt_print_path(SIM_PATH(ahc, sim)); 81365942Sgibbs printf("SCSI bus reset delivered. " 81465942Sgibbs "%d SCBs aborted.\n", found); 81565942Sgibbs } 81665942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 81765942Sgibbs xpt_done(ccb); 81865942Sgibbs break; 81965942Sgibbs } 82065942Sgibbs case XPT_TERM_IO: /* Terminate the I/O process */ 82165942Sgibbs /* XXX Implement */ 82265942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 82365942Sgibbs xpt_done(ccb); 82465942Sgibbs break; 82565942Sgibbs case XPT_PATH_INQ: /* Path routing inquiry */ 82665942Sgibbs { 82765942Sgibbs struct ccb_pathinq *cpi = &ccb->cpi; 82865942Sgibbs 82965942Sgibbs cpi->version_num = 1; /* XXX??? */ 83065942Sgibbs cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; 83165942Sgibbs if ((ahc->features & AHC_WIDE) != 0) 83265942Sgibbs cpi->hba_inquiry |= PI_WIDE_16; 83368087Sgibbs if ((ahc->features & AHC_TARGETMODE) != 0) { 83465942Sgibbs cpi->target_sprt = PIT_PROCESSOR 83565942Sgibbs | PIT_DISCONNECT 83665942Sgibbs | PIT_TERM_IO; 83765942Sgibbs } else { 83865942Sgibbs cpi->target_sprt = 0; 83965942Sgibbs } 84068087Sgibbs cpi->hba_misc = 0; 84165942Sgibbs cpi->hba_eng_cnt = 0; 84265942Sgibbs cpi->max_target = (ahc->features & AHC_WIDE) ? 15 : 7; 84365942Sgibbs cpi->max_lun = 64; 84465942Sgibbs if (SIM_IS_SCSIBUS_B(ahc, sim)) { 84565942Sgibbs cpi->initiator_id = ahc->our_id_b; 84665942Sgibbs if ((ahc->flags & AHC_RESET_BUS_B) == 0) 84765942Sgibbs cpi->hba_misc |= PIM_NOBUSRESET; 84865942Sgibbs } else { 84965942Sgibbs cpi->initiator_id = ahc->our_id; 85065942Sgibbs if ((ahc->flags & AHC_RESET_BUS_A) == 0) 85165942Sgibbs cpi->hba_misc |= PIM_NOBUSRESET; 85265942Sgibbs } 85365942Sgibbs cpi->bus_id = cam_sim_bus(sim); 85465942Sgibbs cpi->base_transfer_speed = 3300; 85565942Sgibbs strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 85665942Sgibbs strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); 85765942Sgibbs strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 85865942Sgibbs cpi->unit_number = cam_sim_unit(sim); 85965942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 86065942Sgibbs cpi->protocol = PROTO_SCSI; 86165942Sgibbs cpi->protocol_version = SCSI_REV_2; 86265942Sgibbs cpi->transport = XPORT_SPI; 86365942Sgibbs cpi->transport_version = 2; 86465942Sgibbs cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_ST; 86565942Sgibbs if ((ahc->features & AHC_DT) != 0) { 86665942Sgibbs cpi->transport_version = 3; 86765942Sgibbs cpi->xport_specific.spi.ppr_options = 86865942Sgibbs SID_SPI_CLOCK_DT_ST; 86965942Sgibbs } 87065942Sgibbs#endif 87165942Sgibbs cpi->ccb_h.status = CAM_REQ_CMP; 87265942Sgibbs xpt_done(ccb); 87365942Sgibbs break; 87465942Sgibbs } 87565942Sgibbs default: 87668087Sgibbs ccb->ccb_h.status = CAM_PROVIDE_FAIL; 87765942Sgibbs xpt_done(ccb); 87865942Sgibbs break; 87965942Sgibbs } 88065942Sgibbs} 88165942Sgibbs 88265942Sgibbsstatic void 88365942Sgibbsahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel, 88465942Sgibbs struct ccb_trans_settings *cts) 88565942Sgibbs{ 88665942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 88765942Sgibbs struct ahc_devinfo devinfo; 88865942Sgibbs struct ccb_trans_settings_scsi *scsi; 88965942Sgibbs struct ccb_trans_settings_spi *spi; 89065942Sgibbs struct ahc_initiator_tinfo *targ_info; 89165942Sgibbs struct tmode_tstate *tstate; 89265942Sgibbs struct ahc_transinfo *tinfo; 89365942Sgibbs 89465942Sgibbs scsi = &cts->proto_specific.scsi; 89565942Sgibbs spi = &cts->xport_specific.spi; 89665942Sgibbs ahc_compile_devinfo(&devinfo, our_id, 89765942Sgibbs cts->ccb_h.target_id, 89865942Sgibbs cts->ccb_h.target_lun, 89965942Sgibbs channel, ROLE_UNKNOWN); 90065942Sgibbs targ_info = ahc_fetch_transinfo(ahc, devinfo.channel, 90165942Sgibbs devinfo.our_scsiid, 90265942Sgibbs devinfo.target, &tstate); 90365942Sgibbs 90465942Sgibbs if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 90565942Sgibbs tinfo = &targ_info->current; 90665942Sgibbs else 90765942Sgibbs tinfo = &targ_info->user; 90865942Sgibbs 90965942Sgibbs scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 91065942Sgibbs spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 91165942Sgibbs if (cts->type == CTS_TYPE_USER_SETTINGS) { 91265942Sgibbs if ((ahc->user_discenable & devinfo.target_mask) != 0) 91365942Sgibbs spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 91465942Sgibbs 91565942Sgibbs if ((ahc->user_tagenable & devinfo.target_mask) != 0) 91665942Sgibbs scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 91765942Sgibbs } else { 91865942Sgibbs if ((tstate->discenable & devinfo.target_mask) != 0) 91965942Sgibbs spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 92065942Sgibbs 92165942Sgibbs if ((tstate->tagenable & devinfo.target_mask) != 0) 92265942Sgibbs scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 92365942Sgibbs } 92465942Sgibbs cts->protocol_version = tinfo->protocol_version; 92565942Sgibbs cts->transport_version = tinfo->transport_version; 92665942Sgibbs 92765942Sgibbs spi->sync_period = tinfo->period; 92865942Sgibbs spi->sync_offset = tinfo->offset; 92965942Sgibbs spi->bus_width = tinfo->width; 93065942Sgibbs spi->ppr_options = tinfo->ppr_options; 93165942Sgibbs 93265942Sgibbs cts->protocol = PROTO_SCSI; 93365942Sgibbs cts->transport = XPORT_SPI; 93465942Sgibbs spi->valid = CTS_SPI_VALID_SYNC_RATE 93565942Sgibbs | CTS_SPI_VALID_SYNC_OFFSET 93665942Sgibbs | CTS_SPI_VALID_BUS_WIDTH 93765942Sgibbs | CTS_SPI_VALID_PPR_OPTIONS; 93865942Sgibbs 93966717Sgibbs if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 94066717Sgibbs scsi->valid = CTS_SCSI_VALID_TQ; 94166717Sgibbs spi->valid |= CTS_SPI_VALID_DISC; 94266717Sgibbs } else { 94366717Sgibbs scsi->valid = 0; 94466717Sgibbs } 94566717Sgibbs 94665942Sgibbs cts->ccb_h.status = CAM_REQ_CMP; 94765942Sgibbs#else 94865942Sgibbs struct ahc_devinfo devinfo; 94965942Sgibbs struct ahc_initiator_tinfo *targ_info; 95065942Sgibbs struct tmode_tstate *tstate; 95165942Sgibbs struct ahc_transinfo *tinfo; 95265942Sgibbs long s; 95365942Sgibbs 95465942Sgibbs ahc_compile_devinfo(&devinfo, our_id, 95565942Sgibbs cts->ccb_h.target_id, 95665942Sgibbs cts->ccb_h.target_lun, 95765942Sgibbs channel, ROLE_UNKNOWN); 95865942Sgibbs targ_info = ahc_fetch_transinfo(ahc, devinfo.channel, 95965942Sgibbs devinfo.our_scsiid, 96065942Sgibbs devinfo.target, &tstate); 96165942Sgibbs 96265942Sgibbs if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) 96365942Sgibbs tinfo = &targ_info->current; 96465942Sgibbs else 96565942Sgibbs tinfo = &targ_info->user; 96665942Sgibbs 96765942Sgibbs ahc_lock(ahc, &s); 96865942Sgibbs 96965942Sgibbs cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); 97066760Sgibbs if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) == 0) { 97165942Sgibbs if ((ahc->user_discenable & devinfo.target_mask) != 0) 97265942Sgibbs cts->flags |= CCB_TRANS_DISC_ENB; 97365942Sgibbs 97465942Sgibbs if ((ahc->user_tagenable & devinfo.target_mask) != 0) 97565942Sgibbs cts->flags |= CCB_TRANS_TAG_ENB; 97665942Sgibbs } else { 97765942Sgibbs if ((tstate->discenable & devinfo.target_mask) != 0) 97865942Sgibbs cts->flags |= CCB_TRANS_DISC_ENB; 97965942Sgibbs 98065942Sgibbs if ((tstate->tagenable & devinfo.target_mask) != 0) 98165942Sgibbs cts->flags |= CCB_TRANS_TAG_ENB; 98265942Sgibbs } 98365942Sgibbs cts->sync_period = tinfo->period; 98465942Sgibbs cts->sync_offset = tinfo->offset; 98565942Sgibbs cts->bus_width = tinfo->width; 98665942Sgibbs 98765942Sgibbs ahc_unlock(ahc, &s); 98865942Sgibbs 98965942Sgibbs cts->valid = CCB_TRANS_SYNC_RATE_VALID 99065942Sgibbs | CCB_TRANS_SYNC_OFFSET_VALID 99166717Sgibbs | CCB_TRANS_BUS_WIDTH_VALID; 99265942Sgibbs 99366717Sgibbs if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) 99466717Sgibbs cts->valid |= CCB_TRANS_DISC_VALID|CCB_TRANS_TQ_VALID; 99566717Sgibbs 99665942Sgibbs cts->ccb_h.status = CAM_REQ_CMP; 99765942Sgibbs#endif 99865942Sgibbs} 99965942Sgibbs 100065942Sgibbsstatic void 100165942Sgibbsahc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) 100265942Sgibbs{ 100365942Sgibbs struct ahc_softc *ahc; 100465942Sgibbs struct cam_sim *sim; 100565942Sgibbs 100665942Sgibbs sim = (struct cam_sim *)callback_arg; 100765942Sgibbs ahc = (struct ahc_softc *)cam_sim_softc(sim); 100865942Sgibbs switch (code) { 100965942Sgibbs case AC_LOST_DEVICE: 101065942Sgibbs { 101165942Sgibbs struct ahc_devinfo devinfo; 101265942Sgibbs long s; 101365942Sgibbs 101465942Sgibbs ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), 101565942Sgibbs xpt_path_target_id(path), 101665942Sgibbs xpt_path_lun_id(path), 101765942Sgibbs SIM_CHANNEL(ahc, sim), 101865942Sgibbs ROLE_UNKNOWN); 101965942Sgibbs 102065942Sgibbs /* 102165942Sgibbs * Revert to async/narrow transfers 102265942Sgibbs * for the next device. 102365942Sgibbs */ 102465942Sgibbs ahc_lock(ahc, &s); 102565942Sgibbs ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, 102665942Sgibbs AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE); 102765942Sgibbs ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL, 102865942Sgibbs /*period*/0, /*offset*/0, /*ppr_options*/0, 102965942Sgibbs AHC_TRANS_GOAL|AHC_TRANS_CUR, 103065942Sgibbs /*paused*/FALSE); 103165942Sgibbs ahc_unlock(ahc, &s); 103265942Sgibbs break; 103365942Sgibbs } 103465942Sgibbs default: 103565942Sgibbs break; 103665942Sgibbs } 103765942Sgibbs} 103865942Sgibbs 103965942Sgibbsstatic void 104065942Sgibbsahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, 104165942Sgibbs int error) 104265942Sgibbs{ 104366717Sgibbs struct scb *scb; 104466717Sgibbs union ccb *ccb; 104566717Sgibbs struct ahc_softc *ahc; 104666717Sgibbs struct ahc_initiator_tinfo *tinfo; 104766717Sgibbs struct tmode_tstate *tstate; 104866717Sgibbs u_int mask; 104966717Sgibbs long s; 105065942Sgibbs 105165942Sgibbs scb = (struct scb *)arg; 105265942Sgibbs ccb = scb->io_ctx; 105366986Sgibbs ahc = scb->ahc_softc; 105465942Sgibbs 105565942Sgibbs if (error != 0) { 105665942Sgibbs if (error == EFBIG) 105765942Sgibbs ahc_set_transaction_status(scb, CAM_REQ_TOO_BIG); 105865942Sgibbs else 105965942Sgibbs ahc_set_transaction_status(scb, CAM_REQ_CMP_ERR); 106065942Sgibbs if (nsegments != 0) 106165942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); 106266647Sgibbs ahc_lock(ahc, &s); 106365942Sgibbs ahc_free_scb(ahc, scb); 106466647Sgibbs ahc_unlock(ahc, &s); 106565942Sgibbs xpt_done(ccb); 106665942Sgibbs return; 106765942Sgibbs } 106865942Sgibbs if (nsegments != 0) { 106965942Sgibbs struct ahc_dma_seg *sg; 107065942Sgibbs bus_dma_segment_t *end_seg; 107165942Sgibbs bus_dmasync_op_t op; 107265942Sgibbs 107365942Sgibbs end_seg = dm_segs + nsegments; 107465942Sgibbs 107565942Sgibbs /* Copy the segments into our SG list */ 107665942Sgibbs sg = scb->sg_list; 107765942Sgibbs while (dm_segs < end_seg) { 107865942Sgibbs sg->addr = dm_segs->ds_addr; 107965942Sgibbs/* XXX Add in the 5th byte of the address later. */ 108065942Sgibbs sg->len = dm_segs->ds_len; 108165942Sgibbs sg++; 108265942Sgibbs dm_segs++; 108365942Sgibbs } 108465942Sgibbs 108565942Sgibbs /* 108665942Sgibbs * Note where to find the SG entries in bus space. 108765942Sgibbs * We also set the full residual flag which the 108865942Sgibbs * sequencer will clear as soon as a data transfer 108965942Sgibbs * occurs. 109065942Sgibbs */ 109165942Sgibbs scb->hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; 109265942Sgibbs 109365942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 109465942Sgibbs op = BUS_DMASYNC_PREREAD; 109565942Sgibbs else 109665942Sgibbs op = BUS_DMASYNC_PREWRITE; 109765942Sgibbs 109865942Sgibbs bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op); 109965942Sgibbs 110065942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 110165942Sgibbs struct target_data *tdata; 110265942Sgibbs 110365942Sgibbs tdata = &scb->hscb->shared_data.tdata; 110465942Sgibbs tdata->target_phases |= DPHASE_PENDING; 110565942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 110665942Sgibbs tdata->data_phase = P_DATAOUT; 110765942Sgibbs else 110865942Sgibbs tdata->data_phase = P_DATAIN; 110965942Sgibbs 111065942Sgibbs /* 111165942Sgibbs * If the transfer is of an odd length and in the 111265942Sgibbs * "in" direction (scsi->HostBus), then it may 111365942Sgibbs * trigger a bug in the 'WideODD' feature of 111465942Sgibbs * non-Ultra2 chips. Force the total data-length 111565942Sgibbs * to be even by adding an extra, 1 byte, SG, 111665942Sgibbs * element. We do this even if we are not currently 111765942Sgibbs * negotiated wide as negotiation could occur before 111865942Sgibbs * this command is executed. 111965942Sgibbs */ 112065942Sgibbs if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0 112165942Sgibbs && (ccb->csio.dxfer_len & 0x1) != 0 112265942Sgibbs && (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 112365942Sgibbs 112465942Sgibbs nsegments++; 112565942Sgibbs if (nsegments > AHC_NSEG) { 112665942Sgibbs 112765942Sgibbs ahc_set_transaction_status(scb, 112865942Sgibbs CAM_REQ_TOO_BIG); 112965942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, 113065942Sgibbs scb->dmamap); 113166647Sgibbs ahc_lock(ahc, &s); 113265942Sgibbs ahc_free_scb(ahc, scb); 113366647Sgibbs ahc_unlock(ahc, &s); 113465942Sgibbs xpt_done(ccb); 113565942Sgibbs return; 113665942Sgibbs } 113765942Sgibbs sg->addr = ahc->dma_bug_buf; 113865942Sgibbs sg->len = 1; 113965942Sgibbs sg++; 114065942Sgibbs } 114165942Sgibbs } 114265942Sgibbs sg--; 114365942Sgibbs sg->len |= AHC_DMA_LAST_SEG; 114465942Sgibbs 114565942Sgibbs /* Copy the first SG into the "current" data pointer area */ 114665942Sgibbs scb->hscb->dataptr = scb->sg_list->addr; 114765942Sgibbs scb->hscb->datacnt = scb->sg_list->len; 114865942Sgibbs } else { 114965942Sgibbs scb->hscb->sgptr = SG_LIST_NULL; 115065942Sgibbs scb->hscb->dataptr = 0; 115165942Sgibbs scb->hscb->datacnt = 0; 115265942Sgibbs } 115365942Sgibbs 115465942Sgibbs scb->sg_count = nsegments; 115565942Sgibbs 115665942Sgibbs ahc_lock(ahc, &s); 115765942Sgibbs 115865942Sgibbs /* 115965942Sgibbs * Last time we need to check if this SCB needs to 116065942Sgibbs * be aborted. 116165942Sgibbs */ 116265942Sgibbs if (ahc_get_transaction_status(scb) != CAM_REQ_INPROG) { 116365942Sgibbs if (nsegments != 0) 116465942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, 116565942Sgibbs scb->dmamap); 116665942Sgibbs ahc_free_scb(ahc, scb); 116766647Sgibbs ahc_unlock(ahc, &s); 116865942Sgibbs xpt_done(ccb); 116965942Sgibbs return; 117065942Sgibbs } 117165942Sgibbs 117266717Sgibbs tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid), 117366717Sgibbs SCSIID_OUR_ID(scb->hscb->scsiid), 117468087Sgibbs SCSIID_TARGET(ahc, scb->hscb->scsiid), 117568087Sgibbs &tstate); 117666717Sgibbs 117766717Sgibbs mask = SCB_GET_TARGET_MASK(ahc, scb); 117866717Sgibbs scb->hscb->scsirate = tinfo->scsirate; 117966717Sgibbs scb->hscb->scsioffset = tinfo->current.offset; 118066717Sgibbs if ((tstate->ultraenb & mask) != 0) 118166717Sgibbs scb->hscb->control |= ULTRAENB; 118266717Sgibbs 118366717Sgibbs if ((tstate->discenable & mask) != 0 118466717Sgibbs && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0) 118566717Sgibbs scb->hscb->control |= DISCENB; 118666717Sgibbs 118766717Sgibbs if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0 118866717Sgibbs && (tinfo->current.width != 0 || tinfo->current.period != 0)) { 118966717Sgibbs scb->flags |= SCB_NEGOTIATE; 119066717Sgibbs scb->hscb->control |= MK_MESSAGE; 119166717Sgibbs } 119266717Sgibbs 119365942Sgibbs LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); 119465942Sgibbs 119565942Sgibbs ccb->ccb_h.status |= CAM_SIM_QUEUED; 119665942Sgibbs 119765942Sgibbs if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { 119865942Sgibbs if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) 119965942Sgibbs ccb->ccb_h.timeout = 5 * 1000; 120065942Sgibbs ccb->ccb_h.timeout_ch = 120165942Sgibbs timeout(ahc_timeout, (caddr_t)scb, 120265942Sgibbs (ccb->ccb_h.timeout * hz) / 1000); 120365942Sgibbs } 120465942Sgibbs 120565942Sgibbs /* 120665942Sgibbs * We only allow one untagged transaction 120765942Sgibbs * per target in the initiator role unless 120865942Sgibbs * we are storing a full busy target *lun* 120965942Sgibbs * table in SCB space. 121065942Sgibbs */ 121165942Sgibbs if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0 121265942Sgibbs && (ahc->features & AHC_SCB_BTT) == 0) { 121365942Sgibbs struct scb_tailq *untagged_q; 121465942Sgibbs 121565942Sgibbs untagged_q = &(ahc->untagged_queues[ccb->ccb_h.target_id]); 121665942Sgibbs TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); 121766986Sgibbs scb->flags |= SCB_UNTAGGEDQ; 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); 127568087Sgibbs scb->flags |= SCB_CDB32_PTR; 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); 128568087Sgibbs scb->flags |= SCB_CDB32_PTR; 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; 140066986Sgibbs ahc = (struct ahc_softc *)scb->ahc_softc; 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 { 141168087Sgibbs ahc_freebsd_intr(ahc); 141265942Sgibbs pause_sequencer(ahc); 141365942Sgibbs } while (ahc_inb(ahc, INTSTAT) & INT_PEND); 141465942Sgibbs 141566800Sgibbs /* Make sure the sequencer is in a safe location. */ 141666800Sgibbs ahc_clear_critical_section(ahc); 141766800Sgibbs 141865942Sgibbs if ((scb->flags & SCB_ACTIVE) == 0) { 141965942Sgibbs /* Previous timeout took care of me already */ 142066986Sgibbs printf("%s: Timedout SCB already complete. " 142166986Sgibbs "Interrupts may not be functioning.\n", ahc_name(ahc)); 142265942Sgibbs unpause_sequencer(ahc); 142365942Sgibbs ahc_unlock(ahc, &s); 142465942Sgibbs return; 142565942Sgibbs } 142665942Sgibbs 142765942Sgibbs target = SCB_GET_TARGET(ahc, scb); 142865942Sgibbs channel = SCB_GET_CHANNEL(ahc, scb); 142965942Sgibbs lun = SCB_GET_LUN(scb); 143065942Sgibbs 143168087Sgibbs ahc_print_path(ahc, scb); 143265942Sgibbs printf("SCB 0x%x - timed out ", scb->hscb->tag); 143365942Sgibbs /* 143465942Sgibbs * Take a snapshot of the bus state and print out 143565942Sgibbs * some information so we can track down driver bugs. 143665942Sgibbs */ 143765942Sgibbs last_phase = ahc_inb(ahc, LASTPHASE); 143865942Sgibbs 143965942Sgibbs for (i = 0; i < num_phases; i++) { 144065942Sgibbs if (last_phase == phase_table[i].phase) 144165942Sgibbs break; 144265942Sgibbs } 144365942Sgibbs printf("%s", phase_table[i].phasemsg); 144465942Sgibbs 144565942Sgibbs printf(", SEQADDR == 0x%x\n", 144665942Sgibbs ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); 144765942Sgibbs 144868087Sgibbs printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n", 144968087Sgibbs ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), 145068087Sgibbs ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), 145168087Sgibbs ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), 145268087Sgibbs ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8)); 145368087Sgibbs 145468087Sgibbs printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0)); 145568087Sgibbs 145668087Sgibbs ahc_dump_card_state(ahc); 145765942Sgibbs if (scb->sg_count > 0) { 145865942Sgibbs for (i = 0; i < scb->sg_count; i++) { 145965942Sgibbs printf("sg[%d] - Addr 0x%x : Length %d\n", 146065942Sgibbs i, 146165942Sgibbs scb->sg_list[i].addr, 146266800Sgibbs scb->sg_list[i].len & AHC_SG_LEN_MASK); 146365942Sgibbs } 146465942Sgibbs } 146565942Sgibbs if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { 146665942Sgibbs /* 146765942Sgibbs * Been down this road before. 146865942Sgibbs * Do a full bus reset. 146965942Sgibbs */ 147065942Sgibbsbus_reset: 147165942Sgibbs ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); 147265942Sgibbs found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE); 147365942Sgibbs printf("%s: Issued Channel %c Bus Reset. " 147465942Sgibbs "%d SCBs aborted\n", ahc_name(ahc), channel, found); 147565942Sgibbs } else { 147665942Sgibbs /* 147765942Sgibbs * If we are a target, transition to bus free and report 147865942Sgibbs * the timeout. 147965942Sgibbs * 148065942Sgibbs * The target/initiator that is holding up the bus may not 148165942Sgibbs * be the same as the one that triggered this timeout 148265942Sgibbs * (different commands have different timeout lengths). 148365942Sgibbs * If the bus is idle and we are actiing as the initiator 148465942Sgibbs * for this request, queue a BDR message to the timed out 148565942Sgibbs * target. Otherwise, if the timed out transaction is 148665942Sgibbs * active: 148765942Sgibbs * Initiator transaction: 148865942Sgibbs * Stuff the message buffer with a BDR message and assert 148965942Sgibbs * ATN in the hopes that the target will let go of the bus 149065942Sgibbs * and go to the mesgout phase. If this fails, we'll 149165942Sgibbs * get another timeout 2 seconds later which will attempt 149265942Sgibbs * a bus reset. 149365942Sgibbs * 149465942Sgibbs * Target transaction: 149565942Sgibbs * Transition to BUS FREE and report the error. 149665942Sgibbs * It's good to be the target! 149765942Sgibbs */ 149865942Sgibbs u_int active_scb_index; 149968087Sgibbs u_int saved_scbptr; 150065942Sgibbs 150168087Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 150265942Sgibbs active_scb_index = ahc_inb(ahc, SCB_TAG); 150365942Sgibbs 150465942Sgibbs if (last_phase != P_BUSFREE 150565942Sgibbs && (active_scb_index < ahc->scb_data->numscbs)) { 150665942Sgibbs struct scb *active_scb; 150765942Sgibbs 150865942Sgibbs /* 150968087Sgibbs * If the active SCB is not us, assume that 151068087Sgibbs * the active SCB has a longer timeout than 151168087Sgibbs * the timedout SCB, and wait for the active 151268087Sgibbs * SCB to timeout. 151365942Sgibbs */ 151466800Sgibbs active_scb = ahc_lookup_scb(ahc, active_scb_index); 151568087Sgibbs if (active_scb != scb) { 151665942Sgibbs struct ccb_hdr *ccbh; 151765942Sgibbs u_int newtimeout; 151865942Sgibbs 151965942Sgibbs ahc_print_path(ahc, scb); 152065942Sgibbs printf("Other SCB Timeout%s", 152165942Sgibbs (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 152265942Sgibbs ? " again\n" : "\n"); 152365942Sgibbs scb->flags |= SCB_OTHERTCL_TIMEOUT; 152465942Sgibbs newtimeout = 152565942Sgibbs MAX(active_scb->io_ctx->ccb_h.timeout, 152665942Sgibbs scb->io_ctx->ccb_h.timeout); 152765942Sgibbs ccbh = &scb->io_ctx->ccb_h; 152865942Sgibbs scb->io_ctx->ccb_h.timeout_ch = 152965942Sgibbs timeout(ahc_timeout, scb, 153065942Sgibbs (newtimeout * hz) / 1000); 153165942Sgibbs ahc_unlock(ahc, &s); 153265942Sgibbs return; 153365942Sgibbs } 153465942Sgibbs 153565942Sgibbs /* It's us */ 153665942Sgibbs if ((scb->hscb->control & TARGET_SCB) != 0) { 153765942Sgibbs 153865942Sgibbs /* 153965942Sgibbs * Send back any queued up transactions 154065942Sgibbs * and properly record the error condition. 154165942Sgibbs */ 154265942Sgibbs ahc_freeze_devq(ahc, scb); 154365942Sgibbs ahc_set_transaction_status(scb, 154465942Sgibbs CAM_CMD_TIMEOUT); 154565942Sgibbs ahc_freeze_scb(scb); 154665942Sgibbs ahc_done(ahc, scb); 154765942Sgibbs 154865942Sgibbs /* Will clear us from the bus */ 154965942Sgibbs restart_sequencer(ahc); 155066717Sgibbs ahc_unlock(ahc, &s); 155165942Sgibbs return; 155265942Sgibbs } 155365942Sgibbs 155465942Sgibbs ahc_set_recoveryscb(ahc, active_scb); 155566845Sgibbs ahc_outb(ahc, MSG_OUT, HOST_MSG); 155665942Sgibbs ahc_outb(ahc, SCSISIGO, last_phase|ATNO); 155765942Sgibbs ahc_print_path(ahc, active_scb); 155865942Sgibbs printf("BDR message in message buffer\n"); 155968087Sgibbs active_scb->flags |= SCB_DEVICE_RESET; 156065942Sgibbs active_scb->io_ctx->ccb_h.timeout_ch = 156165942Sgibbs timeout(ahc_timeout, (caddr_t)active_scb, 2 * hz); 156265942Sgibbs unpause_sequencer(ahc); 156365942Sgibbs } else { 156465942Sgibbs int disconnected; 156565942Sgibbs 156665942Sgibbs /* XXX Shouldn't panic. Just punt instead */ 156765942Sgibbs if ((scb->hscb->control & TARGET_SCB) != 0) 156865942Sgibbs panic("Timed-out target SCB but bus idle"); 156965942Sgibbs 157065942Sgibbs if (last_phase != P_BUSFREE 157165942Sgibbs && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) { 157265942Sgibbs /* XXX What happened to the SCB? */ 157365942Sgibbs /* Hung target selection. Goto busfree */ 157465942Sgibbs printf("%s: Hung target selection\n", 157565942Sgibbs ahc_name(ahc)); 157665942Sgibbs restart_sequencer(ahc); 157766717Sgibbs ahc_unlock(ahc, &s); 157865942Sgibbs return; 157965942Sgibbs } 158065942Sgibbs 158165942Sgibbs if (ahc_search_qinfifo(ahc, target, channel, lun, 158265942Sgibbs scb->hscb->tag, ROLE_INITIATOR, 158365942Sgibbs /*status*/0, SEARCH_COUNT) > 0) { 158465942Sgibbs disconnected = FALSE; 158565942Sgibbs } else { 158665942Sgibbs disconnected = TRUE; 158765942Sgibbs } 158865942Sgibbs 158965942Sgibbs if (disconnected) { 159065942Sgibbs 159165942Sgibbs ahc_set_recoveryscb(ahc, scb); 159265942Sgibbs /* 159366800Sgibbs * Actually re-queue this SCB in an attempt 159466800Sgibbs * to select the device before it reconnects. 159566800Sgibbs * In either case (selection or reselection), 159666800Sgibbs * we will now issue a target reset to the 159766800Sgibbs * timed-out device. 159866800Sgibbs * 159966845Sgibbs * Set the MK_MESSAGE control bit indicating 160066845Sgibbs * that we desire to send a message. We 160166845Sgibbs * also set the disconnected flag since 160266845Sgibbs * in the paging case there is no guarantee 160366845Sgibbs * that our SCB control byte matches the 160466845Sgibbs * version on the card. We don't want the 160566845Sgibbs * sequencer to abort the command thinking 160666845Sgibbs * an unsolicited reselection occurred. 160766845Sgibbs */ 160866845Sgibbs scb->hscb->control |= MK_MESSAGE|DISCONNECTED; 160966845Sgibbs scb->flags |= SCB_DEVICE_RESET; 161066845Sgibbs 161166845Sgibbs /* 161266800Sgibbs * Remove any cached copy of this SCB in the 161366800Sgibbs * disconnected list in preparation for the 161466800Sgibbs * queuing of our abort SCB. We use the 161566800Sgibbs * same element in the SCB, SCB_NEXT, for 161666800Sgibbs * both the qinfifo and the disconnected list. 161765942Sgibbs */ 161866800Sgibbs ahc_search_disc_list(ahc, target, channel, 161966800Sgibbs lun, scb->hscb->tag, 162066800Sgibbs /*stop_on_first*/TRUE, 162166800Sgibbs /*remove*/TRUE, 162266845Sgibbs /*save_state*/FALSE); 162365942Sgibbs 162465942Sgibbs /* 162566845Sgibbs * In the non-paging case, the sequencer will 162666845Sgibbs * never re-reference the in-core SCB. 162766845Sgibbs * To make sure we are notified during 162866845Sgibbs * reslection, set the MK_MESSAGE flag in 162966845Sgibbs * the card's copy of the SCB. 163066845Sgibbs */ 163166845Sgibbs if ((ahc->flags & AHC_PAGESCBS) != 0) { 163266845Sgibbs ahc_outb(ahc, SCBPTR, scb->hscb->tag); 163366845Sgibbs ahc_outb(ahc, SCB_CONTROL, 163466845Sgibbs ahc_inb(ahc, SCB_CONTROL) 163566845Sgibbs | MK_MESSAGE); 163666845Sgibbs } 163766845Sgibbs 163866845Sgibbs /* 163965942Sgibbs * Clear out any entries in the QINFIFO first 164065942Sgibbs * so we are the next SCB for this target 164165942Sgibbs * to run. 164265942Sgibbs */ 164365942Sgibbs ahc_search_qinfifo(ahc, 164465942Sgibbs SCB_GET_TARGET(ahc, scb), 164565942Sgibbs channel, SCB_GET_LUN(scb), 164665942Sgibbs SCB_LIST_NULL, 164765942Sgibbs ROLE_INITIATOR, 164865942Sgibbs CAM_REQUEUE_REQ, 164965942Sgibbs SEARCH_COMPLETE); 165065942Sgibbs ahc_print_path(ahc, scb); 165165942Sgibbs printf("Queuing a BDR SCB\n"); 165268087Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 165368087Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 165465942Sgibbs scb->io_ctx->ccb_h.timeout_ch = 165565942Sgibbs timeout(ahc_timeout, (caddr_t)scb, 2 * hz); 165665942Sgibbs unpause_sequencer(ahc); 165765942Sgibbs } else { 165865942Sgibbs /* Go "immediatly" to the bus reset */ 165965942Sgibbs /* This shouldn't happen */ 166065942Sgibbs ahc_set_recoveryscb(ahc, scb); 166165942Sgibbs ahc_print_path(ahc, scb); 166265942Sgibbs printf("SCB %d: Immediate reset. " 166365942Sgibbs "Flags = 0x%x\n", scb->hscb->tag, 166465942Sgibbs scb->flags); 166565942Sgibbs goto bus_reset; 166665942Sgibbs } 166765942Sgibbs } 166865942Sgibbs } 166965942Sgibbs ahc_unlock(ahc, &s); 167065942Sgibbs} 167165942Sgibbs 167265942Sgibbsstatic void 167365942Sgibbsahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) 167465942Sgibbs{ 167565942Sgibbs union ccb *abort_ccb; 167665942Sgibbs 167765942Sgibbs abort_ccb = ccb->cab.abort_ccb; 167865942Sgibbs switch (abort_ccb->ccb_h.func_code) { 167965942Sgibbs case XPT_ACCEPT_TARGET_IO: 168065942Sgibbs case XPT_IMMED_NOTIFY: 168165942Sgibbs case XPT_CONT_TARGET_IO: 168265942Sgibbs { 168365942Sgibbs struct tmode_tstate *tstate; 168465942Sgibbs struct tmode_lstate *lstate; 168565942Sgibbs struct ccb_hdr_slist *list; 168665942Sgibbs cam_status status; 168765942Sgibbs 168865942Sgibbs status = ahc_find_tmode_devs(ahc, sim, abort_ccb, &tstate, 168965942Sgibbs &lstate, TRUE); 169065942Sgibbs 169165942Sgibbs if (status != CAM_REQ_CMP) { 169265942Sgibbs ccb->ccb_h.status = status; 169365942Sgibbs break; 169465942Sgibbs } 169565942Sgibbs 169665942Sgibbs if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) 169765942Sgibbs list = &lstate->accept_tios; 169865942Sgibbs else if (abort_ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) 169965942Sgibbs list = &lstate->immed_notifies; 170065942Sgibbs else 170165942Sgibbs list = NULL; 170265942Sgibbs 170365942Sgibbs if (list != NULL) { 170465942Sgibbs struct ccb_hdr *curelm; 170565942Sgibbs int found; 170665942Sgibbs 170765942Sgibbs curelm = SLIST_FIRST(list); 170865942Sgibbs found = 0; 170965942Sgibbs if (curelm == &abort_ccb->ccb_h) { 171065942Sgibbs found = 1; 171165942Sgibbs SLIST_REMOVE_HEAD(list, sim_links.sle); 171265942Sgibbs } else { 171365942Sgibbs while(curelm != NULL) { 171465942Sgibbs struct ccb_hdr *nextelm; 171565942Sgibbs 171665942Sgibbs nextelm = 171765942Sgibbs SLIST_NEXT(curelm, sim_links.sle); 171865942Sgibbs 171965942Sgibbs if (nextelm == &abort_ccb->ccb_h) { 172065942Sgibbs found = 1; 172165942Sgibbs SLIST_NEXT(curelm, 172265942Sgibbs sim_links.sle) = 172365942Sgibbs SLIST_NEXT(nextelm, 172465942Sgibbs sim_links.sle); 172565942Sgibbs break; 172665942Sgibbs } 172765942Sgibbs curelm = nextelm; 172865942Sgibbs } 172965942Sgibbs } 173065942Sgibbs 173165942Sgibbs if (found) { 173265942Sgibbs abort_ccb->ccb_h.status = CAM_REQ_ABORTED; 173365942Sgibbs xpt_done(abort_ccb); 173465942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 173565942Sgibbs } else { 173668087Sgibbs xpt_print_path(abort_ccb->ccb_h.path); 173765942Sgibbs printf("Not found\n"); 173865942Sgibbs ccb->ccb_h.status = CAM_PATH_INVALID; 173965942Sgibbs } 174065942Sgibbs break; 174165942Sgibbs } 174265942Sgibbs /* FALLTHROUGH */ 174365942Sgibbs } 174465942Sgibbs case XPT_SCSI_IO: 174565942Sgibbs /* XXX Fully implement the hard ones */ 174665942Sgibbs ccb->ccb_h.status = CAM_UA_ABORT; 174765942Sgibbs break; 174865942Sgibbs default: 174965942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 175065942Sgibbs break; 175165942Sgibbs } 175265942Sgibbs xpt_done(ccb); 175365942Sgibbs} 175465942Sgibbs 175565942Sgibbsvoid 175666269Sgibbsahc_send_async(struct ahc_softc *ahc, char channel, u_int target, 175766269Sgibbs u_int lun, ac_code code) 175865942Sgibbs{ 175965942Sgibbs struct ccb_trans_settings cts; 176065942Sgibbs struct cam_path *path; 176165942Sgibbs void *arg; 176265942Sgibbs int error; 176365942Sgibbs 176465942Sgibbs arg = NULL; 176566269Sgibbs error = ahc_create_path(ahc, channel, target, lun, &path); 176665942Sgibbs 176765942Sgibbs if (error != CAM_REQ_CMP) 176865942Sgibbs return; 176965942Sgibbs 177065942Sgibbs switch (code) { 177165942Sgibbs case AC_TRANSFER_NEG: 177265942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 177365942Sgibbs cts.type = CTS_TYPE_CURRENT_SETTINGS; 177465942Sgibbs#else 177565942Sgibbs cts.flags = CCB_TRANS_CURRENT_SETTINGS; 177665942Sgibbs#endif 177765942Sgibbs cts.ccb_h.path = path; 177866269Sgibbs cts.ccb_h.target_id = target; 177966269Sgibbs cts.ccb_h.target_lun = lun; 178066269Sgibbs ahc_get_tran_settings(ahc, channel == 'A' ? ahc->our_id 178166269Sgibbs : ahc->our_id_b, 178266269Sgibbs channel, &cts); 178365942Sgibbs arg = &cts; 178465942Sgibbs break; 178565942Sgibbs case AC_SENT_BDR: 178665942Sgibbs case AC_BUS_RESET: 178765942Sgibbs break; 178865942Sgibbs default: 178965942Sgibbs panic("ahc_send_async: Unexpected async event"); 179065942Sgibbs } 179165942Sgibbs xpt_async(code, path, arg); 179268402Sgibbs xpt_free_path(path); 179365942Sgibbs} 179465942Sgibbs 179565942Sgibbsvoid 179665942Sgibbsahc_platform_set_tags(struct ahc_softc *ahc, 179765942Sgibbs struct ahc_devinfo *devinfo, int enable) 179865942Sgibbs{ 179965942Sgibbs} 180065942Sgibbs 180165942Sgibbsint 180265942Sgibbsahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) 180365942Sgibbs{ 180467888Sdwmalone ahc->platform_data = malloc(sizeof(struct ahc_platform_data), M_DEVBUF, 180567888Sdwmalone M_NOWAIT | M_ZERO); 180665942Sgibbs if (ahc->platform_data == NULL) 180765942Sgibbs return (ENOMEM); 180865942Sgibbs return (0); 180965942Sgibbs} 181065942Sgibbs 181165942Sgibbsvoid 181265942Sgibbsahc_platform_free(struct ahc_softc *ahc) 181365942Sgibbs{ 181465942Sgibbs if (ahc->platform_data != NULL) { 181565942Sgibbs if (ahc->platform_data->regs != NULL) 181665942Sgibbs bus_release_resource(ahc->dev_softc, 181765942Sgibbs ahc->platform_data->regs_res_type, 181865942Sgibbs ahc->platform_data->regs_res_id, 181965942Sgibbs ahc->platform_data->regs); 182065942Sgibbs 182165942Sgibbs if (ahc->platform_data->irq != NULL) 182265942Sgibbs bus_release_resource(ahc->dev_softc, 182365942Sgibbs ahc->platform_data->irq_res_type, 182465942Sgibbs 0, ahc->platform_data->irq); 182565942Sgibbs 182665942Sgibbs free(ahc->platform_data, M_DEVBUF); 182765942Sgibbs } 182865942Sgibbs} 182965942Sgibbs 183065942Sgibbsint 183165942Sgibbsahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc) 183265942Sgibbs{ 183365942Sgibbs /* We don't sort softcs under FreeBSD so report equal always */ 183465942Sgibbs return (0); 183565942Sgibbs} 183665942Sgibbs 183765942Sgibbs#if UNUSED 183865942Sgibbsstatic void 183965942Sgibbsahc_dump_targcmd(struct target_cmd *cmd) 184065942Sgibbs{ 184165942Sgibbs uint8_t *byte; 184265942Sgibbs uint8_t *last_byte; 184365942Sgibbs int i; 184465942Sgibbs 184565942Sgibbs byte = &cmd->initiator_channel; 184665942Sgibbs /* Debugging info for received commands */ 184765942Sgibbs last_byte = &cmd[1].initiator_channel; 184865942Sgibbs 184965942Sgibbs i = 0; 185065942Sgibbs while (byte < last_byte) { 185165942Sgibbs if (i == 0) 185265942Sgibbs printf("\t"); 185365942Sgibbs printf("%#x", *byte++); 185465942Sgibbs i++; 185565942Sgibbs if (i == 8) { 185665942Sgibbs printf("\n"); 185765942Sgibbs i = 0; 185865942Sgibbs } else { 185965942Sgibbs printf(", "); 186065942Sgibbs } 186165942Sgibbs } 186265942Sgibbs} 186365942Sgibbs#endif 1864