The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/aic7xxx/aic7xxx_osm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Bus independent FreeBSD shim for the aic7xxx based Adaptec SCSI controllers
    3  *
    4  * Copyright (c) 1994-2001 Justin T. Gibbs.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions, and the following disclaimer,
   12  *    without modification.
   13  * 2. The name of the author may not be used to endorse or promote products
   14  *    derived from this software without specific prior written permission.
   15  *
   16  * Alternatively, this software may be distributed under the terms of the
   17  * GNU Public License ("GPL").
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.c#20 $
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 #include <dev/aic7xxx/aic7xxx_osm.h>
   38 #include <dev/aic7xxx/aic7xxx_inline.h>
   39 
   40 #include <sys/kthread.h>
   41 
   42 #ifndef AHC_TMODE_ENABLE
   43 #define AHC_TMODE_ENABLE 0
   44 #endif
   45 
   46 #include <dev/aic7xxx/aic_osm_lib.c>
   47 
   48 #define ccb_scb_ptr spriv_ptr0
   49 
   50 #if 0
   51 static void     ahc_dump_targcmd(struct target_cmd *cmd);
   52 #endif
   53 static int      ahc_modevent(module_t mod, int type, void *data);
   54 static void     ahc_action(struct cam_sim *sim, union ccb *ccb);
   55 static void     ahc_get_tran_settings(struct ahc_softc *ahc,
   56                                       int our_id, char channel,
   57                                       struct ccb_trans_settings *cts);
   58 static void     ahc_async(void *callback_arg, uint32_t code,
   59                           struct cam_path *path, void *arg);
   60 static void     ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
   61                                 int nsegments, int error);
   62 static void     ahc_poll(struct cam_sim *sim);
   63 static void     ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim,
   64                                struct ccb_scsiio *csio, struct scb *scb);
   65 static void     ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim,
   66                               union ccb *ccb);
   67 static int      ahc_create_path(struct ahc_softc *ahc,
   68                                 char channel, u_int target, u_int lun,
   69                                 struct cam_path **path);
   70 
   71 static int
   72 ahc_create_path(struct ahc_softc *ahc, char channel, u_int target,
   73                 u_int lun, struct cam_path **path)
   74 {
   75         path_id_t path_id;
   76 
   77         if (channel == 'B')
   78                 path_id = cam_sim_path(ahc->platform_data->sim_b);
   79         else 
   80                 path_id = cam_sim_path(ahc->platform_data->sim);
   81 
   82         return (xpt_create_path(path, /*periph*/NULL,
   83                                 path_id, target, lun));
   84 }
   85 
   86 int
   87 ahc_map_int(struct ahc_softc *ahc)
   88 {
   89         int error;
   90         int zero;
   91         int shareable;
   92 
   93         zero = 0;
   94         shareable = (ahc->flags & AHC_EDGE_INTERRUPT) ? 0: RF_SHAREABLE;
   95         ahc->platform_data->irq =
   96             bus_alloc_resource_any(ahc->dev_softc, SYS_RES_IRQ, &zero,
   97                                    RF_ACTIVE | shareable);
   98         if (ahc->platform_data->irq == NULL) {
   99                 device_printf(ahc->dev_softc,
  100                               "bus_alloc_resource() failed to allocate IRQ\n");
  101                 return (ENOMEM);
  102         }
  103         ahc->platform_data->irq_res_type = SYS_RES_IRQ;
  104 
  105         /* Hook up our interrupt handler */
  106         error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq,
  107                                INTR_TYPE_CAM|INTR_MPSAFE, NULL, 
  108                                ahc_platform_intr, ahc, &ahc->platform_data->ih);
  109 
  110         if (error != 0)
  111                 device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n",
  112                               error);
  113         return (error);
  114 }
  115 
  116 int
  117 aic7770_map_registers(struct ahc_softc *ahc, u_int unused_ioport_arg)
  118 {
  119         struct  resource *regs;
  120         int     rid;
  121 
  122         rid = 0;
  123         regs = bus_alloc_resource_any(ahc->dev_softc, SYS_RES_IOPORT, &rid,
  124                                       RF_ACTIVE);
  125         if (regs == NULL) {
  126                 device_printf(ahc->dev_softc, "Unable to map I/O space?!\n");
  127                 return ENOMEM;
  128         }
  129         ahc->platform_data->regs_res_type = SYS_RES_IOPORT;
  130         ahc->platform_data->regs_res_id = rid;
  131         ahc->platform_data->regs = regs;
  132         ahc->tag = rman_get_bustag(regs);
  133         ahc->bsh = rman_get_bushandle(regs);
  134         return (0);
  135 }
  136 
  137 /*
  138  * Attach all the sub-devices we can find
  139  */
  140 int
  141 ahc_attach(struct ahc_softc *ahc)
  142 {
  143         char   ahc_info[256];
  144         struct ccb_setasync csa;
  145         struct cam_devq *devq;
  146         int bus_id;
  147         int bus_id2;
  148         struct cam_sim *sim;
  149         struct cam_sim *sim2;
  150         struct cam_path *path;
  151         struct cam_path *path2;
  152         int count;
  153 
  154         count = 0;
  155         sim = NULL;
  156         sim2 = NULL;
  157         path = NULL;
  158         path2 = NULL;
  159 
  160         /*
  161          * Create a thread to perform all recovery.
  162          */
  163         if (ahc_spawn_recovery_thread(ahc) != 0)
  164                 goto fail;
  165 
  166         ahc_controller_info(ahc, ahc_info);
  167         printf("%s\n", ahc_info);
  168         ahc_lock(ahc);
  169 
  170         /*
  171          * Attach secondary channel first if the user has
  172          * declared it the primary channel.
  173          */
  174         if ((ahc->features & AHC_TWIN) != 0
  175          && (ahc->flags & AHC_PRIMARY_CHANNEL) != 0) {
  176                 bus_id = 1;
  177                 bus_id2 = 0;
  178         } else {
  179                 bus_id = 0;
  180                 bus_id2 = 1;
  181         }
  182 
  183         /*
  184          * Create the device queue for our SIM(s).
  185          */
  186         devq = cam_simq_alloc(AHC_MAX_QUEUE);
  187         if (devq == NULL)
  188                 goto fail;
  189 
  190         /*
  191          * Construct our first channel SIM entry
  192          */
  193         sim = cam_sim_alloc(ahc_action, ahc_poll, "ahc", ahc,
  194                             device_get_unit(ahc->dev_softc),
  195                             &ahc->platform_data->mtx, 1, AHC_MAX_QUEUE, devq);
  196         if (sim == NULL) {
  197                 cam_simq_free(devq);
  198                 goto fail;
  199         }
  200 
  201         if (xpt_bus_register(sim, ahc->dev_softc, bus_id) != CAM_SUCCESS) {
  202                 cam_sim_free(sim, /*free_devq*/TRUE);
  203                 sim = NULL;
  204                 goto fail;
  205         }
  206 
  207         if (xpt_create_path(&path, /*periph*/NULL,
  208                             cam_sim_path(sim), CAM_TARGET_WILDCARD,
  209                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  210                 xpt_bus_deregister(cam_sim_path(sim));
  211                 cam_sim_free(sim, /*free_devq*/TRUE);
  212                 sim = NULL;
  213                 goto fail;
  214         }
  215                 
  216         memset(&csa, 0, sizeof(csa));
  217         xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
  218         csa.ccb_h.func_code = XPT_SASYNC_CB;
  219         csa.event_enable = AC_LOST_DEVICE;
  220         csa.callback = ahc_async;
  221         csa.callback_arg = sim;
  222         xpt_action((union ccb *)&csa);
  223         count++;
  224 
  225         if (ahc->features & AHC_TWIN) {
  226                 sim2 = cam_sim_alloc(ahc_action, ahc_poll, "ahc",
  227                                     ahc, device_get_unit(ahc->dev_softc),
  228                                     &ahc->platform_data->mtx, 1,
  229                                     AHC_MAX_QUEUE, devq);
  230 
  231                 if (sim2 == NULL) {
  232                         printf("ahc_attach: Unable to attach second "
  233                                "bus due to resource shortage");
  234                         goto fail;
  235                 }
  236                 
  237                 if (xpt_bus_register(sim2, ahc->dev_softc, bus_id2) !=
  238                     CAM_SUCCESS) {
  239                         printf("ahc_attach: Unable to attach second "
  240                                "bus due to resource shortage");
  241                         /*
  242                          * We do not want to destroy the device queue
  243                          * because the first bus is using it.
  244                          */
  245                         cam_sim_free(sim2, /*free_devq*/FALSE);
  246                         goto fail;
  247                 }
  248 
  249                 if (xpt_create_path(&path2, /*periph*/NULL,
  250                                     cam_sim_path(sim2),
  251                                     CAM_TARGET_WILDCARD,
  252                                     CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  253                         xpt_bus_deregister(cam_sim_path(sim2));
  254                         cam_sim_free(sim2, /*free_devq*/FALSE);
  255                         sim2 = NULL;
  256                         goto fail;
  257                 }
  258                 xpt_setup_ccb(&csa.ccb_h, path2, /*priority*/5);
  259                 csa.ccb_h.func_code = XPT_SASYNC_CB;
  260                 csa.event_enable = AC_LOST_DEVICE;
  261                 csa.callback = ahc_async;
  262                 csa.callback_arg = sim2;
  263                 xpt_action((union ccb *)&csa);
  264                 count++;
  265         }
  266 
  267 fail:
  268         if ((ahc->features & AHC_TWIN) != 0
  269          && (ahc->flags & AHC_PRIMARY_CHANNEL) != 0) {
  270                 ahc->platform_data->sim_b = sim;
  271                 ahc->platform_data->path_b = path;
  272                 ahc->platform_data->sim = sim2;
  273                 ahc->platform_data->path = path2;
  274         } else {
  275                 ahc->platform_data->sim = sim;
  276                 ahc->platform_data->path = path;
  277                 ahc->platform_data->sim_b = sim2;
  278                 ahc->platform_data->path_b = path2;
  279         }
  280         ahc_unlock(ahc);
  281 
  282         if (count != 0) {
  283                 /* We have to wait until after any system dumps... */
  284                 ahc->platform_data->eh =
  285                     EVENTHANDLER_REGISTER(shutdown_final, ahc_shutdown,
  286                                           ahc, SHUTDOWN_PRI_DEFAULT);
  287                 ahc_intr_enable(ahc, TRUE);
  288         }
  289 
  290         return (count);
  291 }
  292 
  293 /*
  294  * Catch an interrupt from the adapter
  295  */
  296 void
  297 ahc_platform_intr(void *arg)
  298 {
  299         struct  ahc_softc *ahc;
  300 
  301         ahc = (struct ahc_softc *)arg; 
  302         ahc_lock(ahc);
  303         ahc_intr(ahc);
  304         ahc_unlock(ahc);
  305 }
  306 
  307 /*
  308  * We have an scb which has been processed by the
  309  * adaptor, now we look to see how the operation
  310  * went.
  311  */
  312 void
  313 ahc_done(struct ahc_softc *ahc, struct scb *scb)
  314 {
  315         union ccb *ccb;
  316 
  317         CAM_DEBUG(scb->io_ctx->ccb_h.path, CAM_DEBUG_TRACE,
  318                   ("ahc_done - scb %d\n", scb->hscb->tag));
  319 
  320         ccb = scb->io_ctx;
  321         LIST_REMOVE(scb, pending_links);
  322         if ((scb->flags & SCB_TIMEDOUT) != 0)
  323                 LIST_REMOVE(scb, timedout_links);
  324         if ((scb->flags & SCB_UNTAGGEDQ) != 0) {
  325                 struct scb_tailq *untagged_q;
  326                 int target_offset;
  327 
  328                 target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
  329                 untagged_q = &ahc->untagged_queues[target_offset];
  330                 TAILQ_REMOVE(untagged_q, scb, links.tqe);
  331                 scb->flags &= ~SCB_UNTAGGEDQ;
  332                 ahc_run_untagged_queue(ahc, untagged_q);
  333         }
  334 
  335         callout_stop(&scb->io_timer);
  336 
  337         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
  338                 bus_dmasync_op_t op;
  339 
  340                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
  341                         op = BUS_DMASYNC_POSTREAD;
  342                 else
  343                         op = BUS_DMASYNC_POSTWRITE;
  344                 bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op);
  345                 bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
  346         }
  347 
  348         if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
  349                 struct cam_path *ccb_path;
  350 
  351                 /*
  352                  * If we have finally disconnected, clean up our
  353                  * pending device state.
  354                  * XXX - There may be error states that cause where
  355                  *       we will remain connected.
  356                  */
  357                 ccb_path = ccb->ccb_h.path;
  358                 if (ahc->pending_device != NULL
  359                  && xpt_path_comp(ahc->pending_device->path, ccb_path) == 0) {
  360                         if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
  361                                 ahc->pending_device = NULL;
  362                         } else {
  363                                 if (bootverbose) {
  364                                         xpt_print_path(ccb->ccb_h.path);
  365                                         printf("Still connected\n");
  366                                 }
  367                                 aic_freeze_ccb(ccb);
  368                         }
  369                 }
  370 
  371                 if (aic_get_transaction_status(scb) == CAM_REQ_INPROG)
  372                         ccb->ccb_h.status |= CAM_REQ_CMP;
  373                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
  374                 ahc_free_scb(ahc, scb);
  375                 xpt_done(ccb);
  376                 return;
  377         }
  378 
  379         /*
  380          * If the recovery SCB completes, we have to be
  381          * out of our timeout.
  382          */
  383         if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
  384                 struct  scb *list_scb;
  385 
  386                 ahc->scb_data->recovery_scbs--;
  387 
  388                 if (aic_get_transaction_status(scb) == CAM_BDR_SENT
  389                  || aic_get_transaction_status(scb) == CAM_REQ_ABORTED)
  390                         aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
  391 
  392                 if (ahc->scb_data->recovery_scbs == 0) {
  393                         /*
  394                          * All recovery actions have completed successfully,
  395                          * so reinstate the timeouts for all other pending
  396                          * commands.
  397                          */
  398                         LIST_FOREACH(list_scb, &ahc->pending_scbs,
  399                                      pending_links) {
  400                                 aic_scb_timer_reset(list_scb,
  401                                                     aic_get_timeout(scb));
  402                         }
  403 
  404                         ahc_print_path(ahc, scb);
  405                         printf("no longer in timeout, status = %x\n",
  406                                ccb->ccb_h.status);
  407                 }
  408         }
  409 
  410         /* Don't clobber any existing error state */
  411         if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) {
  412                 ccb->ccb_h.status |= CAM_REQ_CMP;
  413         } else if ((scb->flags & SCB_SENSE) != 0) {
  414                 /*
  415                  * We performed autosense retrieval.
  416                  *
  417                  * Zero any sense not transferred by the
  418                  * device.  The SCSI spec mandates that any
  419                  * untransfered data should be assumed to be
  420                  * zero.  Complete the 'bounce' of sense information
  421                  * through buffers accessible via bus-space by
  422                  * copying it into the clients csio.
  423                  */
  424                 memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
  425                 memcpy(&ccb->csio.sense_data,
  426                        ahc_get_sense_buf(ahc, scb),
  427                        (aic_le32toh(scb->sg_list->len) & AHC_SG_LEN_MASK)
  428                        - ccb->csio.sense_resid);
  429                 scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID;
  430         }
  431         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
  432         ahc_free_scb(ahc, scb);
  433         xpt_done(ccb);
  434 }
  435 
  436 static void
  437 ahc_action(struct cam_sim *sim, union ccb *ccb)
  438 {
  439         struct  ahc_softc *ahc;
  440         struct  ahc_tmode_lstate *lstate;
  441         u_int   target_id;
  442         u_int   our_id;
  443 
  444         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahc_action\n"));
  445 
  446         ahc = (struct ahc_softc *)cam_sim_softc(sim);
  447 
  448         target_id = ccb->ccb_h.target_id;
  449         our_id = SIM_SCSI_ID(ahc, sim);
  450 
  451         switch (ccb->ccb_h.func_code) {
  452         /* Common cases first */
  453         case XPT_ACCEPT_TARGET_IO:      /* Accept Host Target Mode CDB */
  454         case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/
  455         {
  456                 struct     ahc_tmode_tstate *tstate;
  457                 cam_status status;
  458 
  459                 status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate,
  460                                              &lstate, TRUE);
  461 
  462                 if (status != CAM_REQ_CMP) {
  463                         if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
  464                                 /* Response from the black hole device */
  465                                 tstate = NULL;
  466                                 lstate = ahc->black_hole;
  467                         } else {
  468                                 ccb->ccb_h.status = status;
  469                                 xpt_done(ccb);
  470                                 break;
  471                         }
  472                 }
  473                 if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
  474                         SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
  475                                           sim_links.sle);
  476                         ccb->ccb_h.status = CAM_REQ_INPROG;
  477                         if ((ahc->flags & AHC_TQINFIFO_BLOCKED) != 0)
  478                                 ahc_run_tqinfifo(ahc, /*paused*/FALSE);
  479                         break;
  480                 }
  481 
  482                 /*
  483                  * The target_id represents the target we attempt to
  484                  * select.  In target mode, this is the initiator of
  485                  * the original command.
  486                  */
  487                 our_id = target_id;
  488                 target_id = ccb->csio.init_id;
  489                 /* FALLTHROUGH */
  490         }
  491         case XPT_SCSI_IO:       /* Execute the requested I/O operation */
  492         case XPT_RESET_DEV:     /* Bus Device Reset the specified SCSI device */
  493         {
  494                 struct  scb *scb;
  495                 struct  hardware_scb *hscb;     
  496 
  497                 if ((ahc->flags & AHC_INITIATORROLE) == 0
  498                  && (ccb->ccb_h.func_code == XPT_SCSI_IO
  499                   || ccb->ccb_h.func_code == XPT_RESET_DEV)) {
  500                         ccb->ccb_h.status = CAM_PROVIDE_FAIL;
  501                         xpt_done(ccb);
  502                         return;
  503                 }
  504 
  505                 /*
  506                  * get an scb to use.
  507                  */
  508                 if ((scb = ahc_get_scb(ahc)) == NULL) {
  509                         xpt_freeze_simq(sim, /*count*/1);
  510                         ahc->flags |= AHC_RESOURCE_SHORTAGE;
  511                         ccb->ccb_h.status = CAM_REQUEUE_REQ;
  512                         xpt_done(ccb);
  513                         return;
  514                 }
  515                 
  516                 hscb = scb->hscb;
  517                 
  518                 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE,
  519                           ("start scb(%p)\n", scb));
  520                 scb->io_ctx = ccb;
  521                 /*
  522                  * So we can find the SCB when an abort is requested
  523                  */
  524                 ccb->ccb_h.ccb_scb_ptr = scb;
  525 
  526                 /*
  527                  * Put all the arguments for the xfer in the scb
  528                  */
  529                 hscb->control = 0;
  530                 hscb->scsiid = BUILD_SCSIID(ahc, sim, target_id, our_id);
  531                 hscb->lun = ccb->ccb_h.target_lun;
  532                 if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
  533                         hscb->cdb_len = 0;
  534                         scb->flags |= SCB_DEVICE_RESET;
  535                         hscb->control |= MK_MESSAGE;
  536                         ahc_execute_scb(scb, NULL, 0, 0);
  537                 } else {
  538                         if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
  539                                 struct target_data *tdata;
  540 
  541                                 tdata = &hscb->shared_data.tdata;
  542                                 if (ahc->pending_device == lstate)
  543                                         scb->flags |= SCB_TARGET_IMMEDIATE;
  544                                 hscb->control |= TARGET_SCB;
  545                                 scb->flags |= SCB_TARGET_SCB;
  546                                 tdata->target_phases = 0;
  547                                 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
  548                                         tdata->target_phases |= SPHASE_PENDING;
  549                                         tdata->scsi_status =
  550                                             ccb->csio.scsi_status;
  551                                 }
  552                                 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT)
  553                                         tdata->target_phases |= NO_DISCONNECT;
  554 
  555                                 tdata->initiator_tag = ccb->csio.tag_id;
  556                         }
  557                         if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID)
  558                                 hscb->control |= ccb->csio.tag_action;
  559                         
  560                         ahc_setup_data(ahc, sim, &ccb->csio, scb);
  561                 }
  562                 break;
  563         }
  564         case XPT_NOTIFY_ACKNOWLEDGE:
  565         case XPT_IMMEDIATE_NOTIFY:
  566         {
  567                 struct     ahc_tmode_tstate *tstate;
  568                 struct     ahc_tmode_lstate *lstate;
  569                 cam_status status;
  570 
  571                 status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate,
  572                                              &lstate, TRUE);
  573 
  574                 if (status != CAM_REQ_CMP) {
  575                         ccb->ccb_h.status = status;
  576                         xpt_done(ccb);
  577                         break;
  578                 }
  579                 SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h,
  580                                   sim_links.sle);
  581                 ccb->ccb_h.status = CAM_REQ_INPROG;
  582                 ahc_send_lstate_events(ahc, lstate);
  583                 break;
  584         }
  585         case XPT_EN_LUN:                /* Enable LUN as a target */
  586                 ahc_handle_en_lun(ahc, sim, ccb);
  587                 xpt_done(ccb);
  588                 break;
  589         case XPT_ABORT:                 /* Abort the specified CCB */
  590         {
  591                 ahc_abort_ccb(ahc, sim, ccb);
  592                 break;
  593         }
  594         case XPT_SET_TRAN_SETTINGS:
  595         {
  596                 struct  ahc_devinfo devinfo;
  597                 struct  ccb_trans_settings *cts;
  598                 struct  ccb_trans_settings_scsi *scsi;
  599                 struct  ccb_trans_settings_spi *spi;
  600                 struct  ahc_initiator_tinfo *tinfo;
  601                 struct  ahc_tmode_tstate *tstate;
  602                 uint16_t *discenable;
  603                 uint16_t *tagenable;
  604                 u_int   update_type;
  605 
  606                 cts = &ccb->cts;
  607                 scsi = &cts->proto_specific.scsi;
  608                 spi = &cts->xport_specific.spi;
  609                 ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim),
  610                                     cts->ccb_h.target_id,
  611                                     cts->ccb_h.target_lun,
  612                                     SIM_CHANNEL(ahc, sim),
  613                                     ROLE_UNKNOWN);
  614                 tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
  615                                             devinfo.our_scsiid,
  616                                             devinfo.target, &tstate);
  617                 update_type = 0;
  618                 if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
  619                         update_type |= AHC_TRANS_GOAL;
  620                         discenable = &tstate->discenable;
  621                         tagenable = &tstate->tagenable;
  622                         tinfo->curr.protocol_version =
  623                             cts->protocol_version;
  624                         tinfo->curr.transport_version =
  625                             cts->transport_version;
  626                         tinfo->goal.protocol_version =
  627                             cts->protocol_version;
  628                         tinfo->goal.transport_version =
  629                             cts->transport_version;
  630                 } else if (cts->type == CTS_TYPE_USER_SETTINGS) {
  631                         update_type |= AHC_TRANS_USER;
  632                         discenable = &ahc->user_discenable;
  633                         tagenable = &ahc->user_tagenable;
  634                         tinfo->user.protocol_version =
  635                             cts->protocol_version;
  636                         tinfo->user.transport_version =
  637                             cts->transport_version;
  638                 } else {
  639                         ccb->ccb_h.status = CAM_REQ_INVALID;
  640                         xpt_done(ccb);
  641                         break;
  642                 }
  643                 
  644                 if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
  645                         if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
  646                                 *discenable |= devinfo.target_mask;
  647                         else
  648                                 *discenable &= ~devinfo.target_mask;
  649                 }
  650                 
  651                 if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
  652                         if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
  653                                 *tagenable |= devinfo.target_mask;
  654                         else
  655                                 *tagenable &= ~devinfo.target_mask;
  656                 }       
  657 
  658                 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
  659                         ahc_validate_width(ahc, /*tinfo limit*/NULL,
  660                                            &spi->bus_width, ROLE_UNKNOWN);
  661                         ahc_set_width(ahc, &devinfo, spi->bus_width,
  662                                       update_type, /*paused*/FALSE);
  663                 }
  664 
  665                 if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) {
  666                         if (update_type == AHC_TRANS_USER)
  667                                 spi->ppr_options = tinfo->user.ppr_options;
  668                         else
  669                                 spi->ppr_options = tinfo->goal.ppr_options;
  670                 }
  671 
  672                 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) {
  673                         if (update_type == AHC_TRANS_USER)
  674                                 spi->sync_offset = tinfo->user.offset;
  675                         else
  676                                 spi->sync_offset = tinfo->goal.offset;
  677                 }
  678 
  679                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) {
  680                         if (update_type == AHC_TRANS_USER)
  681                                 spi->sync_period = tinfo->user.period;
  682                         else
  683                                 spi->sync_period = tinfo->goal.period;
  684                 }
  685 
  686                 if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0)
  687                  || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) {
  688                         struct ahc_syncrate *syncrate;
  689                         u_int maxsync;
  690 
  691                         if ((ahc->features & AHC_ULTRA2) != 0)
  692                                 maxsync = AHC_SYNCRATE_DT;
  693                         else if ((ahc->features & AHC_ULTRA) != 0)
  694                                 maxsync = AHC_SYNCRATE_ULTRA;
  695                         else
  696                                 maxsync = AHC_SYNCRATE_FAST;
  697 
  698                         if (spi->bus_width != MSG_EXT_WDTR_BUS_16_BIT)
  699                                 spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ;
  700 
  701                         syncrate = ahc_find_syncrate(ahc, &spi->sync_period,
  702                                                      &spi->ppr_options,
  703                                                      maxsync);
  704                         ahc_validate_offset(ahc, /*tinfo limit*/NULL,
  705                                             syncrate, &spi->sync_offset,
  706                                             spi->bus_width, ROLE_UNKNOWN);
  707 
  708                         /* We use a period of 0 to represent async */
  709                         if (spi->sync_offset == 0) {
  710                                 spi->sync_period = 0;
  711                                 spi->ppr_options = 0;
  712                         }
  713 
  714                         ahc_set_syncrate(ahc, &devinfo, syncrate,
  715                                          spi->sync_period, spi->sync_offset,
  716                                          spi->ppr_options, update_type,
  717                                          /*paused*/FALSE);
  718                 }
  719                 ccb->ccb_h.status = CAM_REQ_CMP;
  720                 xpt_done(ccb);
  721                 break;
  722         }
  723         case XPT_GET_TRAN_SETTINGS:
  724         /* Get default/user set transfer settings for the target */
  725         {
  726                 ahc_get_tran_settings(ahc, SIM_SCSI_ID(ahc, sim),
  727                                       SIM_CHANNEL(ahc, sim), &ccb->cts);
  728                 xpt_done(ccb);
  729                 break;
  730         }
  731         case XPT_CALC_GEOMETRY:
  732         {
  733                 int extended;
  734 
  735                 extended = SIM_IS_SCSIBUS_B(ahc, sim)
  736                          ? ahc->flags & AHC_EXTENDED_TRANS_B
  737                          : ahc->flags & AHC_EXTENDED_TRANS_A;
  738                 aic_calc_geometry(&ccb->ccg, extended);
  739                 xpt_done(ccb);
  740                 break;
  741         }
  742         case XPT_RESET_BUS:             /* Reset the specified SCSI bus */
  743         {
  744                 int  found;
  745                 
  746                 found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim),
  747                                           /*initiate reset*/TRUE);
  748                 if (bootverbose) {
  749                         xpt_print_path(SIM_PATH(ahc, sim));
  750                         printf("SCSI bus reset delivered. "
  751                                "%d SCBs aborted.\n", found);
  752                 }
  753                 ccb->ccb_h.status = CAM_REQ_CMP;
  754                 xpt_done(ccb);
  755                 break;
  756         }
  757         case XPT_TERM_IO:               /* Terminate the I/O process */
  758                 /* XXX Implement */
  759                 ccb->ccb_h.status = CAM_REQ_INVALID;
  760                 xpt_done(ccb);
  761                 break;
  762         case XPT_PATH_INQ:              /* Path routing inquiry */
  763         {
  764                 struct ccb_pathinq *cpi = &ccb->cpi;
  765                 
  766                 cpi->version_num = 1; /* XXX??? */
  767                 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
  768                 if ((ahc->features & AHC_WIDE) != 0)
  769                         cpi->hba_inquiry |= PI_WIDE_16;
  770                 if ((ahc->features & AHC_TARGETMODE) != 0) {
  771                         cpi->target_sprt = PIT_PROCESSOR
  772                                          | PIT_DISCONNECT
  773                                          | PIT_TERM_IO;
  774                 } else {
  775                         cpi->target_sprt = 0;
  776                 }
  777                 cpi->hba_misc = 0;
  778                 cpi->hba_eng_cnt = 0;
  779                 cpi->max_target = (ahc->features & AHC_WIDE) ? 15 : 7;
  780                 cpi->max_lun = AHC_NUM_LUNS - 1;
  781                 if (SIM_IS_SCSIBUS_B(ahc, sim)) {
  782                         cpi->initiator_id = ahc->our_id_b;
  783                         if ((ahc->flags & AHC_RESET_BUS_B) == 0)
  784                                 cpi->hba_misc |= PIM_NOBUSRESET;
  785                 } else {
  786                         cpi->initiator_id = ahc->our_id;
  787                         if ((ahc->flags & AHC_RESET_BUS_A) == 0)
  788                                 cpi->hba_misc |= PIM_NOBUSRESET;
  789                 }
  790                 cpi->bus_id = cam_sim_bus(sim);
  791                 cpi->base_transfer_speed = 3300;
  792                 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
  793                 strlcpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
  794                 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
  795                 cpi->unit_number = cam_sim_unit(sim);
  796                 cpi->protocol = PROTO_SCSI;
  797                 cpi->protocol_version = SCSI_REV_2;
  798                 cpi->transport = XPORT_SPI;
  799                 cpi->transport_version = 2;
  800                 cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_ST;
  801                 if ((ahc->features & AHC_DT) != 0) {
  802                         cpi->transport_version = 3;
  803                         cpi->xport_specific.spi.ppr_options =
  804                             SID_SPI_CLOCK_DT_ST;
  805                 }
  806                 cpi->ccb_h.status = CAM_REQ_CMP;
  807                 xpt_done(ccb);
  808                 break;
  809         }
  810         default:
  811                 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
  812                 xpt_done(ccb);
  813                 break;
  814         }
  815 }
  816 
  817 static void
  818 ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
  819                       struct ccb_trans_settings *cts)
  820 {
  821         struct  ahc_devinfo devinfo;
  822         struct  ccb_trans_settings_scsi *scsi;
  823         struct  ccb_trans_settings_spi *spi;
  824         struct  ahc_initiator_tinfo *targ_info;
  825         struct  ahc_tmode_tstate *tstate;
  826         struct  ahc_transinfo *tinfo;
  827 
  828         scsi = &cts->proto_specific.scsi;
  829         spi = &cts->xport_specific.spi;
  830         ahc_compile_devinfo(&devinfo, our_id,
  831                             cts->ccb_h.target_id,
  832                             cts->ccb_h.target_lun,
  833                             channel, ROLE_UNKNOWN);
  834         targ_info = ahc_fetch_transinfo(ahc, devinfo.channel,
  835                                         devinfo.our_scsiid,
  836                                         devinfo.target, &tstate);
  837 
  838         if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
  839                 tinfo = &targ_info->curr;
  840         else
  841                 tinfo = &targ_info->user;
  842 
  843         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
  844         spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
  845         if (cts->type == CTS_TYPE_USER_SETTINGS) {
  846                 if ((ahc->user_discenable & devinfo.target_mask) != 0)
  847                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
  848 
  849                 if ((ahc->user_tagenable & devinfo.target_mask) != 0)
  850                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
  851         } else {
  852                 if ((tstate->discenable & devinfo.target_mask) != 0)
  853                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
  854 
  855                 if ((tstate->tagenable & devinfo.target_mask) != 0)
  856                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
  857         }
  858         cts->protocol_version = tinfo->protocol_version;
  859         cts->transport_version = tinfo->transport_version;
  860 
  861         spi->sync_period = tinfo->period;
  862         spi->sync_offset = tinfo->offset;
  863         spi->bus_width = tinfo->width;
  864         spi->ppr_options = tinfo->ppr_options;
  865 
  866         cts->protocol = PROTO_SCSI;
  867         cts->transport = XPORT_SPI;
  868         spi->valid = CTS_SPI_VALID_SYNC_RATE
  869                    | CTS_SPI_VALID_SYNC_OFFSET
  870                    | CTS_SPI_VALID_BUS_WIDTH
  871                    | CTS_SPI_VALID_PPR_OPTIONS;
  872 
  873         if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
  874                 scsi->valid = CTS_SCSI_VALID_TQ;
  875                 spi->valid |= CTS_SPI_VALID_DISC;
  876         } else {
  877                 scsi->valid = 0;
  878         }
  879 
  880         cts->ccb_h.status = CAM_REQ_CMP;
  881 }
  882 
  883 static void
  884 ahc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
  885 {
  886         struct ahc_softc *ahc;
  887         struct cam_sim *sim;
  888 
  889         sim = (struct cam_sim *)callback_arg;
  890         ahc = (struct ahc_softc *)cam_sim_softc(sim);
  891         switch (code) {
  892         case AC_LOST_DEVICE:
  893         {
  894                 struct  ahc_devinfo devinfo;
  895 
  896                 ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim),
  897                                     xpt_path_target_id(path),
  898                                     xpt_path_lun_id(path),
  899                                     SIM_CHANNEL(ahc, sim),
  900                                     ROLE_UNKNOWN);
  901 
  902                 /*
  903                  * Revert to async/narrow transfers
  904                  * for the next device.
  905                  */
  906                 ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
  907                               AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE);
  908                 ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL,
  909                                  /*period*/0, /*offset*/0, /*ppr_options*/0,
  910                                  AHC_TRANS_GOAL|AHC_TRANS_CUR,
  911                                  /*paused*/FALSE);
  912                 break;
  913         }
  914         default:
  915                 break;
  916         }
  917 }
  918 
  919 static void
  920 ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
  921                 int error)
  922 {
  923         struct  scb *scb;
  924         union   ccb *ccb;
  925         struct  ahc_softc *ahc;
  926         struct  ahc_initiator_tinfo *tinfo;
  927         struct  ahc_tmode_tstate *tstate;
  928         u_int   mask;
  929 
  930         scb = (struct scb *)arg;
  931         ccb = scb->io_ctx;
  932         ahc = scb->ahc_softc;
  933 
  934         if (error != 0) {
  935                 if (error == EFBIG)
  936                         aic_set_transaction_status(scb, CAM_REQ_TOO_BIG);
  937                 else
  938                         aic_set_transaction_status(scb, CAM_REQ_CMP_ERR);
  939                 if (nsegments != 0)
  940                         bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
  941                 ahc_free_scb(ahc, scb);
  942                 xpt_done(ccb);
  943                 return;
  944         }
  945         if (nsegments != 0) {
  946                 struct    ahc_dma_seg *sg;
  947                 bus_dma_segment_t *end_seg;
  948                 bus_dmasync_op_t op;
  949 
  950                 end_seg = dm_segs + nsegments;
  951 
  952                 /* Copy the segments into our SG list */
  953                 sg = scb->sg_list;
  954                 while (dm_segs < end_seg) {
  955                         uint32_t len;
  956 
  957                         sg->addr = aic_htole32(dm_segs->ds_addr);
  958                         len = dm_segs->ds_len
  959                             | ((dm_segs->ds_addr >> 8) & 0x7F000000);
  960                         sg->len = aic_htole32(len);
  961                         sg++;
  962                         dm_segs++;
  963                 }
  964                 
  965                 /*
  966                  * Note where to find the SG entries in bus space.
  967                  * We also set the full residual flag which the 
  968                  * sequencer will clear as soon as a data transfer
  969                  * occurs.
  970                  */
  971                 scb->hscb->sgptr = aic_htole32(scb->sg_list_phys|SG_FULL_RESID);
  972 
  973                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
  974                         op = BUS_DMASYNC_PREREAD;
  975                 else
  976                         op = BUS_DMASYNC_PREWRITE;
  977 
  978                 bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op);
  979 
  980                 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
  981                         struct target_data *tdata;
  982 
  983                         tdata = &scb->hscb->shared_data.tdata;
  984                         tdata->target_phases |= DPHASE_PENDING;
  985                         /*
  986                          * CAM data direction is relative to the initiator.
  987                          */
  988                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
  989                                 tdata->data_phase = P_DATAOUT;
  990                         else
  991                                 tdata->data_phase = P_DATAIN;
  992 
  993                         /*
  994                          * If the transfer is of an odd length and in the
  995                          * "in" direction (scsi->HostBus), then it may
  996                          * trigger a bug in the 'WideODD' feature of
  997                          * non-Ultra2 chips.  Force the total data-length
  998                          * to be even by adding an extra, 1 byte, SG,
  999                          * element.  We do this even if we are not currently
 1000                          * negotiated wide as negotiation could occur before
 1001                          * this command is executed.
 1002                          */
 1003                         if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0
 1004                          && (ccb->csio.dxfer_len & 0x1) != 0
 1005                          && (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
 1006                                 nsegments++;
 1007                                 if (nsegments > AHC_NSEG) {
 1008                                         aic_set_transaction_status(scb,
 1009                                             CAM_REQ_TOO_BIG);
 1010                                         bus_dmamap_unload(ahc->buffer_dmat,
 1011                                                           scb->dmamap);
 1012                                         ahc_free_scb(ahc, scb);
 1013                                         xpt_done(ccb);
 1014                                         return;
 1015                                 }
 1016                                 sg->addr = aic_htole32(ahc->dma_bug_buf);
 1017                                 sg->len = aic_htole32(1);
 1018                                 sg++;
 1019                         }
 1020                 }
 1021                 sg--;
 1022                 sg->len |= aic_htole32(AHC_DMA_LAST_SEG);
 1023 
 1024                 /* Copy the first SG into the "current" data pointer area */
 1025                 scb->hscb->dataptr = scb->sg_list->addr;
 1026                 scb->hscb->datacnt = scb->sg_list->len;
 1027         } else {
 1028                 scb->hscb->sgptr = aic_htole32(SG_LIST_NULL);
 1029                 scb->hscb->dataptr = 0;
 1030                 scb->hscb->datacnt = 0;
 1031         }
 1032 
 1033         scb->sg_count = nsegments;
 1034 
 1035         /*
 1036          * Last time we need to check if this SCB needs to
 1037          * be aborted.
 1038          */
 1039         if (aic_get_transaction_status(scb) != CAM_REQ_INPROG) {
 1040                 if (nsegments != 0)
 1041                         bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
 1042                 ahc_free_scb(ahc, scb);
 1043                 xpt_done(ccb);
 1044                 return;
 1045         }
 1046 
 1047         tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid),
 1048                                     SCSIID_OUR_ID(scb->hscb->scsiid),
 1049                                     SCSIID_TARGET(ahc, scb->hscb->scsiid),
 1050                                     &tstate);
 1051 
 1052         mask = SCB_GET_TARGET_MASK(ahc, scb);
 1053         scb->hscb->scsirate = tinfo->scsirate;
 1054         scb->hscb->scsioffset = tinfo->curr.offset;
 1055         if ((tstate->ultraenb & mask) != 0)
 1056                 scb->hscb->control |= ULTRAENB;
 1057 
 1058         if ((tstate->discenable & mask) != 0
 1059          && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
 1060                 scb->hscb->control |= DISCENB;
 1061 
 1062         if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0
 1063          && (tinfo->goal.width != 0
 1064           || tinfo->goal.offset != 0
 1065           || tinfo->goal.ppr_options != 0)) {
 1066                 scb->flags |= SCB_NEGOTIATE;
 1067                 scb->hscb->control |= MK_MESSAGE;
 1068         } else if ((tstate->auto_negotiate & mask) != 0) {
 1069                 scb->flags |= SCB_AUTO_NEGOTIATE;
 1070                 scb->hscb->control |= MK_MESSAGE;
 1071         }
 1072 
 1073         LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
 1074 
 1075         ccb->ccb_h.status |= CAM_SIM_QUEUED;
 1076 
 1077         /*
 1078          * We only allow one untagged transaction
 1079          * per target in the initiator role unless
 1080          * we are storing a full busy target *lun*
 1081          * table in SCB space.
 1082          */
 1083         if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0
 1084          && (ahc->flags & AHC_SCB_BTT) == 0) {
 1085                 struct scb_tailq *untagged_q;
 1086                 int target_offset;
 1087 
 1088                 target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
 1089                 untagged_q = &(ahc->untagged_queues[target_offset]);
 1090                 TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
 1091                 scb->flags |= SCB_UNTAGGEDQ;
 1092                 if (TAILQ_FIRST(untagged_q) != scb) {
 1093                         return;
 1094                 }
 1095         }
 1096         scb->flags |= SCB_ACTIVE;
 1097 
 1098         /*
 1099          * Timers are disabled while recovery is in progress.
 1100          */
 1101         aic_scb_timer_start(scb);
 1102 
 1103         if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
 1104                 /* Define a mapping from our tag to the SCB. */
 1105                 ahc->scb_data->scbindex[scb->hscb->tag] = scb;
 1106                 ahc_pause(ahc);
 1107                 if ((ahc->flags & AHC_PAGESCBS) == 0)
 1108                         ahc_outb(ahc, SCBPTR, scb->hscb->tag);
 1109                 ahc_outb(ahc, TARG_IMMEDIATE_SCB, scb->hscb->tag);
 1110                 ahc_unpause(ahc);
 1111         } else {
 1112                 ahc_queue_scb(ahc, scb);
 1113         }
 1114 }
 1115 
 1116 static void
 1117 ahc_poll(struct cam_sim *sim)
 1118 {
 1119         struct ahc_softc *ahc;
 1120 
 1121         ahc = (struct ahc_softc *)cam_sim_softc(sim);
 1122         ahc_intr(ahc);
 1123 }
 1124 
 1125 static void
 1126 ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim,
 1127                struct ccb_scsiio *csio, struct scb *scb)
 1128 {
 1129         struct hardware_scb *hscb;
 1130         struct ccb_hdr *ccb_h;
 1131         int error;
 1132 
 1133         hscb = scb->hscb;
 1134         ccb_h = &csio->ccb_h;
 1135 
 1136         csio->resid = 0;
 1137         csio->sense_resid = 0;
 1138         if (ccb_h->func_code == XPT_SCSI_IO) {
 1139                 hscb->cdb_len = csio->cdb_len;
 1140                 if ((ccb_h->flags & CAM_CDB_POINTER) != 0) {
 1141                         if (hscb->cdb_len > sizeof(hscb->cdb32)
 1142                          || (ccb_h->flags & CAM_CDB_PHYS) != 0) {
 1143                                 aic_set_transaction_status(scb,
 1144                                                            CAM_REQ_INVALID);
 1145                                 ahc_free_scb(ahc, scb);
 1146                                 xpt_done((union ccb *)csio);
 1147                                 return;
 1148                         }
 1149                         if (hscb->cdb_len > 12) {
 1150                                 memcpy(hscb->cdb32, 
 1151                                        csio->cdb_io.cdb_ptr,
 1152                                        hscb->cdb_len);
 1153                                 scb->flags |= SCB_CDB32_PTR;
 1154                         } else {
 1155                                 memcpy(hscb->shared_data.cdb, 
 1156                                        csio->cdb_io.cdb_ptr,
 1157                                        hscb->cdb_len);
 1158                         }
 1159                 } else {
 1160                         if (hscb->cdb_len > 12) {
 1161                                 memcpy(hscb->cdb32, csio->cdb_io.cdb_bytes,
 1162                                        hscb->cdb_len);
 1163                                 scb->flags |= SCB_CDB32_PTR;
 1164                         } else {
 1165                                 memcpy(hscb->shared_data.cdb,
 1166                                        csio->cdb_io.cdb_bytes,
 1167                                        hscb->cdb_len);
 1168                         }
 1169                 }
 1170         }
 1171                 
 1172         error = bus_dmamap_load_ccb(ahc->buffer_dmat,
 1173                                     scb->dmamap,
 1174                                     (union ccb *)csio,
 1175                                     ahc_execute_scb,
 1176                                     scb,
 1177                                     0);
 1178         if (error == EINPROGRESS) {
 1179                 /*
 1180                  * So as to maintain ordering,
 1181                  * freeze the controller queue
 1182                  * until our mapping is
 1183                  * returned.
 1184                  */
 1185                 xpt_freeze_simq(sim, /*count*/1);
 1186                 scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ;
 1187         }
 1188 }
 1189 
 1190 static void
 1191 ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 1192 {
 1193         union ccb *abort_ccb;
 1194 
 1195         abort_ccb = ccb->cab.abort_ccb;
 1196         switch (abort_ccb->ccb_h.func_code) {
 1197         case XPT_ACCEPT_TARGET_IO:
 1198         case XPT_IMMEDIATE_NOTIFY:
 1199         case XPT_CONT_TARGET_IO:
 1200         {
 1201                 struct ahc_tmode_tstate *tstate;
 1202                 struct ahc_tmode_lstate *lstate;
 1203                 struct ccb_hdr_slist *list;
 1204                 cam_status status;
 1205 
 1206                 status = ahc_find_tmode_devs(ahc, sim, abort_ccb, &tstate,
 1207                                              &lstate, TRUE);
 1208 
 1209                 if (status != CAM_REQ_CMP) {
 1210                         ccb->ccb_h.status = status;
 1211                         break;
 1212                 }
 1213 
 1214                 if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO)
 1215                         list = &lstate->accept_tios;
 1216                 else if (abort_ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY)
 1217                         list = &lstate->immed_notifies;
 1218                 else
 1219                         list = NULL;
 1220 
 1221                 if (list != NULL) {
 1222                         struct ccb_hdr *curelm;
 1223                         int found;
 1224 
 1225                         curelm = SLIST_FIRST(list);
 1226                         found = 0;
 1227                         if (curelm == &abort_ccb->ccb_h) {
 1228                                 found = 1;
 1229                                 SLIST_REMOVE_HEAD(list, sim_links.sle);
 1230                         } else {
 1231                                 while(curelm != NULL) {
 1232                                         struct ccb_hdr *nextelm;
 1233 
 1234                                         nextelm =
 1235                                             SLIST_NEXT(curelm, sim_links.sle);
 1236 
 1237                                         if (nextelm == &abort_ccb->ccb_h) {
 1238                                                 found = 1;
 1239                                                 SLIST_NEXT(curelm,
 1240                                                            sim_links.sle) =
 1241                                                     SLIST_NEXT(nextelm,
 1242                                                                sim_links.sle);
 1243                                                 break;
 1244                                         }
 1245                                         curelm = nextelm;
 1246                                 }
 1247                         }
 1248 
 1249                         if (found) {
 1250                                 abort_ccb->ccb_h.status = CAM_REQ_ABORTED;
 1251                                 xpt_done(abort_ccb);
 1252                                 ccb->ccb_h.status = CAM_REQ_CMP;
 1253                         } else {
 1254                                 xpt_print_path(abort_ccb->ccb_h.path);
 1255                                 printf("Not found\n");
 1256                                 ccb->ccb_h.status = CAM_PATH_INVALID;
 1257                         }
 1258                         break;
 1259                 }
 1260                 /* FALLTHROUGH */
 1261         }
 1262         case XPT_SCSI_IO:
 1263                 /* XXX Fully implement the hard ones */
 1264                 ccb->ccb_h.status = CAM_UA_ABORT;
 1265                 break;
 1266         default:
 1267                 ccb->ccb_h.status = CAM_REQ_INVALID;
 1268                 break;
 1269         }
 1270         xpt_done(ccb);
 1271 }
 1272 
 1273 void
 1274 ahc_send_async(struct ahc_softc *ahc, char channel, u_int target,
 1275                 u_int lun, ac_code code, void *opt_arg)
 1276 {
 1277         struct  ccb_trans_settings cts;
 1278         struct cam_path *path;
 1279         void *arg;
 1280         int error;
 1281 
 1282         arg = NULL;
 1283         error = ahc_create_path(ahc, channel, target, lun, &path);
 1284 
 1285         if (error != CAM_REQ_CMP)
 1286                 return;
 1287 
 1288         switch (code) {
 1289         case AC_TRANSFER_NEG:
 1290         {
 1291                 struct  ccb_trans_settings_scsi *scsi;
 1292 
 1293                 cts.type = CTS_TYPE_CURRENT_SETTINGS;
 1294                 scsi = &cts.proto_specific.scsi;
 1295                 cts.ccb_h.path = path;
 1296                 cts.ccb_h.target_id = target;
 1297                 cts.ccb_h.target_lun = lun;
 1298                 ahc_get_tran_settings(ahc, channel == 'A' ? ahc->our_id
 1299                                                           : ahc->our_id_b,
 1300                                       channel, &cts);
 1301                 arg = &cts;
 1302                 scsi->valid &= ~CTS_SCSI_VALID_TQ;
 1303                 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
 1304                 if (opt_arg == NULL)
 1305                         break;
 1306                 if (*((ahc_queue_alg *)opt_arg) == AHC_QUEUE_TAGGED)
 1307                         scsi->flags |= ~CTS_SCSI_FLAGS_TAG_ENB;
 1308                 scsi->valid |= CTS_SCSI_VALID_TQ;
 1309                 break;
 1310         }
 1311         case AC_SENT_BDR:
 1312         case AC_BUS_RESET:
 1313                 break;
 1314         default:
 1315                 panic("ahc_send_async: Unexpected async event");
 1316         }
 1317         xpt_async(code, path, arg);
 1318         xpt_free_path(path);
 1319 }
 1320 
 1321 void
 1322 ahc_platform_set_tags(struct ahc_softc *ahc,
 1323                       struct ahc_devinfo *devinfo, int enable)
 1324 {
 1325 }
 1326 
 1327 int
 1328 ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
 1329 {
 1330         ahc->platform_data = malloc(sizeof(struct ahc_platform_data), M_DEVBUF,
 1331             M_NOWAIT | M_ZERO);
 1332         if (ahc->platform_data == NULL)
 1333                 return (ENOMEM);
 1334         return (0);
 1335 }
 1336 
 1337 void
 1338 ahc_platform_free(struct ahc_softc *ahc)
 1339 {
 1340         struct ahc_platform_data *pdata;
 1341 
 1342         pdata = ahc->platform_data;
 1343         if (pdata != NULL) {
 1344                 if (pdata->regs != NULL)
 1345                         bus_release_resource(ahc->dev_softc,
 1346                                              pdata->regs_res_type,
 1347                                              pdata->regs_res_id,
 1348                                              pdata->regs);
 1349 
 1350                 if (pdata->irq != NULL)
 1351                         bus_release_resource(ahc->dev_softc,
 1352                                              pdata->irq_res_type,
 1353                                              0, pdata->irq);
 1354 
 1355                 if (pdata->sim_b != NULL) {
 1356                         xpt_async(AC_LOST_DEVICE, pdata->path_b, NULL);
 1357                         xpt_free_path(pdata->path_b);
 1358                         xpt_bus_deregister(cam_sim_path(pdata->sim_b));
 1359                         cam_sim_free(pdata->sim_b, /*free_devq*/TRUE);
 1360                 }
 1361                 if (pdata->sim != NULL) {
 1362                         xpt_async(AC_LOST_DEVICE, pdata->path, NULL);
 1363                         xpt_free_path(pdata->path);
 1364                         xpt_bus_deregister(cam_sim_path(pdata->sim));
 1365                         cam_sim_free(pdata->sim, /*free_devq*/TRUE);
 1366                 }
 1367                 if (pdata->eh != NULL)
 1368                         EVENTHANDLER_DEREGISTER(shutdown_final, pdata->eh);
 1369                 free(ahc->platform_data, M_DEVBUF);
 1370         }
 1371 }
 1372 
 1373 int
 1374 ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc)
 1375 {
 1376         /* We don't sort softcs under FreeBSD so report equal always */
 1377         return (0);
 1378 }
 1379 
 1380 int
 1381 ahc_detach(device_t dev)
 1382 {
 1383         struct ahc_softc *ahc;
 1384 
 1385         device_printf(dev, "detaching device\n");
 1386         ahc = device_get_softc(dev);
 1387         ahc_lock(ahc);
 1388         TAILQ_REMOVE(&ahc_tailq, ahc, links);
 1389         ahc_intr_enable(ahc, FALSE);
 1390         bus_teardown_intr(dev, ahc->platform_data->irq, ahc->platform_data->ih);
 1391         ahc_unlock(ahc);
 1392         ahc_free(ahc);
 1393         return (0);
 1394 }
 1395 
 1396 #if 0
 1397 static void
 1398 ahc_dump_targcmd(struct target_cmd *cmd)
 1399 {
 1400         uint8_t *byte;
 1401         uint8_t *last_byte;
 1402         int i;
 1403 
 1404         byte = &cmd->initiator_channel;
 1405         /* Debugging info for received commands */
 1406         last_byte = &cmd[1].initiator_channel;
 1407 
 1408         i = 0;
 1409         while (byte < last_byte) {
 1410                 if (i == 0)
 1411                         printf("\t");
 1412                 printf("%#x", *byte++);
 1413                 i++;
 1414                 if (i == 8) {
 1415                         printf("\n");
 1416                         i = 0;
 1417                 } else {
 1418                         printf(", ");
 1419                 }
 1420         }
 1421 }
 1422 #endif
 1423 
 1424 static int
 1425 ahc_modevent(module_t mod, int type, void *data)
 1426 {
 1427         /* XXX Deal with busy status on unload. */
 1428         /* XXX Deal with unknown events */
 1429         return 0;
 1430 }
 1431   
 1432 static moduledata_t ahc_mod = {
 1433         "ahc",
 1434         ahc_modevent,
 1435         NULL
 1436 };
 1437 
 1438 DECLARE_MODULE(ahc, ahc_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
 1439 MODULE_DEPEND(ahc, cam, 1, 1, 1);
 1440 MODULE_VERSION(ahc, 1);

Cache object: 94f5dfc7e5051762363524f837c36070


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.