aic7xxx_osm.c revision 72811
165942Sgibbs/* 265942Sgibbs * 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 * 3165942Sgibbs * $Id$ 3265942Sgibbs * 3365942Sgibbs * $FreeBSD: head/sys/dev/aic7xxx/aic7xxx_osm.c 72811 2001-02-21 20:50:36Z gibbs $ 3465942Sgibbs */ 3565942Sgibbs 3665942Sgibbs#include <dev/aic7xxx/aic7xxx_freebsd.h> 3765942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h> 3865942Sgibbs 3965942Sgibbs#ifndef AHC_TMODE_ENABLE 4065942Sgibbs#define AHC_TMODE_ENABLE 0 4165942Sgibbs#endif 4265942Sgibbs 4365942Sgibbs#define ccb_scb_ptr spriv_ptr0 4465942Sgibbs 4565942Sgibbs#ifdef AHC_DEBUG 4665942Sgibbsstatic int ahc_debug = AHC_DEBUG; 4765942Sgibbs#endif 4865942Sgibbs 4965942Sgibbs#if UNUSED 5065942Sgibbsstatic void ahc_dump_targcmd(struct target_cmd *cmd); 5165942Sgibbs#endif 5265942Sgibbsstatic void ahc_action(struct cam_sim *sim, union ccb *ccb); 5365942Sgibbsstatic void ahc_get_tran_settings(struct ahc_softc *ahc, 5465942Sgibbs int our_id, char channel, 5565942Sgibbs struct ccb_trans_settings *cts); 5665942Sgibbsstatic void ahc_async(void *callback_arg, uint32_t code, 5765942Sgibbs struct cam_path *path, void *arg); 5865942Sgibbsstatic void ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, 5965942Sgibbs int nsegments, int error); 6065942Sgibbsstatic void ahc_poll(struct cam_sim *sim); 6165942Sgibbsstatic void ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, 6265942Sgibbs struct ccb_scsiio *csio, struct scb *scb); 6365942Sgibbsstatic void ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, 6465942Sgibbs union ccb *ccb); 6565942Sgibbsstatic int ahc_create_path(struct ahc_softc *ahc, 6666269Sgibbs char channel, u_int target, u_int lun, 6765942Sgibbs struct cam_path **path); 6865942Sgibbs 6965942Sgibbsstatic void ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb); 7065942Sgibbs 7165942Sgibbsstatic int 7266269Sgibbsahc_create_path(struct ahc_softc *ahc, char channel, u_int target, 7366269Sgibbs u_int lun, struct cam_path **path) 7465942Sgibbs{ 7565942Sgibbs path_id_t path_id; 7665942Sgibbs 7766269Sgibbs if (channel == 'B') 7865942Sgibbs path_id = cam_sim_path(ahc->platform_data->sim_b); 7965942Sgibbs else 8065942Sgibbs path_id = cam_sim_path(ahc->platform_data->sim); 8165942Sgibbs 8265942Sgibbs return (xpt_create_path(path, /*periph*/NULL, 8366269Sgibbs path_id, target, lun)); 8465942Sgibbs} 8565942Sgibbs 8665942Sgibbs/* 8765942Sgibbs * Attach all the sub-devices we can find 8865942Sgibbs */ 8965942Sgibbsint 9065942Sgibbsahc_attach(struct ahc_softc *ahc) 9165942Sgibbs{ 9265942Sgibbs char ahc_info[256]; 9365942Sgibbs struct ccb_setasync csa; 9465942Sgibbs struct cam_devq *devq; 9565942Sgibbs int bus_id; 9665942Sgibbs int bus_id2; 9765942Sgibbs struct cam_sim *sim; 9865942Sgibbs struct cam_sim *sim2; 9965942Sgibbs struct cam_path *path; 10065942Sgibbs struct cam_path *path2; 10165942Sgibbs long s; 10265942Sgibbs int count; 10365942Sgibbs int error; 10465942Sgibbs 10565942Sgibbs count = 0; 10665942Sgibbs sim = NULL; 10765942Sgibbs sim2 = NULL; 10865942Sgibbs 10965942Sgibbs ahc_controller_info(ahc, ahc_info); 11065942Sgibbs printf("%s\n", ahc_info); 11165942Sgibbs ahc_lock(ahc, &s); 11265942Sgibbs /* Hook up our interrupt handler */ 11365942Sgibbs if ((error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq, 11472670Smarkm INTR_TYPE_CAM|INTR_ENTROPY, ahc_platform_intr, ahc, 11565942Sgibbs &ahc->platform_data->ih)) != 0) { 11665942Sgibbs device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n", 11765942Sgibbs error); 11865942Sgibbs goto fail; 11965942Sgibbs } 12065942Sgibbs 12165942Sgibbs /* 12265942Sgibbs * Attach secondary channel first if the user has 12365942Sgibbs * declared it the primary channel. 12465942Sgibbs */ 12572552Sgibbs if ((ahc->features & AHC_TWIN) != 0 12672552Sgibbs && (ahc->flags & AHC_CHANNEL_B_PRIMARY) != 0) { 12765942Sgibbs bus_id = 1; 12865942Sgibbs bus_id2 = 0; 12965942Sgibbs } else { 13065942Sgibbs bus_id = 0; 13165942Sgibbs bus_id2 = 1; 13265942Sgibbs } 13365942Sgibbs 13465942Sgibbs /* 13565942Sgibbs * Create the device queue for our SIM(s). 13665942Sgibbs */ 13771390Sgibbs devq = cam_simq_alloc(AHC_MAX_QUEUE); 13865942Sgibbs if (devq == NULL) 13965942Sgibbs goto fail; 14065942Sgibbs 14165942Sgibbs /* 14265942Sgibbs * Construct our first channel SIM entry 14365942Sgibbs */ 14466104Sgibbs sim = cam_sim_alloc(ahc_action, ahc_poll, "ahc", ahc, 14566104Sgibbs device_get_unit(ahc->dev_softc), 14671390Sgibbs 1, AHC_MAX_QUEUE, devq); 14765942Sgibbs if (sim == NULL) { 14865942Sgibbs cam_simq_free(devq); 14965942Sgibbs goto fail; 15065942Sgibbs } 15165942Sgibbs 15265942Sgibbs if (xpt_bus_register(sim, bus_id) != CAM_SUCCESS) { 15365942Sgibbs cam_sim_free(sim, /*free_devq*/TRUE); 15465942Sgibbs sim = NULL; 15565942Sgibbs goto fail; 15665942Sgibbs } 15765942Sgibbs 15865942Sgibbs if (xpt_create_path(&path, /*periph*/NULL, 15965942Sgibbs cam_sim_path(sim), CAM_TARGET_WILDCARD, 16065942Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 16165942Sgibbs xpt_bus_deregister(cam_sim_path(sim)); 16265942Sgibbs cam_sim_free(sim, /*free_devq*/TRUE); 16365942Sgibbs sim = NULL; 16465942Sgibbs goto fail; 16565942Sgibbs } 16665942Sgibbs 16765942Sgibbs xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); 16865942Sgibbs csa.ccb_h.func_code = XPT_SASYNC_CB; 16965942Sgibbs csa.event_enable = AC_LOST_DEVICE; 17065942Sgibbs csa.callback = ahc_async; 17165942Sgibbs csa.callback_arg = sim; 17265942Sgibbs xpt_action((union ccb *)&csa); 17365942Sgibbs count++; 17465942Sgibbs 17565942Sgibbs if (ahc->features & AHC_TWIN) { 17665942Sgibbs sim2 = cam_sim_alloc(ahc_action, ahc_poll, "ahc", 17766104Sgibbs ahc, device_get_unit(ahc->dev_softc), 1, 17871390Sgibbs AHC_MAX_QUEUE, devq); 17965942Sgibbs 18065942Sgibbs if (sim2 == NULL) { 18165942Sgibbs printf("ahc_attach: Unable to attach second " 18265942Sgibbs "bus due to resource shortage"); 18365942Sgibbs goto fail; 18465942Sgibbs } 18565942Sgibbs 18665942Sgibbs if (xpt_bus_register(sim2, bus_id2) != CAM_SUCCESS) { 18765942Sgibbs printf("ahc_attach: Unable to attach second " 18865942Sgibbs "bus due to resource shortage"); 18965942Sgibbs /* 19065942Sgibbs * We do not want to destroy the device queue 19165942Sgibbs * because the first bus is using it. 19265942Sgibbs */ 19365942Sgibbs cam_sim_free(sim2, /*free_devq*/FALSE); 19465942Sgibbs goto fail; 19565942Sgibbs } 19665942Sgibbs 19765942Sgibbs if (xpt_create_path(&path2, /*periph*/NULL, 19865942Sgibbs cam_sim_path(sim2), 19965942Sgibbs CAM_TARGET_WILDCARD, 20065942Sgibbs CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 20165942Sgibbs xpt_bus_deregister(cam_sim_path(sim2)); 20265942Sgibbs cam_sim_free(sim2, /*free_devq*/FALSE); 20365942Sgibbs sim2 = NULL; 20465942Sgibbs goto fail; 20565942Sgibbs } 20665942Sgibbs xpt_setup_ccb(&csa.ccb_h, path2, /*priority*/5); 20765942Sgibbs csa.ccb_h.func_code = XPT_SASYNC_CB; 20865942Sgibbs csa.event_enable = AC_LOST_DEVICE; 20965942Sgibbs csa.callback = ahc_async; 21065942Sgibbs csa.callback_arg = sim2; 21165942Sgibbs xpt_action((union ccb *)&csa); 21265942Sgibbs count++; 21365942Sgibbs } 21465942Sgibbs 21565942Sgibbsfail: 21672552Sgibbs if ((ahc->features & AHC_TWIN) != 0 21772552Sgibbs && (ahc->flags & AHC_CHANNEL_B_PRIMARY) != 0) { 21865942Sgibbs ahc->platform_data->sim_b = sim; 21965942Sgibbs ahc->platform_data->path_b = path; 22065942Sgibbs ahc->platform_data->sim = sim2; 22165942Sgibbs ahc->platform_data->path = path2; 22265942Sgibbs } else { 22365942Sgibbs ahc->platform_data->sim = sim; 22465942Sgibbs ahc->platform_data->path = path; 22565942Sgibbs ahc->platform_data->sim_b = sim2; 22665942Sgibbs ahc->platform_data->path_b = path2; 22765942Sgibbs } 22865942Sgibbs ahc_unlock(ahc, &s); 22965942Sgibbs 23065942Sgibbs if (count != 0) 23165942Sgibbs /* We have to wait until after any system dumps... */ 23270204Sgibbs ahc->platform_data->eh = 23370204Sgibbs EVENTHANDLER_REGISTER(shutdown_final, ahc_shutdown, 23470204Sgibbs ahc, SHUTDOWN_PRI_DEFAULT); 23565942Sgibbs 23665942Sgibbs return (count); 23765942Sgibbs} 23865942Sgibbs 23965942Sgibbs/* 24065942Sgibbs * Catch an interrupt from the adapter 24165942Sgibbs */ 24265942Sgibbsvoid 24370204Sgibbsahc_platform_intr(void *arg) 24465942Sgibbs{ 24565942Sgibbs struct ahc_softc *ahc; 24665942Sgibbs 24765942Sgibbs ahc = (struct ahc_softc *)arg; 24865942Sgibbs ahc_intr(ahc); 24965942Sgibbs} 25065942Sgibbs 25165942Sgibbs/* 25265942Sgibbs * We have an scb which has been processed by the 25365942Sgibbs * adaptor, now we look to see how the operation 25465942Sgibbs * went. 25565942Sgibbs */ 25665942Sgibbsvoid 25765942Sgibbsahc_done(struct ahc_softc *ahc, struct scb *scb) 25865942Sgibbs{ 25965942Sgibbs union ccb *ccb; 26065942Sgibbs 26165942Sgibbs CAM_DEBUG(scb->io_ctx->ccb_h.path, CAM_DEBUG_TRACE, 26265942Sgibbs ("ahc_done - scb %d\n", scb->hscb->tag)); 26365942Sgibbs 26465942Sgibbs ccb = scb->io_ctx; 26565942Sgibbs LIST_REMOVE(scb, pending_links); 26666986Sgibbs if ((scb->flags & SCB_UNTAGGEDQ) != 0) { 26765942Sgibbs struct scb_tailq *untagged_q; 26872811Sgibbs int target_offset; 26965942Sgibbs 27072811Sgibbs target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); 27172811Sgibbs untagged_q = &ahc->untagged_queues[target_offset]; 27265942Sgibbs TAILQ_REMOVE(untagged_q, scb, links.tqe); 27366986Sgibbs scb->flags &= ~SCB_UNTAGGEDQ; 27465942Sgibbs ahc_run_untagged_queue(ahc, untagged_q); 27565942Sgibbs } 27665942Sgibbs 27765942Sgibbs untimeout(ahc_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch); 27865942Sgibbs 27965942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 28065942Sgibbs bus_dmasync_op_t op; 28165942Sgibbs 28265942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 28365942Sgibbs op = BUS_DMASYNC_POSTREAD; 28465942Sgibbs else 28565942Sgibbs op = BUS_DMASYNC_POSTWRITE; 28665942Sgibbs bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op); 28765942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); 28865942Sgibbs } 28965942Sgibbs 29065942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 29165942Sgibbs if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) 29265942Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 29365942Sgibbs ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 29465942Sgibbs ahc_free_scb(ahc, scb); 29565942Sgibbs xpt_done(ccb); 29665942Sgibbs return; 29765942Sgibbs } 29865942Sgibbs 29965942Sgibbs /* 30065942Sgibbs * If the recovery SCB completes, we have to be 30165942Sgibbs * out of our timeout. 30265942Sgibbs */ 30365942Sgibbs if ((scb->flags & SCB_RECOVERY_SCB) != 0) { 30465942Sgibbs struct scb *list_scb; 30565942Sgibbs 30665942Sgibbs /* 30765942Sgibbs * We were able to complete the command successfully, 30865942Sgibbs * so reinstate the timeouts for all other pending 30965942Sgibbs * commands. 31065942Sgibbs */ 31165942Sgibbs LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { 31265942Sgibbs union ccb *ccb; 31371390Sgibbs uint64_t time; 31465942Sgibbs 31565942Sgibbs ccb = list_scb->io_ctx; 31671390Sgibbs if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) 31771390Sgibbs continue; 31871390Sgibbs 31971390Sgibbs time = ccb->ccb_h.timeout; 32071390Sgibbs time *= hz; 32171390Sgibbs time /= 1000; 32265942Sgibbs ccb->ccb_h.timeout_ch = 32371390Sgibbs timeout(ahc_timeout, list_scb, time); 32465942Sgibbs } 32565942Sgibbs 32665942Sgibbs if (ahc_get_transaction_status(scb) == CAM_BDR_SENT 32765942Sgibbs || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) 32865942Sgibbs ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); 32965942Sgibbs ahc_print_path(ahc, scb); 33065942Sgibbs printf("no longer in timeout, status = %x\n", 33165942Sgibbs ccb->ccb_h.status); 33265942Sgibbs } 33365942Sgibbs 33465942Sgibbs /* Don't clobber any existing error state */ 33565942Sgibbs if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) { 33665942Sgibbs ccb->ccb_h.status |= CAM_REQ_CMP; 33765942Sgibbs } else if ((scb->flags & SCB_SENSE) != 0) { 33865942Sgibbs /* 33965942Sgibbs * We performed autosense retrieval. 34065942Sgibbs * 34165942Sgibbs * Zero any sense not transferred by the 34265942Sgibbs * device. The SCSI spec mandates that any 34365942Sgibbs * untransfered data should be assumed to be 34465942Sgibbs * zero. Complete the 'bounce' of sense information 34565942Sgibbs * through buffers accessible via bus-space by 34665942Sgibbs * copying it into the clients csio. 34765942Sgibbs */ 34865942Sgibbs memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data)); 34965942Sgibbs memcpy(&ccb->csio.sense_data, 35070807Sgibbs ahc_get_sense_buf(ahc, scb), 35165942Sgibbs (scb->sg_list->len & AHC_SG_LEN_MASK) 35265942Sgibbs - ccb->csio.sense_resid); 35365942Sgibbs scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID; 35465942Sgibbs } 35565942Sgibbs ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 35665942Sgibbs ahc_free_scb(ahc, scb); 35765942Sgibbs xpt_done(ccb); 35865942Sgibbs} 35965942Sgibbs 36065942Sgibbsstatic void 36165942Sgibbsahc_action(struct cam_sim *sim, union ccb *ccb) 36265942Sgibbs{ 36365942Sgibbs struct ahc_softc *ahc; 36465942Sgibbs struct tmode_lstate *lstate; 36565942Sgibbs u_int target_id; 36665942Sgibbs u_int our_id; 36765942Sgibbs long s; 36865942Sgibbs 36965942Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahc_action\n")); 37065942Sgibbs 37165942Sgibbs ahc = (struct ahc_softc *)cam_sim_softc(sim); 37265942Sgibbs 37365942Sgibbs target_id = ccb->ccb_h.target_id; 37465942Sgibbs our_id = SIM_SCSI_ID(ahc, sim); 37565942Sgibbs 37665942Sgibbs switch (ccb->ccb_h.func_code) { 37765942Sgibbs /* Common cases first */ 37865942Sgibbs case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 37965942Sgibbs case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/ 38065942Sgibbs { 38165942Sgibbs struct tmode_tstate *tstate; 38265942Sgibbs cam_status status; 38365942Sgibbs 38465942Sgibbs status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, 38565942Sgibbs &lstate, TRUE); 38665942Sgibbs 38765942Sgibbs if (status != CAM_REQ_CMP) { 38865942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 38965942Sgibbs /* Response from the black hole device */ 39065942Sgibbs tstate = NULL; 39165942Sgibbs lstate = ahc->black_hole; 39265942Sgibbs } else { 39365942Sgibbs ccb->ccb_h.status = status; 39465942Sgibbs xpt_done(ccb); 39565942Sgibbs break; 39665942Sgibbs } 39765942Sgibbs } 39865942Sgibbs if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { 39965942Sgibbs 40065942Sgibbs ahc_lock(ahc, &s); 40165942Sgibbs SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h, 40265942Sgibbs sim_links.sle); 40365942Sgibbs ccb->ccb_h.status = CAM_REQ_INPROG; 40465942Sgibbs if ((ahc->flags & AHC_TQINFIFO_BLOCKED) != 0) 40565942Sgibbs ahc_run_tqinfifo(ahc, /*paused*/FALSE); 40665942Sgibbs ahc_unlock(ahc, &s); 40765942Sgibbs break; 40865942Sgibbs } 40965942Sgibbs 41065942Sgibbs /* 41165942Sgibbs * The target_id represents the target we attempt to 41265942Sgibbs * select. In target mode, this is the initiator of 41365942Sgibbs * the original command. 41465942Sgibbs */ 41565942Sgibbs our_id = target_id; 41665942Sgibbs target_id = ccb->csio.init_id; 41765942Sgibbs /* FALLTHROUGH */ 41865942Sgibbs } 41965942Sgibbs case XPT_SCSI_IO: /* Execute the requested I/O operation */ 42065942Sgibbs case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 42165942Sgibbs { 42266717Sgibbs struct scb *scb; 42366717Sgibbs struct hardware_scb *hscb; 42465942Sgibbs 42568087Sgibbs if ((ahc->flags & AHC_INITIATORROLE) == 0 42668087Sgibbs && (ccb->ccb_h.func_code == XPT_SCSI_IO 42768087Sgibbs || ccb->ccb_h.func_code == XPT_RESET_DEV)) { 42868087Sgibbs ccb->ccb_h.status = CAM_PROVIDE_FAIL; 42968087Sgibbs xpt_done(ccb); 43068087Sgibbs } 43168087Sgibbs 43265942Sgibbs /* 43365942Sgibbs * get an scb to use. 43465942Sgibbs */ 43566717Sgibbs ahc_lock(ahc, &s); 43665942Sgibbs if ((scb = ahc_get_scb(ahc)) == NULL) { 43765942Sgibbs 43866891Sgibbs xpt_freeze_simq(sim, /*count*/1); 43965942Sgibbs ahc->flags |= AHC_RESOURCE_SHORTAGE; 44065942Sgibbs ahc_unlock(ahc, &s); 44166510Sgibbs ccb->ccb_h.status = CAM_REQUEUE_REQ; 44265942Sgibbs xpt_done(ccb); 44365942Sgibbs return; 44465942Sgibbs } 44566717Sgibbs ahc_unlock(ahc, &s); 44665942Sgibbs 44765942Sgibbs hscb = scb->hscb; 44865942Sgibbs 44965942Sgibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, 45065942Sgibbs ("start scb(%p)\n", scb)); 45165942Sgibbs scb->io_ctx = ccb; 45265942Sgibbs /* 45365942Sgibbs * So we can find the SCB when an abort is requested 45465942Sgibbs */ 45565942Sgibbs ccb->ccb_h.ccb_scb_ptr = scb; 45665942Sgibbs 45765942Sgibbs /* 45865942Sgibbs * Put all the arguments for the xfer in the scb 45965942Sgibbs */ 46065942Sgibbs hscb->control = 0; 46165942Sgibbs hscb->scsiid = BUILD_SCSIID(ahc, sim, target_id, our_id); 46265942Sgibbs hscb->lun = ccb->ccb_h.target_lun; 46365942Sgibbs if (ccb->ccb_h.func_code == XPT_RESET_DEV) { 46465942Sgibbs hscb->cdb_len = 0; 46565942Sgibbs scb->flags |= SCB_DEVICE_RESET; 46665942Sgibbs hscb->control |= MK_MESSAGE; 46765942Sgibbs ahc_execute_scb(scb, NULL, 0, 0); 46865942Sgibbs } else { 46965942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 47065942Sgibbs struct target_data *tdata; 47165942Sgibbs 47265942Sgibbs tdata = &hscb->shared_data.tdata; 47365942Sgibbs if (ahc->pending_device == lstate) { 47465942Sgibbs scb->flags |= SCB_TARGET_IMMEDIATE; 47565942Sgibbs ahc->pending_device = NULL; 47665942Sgibbs } 47765942Sgibbs hscb->control |= TARGET_SCB; 47865942Sgibbs tdata->target_phases = IDENTIFY_SEEN; 47965942Sgibbs if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { 48065942Sgibbs tdata->target_phases |= SPHASE_PENDING; 48165942Sgibbs tdata->scsi_status = 48265942Sgibbs ccb->csio.scsi_status; 48365942Sgibbs } 48465942Sgibbs tdata->initiator_tag = ccb->csio.tag_id; 48565942Sgibbs } 48665942Sgibbs if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) 48765942Sgibbs hscb->control |= ccb->csio.tag_action; 48865942Sgibbs 48965942Sgibbs ahc_setup_data(ahc, sim, &ccb->csio, scb); 49065942Sgibbs } 49165942Sgibbs break; 49265942Sgibbs } 49365942Sgibbs case XPT_NOTIFY_ACK: 49465942Sgibbs case XPT_IMMED_NOTIFY: 49565942Sgibbs { 49665942Sgibbs struct tmode_tstate *tstate; 49765942Sgibbs struct tmode_lstate *lstate; 49865942Sgibbs cam_status status; 49965942Sgibbs 50065942Sgibbs status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, 50165942Sgibbs &lstate, TRUE); 50265942Sgibbs 50365942Sgibbs if (status != CAM_REQ_CMP) { 50465942Sgibbs ccb->ccb_h.status = status; 50565942Sgibbs xpt_done(ccb); 50665942Sgibbs break; 50765942Sgibbs } 50865942Sgibbs SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h, 50965942Sgibbs sim_links.sle); 51065942Sgibbs ccb->ccb_h.status = CAM_REQ_INPROG; 51165942Sgibbs ahc_send_lstate_events(ahc, lstate); 51265942Sgibbs break; 51365942Sgibbs } 51465942Sgibbs case XPT_EN_LUN: /* Enable LUN as a target */ 51565942Sgibbs ahc_handle_en_lun(ahc, sim, ccb); 51665942Sgibbs xpt_done(ccb); 51765942Sgibbs break; 51865942Sgibbs case XPT_ABORT: /* Abort the specified CCB */ 51965942Sgibbs { 52065942Sgibbs ahc_abort_ccb(ahc, sim, ccb); 52165942Sgibbs break; 52265942Sgibbs } 52365942Sgibbs case XPT_SET_TRAN_SETTINGS: 52465942Sgibbs { 52565942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 52665942Sgibbs struct ahc_devinfo devinfo; 52765942Sgibbs struct ccb_trans_settings *cts; 52865942Sgibbs struct ccb_trans_settings_scsi *scsi; 52965942Sgibbs struct ccb_trans_settings_spi *spi; 53065942Sgibbs struct ahc_initiator_tinfo *tinfo; 53165942Sgibbs struct tmode_tstate *tstate; 53265942Sgibbs uint16_t *discenable; 53365942Sgibbs uint16_t *tagenable; 53465942Sgibbs u_int update_type; 53565942Sgibbs 53665942Sgibbs cts = &ccb->cts; 53765942Sgibbs scsi = &cts->proto_specific.scsi; 53865942Sgibbs spi = &cts->xport_specific.spi; 53965942Sgibbs ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), 54065942Sgibbs cts->ccb_h.target_id, 54165942Sgibbs cts->ccb_h.target_lun, 54265942Sgibbs SIM_CHANNEL(ahc, sim), 54365942Sgibbs ROLE_UNKNOWN); 54465942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, 54565942Sgibbs devinfo.our_scsiid, 54665942Sgibbs devinfo.target, &tstate); 54765942Sgibbs update_type = 0; 54865942Sgibbs if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 54965942Sgibbs update_type |= AHC_TRANS_GOAL; 55065942Sgibbs discenable = &tstate->discenable; 55165942Sgibbs tagenable = &tstate->tagenable; 55265942Sgibbs tinfo->current.protocol_version = 55365942Sgibbs cts->protocol_version; 55465942Sgibbs tinfo->current.transport_version = 55565942Sgibbs cts->transport_version; 55665942Sgibbs tinfo->goal.protocol_version = 55765942Sgibbs cts->protocol_version; 55865942Sgibbs tinfo->goal.transport_version = 55965942Sgibbs cts->transport_version; 56065942Sgibbs } else if (cts->type == CTS_TYPE_USER_SETTINGS) { 56165942Sgibbs update_type |= AHC_TRANS_USER; 56265942Sgibbs discenable = &ahc->user_discenable; 56365942Sgibbs tagenable = &ahc->user_tagenable; 56465942Sgibbs tinfo->user.protocol_version = 56565942Sgibbs cts->protocol_version; 56665942Sgibbs tinfo->user.transport_version = 56765942Sgibbs cts->transport_version; 56865942Sgibbs } else { 56965942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 57065942Sgibbs xpt_done(ccb); 57165942Sgibbs break; 57265942Sgibbs } 57365942Sgibbs 57465942Sgibbs ahc_lock(ahc, &s); 57565942Sgibbs 57665942Sgibbs if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { 57765942Sgibbs if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) 57865942Sgibbs *discenable |= devinfo.target_mask; 57965942Sgibbs else 58065942Sgibbs *discenable &= ~devinfo.target_mask; 58165942Sgibbs } 58265942Sgibbs 58365942Sgibbs if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 58465942Sgibbs if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) 58565942Sgibbs *tagenable |= devinfo.target_mask; 58665942Sgibbs else 58765942Sgibbs *tagenable &= ~devinfo.target_mask; 58865942Sgibbs } 58965942Sgibbs 59065942Sgibbs if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { 59168087Sgibbs ahc_validate_width(ahc, /*tinfo limit*/NULL, 59268087Sgibbs &spi->bus_width, ROLE_UNKNOWN); 59365942Sgibbs ahc_set_width(ahc, &devinfo, spi->bus_width, 59465942Sgibbs update_type, /*paused*/FALSE); 59565942Sgibbs } 59665942Sgibbs 59765942Sgibbs if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) { 59865942Sgibbs if (update_type == AHC_TRANS_USER) 59965942Sgibbs spi->ppr_options = tinfo->user.ppr_options; 60065942Sgibbs else 60165942Sgibbs spi->ppr_options = tinfo->goal.ppr_options; 60265942Sgibbs } 60365942Sgibbs 60465942Sgibbs if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) { 60565942Sgibbs if (update_type == AHC_TRANS_USER) 60665942Sgibbs spi->sync_offset = tinfo->user.offset; 60765942Sgibbs else 60865942Sgibbs spi->sync_offset = tinfo->goal.offset; 60965942Sgibbs } 61065942Sgibbs 61165942Sgibbs if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 61265942Sgibbs if (update_type == AHC_TRANS_USER) 61365942Sgibbs spi->sync_period = tinfo->user.period; 61465942Sgibbs else 61565942Sgibbs spi->sync_period = tinfo->goal.period; 61665942Sgibbs } 61765942Sgibbs 61865942Sgibbs if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) 61965942Sgibbs || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) { 62065942Sgibbs struct ahc_syncrate *syncrate; 62165942Sgibbs u_int maxsync; 62265942Sgibbs 62365942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 62465942Sgibbs maxsync = AHC_SYNCRATE_DT; 62565942Sgibbs else if ((ahc->features & AHC_ULTRA) != 0) 62665942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 62765942Sgibbs else 62865942Sgibbs maxsync = AHC_SYNCRATE_FAST; 62965942Sgibbs 63065942Sgibbs syncrate = ahc_find_syncrate(ahc, &spi->sync_period, 63165942Sgibbs &spi->ppr_options, 63265942Sgibbs maxsync); 63368087Sgibbs ahc_validate_offset(ahc, /*tinfo limit*/NULL, 63468087Sgibbs syncrate, &spi->sync_offset, 63568087Sgibbs spi->bus_width, ROLE_UNKNOWN); 63665942Sgibbs 63765942Sgibbs /* We use a period of 0 to represent async */ 63865942Sgibbs if (spi->sync_offset == 0) { 63965942Sgibbs spi->sync_period = 0; 64065942Sgibbs spi->ppr_options = 0; 64165942Sgibbs } 64265942Sgibbs 64365942Sgibbs ahc_set_syncrate(ahc, &devinfo, syncrate, 64465942Sgibbs spi->sync_period, spi->sync_offset, 64565942Sgibbs spi->ppr_options, update_type, 64665942Sgibbs /*paused*/FALSE); 64765942Sgibbs } 64865942Sgibbs ahc_unlock(ahc, &s); 64965942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 65065942Sgibbs xpt_done(ccb); 65165942Sgibbs#else 65265942Sgibbs struct ahc_devinfo devinfo; 65365942Sgibbs struct ccb_trans_settings *cts; 65465942Sgibbs struct ahc_initiator_tinfo *tinfo; 65565942Sgibbs struct tmode_tstate *tstate; 65665942Sgibbs uint16_t *discenable; 65765942Sgibbs uint16_t *tagenable; 65865942Sgibbs u_int update_type; 65965942Sgibbs long s; 66065942Sgibbs 66165942Sgibbs cts = &ccb->cts; 66265942Sgibbs ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), 66365942Sgibbs cts->ccb_h.target_id, 66465942Sgibbs cts->ccb_h.target_lun, 66565942Sgibbs SIM_CHANNEL(ahc, sim), 66665942Sgibbs ROLE_UNKNOWN); 66765942Sgibbs tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, 66865942Sgibbs devinfo.our_scsiid, 66965942Sgibbs devinfo.target, &tstate); 67065942Sgibbs update_type = 0; 67165942Sgibbs if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) { 67265942Sgibbs update_type |= AHC_TRANS_GOAL; 67365942Sgibbs discenable = &tstate->discenable; 67465942Sgibbs tagenable = &tstate->tagenable; 67565942Sgibbs } else if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { 67665942Sgibbs update_type |= AHC_TRANS_USER; 67765942Sgibbs discenable = &ahc->user_discenable; 67865942Sgibbs tagenable = &ahc->user_tagenable; 67965942Sgibbs } else { 68065942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 68165942Sgibbs xpt_done(ccb); 68265942Sgibbs break; 68365942Sgibbs } 68465942Sgibbs 68565942Sgibbs ahc_lock(ahc, &s); 68665942Sgibbs 68765942Sgibbs if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) { 68865942Sgibbs if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) 68965942Sgibbs *discenable |= devinfo.target_mask; 69065942Sgibbs else 69165942Sgibbs *discenable &= ~devinfo.target_mask; 69265942Sgibbs } 69365942Sgibbs 69465942Sgibbs if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) { 69565942Sgibbs if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) 69665942Sgibbs *tagenable |= devinfo.target_mask; 69765942Sgibbs else 69865942Sgibbs *tagenable &= ~devinfo.target_mask; 69965942Sgibbs } 70065942Sgibbs 70165942Sgibbs if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0) { 70268087Sgibbs ahc_validate_width(ahc, /*tinfo limit*/NULL, 70368087Sgibbs &cts->bus_width, ROLE_UNKNOWN); 70465942Sgibbs ahc_set_width(ahc, &devinfo, cts->bus_width, 70565942Sgibbs update_type, /*paused*/FALSE); 70665942Sgibbs } 70765942Sgibbs 70865942Sgibbs if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0) { 70965942Sgibbs if (update_type == AHC_TRANS_USER) 71065942Sgibbs cts->sync_offset = tinfo->user.offset; 71165942Sgibbs else 71265942Sgibbs cts->sync_offset = tinfo->goal.offset; 71365942Sgibbs } 71465942Sgibbs 71565942Sgibbs if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) == 0) { 71665942Sgibbs if (update_type == AHC_TRANS_USER) 71765942Sgibbs cts->sync_period = tinfo->user.period; 71865942Sgibbs else 71965942Sgibbs cts->sync_period = tinfo->goal.period; 72065942Sgibbs } 72165942Sgibbs 72265942Sgibbs if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) 72365942Sgibbs || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) { 72465942Sgibbs struct ahc_syncrate *syncrate; 72565942Sgibbs u_int ppr_options; 72665942Sgibbs u_int maxsync; 72765942Sgibbs 72865942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 72965942Sgibbs maxsync = AHC_SYNCRATE_DT; 73065942Sgibbs else if ((ahc->features & AHC_ULTRA) != 0) 73165942Sgibbs maxsync = AHC_SYNCRATE_ULTRA; 73265942Sgibbs else 73365942Sgibbs maxsync = AHC_SYNCRATE_FAST; 73465942Sgibbs 73565942Sgibbs ppr_options = 0; 73665942Sgibbs if (cts->sync_period <= 9) 73765942Sgibbs ppr_options = MSG_EXT_PPR_DT_REQ; 73865942Sgibbs 73965942Sgibbs syncrate = ahc_find_syncrate(ahc, &cts->sync_period, 74065942Sgibbs &ppr_options, 74165942Sgibbs maxsync); 74268087Sgibbs ahc_validate_offset(ahc, /*tinfo limit*/NULL, 74368087Sgibbs syncrate, &cts->sync_offset, 74468087Sgibbs MSG_EXT_WDTR_BUS_8_BIT, 74568087Sgibbs ROLE_UNKNOWN); 74665942Sgibbs 74765942Sgibbs /* We use a period of 0 to represent async */ 74865942Sgibbs if (cts->sync_offset == 0) { 74965942Sgibbs cts->sync_period = 0; 75065942Sgibbs ppr_options = 0; 75165942Sgibbs } 75265942Sgibbs 75365942Sgibbs if (ppr_options == MSG_EXT_PPR_DT_REQ 75465942Sgibbs && tinfo->user.transport_version >= 3) { 75565942Sgibbs tinfo->goal.transport_version = 75665942Sgibbs tinfo->user.transport_version; 75765942Sgibbs tinfo->current.transport_version = 75865942Sgibbs tinfo->user.transport_version; 75965942Sgibbs } 76065942Sgibbs 76165942Sgibbs ahc_set_syncrate(ahc, &devinfo, syncrate, 76265942Sgibbs cts->sync_period, cts->sync_offset, 76365942Sgibbs ppr_options, update_type, 76465942Sgibbs /*paused*/FALSE); 76565942Sgibbs } 76665942Sgibbs ahc_unlock(ahc, &s); 76765942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 76865942Sgibbs xpt_done(ccb); 76965942Sgibbs#endif 77065942Sgibbs break; 77165942Sgibbs } 77265942Sgibbs case XPT_GET_TRAN_SETTINGS: 77365942Sgibbs /* Get default/user set transfer settings for the target */ 77465942Sgibbs { 77565942Sgibbs 77665942Sgibbs ahc_lock(ahc, &s); 77765942Sgibbs ahc_get_tran_settings(ahc, SIM_SCSI_ID(ahc, sim), 77865942Sgibbs SIM_CHANNEL(ahc, sim), &ccb->cts); 77965942Sgibbs ahc_unlock(ahc, &s); 78065942Sgibbs xpt_done(ccb); 78165942Sgibbs break; 78265942Sgibbs } 78365942Sgibbs case XPT_CALC_GEOMETRY: 78465942Sgibbs { 78565942Sgibbs struct ccb_calc_geometry *ccg; 78665942Sgibbs uint32_t size_mb; 78765942Sgibbs uint32_t secs_per_cylinder; 78865942Sgibbs int extended; 78965942Sgibbs 79065942Sgibbs ccg = &ccb->ccg; 79165942Sgibbs size_mb = ccg->volume_size 79265942Sgibbs / ((1024L * 1024L) / ccg->block_size); 79365942Sgibbs extended = SIM_IS_SCSIBUS_B(ahc, sim) 79465942Sgibbs ? ahc->flags & AHC_EXTENDED_TRANS_B 79565942Sgibbs : ahc->flags & AHC_EXTENDED_TRANS_A; 79665942Sgibbs 79765942Sgibbs if (size_mb > 1024 && extended) { 79865942Sgibbs ccg->heads = 255; 79965942Sgibbs ccg->secs_per_track = 63; 80065942Sgibbs } else { 80165942Sgibbs ccg->heads = 64; 80265942Sgibbs ccg->secs_per_track = 32; 80365942Sgibbs } 80465942Sgibbs secs_per_cylinder = ccg->heads * ccg->secs_per_track; 80565942Sgibbs ccg->cylinders = ccg->volume_size / secs_per_cylinder; 80665942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 80765942Sgibbs xpt_done(ccb); 80865942Sgibbs break; 80965942Sgibbs } 81065942Sgibbs case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 81165942Sgibbs { 81265942Sgibbs int found; 81365942Sgibbs 81465942Sgibbs ahc_lock(ahc, &s); 81565942Sgibbs found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim), 81665942Sgibbs /*initiate reset*/TRUE); 81765942Sgibbs ahc_unlock(ahc, &s); 81865942Sgibbs if (bootverbose) { 81965942Sgibbs xpt_print_path(SIM_PATH(ahc, sim)); 82065942Sgibbs printf("SCSI bus reset delivered. " 82165942Sgibbs "%d SCBs aborted.\n", found); 82265942Sgibbs } 82365942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 82465942Sgibbs xpt_done(ccb); 82565942Sgibbs break; 82665942Sgibbs } 82765942Sgibbs case XPT_TERM_IO: /* Terminate the I/O process */ 82865942Sgibbs /* XXX Implement */ 82965942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 83065942Sgibbs xpt_done(ccb); 83165942Sgibbs break; 83265942Sgibbs case XPT_PATH_INQ: /* Path routing inquiry */ 83365942Sgibbs { 83465942Sgibbs struct ccb_pathinq *cpi = &ccb->cpi; 83565942Sgibbs 83665942Sgibbs cpi->version_num = 1; /* XXX??? */ 83765942Sgibbs cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; 83865942Sgibbs if ((ahc->features & AHC_WIDE) != 0) 83965942Sgibbs cpi->hba_inquiry |= PI_WIDE_16; 84068087Sgibbs if ((ahc->features & AHC_TARGETMODE) != 0) { 84165942Sgibbs cpi->target_sprt = PIT_PROCESSOR 84265942Sgibbs | PIT_DISCONNECT 84365942Sgibbs | PIT_TERM_IO; 84465942Sgibbs } else { 84565942Sgibbs cpi->target_sprt = 0; 84665942Sgibbs } 84768087Sgibbs cpi->hba_misc = 0; 84865942Sgibbs cpi->hba_eng_cnt = 0; 84965942Sgibbs cpi->max_target = (ahc->features & AHC_WIDE) ? 15 : 7; 85070204Sgibbs cpi->max_lun = AHC_NUM_LUNS - 1; 85165942Sgibbs if (SIM_IS_SCSIBUS_B(ahc, sim)) { 85265942Sgibbs cpi->initiator_id = ahc->our_id_b; 85365942Sgibbs if ((ahc->flags & AHC_RESET_BUS_B) == 0) 85465942Sgibbs cpi->hba_misc |= PIM_NOBUSRESET; 85565942Sgibbs } else { 85665942Sgibbs cpi->initiator_id = ahc->our_id; 85765942Sgibbs if ((ahc->flags & AHC_RESET_BUS_A) == 0) 85865942Sgibbs cpi->hba_misc |= PIM_NOBUSRESET; 85965942Sgibbs } 86065942Sgibbs cpi->bus_id = cam_sim_bus(sim); 86165942Sgibbs cpi->base_transfer_speed = 3300; 86265942Sgibbs strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 86365942Sgibbs strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); 86465942Sgibbs strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 86565942Sgibbs cpi->unit_number = cam_sim_unit(sim); 86665942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 86765942Sgibbs cpi->protocol = PROTO_SCSI; 86865942Sgibbs cpi->protocol_version = SCSI_REV_2; 86965942Sgibbs cpi->transport = XPORT_SPI; 87065942Sgibbs cpi->transport_version = 2; 87165942Sgibbs cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_ST; 87265942Sgibbs if ((ahc->features & AHC_DT) != 0) { 87365942Sgibbs cpi->transport_version = 3; 87465942Sgibbs cpi->xport_specific.spi.ppr_options = 87565942Sgibbs SID_SPI_CLOCK_DT_ST; 87665942Sgibbs } 87765942Sgibbs#endif 87865942Sgibbs cpi->ccb_h.status = CAM_REQ_CMP; 87965942Sgibbs xpt_done(ccb); 88065942Sgibbs break; 88165942Sgibbs } 88265942Sgibbs default: 88368087Sgibbs ccb->ccb_h.status = CAM_PROVIDE_FAIL; 88465942Sgibbs xpt_done(ccb); 88565942Sgibbs break; 88665942Sgibbs } 88765942Sgibbs} 88865942Sgibbs 88965942Sgibbsstatic void 89065942Sgibbsahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel, 89165942Sgibbs struct ccb_trans_settings *cts) 89265942Sgibbs{ 89365942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 89465942Sgibbs struct ahc_devinfo devinfo; 89565942Sgibbs struct ccb_trans_settings_scsi *scsi; 89665942Sgibbs struct ccb_trans_settings_spi *spi; 89765942Sgibbs struct ahc_initiator_tinfo *targ_info; 89865942Sgibbs struct tmode_tstate *tstate; 89965942Sgibbs struct ahc_transinfo *tinfo; 90065942Sgibbs 90165942Sgibbs scsi = &cts->proto_specific.scsi; 90265942Sgibbs spi = &cts->xport_specific.spi; 90365942Sgibbs ahc_compile_devinfo(&devinfo, our_id, 90465942Sgibbs cts->ccb_h.target_id, 90565942Sgibbs cts->ccb_h.target_lun, 90665942Sgibbs channel, ROLE_UNKNOWN); 90765942Sgibbs targ_info = ahc_fetch_transinfo(ahc, devinfo.channel, 90865942Sgibbs devinfo.our_scsiid, 90965942Sgibbs devinfo.target, &tstate); 91065942Sgibbs 91165942Sgibbs if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 91265942Sgibbs tinfo = &targ_info->current; 91365942Sgibbs else 91465942Sgibbs tinfo = &targ_info->user; 91565942Sgibbs 91665942Sgibbs scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 91765942Sgibbs spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 91865942Sgibbs if (cts->type == CTS_TYPE_USER_SETTINGS) { 91965942Sgibbs if ((ahc->user_discenable & devinfo.target_mask) != 0) 92065942Sgibbs spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 92165942Sgibbs 92265942Sgibbs if ((ahc->user_tagenable & devinfo.target_mask) != 0) 92365942Sgibbs scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 92465942Sgibbs } else { 92565942Sgibbs if ((tstate->discenable & devinfo.target_mask) != 0) 92665942Sgibbs spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 92765942Sgibbs 92865942Sgibbs if ((tstate->tagenable & devinfo.target_mask) != 0) 92965942Sgibbs scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 93065942Sgibbs } 93165942Sgibbs cts->protocol_version = tinfo->protocol_version; 93265942Sgibbs cts->transport_version = tinfo->transport_version; 93365942Sgibbs 93465942Sgibbs spi->sync_period = tinfo->period; 93565942Sgibbs spi->sync_offset = tinfo->offset; 93665942Sgibbs spi->bus_width = tinfo->width; 93765942Sgibbs spi->ppr_options = tinfo->ppr_options; 93865942Sgibbs 93965942Sgibbs cts->protocol = PROTO_SCSI; 94065942Sgibbs cts->transport = XPORT_SPI; 94165942Sgibbs spi->valid = CTS_SPI_VALID_SYNC_RATE 94265942Sgibbs | CTS_SPI_VALID_SYNC_OFFSET 94365942Sgibbs | CTS_SPI_VALID_BUS_WIDTH 94465942Sgibbs | CTS_SPI_VALID_PPR_OPTIONS; 94565942Sgibbs 94666717Sgibbs if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 94766717Sgibbs scsi->valid = CTS_SCSI_VALID_TQ; 94866717Sgibbs spi->valid |= CTS_SPI_VALID_DISC; 94966717Sgibbs } else { 95066717Sgibbs scsi->valid = 0; 95166717Sgibbs } 95266717Sgibbs 95365942Sgibbs cts->ccb_h.status = CAM_REQ_CMP; 95465942Sgibbs#else 95565942Sgibbs struct ahc_devinfo devinfo; 95665942Sgibbs struct ahc_initiator_tinfo *targ_info; 95765942Sgibbs struct tmode_tstate *tstate; 95865942Sgibbs struct ahc_transinfo *tinfo; 95965942Sgibbs long s; 96065942Sgibbs 96165942Sgibbs ahc_compile_devinfo(&devinfo, our_id, 96265942Sgibbs cts->ccb_h.target_id, 96365942Sgibbs cts->ccb_h.target_lun, 96465942Sgibbs channel, ROLE_UNKNOWN); 96565942Sgibbs targ_info = ahc_fetch_transinfo(ahc, devinfo.channel, 96665942Sgibbs devinfo.our_scsiid, 96765942Sgibbs devinfo.target, &tstate); 96865942Sgibbs 96965942Sgibbs if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) 97065942Sgibbs tinfo = &targ_info->current; 97165942Sgibbs else 97265942Sgibbs tinfo = &targ_info->user; 97365942Sgibbs 97465942Sgibbs ahc_lock(ahc, &s); 97565942Sgibbs 97665942Sgibbs cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); 97766760Sgibbs if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) == 0) { 97865942Sgibbs if ((ahc->user_discenable & devinfo.target_mask) != 0) 97965942Sgibbs cts->flags |= CCB_TRANS_DISC_ENB; 98065942Sgibbs 98165942Sgibbs if ((ahc->user_tagenable & devinfo.target_mask) != 0) 98265942Sgibbs cts->flags |= CCB_TRANS_TAG_ENB; 98365942Sgibbs } else { 98465942Sgibbs if ((tstate->discenable & devinfo.target_mask) != 0) 98565942Sgibbs cts->flags |= CCB_TRANS_DISC_ENB; 98665942Sgibbs 98765942Sgibbs if ((tstate->tagenable & devinfo.target_mask) != 0) 98865942Sgibbs cts->flags |= CCB_TRANS_TAG_ENB; 98965942Sgibbs } 99065942Sgibbs cts->sync_period = tinfo->period; 99165942Sgibbs cts->sync_offset = tinfo->offset; 99265942Sgibbs cts->bus_width = tinfo->width; 99365942Sgibbs 99465942Sgibbs ahc_unlock(ahc, &s); 99565942Sgibbs 99665942Sgibbs cts->valid = CCB_TRANS_SYNC_RATE_VALID 99765942Sgibbs | CCB_TRANS_SYNC_OFFSET_VALID 99866717Sgibbs | CCB_TRANS_BUS_WIDTH_VALID; 99965942Sgibbs 100066717Sgibbs if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) 100166717Sgibbs cts->valid |= CCB_TRANS_DISC_VALID|CCB_TRANS_TQ_VALID; 100266717Sgibbs 100365942Sgibbs cts->ccb_h.status = CAM_REQ_CMP; 100465942Sgibbs#endif 100565942Sgibbs} 100665942Sgibbs 100765942Sgibbsstatic void 100865942Sgibbsahc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) 100965942Sgibbs{ 101065942Sgibbs struct ahc_softc *ahc; 101165942Sgibbs struct cam_sim *sim; 101265942Sgibbs 101365942Sgibbs sim = (struct cam_sim *)callback_arg; 101465942Sgibbs ahc = (struct ahc_softc *)cam_sim_softc(sim); 101565942Sgibbs switch (code) { 101665942Sgibbs case AC_LOST_DEVICE: 101765942Sgibbs { 101865942Sgibbs struct ahc_devinfo devinfo; 101965942Sgibbs long s; 102065942Sgibbs 102165942Sgibbs ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), 102265942Sgibbs xpt_path_target_id(path), 102365942Sgibbs xpt_path_lun_id(path), 102465942Sgibbs SIM_CHANNEL(ahc, sim), 102565942Sgibbs ROLE_UNKNOWN); 102665942Sgibbs 102765942Sgibbs /* 102865942Sgibbs * Revert to async/narrow transfers 102965942Sgibbs * for the next device. 103065942Sgibbs */ 103165942Sgibbs ahc_lock(ahc, &s); 103265942Sgibbs ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, 103365942Sgibbs AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE); 103465942Sgibbs ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL, 103565942Sgibbs /*period*/0, /*offset*/0, /*ppr_options*/0, 103665942Sgibbs AHC_TRANS_GOAL|AHC_TRANS_CUR, 103765942Sgibbs /*paused*/FALSE); 103865942Sgibbs ahc_unlock(ahc, &s); 103965942Sgibbs break; 104065942Sgibbs } 104165942Sgibbs default: 104265942Sgibbs break; 104365942Sgibbs } 104465942Sgibbs} 104565942Sgibbs 104665942Sgibbsstatic void 104765942Sgibbsahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, 104865942Sgibbs int error) 104965942Sgibbs{ 105066717Sgibbs struct scb *scb; 105166717Sgibbs union ccb *ccb; 105266717Sgibbs struct ahc_softc *ahc; 105366717Sgibbs struct ahc_initiator_tinfo *tinfo; 105466717Sgibbs struct tmode_tstate *tstate; 105566717Sgibbs u_int mask; 105666717Sgibbs long s; 105765942Sgibbs 105865942Sgibbs scb = (struct scb *)arg; 105965942Sgibbs ccb = scb->io_ctx; 106066986Sgibbs ahc = scb->ahc_softc; 106165942Sgibbs 106265942Sgibbs if (error != 0) { 106365942Sgibbs if (error == EFBIG) 106465942Sgibbs ahc_set_transaction_status(scb, CAM_REQ_TOO_BIG); 106565942Sgibbs else 106665942Sgibbs ahc_set_transaction_status(scb, CAM_REQ_CMP_ERR); 106765942Sgibbs if (nsegments != 0) 106865942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); 106966647Sgibbs ahc_lock(ahc, &s); 107065942Sgibbs ahc_free_scb(ahc, scb); 107166647Sgibbs ahc_unlock(ahc, &s); 107265942Sgibbs xpt_done(ccb); 107365942Sgibbs return; 107465942Sgibbs } 107565942Sgibbs if (nsegments != 0) { 107665942Sgibbs struct ahc_dma_seg *sg; 107765942Sgibbs bus_dma_segment_t *end_seg; 107865942Sgibbs bus_dmasync_op_t op; 107965942Sgibbs 108065942Sgibbs end_seg = dm_segs + nsegments; 108165942Sgibbs 108265942Sgibbs /* Copy the segments into our SG list */ 108365942Sgibbs sg = scb->sg_list; 108465942Sgibbs while (dm_segs < end_seg) { 108565942Sgibbs sg->addr = dm_segs->ds_addr; 108665942Sgibbs/* XXX Add in the 5th byte of the address later. */ 108765942Sgibbs sg->len = dm_segs->ds_len; 108865942Sgibbs sg++; 108965942Sgibbs dm_segs++; 109065942Sgibbs } 109165942Sgibbs 109265942Sgibbs /* 109365942Sgibbs * Note where to find the SG entries in bus space. 109465942Sgibbs * We also set the full residual flag which the 109565942Sgibbs * sequencer will clear as soon as a data transfer 109665942Sgibbs * occurs. 109765942Sgibbs */ 109865942Sgibbs scb->hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; 109965942Sgibbs 110065942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 110165942Sgibbs op = BUS_DMASYNC_PREREAD; 110265942Sgibbs else 110365942Sgibbs op = BUS_DMASYNC_PREWRITE; 110465942Sgibbs 110565942Sgibbs bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op); 110665942Sgibbs 110765942Sgibbs if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 110865942Sgibbs struct target_data *tdata; 110965942Sgibbs 111065942Sgibbs tdata = &scb->hscb->shared_data.tdata; 111165942Sgibbs tdata->target_phases |= DPHASE_PENDING; 111265942Sgibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 111365942Sgibbs tdata->data_phase = P_DATAOUT; 111465942Sgibbs else 111565942Sgibbs tdata->data_phase = P_DATAIN; 111665942Sgibbs 111765942Sgibbs /* 111865942Sgibbs * If the transfer is of an odd length and in the 111965942Sgibbs * "in" direction (scsi->HostBus), then it may 112065942Sgibbs * trigger a bug in the 'WideODD' feature of 112165942Sgibbs * non-Ultra2 chips. Force the total data-length 112265942Sgibbs * to be even by adding an extra, 1 byte, SG, 112365942Sgibbs * element. We do this even if we are not currently 112465942Sgibbs * negotiated wide as negotiation could occur before 112565942Sgibbs * this command is executed. 112665942Sgibbs */ 112765942Sgibbs if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0 112865942Sgibbs && (ccb->csio.dxfer_len & 0x1) != 0 112965942Sgibbs && (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 113065942Sgibbs 113165942Sgibbs nsegments++; 113265942Sgibbs if (nsegments > AHC_NSEG) { 113365942Sgibbs 113465942Sgibbs ahc_set_transaction_status(scb, 113565942Sgibbs CAM_REQ_TOO_BIG); 113665942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, 113765942Sgibbs scb->dmamap); 113866647Sgibbs ahc_lock(ahc, &s); 113965942Sgibbs ahc_free_scb(ahc, scb); 114066647Sgibbs ahc_unlock(ahc, &s); 114165942Sgibbs xpt_done(ccb); 114265942Sgibbs return; 114365942Sgibbs } 114465942Sgibbs sg->addr = ahc->dma_bug_buf; 114565942Sgibbs sg->len = 1; 114665942Sgibbs sg++; 114765942Sgibbs } 114865942Sgibbs } 114965942Sgibbs sg--; 115065942Sgibbs sg->len |= AHC_DMA_LAST_SEG; 115165942Sgibbs 115265942Sgibbs /* Copy the first SG into the "current" data pointer area */ 115365942Sgibbs scb->hscb->dataptr = scb->sg_list->addr; 115465942Sgibbs scb->hscb->datacnt = scb->sg_list->len; 115565942Sgibbs } else { 115665942Sgibbs scb->hscb->sgptr = SG_LIST_NULL; 115765942Sgibbs scb->hscb->dataptr = 0; 115865942Sgibbs scb->hscb->datacnt = 0; 115965942Sgibbs } 116065942Sgibbs 116165942Sgibbs scb->sg_count = nsegments; 116265942Sgibbs 116365942Sgibbs ahc_lock(ahc, &s); 116465942Sgibbs 116565942Sgibbs /* 116665942Sgibbs * Last time we need to check if this SCB needs to 116765942Sgibbs * be aborted. 116865942Sgibbs */ 116965942Sgibbs if (ahc_get_transaction_status(scb) != CAM_REQ_INPROG) { 117065942Sgibbs if (nsegments != 0) 117165942Sgibbs bus_dmamap_unload(ahc->buffer_dmat, 117265942Sgibbs scb->dmamap); 117365942Sgibbs ahc_free_scb(ahc, scb); 117466647Sgibbs ahc_unlock(ahc, &s); 117565942Sgibbs xpt_done(ccb); 117665942Sgibbs return; 117765942Sgibbs } 117865942Sgibbs 117966717Sgibbs tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid), 118066717Sgibbs SCSIID_OUR_ID(scb->hscb->scsiid), 118168087Sgibbs SCSIID_TARGET(ahc, scb->hscb->scsiid), 118268087Sgibbs &tstate); 118366717Sgibbs 118466717Sgibbs mask = SCB_GET_TARGET_MASK(ahc, scb); 118566717Sgibbs scb->hscb->scsirate = tinfo->scsirate; 118666717Sgibbs scb->hscb->scsioffset = tinfo->current.offset; 118766717Sgibbs if ((tstate->ultraenb & mask) != 0) 118866717Sgibbs scb->hscb->control |= ULTRAENB; 118966717Sgibbs 119066717Sgibbs if ((tstate->discenable & mask) != 0 119166717Sgibbs && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0) 119266717Sgibbs scb->hscb->control |= DISCENB; 119366717Sgibbs 119466717Sgibbs if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0 119570204Sgibbs && (tinfo->goal.width != 0 119670204Sgibbs || tinfo->goal.period != 0 119770204Sgibbs || tinfo->goal.ppr_options != 0)) { 119866717Sgibbs scb->flags |= SCB_NEGOTIATE; 119966717Sgibbs scb->hscb->control |= MK_MESSAGE; 120066717Sgibbs } 120166717Sgibbs 120265942Sgibbs LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); 120365942Sgibbs 120465942Sgibbs ccb->ccb_h.status |= CAM_SIM_QUEUED; 120565942Sgibbs 120665942Sgibbs if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { 120771390Sgibbs uint64_t time; 120871390Sgibbs 120965942Sgibbs if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) 121065942Sgibbs ccb->ccb_h.timeout = 5 * 1000; 121171390Sgibbs 121271390Sgibbs time = ccb->ccb_h.timeout; 121371390Sgibbs time *= hz; 121471390Sgibbs time /= 1000; 121565942Sgibbs ccb->ccb_h.timeout_ch = 121671390Sgibbs timeout(ahc_timeout, (caddr_t)scb, time); 121765942Sgibbs } 121865942Sgibbs 121965942Sgibbs /* 122065942Sgibbs * We only allow one untagged transaction 122165942Sgibbs * per target in the initiator role unless 122265942Sgibbs * we are storing a full busy target *lun* 122365942Sgibbs * table in SCB space. 122465942Sgibbs */ 122565942Sgibbs if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0 122671390Sgibbs && (ahc->flags & AHC_SCB_BTT) == 0) { 122765942Sgibbs struct scb_tailq *untagged_q; 122872811Sgibbs int target_offset; 122965942Sgibbs 123072811Sgibbs target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); 123172811Sgibbs untagged_q = &(ahc->untagged_queues[target_offset]); 123265942Sgibbs TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); 123366986Sgibbs scb->flags |= SCB_UNTAGGEDQ; 123465942Sgibbs if (TAILQ_FIRST(untagged_q) != scb) { 123565942Sgibbs ahc_unlock(ahc, &s); 123665942Sgibbs return; 123765942Sgibbs } 123865942Sgibbs } 123965942Sgibbs scb->flags |= SCB_ACTIVE; 124065942Sgibbs 124165942Sgibbs if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { 124265942Sgibbs pause_sequencer(ahc); 124365942Sgibbs if ((ahc->flags & AHC_PAGESCBS) == 0) 124465942Sgibbs ahc_outb(ahc, SCBPTR, scb->hscb->tag); 124565942Sgibbs ahc_outb(ahc, SCB_TAG, scb->hscb->tag); 124665942Sgibbs ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP); 124765942Sgibbs unpause_sequencer(ahc); 124865942Sgibbs } else { 124965942Sgibbs ahc_queue_scb(ahc, scb); 125065942Sgibbs } 125165942Sgibbs 125265942Sgibbs ahc_unlock(ahc, &s); 125365942Sgibbs} 125465942Sgibbs 125565942Sgibbsstatic void 125665942Sgibbsahc_poll(struct cam_sim *sim) 125765942Sgibbs{ 125865942Sgibbs ahc_intr(cam_sim_softc(sim)); 125965942Sgibbs} 126065942Sgibbs 126165942Sgibbsstatic void 126265942Sgibbsahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, 126365942Sgibbs struct ccb_scsiio *csio, struct scb *scb) 126465942Sgibbs{ 126565942Sgibbs struct hardware_scb *hscb; 126665942Sgibbs struct ccb_hdr *ccb_h; 126765942Sgibbs 126865942Sgibbs hscb = scb->hscb; 126965942Sgibbs ccb_h = &csio->ccb_h; 127065942Sgibbs 127165942Sgibbs if (ccb_h->func_code == XPT_SCSI_IO) { 127265942Sgibbs hscb->cdb_len = csio->cdb_len; 127365942Sgibbs if ((ccb_h->flags & CAM_CDB_POINTER) != 0) { 127465942Sgibbs 127565942Sgibbs if (hscb->cdb_len > sizeof(hscb->cdb32) 127665942Sgibbs || (ccb_h->flags & CAM_CDB_PHYS) != 0) { 127766647Sgibbs u_long s; 127866647Sgibbs 127965942Sgibbs ahc_set_transaction_status(scb, 128065942Sgibbs CAM_REQ_INVALID); 128166647Sgibbs ahc_lock(ahc, &s); 128265942Sgibbs ahc_free_scb(ahc, scb); 128366647Sgibbs ahc_unlock(ahc, &s); 128466647Sgibbs xpt_done((union ccb *)csio); 128565942Sgibbs return; 128665942Sgibbs } 128765942Sgibbs if (hscb->cdb_len > 12) { 128865942Sgibbs memcpy(hscb->cdb32, 128965942Sgibbs csio->cdb_io.cdb_ptr, 129065942Sgibbs hscb->cdb_len); 129168087Sgibbs scb->flags |= SCB_CDB32_PTR; 129265942Sgibbs } else { 129365942Sgibbs memcpy(hscb->shared_data.cdb, 129465942Sgibbs csio->cdb_io.cdb_ptr, 129565942Sgibbs hscb->cdb_len); 129665942Sgibbs } 129765942Sgibbs } else { 129865942Sgibbs if (hscb->cdb_len > 12) { 129965942Sgibbs memcpy(hscb->cdb32, csio->cdb_io.cdb_bytes, 130065942Sgibbs hscb->cdb_len); 130168087Sgibbs scb->flags |= SCB_CDB32_PTR; 130265942Sgibbs } else { 130365942Sgibbs memcpy(hscb->shared_data.cdb, 130465942Sgibbs csio->cdb_io.cdb_bytes, 130565942Sgibbs hscb->cdb_len); 130665942Sgibbs } 130765942Sgibbs } 130865942Sgibbs } 130965942Sgibbs 131065942Sgibbs /* Only use S/G if there is a transfer */ 131165942Sgibbs if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 131265942Sgibbs if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { 131365942Sgibbs /* We've been given a pointer to a single buffer */ 131465942Sgibbs if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { 131565942Sgibbs int s; 131665942Sgibbs int error; 131765942Sgibbs 131865942Sgibbs s = splsoftvm(); 131965942Sgibbs error = bus_dmamap_load(ahc->buffer_dmat, 132065942Sgibbs scb->dmamap, 132165942Sgibbs csio->data_ptr, 132265942Sgibbs csio->dxfer_len, 132365942Sgibbs ahc_execute_scb, 132465942Sgibbs scb, /*flags*/0); 132565942Sgibbs if (error == EINPROGRESS) { 132665942Sgibbs /* 132765942Sgibbs * So as to maintain ordering, 132865942Sgibbs * freeze the controller queue 132965942Sgibbs * until our mapping is 133065942Sgibbs * returned. 133165942Sgibbs */ 133265942Sgibbs xpt_freeze_simq(sim, 133365942Sgibbs /*count*/1); 133465942Sgibbs scb->io_ctx->ccb_h.status |= 133565942Sgibbs CAM_RELEASE_SIMQ; 133665942Sgibbs } 133765942Sgibbs splx(s); 133865942Sgibbs } else { 133965942Sgibbs struct bus_dma_segment seg; 134065942Sgibbs 134165942Sgibbs /* Pointer to physical buffer */ 134265942Sgibbs if (csio->dxfer_len > AHC_MAXTRANSFER_SIZE) 134365942Sgibbs panic("ahc_setup_data - Transfer size " 134465942Sgibbs "larger than can device max"); 134565942Sgibbs 134665942Sgibbs seg.ds_addr = (bus_addr_t)csio->data_ptr; 134765942Sgibbs seg.ds_len = csio->dxfer_len; 134865942Sgibbs ahc_execute_scb(scb, &seg, 1, 0); 134965942Sgibbs } 135065942Sgibbs } else { 135165942Sgibbs struct bus_dma_segment *segs; 135265942Sgibbs 135365942Sgibbs if ((ccb_h->flags & CAM_DATA_PHYS) != 0) 135465942Sgibbs panic("ahc_setup_data - Physical segment " 135565942Sgibbs "pointers unsupported"); 135665942Sgibbs 135765942Sgibbs if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) 135865942Sgibbs panic("ahc_setup_data - Virtual segment " 135965942Sgibbs "addresses unsupported"); 136065942Sgibbs 136165942Sgibbs /* Just use the segments provided */ 136265942Sgibbs segs = (struct bus_dma_segment *)csio->data_ptr; 136365942Sgibbs ahc_execute_scb(scb, segs, csio->sglist_cnt, 0); 136465942Sgibbs } 136565942Sgibbs } else { 136665942Sgibbs ahc_execute_scb(scb, NULL, 0, 0); 136765942Sgibbs } 136865942Sgibbs} 136965942Sgibbs 137065942Sgibbsstatic void 137165942Sgibbsahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb) { 137265942Sgibbs 137365942Sgibbs if ((scb->flags & SCB_RECOVERY_SCB) == 0) { 137465942Sgibbs struct scb *list_scb; 137565942Sgibbs 137665942Sgibbs scb->flags |= SCB_RECOVERY_SCB; 137765942Sgibbs 137865942Sgibbs /* 137965942Sgibbs * Take all queued, but not sent SCBs out of the equation. 138065942Sgibbs * Also ensure that no new CCBs are queued to us while we 138165942Sgibbs * try to fix this problem. 138265942Sgibbs */ 138365942Sgibbs if ((scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 138465942Sgibbs xpt_freeze_simq(SCB_GET_SIM(ahc, scb), /*count*/1); 138565942Sgibbs scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; 138665942Sgibbs } 138765942Sgibbs 138865942Sgibbs /* 138965942Sgibbs * Go through all of our pending SCBs and remove 139065942Sgibbs * any scheduled timeouts for them. We will reschedule 139165942Sgibbs * them after we've successfully fixed this problem. 139265942Sgibbs */ 139365942Sgibbs LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { 139465942Sgibbs union ccb *ccb; 139565942Sgibbs 139665942Sgibbs ccb = list_scb->io_ctx; 139765942Sgibbs untimeout(ahc_timeout, list_scb, ccb->ccb_h.timeout_ch); 139865942Sgibbs } 139965942Sgibbs } 140065942Sgibbs} 140165942Sgibbs 140265942Sgibbsvoid 140365942Sgibbsahc_timeout(void *arg) 140465942Sgibbs{ 140565942Sgibbs struct scb *scb; 140665942Sgibbs struct ahc_softc *ahc; 140765942Sgibbs long s; 140865942Sgibbs int found; 140965942Sgibbs u_int last_phase; 141065942Sgibbs int target; 141165942Sgibbs int lun; 141265942Sgibbs int i; 141365942Sgibbs char channel; 141465942Sgibbs 141565942Sgibbs scb = (struct scb *)arg; 141666986Sgibbs ahc = (struct ahc_softc *)scb->ahc_softc; 141765942Sgibbs 141865942Sgibbs ahc_lock(ahc, &s); 141965942Sgibbs 142070204Sgibbs ahc_pause_and_flushwork(ahc); 142165942Sgibbs 142265942Sgibbs if ((scb->flags & SCB_ACTIVE) == 0) { 142365942Sgibbs /* Previous timeout took care of me already */ 142466986Sgibbs printf("%s: Timedout SCB already complete. " 142566986Sgibbs "Interrupts may not be functioning.\n", ahc_name(ahc)); 142665942Sgibbs unpause_sequencer(ahc); 142765942Sgibbs ahc_unlock(ahc, &s); 142865942Sgibbs return; 142965942Sgibbs } 143065942Sgibbs 143165942Sgibbs target = SCB_GET_TARGET(ahc, scb); 143265942Sgibbs channel = SCB_GET_CHANNEL(ahc, scb); 143365942Sgibbs lun = SCB_GET_LUN(scb); 143465942Sgibbs 143568087Sgibbs ahc_print_path(ahc, scb); 143665942Sgibbs printf("SCB 0x%x - timed out ", scb->hscb->tag); 143765942Sgibbs /* 143865942Sgibbs * Take a snapshot of the bus state and print out 143965942Sgibbs * some information so we can track down driver bugs. 144065942Sgibbs */ 144165942Sgibbs last_phase = ahc_inb(ahc, LASTPHASE); 144265942Sgibbs 144365942Sgibbs for (i = 0; i < num_phases; i++) { 144465942Sgibbs if (last_phase == phase_table[i].phase) 144565942Sgibbs break; 144665942Sgibbs } 144765942Sgibbs printf("%s", phase_table[i].phasemsg); 144865942Sgibbs 144965942Sgibbs printf(", SEQADDR == 0x%x\n", 145065942Sgibbs ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); 145165942Sgibbs 145268087Sgibbs printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n", 145368087Sgibbs ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), 145468087Sgibbs ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), 145568087Sgibbs ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), 145668087Sgibbs ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8)); 145768087Sgibbs 145868087Sgibbs printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0)); 145968087Sgibbs 146068087Sgibbs ahc_dump_card_state(ahc); 146165942Sgibbs if (scb->sg_count > 0) { 146265942Sgibbs for (i = 0; i < scb->sg_count; i++) { 146365942Sgibbs printf("sg[%d] - Addr 0x%x : Length %d\n", 146465942Sgibbs i, 146565942Sgibbs scb->sg_list[i].addr, 146666800Sgibbs scb->sg_list[i].len & AHC_SG_LEN_MASK); 146765942Sgibbs } 146865942Sgibbs } 146965942Sgibbs if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { 147065942Sgibbs /* 147165942Sgibbs * Been down this road before. 147265942Sgibbs * Do a full bus reset. 147365942Sgibbs */ 147465942Sgibbsbus_reset: 147565942Sgibbs ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); 147665942Sgibbs found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE); 147765942Sgibbs printf("%s: Issued Channel %c Bus Reset. " 147865942Sgibbs "%d SCBs aborted\n", ahc_name(ahc), channel, found); 147965942Sgibbs } else { 148065942Sgibbs /* 148165942Sgibbs * If we are a target, transition to bus free and report 148265942Sgibbs * the timeout. 148365942Sgibbs * 148465942Sgibbs * The target/initiator that is holding up the bus may not 148565942Sgibbs * be the same as the one that triggered this timeout 148665942Sgibbs * (different commands have different timeout lengths). 148765942Sgibbs * If the bus is idle and we are actiing as the initiator 148865942Sgibbs * for this request, queue a BDR message to the timed out 148965942Sgibbs * target. Otherwise, if the timed out transaction is 149065942Sgibbs * active: 149165942Sgibbs * Initiator transaction: 149265942Sgibbs * Stuff the message buffer with a BDR message and assert 149365942Sgibbs * ATN in the hopes that the target will let go of the bus 149465942Sgibbs * and go to the mesgout phase. If this fails, we'll 149565942Sgibbs * get another timeout 2 seconds later which will attempt 149665942Sgibbs * a bus reset. 149765942Sgibbs * 149865942Sgibbs * Target transaction: 149965942Sgibbs * Transition to BUS FREE and report the error. 150065942Sgibbs * It's good to be the target! 150165942Sgibbs */ 150265942Sgibbs u_int active_scb_index; 150368087Sgibbs u_int saved_scbptr; 150465942Sgibbs 150568087Sgibbs saved_scbptr = ahc_inb(ahc, SCBPTR); 150665942Sgibbs active_scb_index = ahc_inb(ahc, SCB_TAG); 150765942Sgibbs 150865942Sgibbs if (last_phase != P_BUSFREE 150968579Sgibbs && (ahc_inb(ahc, SEQ_FLAGS) & IDENTIFY_SEEN) != 0 151065942Sgibbs && (active_scb_index < ahc->scb_data->numscbs)) { 151165942Sgibbs struct scb *active_scb; 151265942Sgibbs 151365942Sgibbs /* 151468087Sgibbs * If the active SCB is not us, assume that 151568087Sgibbs * the active SCB has a longer timeout than 151668087Sgibbs * the timedout SCB, and wait for the active 151768087Sgibbs * SCB to timeout. 151865942Sgibbs */ 151966800Sgibbs active_scb = ahc_lookup_scb(ahc, active_scb_index); 152068087Sgibbs if (active_scb != scb) { 152171390Sgibbs struct ccb_hdr *ccbh; 152271390Sgibbs uint64_t newtimeout; 152365942Sgibbs 152465942Sgibbs ahc_print_path(ahc, scb); 152565942Sgibbs printf("Other SCB Timeout%s", 152665942Sgibbs (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 152765942Sgibbs ? " again\n" : "\n"); 152865942Sgibbs scb->flags |= SCB_OTHERTCL_TIMEOUT; 152965942Sgibbs newtimeout = 153065942Sgibbs MAX(active_scb->io_ctx->ccb_h.timeout, 153165942Sgibbs scb->io_ctx->ccb_h.timeout); 153271390Sgibbs newtimeout *= hz; 153371390Sgibbs newtimeout /= 1000; 153465942Sgibbs ccbh = &scb->io_ctx->ccb_h; 153565942Sgibbs scb->io_ctx->ccb_h.timeout_ch = 153671390Sgibbs timeout(ahc_timeout, scb, newtimeout); 153765942Sgibbs ahc_unlock(ahc, &s); 153865942Sgibbs return; 153965942Sgibbs } 154065942Sgibbs 154165942Sgibbs /* It's us */ 154265942Sgibbs if ((scb->hscb->control & TARGET_SCB) != 0) { 154365942Sgibbs 154465942Sgibbs /* 154565942Sgibbs * Send back any queued up transactions 154665942Sgibbs * and properly record the error condition. 154765942Sgibbs */ 154865942Sgibbs ahc_freeze_devq(ahc, scb); 154965942Sgibbs ahc_set_transaction_status(scb, 155065942Sgibbs CAM_CMD_TIMEOUT); 155165942Sgibbs ahc_freeze_scb(scb); 155265942Sgibbs ahc_done(ahc, scb); 155365942Sgibbs 155465942Sgibbs /* Will clear us from the bus */ 155565942Sgibbs restart_sequencer(ahc); 155666717Sgibbs ahc_unlock(ahc, &s); 155765942Sgibbs return; 155865942Sgibbs } 155965942Sgibbs 156065942Sgibbs ahc_set_recoveryscb(ahc, active_scb); 156166845Sgibbs ahc_outb(ahc, MSG_OUT, HOST_MSG); 156265942Sgibbs ahc_outb(ahc, SCSISIGO, last_phase|ATNO); 156365942Sgibbs ahc_print_path(ahc, active_scb); 156465942Sgibbs printf("BDR message in message buffer\n"); 156568087Sgibbs active_scb->flags |= SCB_DEVICE_RESET; 156665942Sgibbs active_scb->io_ctx->ccb_h.timeout_ch = 156765942Sgibbs timeout(ahc_timeout, (caddr_t)active_scb, 2 * hz); 156865942Sgibbs unpause_sequencer(ahc); 156965942Sgibbs } else { 157065942Sgibbs int disconnected; 157165942Sgibbs 157265942Sgibbs /* XXX Shouldn't panic. Just punt instead */ 157365942Sgibbs if ((scb->hscb->control & TARGET_SCB) != 0) 157465942Sgibbs panic("Timed-out target SCB but bus idle"); 157565942Sgibbs 157665942Sgibbs if (last_phase != P_BUSFREE 157765942Sgibbs && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) { 157865942Sgibbs /* XXX What happened to the SCB? */ 157965942Sgibbs /* Hung target selection. Goto busfree */ 158065942Sgibbs printf("%s: Hung target selection\n", 158165942Sgibbs ahc_name(ahc)); 158265942Sgibbs restart_sequencer(ahc); 158366717Sgibbs ahc_unlock(ahc, &s); 158465942Sgibbs return; 158565942Sgibbs } 158665942Sgibbs 158765942Sgibbs if (ahc_search_qinfifo(ahc, target, channel, lun, 158865942Sgibbs scb->hscb->tag, ROLE_INITIATOR, 158965942Sgibbs /*status*/0, SEARCH_COUNT) > 0) { 159065942Sgibbs disconnected = FALSE; 159165942Sgibbs } else { 159265942Sgibbs disconnected = TRUE; 159365942Sgibbs } 159465942Sgibbs 159565942Sgibbs if (disconnected) { 159665942Sgibbs 159765942Sgibbs ahc_set_recoveryscb(ahc, scb); 159865942Sgibbs /* 159966800Sgibbs * Actually re-queue this SCB in an attempt 160066800Sgibbs * to select the device before it reconnects. 160166800Sgibbs * In either case (selection or reselection), 160266800Sgibbs * we will now issue a target reset to the 160366800Sgibbs * timed-out device. 160466800Sgibbs * 160566845Sgibbs * Set the MK_MESSAGE control bit indicating 160666845Sgibbs * that we desire to send a message. We 160766845Sgibbs * also set the disconnected flag since 160866845Sgibbs * in the paging case there is no guarantee 160966845Sgibbs * that our SCB control byte matches the 161066845Sgibbs * version on the card. We don't want the 161166845Sgibbs * sequencer to abort the command thinking 161266845Sgibbs * an unsolicited reselection occurred. 161366845Sgibbs */ 161466845Sgibbs scb->hscb->control |= MK_MESSAGE|DISCONNECTED; 161566845Sgibbs scb->flags |= SCB_DEVICE_RESET; 161666845Sgibbs 161766845Sgibbs /* 161866800Sgibbs * Remove any cached copy of this SCB in the 161966800Sgibbs * disconnected list in preparation for the 162066800Sgibbs * queuing of our abort SCB. We use the 162166800Sgibbs * same element in the SCB, SCB_NEXT, for 162266800Sgibbs * both the qinfifo and the disconnected list. 162365942Sgibbs */ 162466800Sgibbs ahc_search_disc_list(ahc, target, channel, 162566800Sgibbs lun, scb->hscb->tag, 162666800Sgibbs /*stop_on_first*/TRUE, 162766800Sgibbs /*remove*/TRUE, 162866845Sgibbs /*save_state*/FALSE); 162965942Sgibbs 163065942Sgibbs /* 163166845Sgibbs * In the non-paging case, the sequencer will 163266845Sgibbs * never re-reference the in-core SCB. 163366845Sgibbs * To make sure we are notified during 163466845Sgibbs * reslection, set the MK_MESSAGE flag in 163566845Sgibbs * the card's copy of the SCB. 163666845Sgibbs */ 163768579Sgibbs if ((ahc->flags & AHC_PAGESCBS) == 0) { 163866845Sgibbs ahc_outb(ahc, SCBPTR, scb->hscb->tag); 163966845Sgibbs ahc_outb(ahc, SCB_CONTROL, 164066845Sgibbs ahc_inb(ahc, SCB_CONTROL) 164166845Sgibbs | MK_MESSAGE); 164266845Sgibbs } 164366845Sgibbs 164466845Sgibbs /* 164565942Sgibbs * Clear out any entries in the QINFIFO first 164665942Sgibbs * so we are the next SCB for this target 164765942Sgibbs * to run. 164865942Sgibbs */ 164965942Sgibbs ahc_search_qinfifo(ahc, 165065942Sgibbs SCB_GET_TARGET(ahc, scb), 165165942Sgibbs channel, SCB_GET_LUN(scb), 165265942Sgibbs SCB_LIST_NULL, 165365942Sgibbs ROLE_INITIATOR, 165465942Sgibbs CAM_REQUEUE_REQ, 165565942Sgibbs SEARCH_COMPLETE); 165665942Sgibbs ahc_print_path(ahc, scb); 165765942Sgibbs printf("Queuing a BDR SCB\n"); 165868087Sgibbs ahc_qinfifo_requeue_tail(ahc, scb); 165968087Sgibbs ahc_outb(ahc, SCBPTR, saved_scbptr); 166065942Sgibbs scb->io_ctx->ccb_h.timeout_ch = 166165942Sgibbs timeout(ahc_timeout, (caddr_t)scb, 2 * hz); 166265942Sgibbs unpause_sequencer(ahc); 166365942Sgibbs } else { 166465942Sgibbs /* Go "immediatly" to the bus reset */ 166565942Sgibbs /* This shouldn't happen */ 166665942Sgibbs ahc_set_recoveryscb(ahc, scb); 166765942Sgibbs ahc_print_path(ahc, scb); 166865942Sgibbs printf("SCB %d: Immediate reset. " 166965942Sgibbs "Flags = 0x%x\n", scb->hscb->tag, 167065942Sgibbs scb->flags); 167165942Sgibbs goto bus_reset; 167265942Sgibbs } 167365942Sgibbs } 167465942Sgibbs } 167565942Sgibbs ahc_unlock(ahc, &s); 167665942Sgibbs} 167765942Sgibbs 167865942Sgibbsstatic void 167965942Sgibbsahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) 168065942Sgibbs{ 168165942Sgibbs union ccb *abort_ccb; 168265942Sgibbs 168365942Sgibbs abort_ccb = ccb->cab.abort_ccb; 168465942Sgibbs switch (abort_ccb->ccb_h.func_code) { 168565942Sgibbs case XPT_ACCEPT_TARGET_IO: 168665942Sgibbs case XPT_IMMED_NOTIFY: 168765942Sgibbs case XPT_CONT_TARGET_IO: 168865942Sgibbs { 168965942Sgibbs struct tmode_tstate *tstate; 169065942Sgibbs struct tmode_lstate *lstate; 169165942Sgibbs struct ccb_hdr_slist *list; 169265942Sgibbs cam_status status; 169365942Sgibbs 169465942Sgibbs status = ahc_find_tmode_devs(ahc, sim, abort_ccb, &tstate, 169565942Sgibbs &lstate, TRUE); 169665942Sgibbs 169765942Sgibbs if (status != CAM_REQ_CMP) { 169865942Sgibbs ccb->ccb_h.status = status; 169965942Sgibbs break; 170065942Sgibbs } 170165942Sgibbs 170265942Sgibbs if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) 170365942Sgibbs list = &lstate->accept_tios; 170465942Sgibbs else if (abort_ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) 170565942Sgibbs list = &lstate->immed_notifies; 170665942Sgibbs else 170765942Sgibbs list = NULL; 170865942Sgibbs 170965942Sgibbs if (list != NULL) { 171065942Sgibbs struct ccb_hdr *curelm; 171165942Sgibbs int found; 171265942Sgibbs 171365942Sgibbs curelm = SLIST_FIRST(list); 171465942Sgibbs found = 0; 171565942Sgibbs if (curelm == &abort_ccb->ccb_h) { 171665942Sgibbs found = 1; 171765942Sgibbs SLIST_REMOVE_HEAD(list, sim_links.sle); 171865942Sgibbs } else { 171965942Sgibbs while(curelm != NULL) { 172065942Sgibbs struct ccb_hdr *nextelm; 172165942Sgibbs 172265942Sgibbs nextelm = 172365942Sgibbs SLIST_NEXT(curelm, sim_links.sle); 172465942Sgibbs 172565942Sgibbs if (nextelm == &abort_ccb->ccb_h) { 172665942Sgibbs found = 1; 172765942Sgibbs SLIST_NEXT(curelm, 172865942Sgibbs sim_links.sle) = 172965942Sgibbs SLIST_NEXT(nextelm, 173065942Sgibbs sim_links.sle); 173165942Sgibbs break; 173265942Sgibbs } 173365942Sgibbs curelm = nextelm; 173465942Sgibbs } 173565942Sgibbs } 173665942Sgibbs 173765942Sgibbs if (found) { 173865942Sgibbs abort_ccb->ccb_h.status = CAM_REQ_ABORTED; 173965942Sgibbs xpt_done(abort_ccb); 174065942Sgibbs ccb->ccb_h.status = CAM_REQ_CMP; 174165942Sgibbs } else { 174268087Sgibbs xpt_print_path(abort_ccb->ccb_h.path); 174365942Sgibbs printf("Not found\n"); 174465942Sgibbs ccb->ccb_h.status = CAM_PATH_INVALID; 174565942Sgibbs } 174665942Sgibbs break; 174765942Sgibbs } 174865942Sgibbs /* FALLTHROUGH */ 174965942Sgibbs } 175065942Sgibbs case XPT_SCSI_IO: 175165942Sgibbs /* XXX Fully implement the hard ones */ 175265942Sgibbs ccb->ccb_h.status = CAM_UA_ABORT; 175365942Sgibbs break; 175465942Sgibbs default: 175565942Sgibbs ccb->ccb_h.status = CAM_REQ_INVALID; 175665942Sgibbs break; 175765942Sgibbs } 175865942Sgibbs xpt_done(ccb); 175965942Sgibbs} 176065942Sgibbs 176165942Sgibbsvoid 176266269Sgibbsahc_send_async(struct ahc_softc *ahc, char channel, u_int target, 176366269Sgibbs u_int lun, ac_code code) 176465942Sgibbs{ 176565942Sgibbs struct ccb_trans_settings cts; 176665942Sgibbs struct cam_path *path; 176765942Sgibbs void *arg; 176865942Sgibbs int error; 176965942Sgibbs 177065942Sgibbs arg = NULL; 177166269Sgibbs error = ahc_create_path(ahc, channel, target, lun, &path); 177265942Sgibbs 177365942Sgibbs if (error != CAM_REQ_CMP) 177465942Sgibbs return; 177565942Sgibbs 177665942Sgibbs switch (code) { 177765942Sgibbs case AC_TRANSFER_NEG: 177865942Sgibbs#ifdef AHC_NEW_TRAN_SETTINGS 177965942Sgibbs cts.type = CTS_TYPE_CURRENT_SETTINGS; 178065942Sgibbs#else 178165942Sgibbs cts.flags = CCB_TRANS_CURRENT_SETTINGS; 178265942Sgibbs#endif 178365942Sgibbs cts.ccb_h.path = path; 178466269Sgibbs cts.ccb_h.target_id = target; 178566269Sgibbs cts.ccb_h.target_lun = lun; 178666269Sgibbs ahc_get_tran_settings(ahc, channel == 'A' ? ahc->our_id 178766269Sgibbs : ahc->our_id_b, 178866269Sgibbs channel, &cts); 178965942Sgibbs arg = &cts; 179065942Sgibbs break; 179165942Sgibbs case AC_SENT_BDR: 179265942Sgibbs case AC_BUS_RESET: 179365942Sgibbs break; 179465942Sgibbs default: 179565942Sgibbs panic("ahc_send_async: Unexpected async event"); 179665942Sgibbs } 179765942Sgibbs xpt_async(code, path, arg); 179868402Sgibbs xpt_free_path(path); 179965942Sgibbs} 180065942Sgibbs 180165942Sgibbsvoid 180265942Sgibbsahc_platform_set_tags(struct ahc_softc *ahc, 180365942Sgibbs struct ahc_devinfo *devinfo, int enable) 180465942Sgibbs{ 180565942Sgibbs} 180665942Sgibbs 180765942Sgibbsint 180865942Sgibbsahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) 180965942Sgibbs{ 181067888Sdwmalone ahc->platform_data = malloc(sizeof(struct ahc_platform_data), M_DEVBUF, 181167888Sdwmalone M_NOWAIT | M_ZERO); 181265942Sgibbs if (ahc->platform_data == NULL) 181365942Sgibbs return (ENOMEM); 181465942Sgibbs return (0); 181565942Sgibbs} 181665942Sgibbs 181765942Sgibbsvoid 181865942Sgibbsahc_platform_free(struct ahc_softc *ahc) 181965942Sgibbs{ 182070204Sgibbs struct ahc_platform_data *pdata; 182170204Sgibbs 182270204Sgibbs pdata = ahc->platform_data; 182370204Sgibbs if (pdata != NULL) { 182470204Sgibbs device_printf(ahc->dev_softc, "Platform free\n"); 182570204Sgibbs if (pdata->regs != NULL) 182665942Sgibbs bus_release_resource(ahc->dev_softc, 182770204Sgibbs pdata->regs_res_type, 182870204Sgibbs pdata->regs_res_id, 182970204Sgibbs pdata->regs); 183065942Sgibbs 183170204Sgibbs if (pdata->irq != NULL) 183265942Sgibbs bus_release_resource(ahc->dev_softc, 183370204Sgibbs pdata->irq_res_type, 183470204Sgibbs 0, pdata->irq); 183565942Sgibbs 183670204Sgibbs if (pdata->sim_b != NULL) { 183770204Sgibbs xpt_async(AC_LOST_DEVICE, pdata->path_b, NULL); 183870204Sgibbs xpt_free_path(pdata->path_b); 183970204Sgibbs xpt_bus_deregister(cam_sim_path(pdata->sim_b)); 184070204Sgibbs cam_sim_free(pdata->sim_b, /*free_devq*/TRUE); 184170204Sgibbs } 184270204Sgibbs if (pdata->sim != NULL) { 184370204Sgibbs xpt_async(AC_LOST_DEVICE, pdata->path, NULL); 184470204Sgibbs xpt_free_path(pdata->path); 184570204Sgibbs xpt_bus_deregister(cam_sim_path(pdata->sim)); 184670204Sgibbs cam_sim_free(pdata->sim, /*free_devq*/TRUE); 184770204Sgibbs } 184870204Sgibbs if (pdata->eh != NULL) 184970204Sgibbs EVENTHANDLER_DEREGISTER(shutdown_final, pdata->eh); 185065942Sgibbs free(ahc->platform_data, M_DEVBUF); 185165942Sgibbs } 185265942Sgibbs} 185365942Sgibbs 185465942Sgibbsint 185565942Sgibbsahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc) 185665942Sgibbs{ 185765942Sgibbs /* We don't sort softcs under FreeBSD so report equal always */ 185865942Sgibbs return (0); 185965942Sgibbs} 186065942Sgibbs 186170204Sgibbsint 186270204Sgibbsahc_detach(device_t dev) 186370204Sgibbs{ 186470204Sgibbs struct ahc_softc *ahc; 186570204Sgibbs u_long s; 186670204Sgibbs 186770204Sgibbs device_printf(dev, "detaching device\n"); 186870204Sgibbs ahc = device_get_softc(dev); 186970204Sgibbs ahc_lock(ahc, &s); 187070204Sgibbs bus_teardown_intr(dev, ahc->platform_data->irq, ahc->platform_data->ih); 187170204Sgibbs ahc_unlock(ahc, &s); 187270204Sgibbs ahc_free(ahc); 187370204Sgibbs return (0); 187470204Sgibbs} 187570204Sgibbs 187665942Sgibbs#if UNUSED 187765942Sgibbsstatic void 187865942Sgibbsahc_dump_targcmd(struct target_cmd *cmd) 187965942Sgibbs{ 188065942Sgibbs uint8_t *byte; 188165942Sgibbs uint8_t *last_byte; 188265942Sgibbs int i; 188365942Sgibbs 188465942Sgibbs byte = &cmd->initiator_channel; 188565942Sgibbs /* Debugging info for received commands */ 188665942Sgibbs last_byte = &cmd[1].initiator_channel; 188765942Sgibbs 188865942Sgibbs i = 0; 188965942Sgibbs while (byte < last_byte) { 189065942Sgibbs if (i == 0) 189165942Sgibbs printf("\t"); 189265942Sgibbs printf("%#x", *byte++); 189365942Sgibbs i++; 189465942Sgibbs if (i == 8) { 189565942Sgibbs printf("\n"); 189665942Sgibbs i = 0; 189765942Sgibbs } else { 189865942Sgibbs printf(", "); 189965942Sgibbs } 190065942Sgibbs } 190165942Sgibbs} 190265942Sgibbs#endif 1903