1139749Simp/*- 2123579Sgibbs * Bus independent FreeBSD shim for the aic7xxx based Adaptec SCSI controllers 365942Sgibbs * 471717Sgibbs * Copyright (c) 1994-2001 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 * 31123579Sgibbs * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.c#20 $ 3265942Sgibbs */ 3365942Sgibbs 34119418Sobrien#include <sys/cdefs.h> 35119418Sobrien__FBSDID("$FreeBSD: stable/11/sys/dev/aic7xxx/aic7xxx_osm.c 315812 2017-03-23 06:40:20Z mav $"); 36119418Sobrien 3795378Sgibbs#include <dev/aic7xxx/aic7xxx_osm.h> 3865942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h> 3965942Sgibbs 40123579Sgibbs#include <sys/kthread.h> 41123579Sgibbs 4265942Sgibbs#ifndef AHC_TMODE_ENABLE 4365942Sgibbs#define AHC_TMODE_ENABLE 0 4465942Sgibbs#endif 4565942Sgibbs 46123579Sgibbs#include <dev/aic7xxx/aic_osm_lib.c> 47123579Sgibbs 4865942Sgibbs#define ccb_scb_ptr spriv_ptr0 4965942Sgibbs 50103811Sscottldevclass_t ahc_devclass; 51103811Sscottl 52153072Sru#if 0 5365942Sgibbsstatic void ahc_dump_targcmd(struct target_cmd *cmd); 5465942Sgibbs#endif 5576634Sgibbsstatic int ahc_modevent(module_t mod, int type, void *data); 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 7365942Sgibbs 7465942Sgibbsstatic int 7566269Sgibbsahc_create_path(struct ahc_softc *ahc, char channel, u_int target, 7666269Sgibbs u_int lun, struct cam_path **path) 7765942Sgibbs{ 7865942Sgibbs path_id_t path_id; 7965942Sgibbs 8066269Sgibbs if (channel == 'B') 8165942Sgibbs path_id = cam_sim_path(ahc->platform_data->sim_b); 8265942Sgibbs else 8365942Sgibbs path_id = cam_sim_path(ahc->platform_data->sim); 8465942Sgibbs 8565942Sgibbs return (xpt_create_path(path, /*periph*/NULL, 8666269Sgibbs path_id, target, lun)); 8765942Sgibbs} 8865942Sgibbs 8995378Sgibbsint 9095378Sgibbsahc_map_int(struct ahc_softc *ahc) 9195378Sgibbs{ 9295378Sgibbs int error; 93133911Sgibbs int zero; 94133911Sgibbs int shareable; 9595378Sgibbs 96133911Sgibbs zero = 0; 97133911Sgibbs shareable = (ahc->flags & AHC_EDGE_INTERRUPT) ? 0: RF_SHAREABLE; 98133911Sgibbs ahc->platform_data->irq = 99133911Sgibbs bus_alloc_resource_any(ahc->dev_softc, SYS_RES_IRQ, &zero, 100133911Sgibbs RF_ACTIVE | shareable); 101133911Sgibbs if (ahc->platform_data->irq == NULL) { 102133911Sgibbs device_printf(ahc->dev_softc, 103133911Sgibbs "bus_alloc_resource() failed to allocate IRQ\n"); 104133911Sgibbs return (ENOMEM); 105133911Sgibbs } 106133911Sgibbs ahc->platform_data->irq_res_type = SYS_RES_IRQ; 107133911Sgibbs 10895378Sgibbs /* Hook up our interrupt handler */ 10995378Sgibbs error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq, 110168807Sscottl INTR_TYPE_CAM|INTR_MPSAFE, NULL, 111168807Sscottl ahc_platform_intr, ahc, &ahc->platform_data->ih); 11295378Sgibbs 11395378Sgibbs if (error != 0) 11495378Sgibbs device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n", 11595378Sgibbs error); 11695378Sgibbs return (error); 11795378Sgibbs} 11895378Sgibbs 119133911Sgibbsint 120133911Sgibbsaic7770_map_registers(struct ahc_softc *ahc, u_int unused_ioport_arg) 121133911Sgibbs{ 122133911Sgibbs struct resource *regs; 123133911Sgibbs int rid; 124133911Sgibbs 125133911Sgibbs rid = 0; 126133911Sgibbs regs = bus_alloc_resource_any(ahc->dev_softc, SYS_RES_IOPORT, &rid, 127133911Sgibbs RF_ACTIVE); 128133911Sgibbs if (regs == NULL) { 129133911Sgibbs device_printf(ahc->dev_softc, "Unable to map I/O space?!\n"); 130133911Sgibbs return ENOMEM; 131133911Sgibbs } 132133911Sgibbs ahc->platform_data->regs_res_type = SYS_RES_IOPORT; 133305614Spfg ahc->platform_data->regs_res_id = rid; 134133911Sgibbs ahc->platform_data->regs = regs; 135133911Sgibbs ahc->tag = rman_get_bustag(regs); 136133911Sgibbs ahc->bsh = rman_get_bushandle(regs); 137133911Sgibbs return (0); 138133911Sgibbs} 139133911Sgibbs 14065942Sgibbs/* 14165942Sgibbs * Attach all the sub-devices we can find 14265942Sgibbs */ 14365942Sgibbsint 14465942Sgibbsahc_attach(struct ahc_softc *ahc) 14565942Sgibbs{ 14665942Sgibbs char ahc_info[256]; 14765942Sgibbs struct ccb_setasync csa; 14865942Sgibbs struct cam_devq *devq; 14965942Sgibbs int bus_id; 15065942Sgibbs int bus_id2; 15165942Sgibbs struct cam_sim *sim; 15265942Sgibbs struct cam_sim *sim2; 15365942Sgibbs struct cam_path *path; 15465942Sgibbs struct cam_path *path2; 15565942Sgibbs int count; 15665942Sgibbs 15765942Sgibbs count = 0; 15865942Sgibbs sim = NULL; 15965942Sgibbs sim2 = NULL; 160162051Smjacob path = NULL; 161162051Smjacob path2 = NULL; 16265942Sgibbs 163168807Sscottl 164123579Sgibbs /* 165123579Sgibbs * Create a thread to perform all recovery. 166123579Sgibbs */ 167123579Sgibbs if (ahc_spawn_recovery_thread(ahc) != 0) 168123579Sgibbs goto fail; 169123579Sgibbs 17065942Sgibbs ahc_controller_info(ahc, ahc_info); 17165942Sgibbs printf("%s\n", ahc_info); 172168807Sscottl ahc_lock(ahc); 173123579Sgibbs 17465942Sgibbs /* 17565942Sgibbs * Attach secondary channel first if the user has 17665942Sgibbs * declared it the primary channel. 17765942Sgibbs */ 17872552Sgibbs if ((ahc->features & AHC_TWIN) != 0 17974094Sgibbs && (ahc->flags & AHC_PRIMARY_CHANNEL) != 0) { 18065942Sgibbs bus_id = 1; 18165942Sgibbs bus_id2 = 0; 18265942Sgibbs } else { 18365942Sgibbs bus_id = 0; 18465942Sgibbs bus_id2 = 1; 18565942Sgibbs } 18665942Sgibbs 18765942Sgibbs /* 18865942Sgibbs * Create the device queue for our SIM(s). 18965942Sgibbs */ 19071390Sgibbs devq = cam_simq_alloc(AHC_MAX_QUEUE); 19165942Sgibbs if (devq == NULL) 19265942Sgibbs goto fail; 19365942Sgibbs 19465942Sgibbs /* 19565942Sgibbs * Construct our first channel SIM entry 19665942Sgibbs */ 19766104Sgibbs sim = cam_sim_alloc(ahc_action, ahc_poll, "ahc", ahc, 19866104Sgibbs device_get_unit(ahc->dev_softc), 199168807Sscottl &ahc->platform_data->mtx, 1, AHC_MAX_QUEUE, devq); 20065942Sgibbs if (sim == NULL) { 20165942Sgibbs cam_simq_free(devq); 20265942Sgibbs goto fail; 20365942Sgibbs } 20465942Sgibbs 205170872Sscottl if (xpt_bus_register(sim, ahc->dev_softc, bus_id) != CAM_SUCCESS) { 20665942Sgibbs cam_sim_free(sim, /*free_devq*/TRUE); 20765942Sgibbs sim = NULL; 20865942Sgibbs goto fail; 20965942Sgibbs } 21065942Sgibbs 21165942Sgibbs if (xpt_create_path(&path, /*periph*/NULL, 21265942Sgibbs cam_sim_path(sim), CAM_TARGET_WILDCARD, 21365942Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 21465942Sgibbs xpt_bus_deregister(cam_sim_path(sim)); 21565942Sgibbs cam_sim_free(sim, /*free_devq*/TRUE); 21665942Sgibbs sim = NULL; 21765942Sgibbs goto fail; 21865942Sgibbs } 21965942Sgibbs 22065942Sgibbs xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); 22165942Sgibbs csa.ccb_h.func_code = XPT_SASYNC_CB; 22265942Sgibbs csa.event_enable = AC_LOST_DEVICE; 22365942Sgibbs csa.callback = ahc_async; 22465942Sgibbs csa.callback_arg = sim; 22565942Sgibbs xpt_action((union ccb *)&csa); 22665942Sgibbs count++; 22765942Sgibbs 22865942Sgibbs if (ahc->features & AHC_TWIN) { 22965942Sgibbs sim2 = cam_sim_alloc(ahc_action, ahc_poll, "ahc", 230168752Sscottl ahc, device_get_unit(ahc->dev_softc), 231168807Sscottl &ahc->platform_data->mtx, 1, 23271390Sgibbs AHC_MAX_QUEUE, devq); 23365942Sgibbs 23465942Sgibbs if (sim2 == NULL) { 23565942Sgibbs printf("ahc_attach: Unable to attach second " 23665942Sgibbs "bus due to resource shortage"); 23765942Sgibbs goto fail; 23865942Sgibbs } 23965942Sgibbs 240170872Sscottl if (xpt_bus_register(sim2, ahc->dev_softc, bus_id2) != 241170872Sscottl CAM_SUCCESS) { 24265942Sgibbs printf("ahc_attach: Unable to attach second " 24365942Sgibbs "bus due to resource shortage"); 24465942Sgibbs /* 24565942Sgibbs * We do not want to destroy the device queue 24665942Sgibbs * because the first bus is using it. 24765942Sgibbs */ 24865942Sgibbs cam_sim_free(sim2, /*free_devq*/FALSE); 24965942Sgibbs goto fail; 25065942Sgibbs } 25165942Sgibbs 25265942Sgibbs if (xpt_create_path(&path2, /*periph*/NULL, 25365942Sgibbs cam_sim_path(sim2), 25465942Sgibbs CAM_TARGET_WILDCARD, 25565942Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 25665942Sgibbs xpt_bus_deregister(cam_sim_path(sim2)); 25765942Sgibbs cam_sim_free(sim2, /*free_devq*/FALSE); 25865942Sgibbs sim2 = NULL; 25965942Sgibbs goto fail; 26065942Sgibbs } 26165942Sgibbs xpt_setup_ccb(&csa.ccb_h, path2, /*priority*/5); 26265942Sgibbs csa.ccb_h.func_code = XPT_SASYNC_CB; 26365942Sgibbs csa.event_enable = AC_LOST_DEVICE; 26465942Sgibbs csa.callback = ahc_async; 26565942Sgibbs csa.callback_arg = sim2; 26665942Sgibbs xpt_action((union ccb *)&csa); 26765942Sgibbs count++; 26865942Sgibbs } 26965942Sgibbs 27065942Sgibbsfail: 27172552Sgibbs if ((ahc->features & AHC_TWIN) != 0 27274094Sgibbs && (ahc->flags & AHC_PRIMARY_CHANNEL) != 0) { 27365942Sgibbs ahc->platform_data->sim_b = sim; 27465942Sgibbs ahc->platform_data->path_b = path; 27565942Sgibbs ahc->platform_data->sim = sim2; 27665942Sgibbs ahc->platform_data->path = path2; 27765942Sgibbs } else { 27865942Sgibbs ahc->platform_data->sim = sim; 27965942Sgibbs ahc->platform_data->path = path; 28065942Sgibbs ahc->platform_data->sim_b = sim2; 28165942Sgibbs ahc->platform_data->path_b = path2; 28265942Sgibbs } 283168807Sscottl ahc_unlock(ahc); 28465942Sgibbs 285102674Sgibbs if (count != 0) { 28665942Sgibbs /* We have to wait until after any system dumps... */ 28770204Sgibbs ahc->platform_data->eh = 28870204Sgibbs EVENTHANDLER_REGISTER(shutdown_final, ahc_shutdown, 28970204Sgibbs ahc, SHUTDOWN_PRI_DEFAULT); 290102674Sgibbs ahc_intr_enable(ahc, TRUE); 291102674Sgibbs } 29265942Sgibbs 29365942Sgibbs return (count); 29465942Sgibbs} 29565942Sgibbs 29665942Sgibbs/* 29765942Sgibbs * Catch an interrupt from the adapter 29865942Sgibbs */ 29965942Sgibbsvoid 30070204Sgibbsahc_platform_intr(void *arg) 30165942Sgibbs{ 30265942Sgibbs struct ahc_softc *ahc; 30365942Sgibbs 30465942Sgibbs ahc = (struct ahc_softc *)arg; 305168807Sscottl ahc_lock(ahc); 30665942Sgibbs ahc_intr(ahc); 307168807Sscottl ahc_unlock(ahc); 30865942Sgibbs} 30965942Sgibbs 31065942Sgibbs/* 31165942Sgibbs * We have an scb which has been processed by the 31265942Sgibbs * adaptor, now we look to see how the operation 31365942Sgibbs * went. 31465942Sgibbs */ 31565942Sgibbsvoid 31665942Sgibbsahc_done(struct ahc_softc *ahc, struct scb *scb) 31765942Sgibbs{ 31865942Sgibbs union ccb *ccb; 31965942Sgibbs 32065942Sgibbs CAM_DEBUG(scb->io_ctx->ccb_h.path, CAM_DEBUG_TRACE, 32165942Sgibbs ("ahc_done - scb %d\n", scb->hscb->tag)); 32265942Sgibbs 32365942Sgibbs ccb = scb->io_ctx; 32465942Sgibbs LIST_REMOVE(scb, pending_links); 325123579Sgibbs if ((scb->flags & SCB_TIMEDOUT) != 0) 326123579Sgibbs LIST_REMOVE(scb, timedout_links); 32766986Sgibbs if ((scb->flags & SCB_UNTAGGEDQ) != 0) { 32865942Sgibbs struct scb_tailq *untagged_q; 32972811Sgibbs int target_offset; 33065942Sgibbs 33172811Sgibbs target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); 33272811Sgibbs untagged_q = &ahc->untagged_queues[target_offset]; 33365942Sgibbs TAILQ_REMOVE(untagged_q, scb, links.tqe); 33466986Sgibbs scb->flags &= ~SCB_UNTAGGEDQ; 33565942Sgibbs ahc_run_untagged_queue(ahc, untagged_q); 33665942Sgibbs } 33765942Sgibbs 338168807Sscottl callout_stop(&scb->io_timer); 33965942Sgibbs 34065942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 341115343Sscottl bus_dmasync_op_t op; 34265942Sgibbs 34365942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 34465942Sgibbs op = BUS_DMASYNC_POSTREAD; 34565942Sgibbs else 34665942Sgibbs op = BUS_DMASYNC_POSTWRITE; 34765942Sgibbs bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op); 34865942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); 34965942Sgibbs } 35065942Sgibbs 35165942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 35274972Sgibbs struct cam_path *ccb_path; 35374972Sgibbs 35474972Sgibbs /* 35574972Sgibbs * If we have finally disconnected, clean up our 35674972Sgibbs * pending device state. 35774972Sgibbs * XXX - There may be error states that cause where 35874972Sgibbs * we will remain connected. 35974972Sgibbs */ 36074972Sgibbs ccb_path = ccb->ccb_h.path; 36174972Sgibbs if (ahc->pending_device != NULL 36274972Sgibbs && xpt_path_comp(ahc->pending_device->path, ccb_path) == 0) { 36374972Sgibbs 36474972Sgibbs if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { 36574972Sgibbs ahc->pending_device = NULL; 36674972Sgibbs } else { 36795378Sgibbs if (bootverbose) { 36895378Sgibbs xpt_print_path(ccb->ccb_h.path); 36995378Sgibbs printf("Still connected\n"); 37095378Sgibbs } 371123579Sgibbs aic_freeze_ccb(ccb); 37274972Sgibbs } 37374972Sgibbs } 37474972Sgibbs 375123579Sgibbs if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) 37665942Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 37765942Sgibbs ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 37865942Sgibbs ahc_free_scb(ahc, scb); 37965942Sgibbs xpt_done(ccb); 38065942Sgibbs return; 38165942Sgibbs } 38265942Sgibbs 38365942Sgibbs /* 38465942Sgibbs * If the recovery SCB completes, we have to be 38565942Sgibbs * out of our timeout. 38665942Sgibbs */ 38765942Sgibbs if ((scb->flags & SCB_RECOVERY_SCB) != 0) { 38865942Sgibbs struct scb *list_scb; 38965942Sgibbs 390133911Sgibbs ahc->scb_data->recovery_scbs--; 39165942Sgibbs 392123579Sgibbs if (aic_get_transaction_status(scb) == CAM_BDR_SENT 393123579Sgibbs || aic_get_transaction_status(scb) == CAM_REQ_ABORTED) 394123579Sgibbs aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); 395133911Sgibbs 396133911Sgibbs if (ahc->scb_data->recovery_scbs == 0) { 397133911Sgibbs /* 398133911Sgibbs * All recovery actions have completed successfully, 399133911Sgibbs * so reinstate the timeouts for all other pending 400133911Sgibbs * commands. 401133911Sgibbs */ 402133911Sgibbs LIST_FOREACH(list_scb, &ahc->pending_scbs, 403133911Sgibbs pending_links) { 404133911Sgibbs 405150450Sgibbs aic_scb_timer_reset(list_scb, 406150450Sgibbs aic_get_timeout(scb)); 407133911Sgibbs } 408133911Sgibbs 409133911Sgibbs ahc_print_path(ahc, scb); 410133911Sgibbs printf("no longer in timeout, status = %x\n", 411133911Sgibbs ccb->ccb_h.status); 412133911Sgibbs } 41365942Sgibbs } 41465942Sgibbs 41565942Sgibbs /* Don't clobber any existing error state */ 416123579Sgibbs if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) { 41765942Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 41865942Sgibbs } else if ((scb->flags & SCB_SENSE) != 0) { 41965942Sgibbs /* 42065942Sgibbs * We performed autosense retrieval. 42165942Sgibbs * 42265942Sgibbs * Zero any sense not transferred by the 42365942Sgibbs * device. The SCSI spec mandates that any 42465942Sgibbs * untransfered data should be assumed to be 42565942Sgibbs * zero. Complete the 'bounce' of sense information 42665942Sgibbs * through buffers accessible via bus-space by 42765942Sgibbs * copying it into the clients csio. 42865942Sgibbs */ 42965942Sgibbs memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data)); 43065942Sgibbs memcpy(&ccb->csio.sense_data, 43170807Sgibbs ahc_get_sense_buf(ahc, scb), 432123579Sgibbs (aic_le32toh(scb->sg_list->len) & AHC_SG_LEN_MASK) 43365942Sgibbs - ccb->csio.sense_resid); 43465942Sgibbs scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID; 43565942Sgibbs } 43665942Sgibbs ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 43765942Sgibbs ahc_free_scb(ahc, scb); 43865942Sgibbs xpt_done(ccb); 43965942Sgibbs} 44065942Sgibbs 44165942Sgibbsstatic void 44265942Sgibbsahc_action(struct cam_sim *sim, union ccb *ccb) 44365942Sgibbs{ 44465942Sgibbs struct ahc_softc *ahc; 44574972Sgibbs struct ahc_tmode_lstate *lstate; 44665942Sgibbs u_int target_id; 44765942Sgibbs u_int our_id; 44865942Sgibbs 44965942Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahc_action\n")); 45065942Sgibbs 45165942Sgibbs ahc = (struct ahc_softc *)cam_sim_softc(sim); 45265942Sgibbs 45365942Sgibbs target_id = ccb->ccb_h.target_id; 45465942Sgibbs our_id = SIM_SCSI_ID(ahc, sim); 45565942Sgibbs 45665942Sgibbs switch (ccb->ccb_h.func_code) { 45765942Sgibbs /* Common cases first */ 45865942Sgibbs case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 45965942Sgibbs case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/ 46065942Sgibbs { 46174972Sgibbs struct ahc_tmode_tstate *tstate; 46265942Sgibbs cam_status status; 46365942Sgibbs 46465942Sgibbs status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, 46565942Sgibbs &lstate, TRUE); 46665942Sgibbs 46765942Sgibbs if (status != CAM_REQ_CMP) { 46865942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 46965942Sgibbs /* Response from the black hole device */ 47065942Sgibbs tstate = NULL; 47165942Sgibbs lstate = ahc->black_hole; 47265942Sgibbs } else { 47365942Sgibbs ccb->ccb_h.status = status; 47465942Sgibbs xpt_done(ccb); 47565942Sgibbs break; 47665942Sgibbs } 47765942Sgibbs } 47865942Sgibbs if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { 47965942Sgibbs 48065942Sgibbs SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h, 48165942Sgibbs sim_links.sle); 48265942Sgibbs ccb->ccb_h.status = CAM_REQ_INPROG; 48365942Sgibbs if ((ahc->flags & AHC_TQINFIFO_BLOCKED) != 0) 48465942Sgibbs ahc_run_tqinfifo(ahc, /*paused*/FALSE); 48565942Sgibbs break; 48665942Sgibbs } 48765942Sgibbs 48865942Sgibbs /* 48965942Sgibbs * The target_id represents the target we attempt to 49065942Sgibbs * select. In target mode, this is the initiator of 49165942Sgibbs * the original command. 49265942Sgibbs */ 49365942Sgibbs our_id = target_id; 49465942Sgibbs target_id = ccb->csio.init_id; 49565942Sgibbs /* FALLTHROUGH */ 49665942Sgibbs } 49765942Sgibbs case XPT_SCSI_IO: /* Execute the requested I/O operation */ 49865942Sgibbs case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 49965942Sgibbs { 50066717Sgibbs struct scb *scb; 50166717Sgibbs struct hardware_scb *hscb; 50265942Sgibbs 50368087Sgibbs if ((ahc->flags & AHC_INITIATORROLE) == 0 50468087Sgibbs && (ccb->ccb_h.func_code == XPT_SCSI_IO 50568087Sgibbs || ccb->ccb_h.func_code == XPT_RESET_DEV)) { 50668087Sgibbs ccb->ccb_h.status = CAM_PROVIDE_FAIL; 50768087Sgibbs xpt_done(ccb); 50874972Sgibbs return; 50968087Sgibbs } 51068087Sgibbs 51165942Sgibbs /* 51265942Sgibbs * get an scb to use. 51365942Sgibbs */ 51465942Sgibbs if ((scb = ahc_get_scb(ahc)) == NULL) { 51565942Sgibbs 51666891Sgibbs xpt_freeze_simq(sim, /*count*/1); 51765942Sgibbs ahc->flags |= AHC_RESOURCE_SHORTAGE; 51866510Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 51965942Sgibbs xpt_done(ccb); 52065942Sgibbs return; 52165942Sgibbs } 52265942Sgibbs 52365942Sgibbs hscb = scb->hscb; 52465942Sgibbs 52565942Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, 52665942Sgibbs ("start scb(%p)\n", scb)); 52765942Sgibbs scb->io_ctx = ccb; 52865942Sgibbs /* 52965942Sgibbs * So we can find the SCB when an abort is requested 53065942Sgibbs */ 53165942Sgibbs ccb->ccb_h.ccb_scb_ptr = scb; 53265942Sgibbs 53365942Sgibbs /* 53465942Sgibbs * Put all the arguments for the xfer in the scb 53565942Sgibbs */ 53665942Sgibbs hscb->control = 0; 53765942Sgibbs hscb->scsiid = BUILD_SCSIID(ahc, sim, target_id, our_id); 53865942Sgibbs hscb->lun = ccb->ccb_h.target_lun; 53965942Sgibbs if (ccb->ccb_h.func_code == XPT_RESET_DEV) { 54065942Sgibbs hscb->cdb_len = 0; 54165942Sgibbs scb->flags |= SCB_DEVICE_RESET; 54265942Sgibbs hscb->control |= MK_MESSAGE; 54365942Sgibbs ahc_execute_scb(scb, NULL, 0, 0); 54465942Sgibbs } else { 54565942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 54665942Sgibbs struct target_data *tdata; 54765942Sgibbs 54865942Sgibbs tdata = &hscb->shared_data.tdata; 54974972Sgibbs if (ahc->pending_device == lstate) 55065942Sgibbs scb->flags |= SCB_TARGET_IMMEDIATE; 55165942Sgibbs hscb->control |= TARGET_SCB; 552107417Sscottl scb->flags |= SCB_TARGET_SCB; 553107417Sscottl tdata->target_phases = 0; 55465942Sgibbs if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { 55565942Sgibbs tdata->target_phases |= SPHASE_PENDING; 55665942Sgibbs tdata->scsi_status = 55765942Sgibbs ccb->csio.scsi_status; 55865942Sgibbs } 55974972Sgibbs if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) 56074972Sgibbs tdata->target_phases |= NO_DISCONNECT; 56174972Sgibbs 56265942Sgibbs tdata->initiator_tag = ccb->csio.tag_id; 56365942Sgibbs } 56465942Sgibbs if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) 56565942Sgibbs hscb->control |= ccb->csio.tag_action; 56665942Sgibbs 56765942Sgibbs ahc_setup_data(ahc, sim, &ccb->csio, scb); 56865942Sgibbs } 56965942Sgibbs break; 57065942Sgibbs } 571237601Sken case XPT_NOTIFY_ACKNOWLEDGE: 572237601Sken case XPT_IMMEDIATE_NOTIFY: 57365942Sgibbs { 57474972Sgibbs struct ahc_tmode_tstate *tstate; 57574972Sgibbs struct ahc_tmode_lstate *lstate; 57665942Sgibbs cam_status status; 57765942Sgibbs 57865942Sgibbs status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, 57965942Sgibbs &lstate, TRUE); 58065942Sgibbs 58165942Sgibbs if (status != CAM_REQ_CMP) { 58265942Sgibbs ccb->ccb_h.status = status; 58365942Sgibbs xpt_done(ccb); 58465942Sgibbs break; 58565942Sgibbs } 58665942Sgibbs SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h, 58765942Sgibbs sim_links.sle); 58865942Sgibbs ccb->ccb_h.status = CAM_REQ_INPROG; 58965942Sgibbs ahc_send_lstate_events(ahc, lstate); 59065942Sgibbs break; 59165942Sgibbs } 59265942Sgibbs case XPT_EN_LUN: /* Enable LUN as a target */ 59365942Sgibbs ahc_handle_en_lun(ahc, sim, ccb); 59465942Sgibbs xpt_done(ccb); 59565942Sgibbs break; 59665942Sgibbs case XPT_ABORT: /* Abort the specified CCB */ 59765942Sgibbs { 59865942Sgibbs ahc_abort_ccb(ahc, sim, ccb); 59965942Sgibbs break; 60065942Sgibbs } 60165942Sgibbs case XPT_SET_TRAN_SETTINGS: 60265942Sgibbs { 60365942Sgibbs struct ahc_devinfo devinfo; 60465942Sgibbs struct ccb_trans_settings *cts; 60565942Sgibbs struct ccb_trans_settings_scsi *scsi; 60665942Sgibbs struct ccb_trans_settings_spi *spi; 60765942Sgibbs struct ahc_initiator_tinfo *tinfo; 60874972Sgibbs struct ahc_tmode_tstate *tstate; 60965942Sgibbs uint16_t *discenable; 61065942Sgibbs uint16_t *tagenable; 61165942Sgibbs u_int update_type; 61265942Sgibbs 61365942Sgibbs cts = &ccb->cts; 61465942Sgibbs scsi = &cts->proto_specific.scsi; 61565942Sgibbs spi = &cts->xport_specific.spi; 61665942Sgibbs ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), 61765942Sgibbs cts->ccb_h.target_id, 61865942Sgibbs cts->ccb_h.target_lun, 61965942Sgibbs SIM_CHANNEL(ahc, sim), 62065942Sgibbs ROLE_UNKNOWN); 62165942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, 62265942Sgibbs devinfo.our_scsiid, 62365942Sgibbs devinfo.target, &tstate); 62465942Sgibbs update_type = 0; 62565942Sgibbs if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 62665942Sgibbs update_type |= AHC_TRANS_GOAL; 62765942Sgibbs discenable = &tstate->discenable; 62865942Sgibbs tagenable = &tstate->tagenable; 62976634Sgibbs tinfo->curr.protocol_version = 63065942Sgibbs cts->protocol_version; 63176634Sgibbs tinfo->curr.transport_version = 63265942Sgibbs cts->transport_version; 63365942Sgibbs tinfo->goal.protocol_version = 63465942Sgibbs cts->protocol_version; 63565942Sgibbs tinfo->goal.transport_version = 63665942Sgibbs cts->transport_version; 63765942Sgibbs } else if (cts->type == CTS_TYPE_USER_SETTINGS) { 63865942Sgibbs update_type |= AHC_TRANS_USER; 63965942Sgibbs discenable = &ahc->user_discenable; 64065942Sgibbs tagenable = &ahc->user_tagenable; 64165942Sgibbs tinfo->user.protocol_version = 64265942Sgibbs cts->protocol_version; 64365942Sgibbs tinfo->user.transport_version = 64465942Sgibbs cts->transport_version; 64565942Sgibbs } else { 64665942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 64765942Sgibbs xpt_done(ccb); 64865942Sgibbs break; 64965942Sgibbs } 65065942Sgibbs 65165942Sgibbs if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { 65265942Sgibbs if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) 65365942Sgibbs *discenable |= devinfo.target_mask; 65465942Sgibbs else 65565942Sgibbs *discenable &= ~devinfo.target_mask; 65665942Sgibbs } 65765942Sgibbs 65865942Sgibbs if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 65965942Sgibbs if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) 66065942Sgibbs *tagenable |= devinfo.target_mask; 66165942Sgibbs else 66265942Sgibbs *tagenable &= ~devinfo.target_mask; 66365942Sgibbs } 66465942Sgibbs 66565942Sgibbs if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { 66668087Sgibbs ahc_validate_width(ahc, /*tinfo limit*/NULL, 66768087Sgibbs &spi->bus_width, ROLE_UNKNOWN); 66865942Sgibbs ahc_set_width(ahc, &devinfo, spi->bus_width, 66965942Sgibbs update_type, /*paused*/FALSE); 67065942Sgibbs } 67165942Sgibbs 67265942Sgibbs if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) { 67365942Sgibbs if (update_type == AHC_TRANS_USER) 67465942Sgibbs spi->ppr_options = tinfo->user.ppr_options; 67565942Sgibbs else 67665942Sgibbs spi->ppr_options = tinfo->goal.ppr_options; 67765942Sgibbs } 67865942Sgibbs 67965942Sgibbs if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) { 68065942Sgibbs if (update_type == AHC_TRANS_USER) 68165942Sgibbs spi->sync_offset = tinfo->user.offset; 68265942Sgibbs else 68365942Sgibbs spi->sync_offset = tinfo->goal.offset; 68465942Sgibbs } 68565942Sgibbs 68665942Sgibbs if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 68765942Sgibbs if (update_type == AHC_TRANS_USER) 68865942Sgibbs spi->sync_period = tinfo->user.period; 68965942Sgibbs else 69065942Sgibbs spi->sync_period = tinfo->goal.period; 69165942Sgibbs } 69265942Sgibbs 69365942Sgibbs if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) 69465942Sgibbs || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) { 69565942Sgibbs struct ahc_syncrate *syncrate; 69665942Sgibbs u_int maxsync; 69765942Sgibbs 69865942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 69965942Sgibbs maxsync = AHC_SYNCRATE_DT; 70065942Sgibbs else if ((ahc->features & AHC_ULTRA) != 0) 70165942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 70265942Sgibbs else 70365942Sgibbs maxsync = AHC_SYNCRATE_FAST; 70465942Sgibbs 70595378Sgibbs if (spi->bus_width != MSG_EXT_WDTR_BUS_16_BIT) 70695378Sgibbs spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ; 70795378Sgibbs 70865942Sgibbs syncrate = ahc_find_syncrate(ahc, &spi->sync_period, 70965942Sgibbs &spi->ppr_options, 71065942Sgibbs maxsync); 71168087Sgibbs ahc_validate_offset(ahc, /*tinfo limit*/NULL, 71268087Sgibbs syncrate, &spi->sync_offset, 71368087Sgibbs spi->bus_width, ROLE_UNKNOWN); 71465942Sgibbs 71565942Sgibbs /* We use a period of 0 to represent async */ 71665942Sgibbs if (spi->sync_offset == 0) { 71765942Sgibbs spi->sync_period = 0; 71865942Sgibbs spi->ppr_options = 0; 71965942Sgibbs } 72065942Sgibbs 72165942Sgibbs ahc_set_syncrate(ahc, &devinfo, syncrate, 72265942Sgibbs spi->sync_period, spi->sync_offset, 72365942Sgibbs spi->ppr_options, update_type, 72465942Sgibbs /*paused*/FALSE); 72565942Sgibbs } 72665942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 72765942Sgibbs xpt_done(ccb); 72865942Sgibbs break; 72965942Sgibbs } 73065942Sgibbs case XPT_GET_TRAN_SETTINGS: 73165942Sgibbs /* Get default/user set transfer settings for the target */ 73265942Sgibbs { 73365942Sgibbs 73465942Sgibbs ahc_get_tran_settings(ahc, SIM_SCSI_ID(ahc, sim), 73565942Sgibbs SIM_CHANNEL(ahc, sim), &ccb->cts); 73665942Sgibbs xpt_done(ccb); 73765942Sgibbs break; 73865942Sgibbs } 73965942Sgibbs case XPT_CALC_GEOMETRY: 74065942Sgibbs { 741123579Sgibbs int extended; 74265942Sgibbs 74365942Sgibbs extended = SIM_IS_SCSIBUS_B(ahc, sim) 744123579Sgibbs ? ahc->flags & AHC_EXTENDED_TRANS_B 745123579Sgibbs : ahc->flags & AHC_EXTENDED_TRANS_A; 746123579Sgibbs aic_calc_geometry(&ccb->ccg, extended); 74765942Sgibbs xpt_done(ccb); 74865942Sgibbs break; 74965942Sgibbs } 75065942Sgibbs case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 75165942Sgibbs { 75265942Sgibbs int found; 75365942Sgibbs 75465942Sgibbs found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim), 75565942Sgibbs /*initiate reset*/TRUE); 75665942Sgibbs if (bootverbose) { 75765942Sgibbs xpt_print_path(SIM_PATH(ahc, sim)); 75865942Sgibbs printf("SCSI bus reset delivered. " 75965942Sgibbs "%d SCBs aborted.\n", found); 76065942Sgibbs } 76165942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 76265942Sgibbs xpt_done(ccb); 76365942Sgibbs break; 76465942Sgibbs } 76565942Sgibbs case XPT_TERM_IO: /* Terminate the I/O process */ 76665942Sgibbs /* XXX Implement */ 76765942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 76865942Sgibbs xpt_done(ccb); 76965942Sgibbs break; 77065942Sgibbs case XPT_PATH_INQ: /* Path routing inquiry */ 77165942Sgibbs { 77265942Sgibbs struct ccb_pathinq *cpi = &ccb->cpi; 77365942Sgibbs 77465942Sgibbs cpi->version_num = 1; /* XXX??? */ 77565942Sgibbs cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; 77665942Sgibbs if ((ahc->features & AHC_WIDE) != 0) 77765942Sgibbs cpi->hba_inquiry |= PI_WIDE_16; 77868087Sgibbs if ((ahc->features & AHC_TARGETMODE) != 0) { 77965942Sgibbs cpi->target_sprt = PIT_PROCESSOR 78065942Sgibbs | PIT_DISCONNECT 78165942Sgibbs | PIT_TERM_IO; 78265942Sgibbs } else { 78365942Sgibbs cpi->target_sprt = 0; 78465942Sgibbs } 78568087Sgibbs cpi->hba_misc = 0; 78665942Sgibbs cpi->hba_eng_cnt = 0; 78765942Sgibbs cpi->max_target = (ahc->features & AHC_WIDE) ? 15 : 7; 78870204Sgibbs cpi->max_lun = AHC_NUM_LUNS - 1; 78965942Sgibbs if (SIM_IS_SCSIBUS_B(ahc, sim)) { 79065942Sgibbs cpi->initiator_id = ahc->our_id_b; 79165942Sgibbs if ((ahc->flags & AHC_RESET_BUS_B) == 0) 79265942Sgibbs cpi->hba_misc |= PIM_NOBUSRESET; 79365942Sgibbs } else { 79465942Sgibbs cpi->initiator_id = ahc->our_id; 79565942Sgibbs if ((ahc->flags & AHC_RESET_BUS_A) == 0) 79665942Sgibbs cpi->hba_misc |= PIM_NOBUSRESET; 79765942Sgibbs } 79865942Sgibbs cpi->bus_id = cam_sim_bus(sim); 79965942Sgibbs cpi->base_transfer_speed = 3300; 800315812Smav strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 801315812Smav strlcpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); 802315812Smav strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 80365942Sgibbs cpi->unit_number = cam_sim_unit(sim); 80465942Sgibbs cpi->protocol = PROTO_SCSI; 80565942Sgibbs cpi->protocol_version = SCSI_REV_2; 80665942Sgibbs cpi->transport = XPORT_SPI; 80765942Sgibbs cpi->transport_version = 2; 80865942Sgibbs cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_ST; 80965942Sgibbs if ((ahc->features & AHC_DT) != 0) { 81065942Sgibbs cpi->transport_version = 3; 81165942Sgibbs cpi->xport_specific.spi.ppr_options = 81265942Sgibbs SID_SPI_CLOCK_DT_ST; 81365942Sgibbs } 81465942Sgibbs cpi->ccb_h.status = CAM_REQ_CMP; 81565942Sgibbs xpt_done(ccb); 81665942Sgibbs break; 81765942Sgibbs } 81865942Sgibbs default: 81968087Sgibbs ccb->ccb_h.status = CAM_PROVIDE_FAIL; 82065942Sgibbs xpt_done(ccb); 82165942Sgibbs break; 82265942Sgibbs } 82365942Sgibbs} 82465942Sgibbs 82565942Sgibbsstatic void 82665942Sgibbsahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel, 82765942Sgibbs struct ccb_trans_settings *cts) 82865942Sgibbs{ 82965942Sgibbs struct ahc_devinfo devinfo; 83065942Sgibbs struct ccb_trans_settings_scsi *scsi; 83165942Sgibbs struct ccb_trans_settings_spi *spi; 83265942Sgibbs struct ahc_initiator_tinfo *targ_info; 83374972Sgibbs struct ahc_tmode_tstate *tstate; 83465942Sgibbs struct ahc_transinfo *tinfo; 83565942Sgibbs 83665942Sgibbs scsi = &cts->proto_specific.scsi; 83765942Sgibbs spi = &cts->xport_specific.spi; 83865942Sgibbs ahc_compile_devinfo(&devinfo, our_id, 83965942Sgibbs cts->ccb_h.target_id, 84065942Sgibbs cts->ccb_h.target_lun, 84165942Sgibbs channel, ROLE_UNKNOWN); 84265942Sgibbs targ_info = ahc_fetch_transinfo(ahc, devinfo.channel, 84365942Sgibbs devinfo.our_scsiid, 84465942Sgibbs devinfo.target, &tstate); 84565942Sgibbs 84665942Sgibbs if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 84776634Sgibbs tinfo = &targ_info->curr; 84865942Sgibbs else 84965942Sgibbs tinfo = &targ_info->user; 85065942Sgibbs 85165942Sgibbs scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 85265942Sgibbs spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 85365942Sgibbs if (cts->type == CTS_TYPE_USER_SETTINGS) { 85465942Sgibbs if ((ahc->user_discenable & devinfo.target_mask) != 0) 85565942Sgibbs spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 85665942Sgibbs 85765942Sgibbs if ((ahc->user_tagenable & devinfo.target_mask) != 0) 85865942Sgibbs scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 85965942Sgibbs } else { 86065942Sgibbs if ((tstate->discenable & devinfo.target_mask) != 0) 86165942Sgibbs spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 86265942Sgibbs 86365942Sgibbs if ((tstate->tagenable & devinfo.target_mask) != 0) 86465942Sgibbs scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 86565942Sgibbs } 86665942Sgibbs cts->protocol_version = tinfo->protocol_version; 86765942Sgibbs cts->transport_version = tinfo->transport_version; 86865942Sgibbs 86965942Sgibbs spi->sync_period = tinfo->period; 87065942Sgibbs spi->sync_offset = tinfo->offset; 87165942Sgibbs spi->bus_width = tinfo->width; 87265942Sgibbs spi->ppr_options = tinfo->ppr_options; 87365942Sgibbs 87465942Sgibbs cts->protocol = PROTO_SCSI; 87565942Sgibbs cts->transport = XPORT_SPI; 87665942Sgibbs spi->valid = CTS_SPI_VALID_SYNC_RATE 87765942Sgibbs | CTS_SPI_VALID_SYNC_OFFSET 87865942Sgibbs | CTS_SPI_VALID_BUS_WIDTH 87965942Sgibbs | CTS_SPI_VALID_PPR_OPTIONS; 88065942Sgibbs 88166717Sgibbs if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 88266717Sgibbs scsi->valid = CTS_SCSI_VALID_TQ; 88366717Sgibbs spi->valid |= CTS_SPI_VALID_DISC; 88466717Sgibbs } else { 88566717Sgibbs scsi->valid = 0; 88666717Sgibbs } 88766717Sgibbs 88865942Sgibbs cts->ccb_h.status = CAM_REQ_CMP; 88965942Sgibbs} 89065942Sgibbs 89165942Sgibbsstatic void 89265942Sgibbsahc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) 89365942Sgibbs{ 89465942Sgibbs struct ahc_softc *ahc; 89565942Sgibbs struct cam_sim *sim; 89665942Sgibbs 89765942Sgibbs sim = (struct cam_sim *)callback_arg; 89865942Sgibbs ahc = (struct ahc_softc *)cam_sim_softc(sim); 89965942Sgibbs switch (code) { 90065942Sgibbs case AC_LOST_DEVICE: 90165942Sgibbs { 90265942Sgibbs struct ahc_devinfo devinfo; 90365942Sgibbs 90465942Sgibbs ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), 90565942Sgibbs xpt_path_target_id(path), 90665942Sgibbs xpt_path_lun_id(path), 90765942Sgibbs SIM_CHANNEL(ahc, sim), 90865942Sgibbs ROLE_UNKNOWN); 90965942Sgibbs 91065942Sgibbs /* 91165942Sgibbs * Revert to async/narrow transfers 91265942Sgibbs * for the next device. 91365942Sgibbs */ 91465942Sgibbs ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, 91565942Sgibbs AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE); 91665942Sgibbs ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL, 91765942Sgibbs /*period*/0, /*offset*/0, /*ppr_options*/0, 91865942Sgibbs AHC_TRANS_GOAL|AHC_TRANS_CUR, 91965942Sgibbs /*paused*/FALSE); 92065942Sgibbs break; 92165942Sgibbs } 92265942Sgibbs default: 92365942Sgibbs break; 92465942Sgibbs } 92565942Sgibbs} 92665942Sgibbs 92765942Sgibbsstatic void 92865942Sgibbsahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, 92965942Sgibbs int error) 93065942Sgibbs{ 93166717Sgibbs struct scb *scb; 93266717Sgibbs union ccb *ccb; 93366717Sgibbs struct ahc_softc *ahc; 93466717Sgibbs struct ahc_initiator_tinfo *tinfo; 93574972Sgibbs struct ahc_tmode_tstate *tstate; 93666717Sgibbs u_int mask; 93765942Sgibbs 93865942Sgibbs scb = (struct scb *)arg; 93965942Sgibbs ccb = scb->io_ctx; 94066986Sgibbs ahc = scb->ahc_softc; 94165942Sgibbs 94265942Sgibbs if (error != 0) { 94365942Sgibbs if (error == EFBIG) 944123579Sgibbs aic_set_transaction_status(scb, CAM_REQ_TOO_BIG); 94565942Sgibbs else 946123579Sgibbs aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); 94765942Sgibbs if (nsegments != 0) 94865942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); 94965942Sgibbs ahc_free_scb(ahc, scb); 95065942Sgibbs xpt_done(ccb); 95165942Sgibbs return; 95265942Sgibbs } 95365942Sgibbs if (nsegments != 0) { 95465942Sgibbs struct ahc_dma_seg *sg; 95565942Sgibbs bus_dma_segment_t *end_seg; 956115343Sscottl bus_dmasync_op_t op; 95765942Sgibbs 95865942Sgibbs end_seg = dm_segs + nsegments; 95965942Sgibbs 96065942Sgibbs /* Copy the segments into our SG list */ 96165942Sgibbs sg = scb->sg_list; 96265942Sgibbs while (dm_segs < end_seg) { 96379874Sgibbs uint32_t len; 96479874Sgibbs 965123579Sgibbs sg->addr = aic_htole32(dm_segs->ds_addr); 96679874Sgibbs len = dm_segs->ds_len 96779874Sgibbs | ((dm_segs->ds_addr >> 8) & 0x7F000000); 968123579Sgibbs sg->len = aic_htole32(len); 96965942Sgibbs sg++; 97065942Sgibbs dm_segs++; 97165942Sgibbs } 97265942Sgibbs 97365942Sgibbs /* 97465942Sgibbs * Note where to find the SG entries in bus space. 97565942Sgibbs * We also set the full residual flag which the 97665942Sgibbs * sequencer will clear as soon as a data transfer 97765942Sgibbs * occurs. 97865942Sgibbs */ 979123579Sgibbs scb->hscb->sgptr = aic_htole32(scb->sg_list_phys|SG_FULL_RESID); 98065942Sgibbs 98165942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 98265942Sgibbs op = BUS_DMASYNC_PREREAD; 98365942Sgibbs else 98465942Sgibbs op = BUS_DMASYNC_PREWRITE; 98565942Sgibbs 98665942Sgibbs bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op); 98765942Sgibbs 98865942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 98965942Sgibbs struct target_data *tdata; 99065942Sgibbs 99165942Sgibbs tdata = &scb->hscb->shared_data.tdata; 99265942Sgibbs tdata->target_phases |= DPHASE_PENDING; 993123579Sgibbs /* 994123579Sgibbs * CAM data direction is relative to the initiator. 995123579Sgibbs */ 99665942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 99765942Sgibbs tdata->data_phase = P_DATAOUT; 99865942Sgibbs else 99965942Sgibbs tdata->data_phase = P_DATAIN; 100065942Sgibbs 100165942Sgibbs /* 100265942Sgibbs * If the transfer is of an odd length and in the 100365942Sgibbs * "in" direction (scsi->HostBus), then it may 100465942Sgibbs * trigger a bug in the 'WideODD' feature of 100565942Sgibbs * non-Ultra2 chips. Force the total data-length 100665942Sgibbs * to be even by adding an extra, 1 byte, SG, 100765942Sgibbs * element. We do this even if we are not currently 100865942Sgibbs * negotiated wide as negotiation could occur before 100965942Sgibbs * this command is executed. 101065942Sgibbs */ 101165942Sgibbs if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0 101265942Sgibbs && (ccb->csio.dxfer_len & 0x1) != 0 1013123579Sgibbs && (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 101465942Sgibbs 101565942Sgibbs nsegments++; 101665942Sgibbs if (nsegments > AHC_NSEG) { 101765942Sgibbs 1018123579Sgibbs aic_set_transaction_status(scb, 101965942Sgibbs CAM_REQ_TOO_BIG); 102065942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, 102165942Sgibbs scb->dmamap); 102265942Sgibbs ahc_free_scb(ahc, scb); 102365942Sgibbs xpt_done(ccb); 102465942Sgibbs return; 102565942Sgibbs } 1026123579Sgibbs sg->addr = aic_htole32(ahc->dma_bug_buf); 1027123579Sgibbs sg->len = aic_htole32(1); 102865942Sgibbs sg++; 102965942Sgibbs } 103065942Sgibbs } 103165942Sgibbs sg--; 1032123579Sgibbs sg->len |= aic_htole32(AHC_DMA_LAST_SEG); 103365942Sgibbs 103465942Sgibbs /* Copy the first SG into the "current" data pointer area */ 103565942Sgibbs scb->hscb->dataptr = scb->sg_list->addr; 103665942Sgibbs scb->hscb->datacnt = scb->sg_list->len; 103765942Sgibbs } else { 1038123579Sgibbs scb->hscb->sgptr = aic_htole32(SG_LIST_NULL); 103965942Sgibbs scb->hscb->dataptr = 0; 104065942Sgibbs scb->hscb->datacnt = 0; 104165942Sgibbs } 104265942Sgibbs 104365942Sgibbs scb->sg_count = nsegments; 104465942Sgibbs 104565942Sgibbs /* 104665942Sgibbs * Last time we need to check if this SCB needs to 104765942Sgibbs * be aborted. 104865942Sgibbs */ 1049123579Sgibbs if (aic_get_transaction_status(scb) != CAM_REQ_INPROG) { 105065942Sgibbs if (nsegments != 0) 105195378Sgibbs bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); 105265942Sgibbs ahc_free_scb(ahc, scb); 105365942Sgibbs xpt_done(ccb); 105465942Sgibbs return; 105565942Sgibbs } 105665942Sgibbs 105766717Sgibbs tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid), 105866717Sgibbs SCSIID_OUR_ID(scb->hscb->scsiid), 105968087Sgibbs SCSIID_TARGET(ahc, scb->hscb->scsiid), 106068087Sgibbs &tstate); 106166717Sgibbs 106266717Sgibbs mask = SCB_GET_TARGET_MASK(ahc, scb); 106366717Sgibbs scb->hscb->scsirate = tinfo->scsirate; 106476634Sgibbs scb->hscb->scsioffset = tinfo->curr.offset; 106566717Sgibbs if ((tstate->ultraenb & mask) != 0) 106666717Sgibbs scb->hscb->control |= ULTRAENB; 106774972Sgibbs 106866717Sgibbs if ((tstate->discenable & mask) != 0 106966717Sgibbs && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0) 107066717Sgibbs scb->hscb->control |= DISCENB; 107166717Sgibbs 107266717Sgibbs if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0 107370204Sgibbs && (tinfo->goal.width != 0 1074102674Sgibbs || tinfo->goal.offset != 0 107570204Sgibbs || tinfo->goal.ppr_options != 0)) { 107666717Sgibbs scb->flags |= SCB_NEGOTIATE; 107766717Sgibbs scb->hscb->control |= MK_MESSAGE; 107874972Sgibbs } else if ((tstate->auto_negotiate & mask) != 0) { 107974972Sgibbs scb->flags |= SCB_AUTO_NEGOTIATE; 108074972Sgibbs scb->hscb->control |= MK_MESSAGE; 108166717Sgibbs } 108266717Sgibbs 108365942Sgibbs LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); 108465942Sgibbs 108565942Sgibbs ccb->ccb_h.status |= CAM_SIM_QUEUED; 108665942Sgibbs 108765942Sgibbs /* 108865942Sgibbs * We only allow one untagged transaction 108965942Sgibbs * per target in the initiator role unless 109065942Sgibbs * we are storing a full busy target *lun* 109165942Sgibbs * table in SCB space. 109265942Sgibbs */ 109365942Sgibbs if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0 109471390Sgibbs && (ahc->flags & AHC_SCB_BTT) == 0) { 109565942Sgibbs struct scb_tailq *untagged_q; 109672811Sgibbs int target_offset; 109765942Sgibbs 109872811Sgibbs target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); 109972811Sgibbs untagged_q = &(ahc->untagged_queues[target_offset]); 110065942Sgibbs TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); 110166986Sgibbs scb->flags |= SCB_UNTAGGEDQ; 110265942Sgibbs if (TAILQ_FIRST(untagged_q) != scb) { 110365942Sgibbs return; 110465942Sgibbs } 110565942Sgibbs } 110665942Sgibbs scb->flags |= SCB_ACTIVE; 110765942Sgibbs 1108133911Sgibbs /* 1109133911Sgibbs * Timers are disabled while recovery is in progress. 1110133911Sgibbs */ 1111133911Sgibbs aic_scb_timer_start(scb); 1112133911Sgibbs 111365942Sgibbs if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { 111474972Sgibbs /* Define a mapping from our tag to the SCB. */ 111574972Sgibbs ahc->scb_data->scbindex[scb->hscb->tag] = scb; 111674094Sgibbs ahc_pause(ahc); 111765942Sgibbs if ((ahc->flags & AHC_PAGESCBS) == 0) 111865942Sgibbs ahc_outb(ahc, SCBPTR, scb->hscb->tag); 1119102674Sgibbs ahc_outb(ahc, TARG_IMMEDIATE_SCB, scb->hscb->tag); 112074094Sgibbs ahc_unpause(ahc); 112165942Sgibbs } else { 112265942Sgibbs ahc_queue_scb(ahc, scb); 112365942Sgibbs } 112465942Sgibbs} 112565942Sgibbs 112665942Sgibbsstatic void 112765942Sgibbsahc_poll(struct cam_sim *sim) 112865942Sgibbs{ 1129102674Sgibbs struct ahc_softc *ahc; 1130102674Sgibbs 1131102674Sgibbs ahc = (struct ahc_softc *)cam_sim_softc(sim); 1132102674Sgibbs ahc_intr(ahc); 113365942Sgibbs} 113465942Sgibbs 113565942Sgibbsstatic void 113665942Sgibbsahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, 113765942Sgibbs struct ccb_scsiio *csio, struct scb *scb) 113865942Sgibbs{ 113965942Sgibbs struct hardware_scb *hscb; 114065942Sgibbs struct ccb_hdr *ccb_h; 1141246713Skib int error; 114265942Sgibbs 114365942Sgibbs hscb = scb->hscb; 114465942Sgibbs ccb_h = &csio->ccb_h; 114565942Sgibbs 114679874Sgibbs csio->resid = 0; 114779874Sgibbs csio->sense_resid = 0; 114865942Sgibbs if (ccb_h->func_code == XPT_SCSI_IO) { 114965942Sgibbs hscb->cdb_len = csio->cdb_len; 115065942Sgibbs if ((ccb_h->flags & CAM_CDB_POINTER) != 0) { 115165942Sgibbs 115265942Sgibbs if (hscb->cdb_len > sizeof(hscb->cdb32) 115365942Sgibbs || (ccb_h->flags & CAM_CDB_PHYS) != 0) { 1154123579Sgibbs aic_set_transaction_status(scb, 115565942Sgibbs CAM_REQ_INVALID); 115665942Sgibbs ahc_free_scb(ahc, scb); 115766647Sgibbs xpt_done((union ccb *)csio); 115865942Sgibbs return; 115965942Sgibbs } 116065942Sgibbs if (hscb->cdb_len > 12) { 116165942Sgibbs memcpy(hscb->cdb32, 116265942Sgibbs csio->cdb_io.cdb_ptr, 116365942Sgibbs hscb->cdb_len); 116468087Sgibbs scb->flags |= SCB_CDB32_PTR; 116565942Sgibbs } else { 116665942Sgibbs memcpy(hscb->shared_data.cdb, 116765942Sgibbs csio->cdb_io.cdb_ptr, 116865942Sgibbs hscb->cdb_len); 116965942Sgibbs } 117065942Sgibbs } else { 117165942Sgibbs if (hscb->cdb_len > 12) { 117265942Sgibbs memcpy(hscb->cdb32, csio->cdb_io.cdb_bytes, 117365942Sgibbs hscb->cdb_len); 117468087Sgibbs scb->flags |= SCB_CDB32_PTR; 117565942Sgibbs } else { 117665942Sgibbs memcpy(hscb->shared_data.cdb, 117765942Sgibbs csio->cdb_io.cdb_bytes, 117865942Sgibbs hscb->cdb_len); 117965942Sgibbs } 118065942Sgibbs } 118165942Sgibbs } 118265942Sgibbs 1183246713Skib error = bus_dmamap_load_ccb(ahc->buffer_dmat, 1184246713Skib scb->dmamap, 1185246713Skib (union ccb *)csio, 1186246713Skib ahc_execute_scb, 1187246713Skib scb, 1188246713Skib 0); 1189246713Skib if (error == EINPROGRESS) { 1190246713Skib /* 1191246713Skib * So as to maintain ordering, 1192246713Skib * freeze the controller queue 1193246713Skib * until our mapping is 1194246713Skib * returned. 1195246713Skib */ 1196246713Skib xpt_freeze_simq(sim, /*count*/1); 1197246713Skib scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; 119865942Sgibbs } 119965942Sgibbs} 120065942Sgibbs 120165942Sgibbsstatic void 120265942Sgibbsahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) 120365942Sgibbs{ 120465942Sgibbs union ccb *abort_ccb; 120565942Sgibbs 120665942Sgibbs abort_ccb = ccb->cab.abort_ccb; 120765942Sgibbs switch (abort_ccb->ccb_h.func_code) { 120865942Sgibbs case XPT_ACCEPT_TARGET_IO: 1209237601Sken case XPT_IMMEDIATE_NOTIFY: 121065942Sgibbs case XPT_CONT_TARGET_IO: 121165942Sgibbs { 121274972Sgibbs struct ahc_tmode_tstate *tstate; 121374972Sgibbs struct ahc_tmode_lstate *lstate; 121465942Sgibbs struct ccb_hdr_slist *list; 121565942Sgibbs cam_status status; 121665942Sgibbs 121765942Sgibbs status = ahc_find_tmode_devs(ahc, sim, abort_ccb, &tstate, 121865942Sgibbs &lstate, TRUE); 121965942Sgibbs 122065942Sgibbs if (status != CAM_REQ_CMP) { 122165942Sgibbs ccb->ccb_h.status = status; 122265942Sgibbs break; 122365942Sgibbs } 122465942Sgibbs 122565942Sgibbs if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) 122665942Sgibbs list = &lstate->accept_tios; 1227237601Sken else if (abort_ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) 122865942Sgibbs list = &lstate->immed_notifies; 122965942Sgibbs else 123065942Sgibbs list = NULL; 123165942Sgibbs 123265942Sgibbs if (list != NULL) { 123365942Sgibbs struct ccb_hdr *curelm; 123465942Sgibbs int found; 123565942Sgibbs 123665942Sgibbs curelm = SLIST_FIRST(list); 123765942Sgibbs found = 0; 123865942Sgibbs if (curelm == &abort_ccb->ccb_h) { 123965942Sgibbs found = 1; 124065942Sgibbs SLIST_REMOVE_HEAD(list, sim_links.sle); 124165942Sgibbs } else { 124265942Sgibbs while(curelm != NULL) { 124365942Sgibbs struct ccb_hdr *nextelm; 124465942Sgibbs 124565942Sgibbs nextelm = 124665942Sgibbs SLIST_NEXT(curelm, sim_links.sle); 124765942Sgibbs 124865942Sgibbs if (nextelm == &abort_ccb->ccb_h) { 124965942Sgibbs found = 1; 125065942Sgibbs SLIST_NEXT(curelm, 125165942Sgibbs sim_links.sle) = 125265942Sgibbs SLIST_NEXT(nextelm, 125365942Sgibbs sim_links.sle); 125465942Sgibbs break; 125565942Sgibbs } 125665942Sgibbs curelm = nextelm; 125765942Sgibbs } 125865942Sgibbs } 125965942Sgibbs 126065942Sgibbs if (found) { 126165942Sgibbs abort_ccb->ccb_h.status = CAM_REQ_ABORTED; 126265942Sgibbs xpt_done(abort_ccb); 126365942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 126465942Sgibbs } else { 126568087Sgibbs xpt_print_path(abort_ccb->ccb_h.path); 126665942Sgibbs printf("Not found\n"); 126765942Sgibbs ccb->ccb_h.status = CAM_PATH_INVALID; 126865942Sgibbs } 126965942Sgibbs break; 127065942Sgibbs } 127165942Sgibbs /* FALLTHROUGH */ 127265942Sgibbs } 127365942Sgibbs case XPT_SCSI_IO: 127465942Sgibbs /* XXX Fully implement the hard ones */ 127565942Sgibbs ccb->ccb_h.status = CAM_UA_ABORT; 127665942Sgibbs break; 127765942Sgibbs default: 127865942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 127965942Sgibbs break; 128065942Sgibbs } 128165942Sgibbs xpt_done(ccb); 128265942Sgibbs} 128365942Sgibbs 128465942Sgibbsvoid 128566269Sgibbsahc_send_async(struct ahc_softc *ahc, char channel, u_int target, 128676634Sgibbs u_int lun, ac_code code, void *opt_arg) 128765942Sgibbs{ 128865942Sgibbs struct ccb_trans_settings cts; 128965942Sgibbs struct cam_path *path; 129065942Sgibbs void *arg; 129165942Sgibbs int error; 129265942Sgibbs 129365942Sgibbs arg = NULL; 129466269Sgibbs error = ahc_create_path(ahc, channel, target, lun, &path); 129565942Sgibbs 129665942Sgibbs if (error != CAM_REQ_CMP) 129765942Sgibbs return; 129865942Sgibbs 129965942Sgibbs switch (code) { 130065942Sgibbs case AC_TRANSFER_NEG: 130176634Sgibbs { 130276634Sgibbs struct ccb_trans_settings_scsi *scsi; 130376634Sgibbs 130465942Sgibbs cts.type = CTS_TYPE_CURRENT_SETTINGS; 130576634Sgibbs scsi = &cts.proto_specific.scsi; 130665942Sgibbs cts.ccb_h.path = path; 130766269Sgibbs cts.ccb_h.target_id = target; 130866269Sgibbs cts.ccb_h.target_lun = lun; 130966269Sgibbs ahc_get_tran_settings(ahc, channel == 'A' ? ahc->our_id 131066269Sgibbs : ahc->our_id_b, 131166269Sgibbs channel, &cts); 131265942Sgibbs arg = &cts; 131376634Sgibbs scsi->valid &= ~CTS_SCSI_VALID_TQ; 131476634Sgibbs scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 131576634Sgibbs if (opt_arg == NULL) 131676634Sgibbs break; 131776634Sgibbs if (*((ahc_queue_alg *)opt_arg) == AHC_QUEUE_TAGGED) 131876634Sgibbs scsi->flags |= ~CTS_SCSI_FLAGS_TAG_ENB; 131976634Sgibbs scsi->valid |= CTS_SCSI_VALID_TQ; 132065942Sgibbs break; 132176634Sgibbs } 132265942Sgibbs case AC_SENT_BDR: 132365942Sgibbs case AC_BUS_RESET: 132465942Sgibbs break; 132565942Sgibbs default: 132665942Sgibbs panic("ahc_send_async: Unexpected async event"); 132765942Sgibbs } 132865942Sgibbs xpt_async(code, path, arg); 132968402Sgibbs xpt_free_path(path); 133065942Sgibbs} 133165942Sgibbs 133265942Sgibbsvoid 133365942Sgibbsahc_platform_set_tags(struct ahc_softc *ahc, 133465942Sgibbs struct ahc_devinfo *devinfo, int enable) 133565942Sgibbs{ 133665942Sgibbs} 133765942Sgibbs 133865942Sgibbsint 133965942Sgibbsahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) 134065942Sgibbs{ 134167888Sdwmalone ahc->platform_data = malloc(sizeof(struct ahc_platform_data), M_DEVBUF, 134267888Sdwmalone M_NOWAIT | M_ZERO); 134365942Sgibbs if (ahc->platform_data == NULL) 134465942Sgibbs return (ENOMEM); 134565942Sgibbs return (0); 134665942Sgibbs} 134765942Sgibbs 134865942Sgibbsvoid 134965942Sgibbsahc_platform_free(struct ahc_softc *ahc) 135065942Sgibbs{ 135170204Sgibbs struct ahc_platform_data *pdata; 135270204Sgibbs 135370204Sgibbs pdata = ahc->platform_data; 135470204Sgibbs if (pdata != NULL) { 135570204Sgibbs if (pdata->regs != NULL) 135665942Sgibbs bus_release_resource(ahc->dev_softc, 135770204Sgibbs pdata->regs_res_type, 135870204Sgibbs pdata->regs_res_id, 135970204Sgibbs pdata->regs); 136065942Sgibbs 136170204Sgibbs if (pdata->irq != NULL) 136265942Sgibbs bus_release_resource(ahc->dev_softc, 136370204Sgibbs pdata->irq_res_type, 136470204Sgibbs 0, pdata->irq); 136565942Sgibbs 136670204Sgibbs if (pdata->sim_b != NULL) { 136770204Sgibbs xpt_async(AC_LOST_DEVICE, pdata->path_b, NULL); 136870204Sgibbs xpt_free_path(pdata->path_b); 136970204Sgibbs xpt_bus_deregister(cam_sim_path(pdata->sim_b)); 137070204Sgibbs cam_sim_free(pdata->sim_b, /*free_devq*/TRUE); 137170204Sgibbs } 137270204Sgibbs if (pdata->sim != NULL) { 137370204Sgibbs xpt_async(AC_LOST_DEVICE, pdata->path, NULL); 137470204Sgibbs xpt_free_path(pdata->path); 137570204Sgibbs xpt_bus_deregister(cam_sim_path(pdata->sim)); 137670204Sgibbs cam_sim_free(pdata->sim, /*free_devq*/TRUE); 137770204Sgibbs } 137870204Sgibbs if (pdata->eh != NULL) 137970204Sgibbs EVENTHANDLER_DEREGISTER(shutdown_final, pdata->eh); 138065942Sgibbs free(ahc->platform_data, M_DEVBUF); 138165942Sgibbs } 138265942Sgibbs} 138365942Sgibbs 138465942Sgibbsint 138565942Sgibbsahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc) 138665942Sgibbs{ 138765942Sgibbs /* We don't sort softcs under FreeBSD so report equal always */ 138865942Sgibbs return (0); 138965942Sgibbs} 139065942Sgibbs 139170204Sgibbsint 139270204Sgibbsahc_detach(device_t dev) 139370204Sgibbs{ 139470204Sgibbs struct ahc_softc *ahc; 139570204Sgibbs 139670204Sgibbs device_printf(dev, "detaching device\n"); 139770204Sgibbs ahc = device_get_softc(dev); 1398168807Sscottl ahc_lock(ahc); 1399123579Sgibbs TAILQ_REMOVE(&ahc_tailq, ahc, links); 1400102674Sgibbs ahc_intr_enable(ahc, FALSE); 140170204Sgibbs bus_teardown_intr(dev, ahc->platform_data->irq, ahc->platform_data->ih); 1402168807Sscottl ahc_unlock(ahc); 140370204Sgibbs ahc_free(ahc); 140470204Sgibbs return (0); 140570204Sgibbs} 140670204Sgibbs 1407153072Sru#if 0 140865942Sgibbsstatic void 140965942Sgibbsahc_dump_targcmd(struct target_cmd *cmd) 141065942Sgibbs{ 141165942Sgibbs uint8_t *byte; 141265942Sgibbs uint8_t *last_byte; 141365942Sgibbs int i; 141465942Sgibbs 141565942Sgibbs byte = &cmd->initiator_channel; 141665942Sgibbs /* Debugging info for received commands */ 141765942Sgibbs last_byte = &cmd[1].initiator_channel; 141865942Sgibbs 141965942Sgibbs i = 0; 142065942Sgibbs while (byte < last_byte) { 142165942Sgibbs if (i == 0) 142265942Sgibbs printf("\t"); 142365942Sgibbs printf("%#x", *byte++); 142465942Sgibbs i++; 142565942Sgibbs if (i == 8) { 142665942Sgibbs printf("\n"); 142765942Sgibbs i = 0; 142865942Sgibbs } else { 142965942Sgibbs printf(", "); 143065942Sgibbs } 143165942Sgibbs } 143265942Sgibbs} 143365942Sgibbs#endif 143476634Sgibbs 143576634Sgibbsstatic int 143676634Sgibbsahc_modevent(module_t mod, int type, void *data) 143776634Sgibbs{ 143876634Sgibbs /* XXX Deal with busy status on unload. */ 1439132199Sphk /* XXX Deal with unknown events */ 144076634Sgibbs return 0; 144176634Sgibbs} 144276634Sgibbs 144376634Sgibbsstatic moduledata_t ahc_mod = { 144476634Sgibbs "ahc", 144576634Sgibbs ahc_modevent, 144676634Sgibbs NULL 144776634Sgibbs}; 144876634Sgibbs 144976634SgibbsDECLARE_MODULE(ahc, ahc_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); 145076634SgibbsMODULE_DEPEND(ahc, cam, 1, 1, 1); 145176634SgibbsMODULE_VERSION(ahc, 1); 1452