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/aic/aic.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999 Luoqi Chen.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/9.1/sys/dev/aic/aic.c 192066 2009-05-13 22:31:25Z des $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/lock.h>
   34 #include <sys/mutex.h>
   35 #include <sys/malloc.h>
   36 #include <sys/bus.h>
   37 
   38 #include <machine/bus.h>
   39 
   40 #include <cam/cam.h>
   41 #include <cam/cam_ccb.h>
   42 #include <cam/cam_sim.h>
   43 #include <cam/cam_xpt_sim.h>
   44 #include <cam/cam_debug.h>
   45 
   46 #include <cam/scsi/scsi_message.h>
   47 
   48 #include <dev/aic/aic6360reg.h>
   49 #include <dev/aic/aicvar.h>
   50 
   51 static void aic_action(struct cam_sim *sim, union ccb *ccb);
   52 static void aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
   53                                 int nseg, int error);
   54 static void aic_start(struct aic_softc *aic);
   55 static void aic_select(struct aic_softc *aic);
   56 static void aic_selected(struct aic_softc *aic);
   57 static void aic_reselected(struct aic_softc *aic);
   58 static void aic_reconnect(struct aic_softc *aic, int tag);
   59 static void aic_cmd(struct aic_softc *aic);
   60 static void aic_msgin(struct aic_softc *aic);
   61 static void aic_handle_msgin(struct aic_softc *aic);
   62 static void aic_msgout(struct aic_softc *aic);
   63 static void aic_datain(struct aic_softc *aic);
   64 static void aic_dataout(struct aic_softc *aic);
   65 static void aic_done(struct aic_softc *aic, struct aic_scb *scb);
   66 static void aic_poll(struct cam_sim *sim);
   67 static void aic_timeout(void *arg);
   68 static void aic_scsi_reset(struct aic_softc *aic);
   69 static void aic_chip_reset(struct aic_softc *aic);
   70 static void aic_reset(struct aic_softc *aic, int initiate_reset);
   71 
   72 devclass_t aic_devclass;
   73 
   74 static struct aic_scb *free_scbs;
   75 
   76 static struct aic_scb *
   77 aic_get_scb(struct aic_softc *aic)
   78 {
   79         struct aic_scb *scb;
   80         int s = splcam();
   81         if ((scb = free_scbs) != NULL)
   82                 free_scbs = (struct aic_scb *)free_scbs->ccb;
   83         splx(s);
   84         return (scb);
   85 }
   86 
   87 static void
   88 aic_free_scb(struct aic_softc *aic, struct aic_scb *scb)
   89 {
   90         int s = splcam();
   91         if ((aic->flags & AIC_RESOURCE_SHORTAGE) != 0 &&
   92             (scb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
   93                 scb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
   94                 aic->flags &= ~AIC_RESOURCE_SHORTAGE;
   95         }
   96         scb->flags = 0;
   97         scb->ccb = (union ccb *)free_scbs;
   98         free_scbs = scb;
   99         splx(s);
  100 }
  101 
  102 static void
  103 aic_action(struct cam_sim *sim, union ccb *ccb)
  104 {
  105         struct aic_softc *aic;
  106         int s;
  107 
  108         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("aic_action\n"));
  109 
  110         aic = (struct aic_softc *)cam_sim_softc(sim);
  111 
  112         switch (ccb->ccb_h.func_code) {
  113         case XPT_SCSI_IO:       /* Execute the requested I/O operation */
  114         case XPT_RESET_DEV:     /* Bus Device Reset the specified SCSI device */
  115         {               
  116                 struct aic_scb *scb;
  117 
  118                 if ((scb = aic_get_scb(aic)) == NULL) {
  119                         s = splcam();
  120                         aic->flags |= AIC_RESOURCE_SHORTAGE;
  121                         splx(s);
  122                         xpt_freeze_simq(aic->sim, /*count*/1);
  123                         ccb->ccb_h.status = CAM_REQUEUE_REQ;
  124                         xpt_done(ccb);
  125                         return;
  126                 }
  127 
  128                 scb->ccb = ccb;
  129                 ccb->ccb_h.ccb_scb_ptr = scb;
  130                 ccb->ccb_h.ccb_aic_ptr = aic;
  131 
  132                 scb->target = ccb->ccb_h.target_id;
  133                 scb->lun = ccb->ccb_h.target_lun;
  134 
  135                 if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
  136                         scb->cmd_len = ccb->csio.cdb_len;
  137                         if (ccb->ccb_h.flags & CAM_CDB_POINTER) {
  138                                 if (ccb->ccb_h.flags & CAM_CDB_PHYS) {
  139                                         ccb->ccb_h.status = CAM_REQ_INVALID;
  140                                         aic_free_scb(aic, scb);
  141                                         xpt_done(ccb);
  142                                         return;
  143                                 }
  144                                 scb->cmd_ptr = ccb->csio.cdb_io.cdb_ptr;
  145                         } else {
  146                                 scb->cmd_ptr = ccb->csio.cdb_io.cdb_bytes;
  147                         }
  148                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
  149                                 if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) ||
  150                                     (ccb->ccb_h.flags & CAM_DATA_PHYS)) {
  151                                         ccb->ccb_h.status = CAM_REQ_INVALID;
  152                                         aic_free_scb(aic, scb);
  153                                         xpt_done(ccb);
  154                                         return;
  155                                 }
  156                                 scb->data_ptr = ccb->csio.data_ptr;
  157                                 scb->data_len = ccb->csio.dxfer_len;
  158                         } else {
  159                                 scb->data_ptr = NULL;
  160                                 scb->data_len = 0;
  161                         }
  162                         aic_execute_scb(scb, NULL, 0, 0);
  163                 } else {
  164                         scb->flags |= SCB_DEVICE_RESET;
  165                         aic_execute_scb(scb, NULL, 0, 0);
  166                 }
  167                 break;
  168         }
  169         case XPT_SET_TRAN_SETTINGS:
  170         {
  171                 struct ccb_trans_settings *cts = &ccb->cts;
  172                 struct aic_tinfo *ti = &aic->tinfo[ccb->ccb_h.target_id];
  173                 struct ccb_trans_settings_scsi *scsi =
  174                     &cts->proto_specific.scsi;
  175                 struct ccb_trans_settings_spi *spi =
  176                     &cts->xport_specific.spi;
  177 
  178                 s = splcam();
  179 
  180                 if ((spi->valid & CTS_SPI_VALID_DISC) != 0 &&
  181                     (aic->flags & AIC_DISC_ENABLE) != 0) {
  182                         if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
  183                                 ti->flags |= TINFO_DISC_ENB;
  184                         else
  185                                 ti->flags &= ~TINFO_DISC_ENB;
  186                 }
  187 
  188                 if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
  189                         if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
  190                                 ti->flags |= TINFO_TAG_ENB;
  191                         else
  192                                 ti->flags &= ~TINFO_TAG_ENB;
  193                 }
  194 
  195                 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
  196                         ti->goal.period = spi->sync_period;
  197 
  198                         if (ti->goal.period > aic->min_period) {
  199                                 ti->goal.period = 0;
  200                                 ti->goal.offset = 0;
  201                         } else if (ti->goal.period < aic->max_period)
  202                                 ti->goal.period = aic->max_period;
  203                 }
  204 
  205                 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) {
  206                         ti->goal.offset = spi->sync_offset;
  207                         if (ti->goal.offset == 0)
  208                                 ti->goal.period = 0;
  209                         else if (ti->goal.offset > AIC_SYNC_OFFSET)
  210                                 ti->goal.offset = AIC_SYNC_OFFSET;
  211                 }
  212 
  213                 if ((ti->goal.period != ti->current.period)
  214                  || (ti->goal.offset != ti->current.offset))
  215                         ti->flags |= TINFO_SDTR_NEGO;
  216 
  217                 splx(s);
  218                 ccb->ccb_h.status = CAM_REQ_CMP;
  219                 xpt_done(ccb);
  220                 break;
  221         }
  222         case XPT_GET_TRAN_SETTINGS:
  223         {
  224                 struct ccb_trans_settings *cts = &ccb->cts;
  225                 struct aic_tinfo *ti = &aic->tinfo[ccb->ccb_h.target_id];
  226                 struct ccb_trans_settings_scsi *scsi =
  227                     &cts->proto_specific.scsi;
  228                 struct ccb_trans_settings_spi *spi =
  229                     &cts->xport_specific.spi;
  230 
  231                 cts->protocol = PROTO_SCSI;
  232                 cts->protocol_version = SCSI_REV_2;
  233                 cts->transport = XPORT_SPI;
  234                 cts->transport_version = 2;
  235                 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
  236                 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
  237 
  238                 s = splcam();
  239                 if ((ti->flags & TINFO_DISC_ENB) != 0)
  240                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
  241                 if ((ti->flags & TINFO_TAG_ENB) != 0)
  242                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
  243 
  244                 if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
  245                         spi->sync_period = ti->current.period;
  246                         spi->sync_offset = ti->current.offset;
  247                 } else {
  248                         spi->sync_period = ti->user.period;
  249                         spi->sync_offset = ti->user.offset;
  250                 }
  251                 splx(s);
  252 
  253                 spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
  254                 spi->valid = CTS_SPI_VALID_SYNC_RATE
  255                            | CTS_SPI_VALID_SYNC_OFFSET
  256                            | CTS_SPI_VALID_BUS_WIDTH
  257                            | CTS_SPI_VALID_DISC;
  258                 scsi->valid = CTS_SCSI_VALID_TQ;
  259 
  260                 ccb->ccb_h.status = CAM_REQ_CMP;
  261                 xpt_done(ccb);
  262                 break;
  263         }
  264         case XPT_CALC_GEOMETRY:
  265         {
  266                 cam_calc_geometry(&ccb->ccg, /*extended*/1);
  267                 xpt_done(ccb);
  268                 break;
  269         }
  270         case XPT_RESET_BUS:             /* Reset the specified SCSI bus */
  271                 aic_reset(aic, /*initiate_reset*/TRUE);
  272                 ccb->ccb_h.status = CAM_REQ_CMP;
  273                 xpt_done(ccb);
  274                 break;
  275         case XPT_PATH_INQ:              /* Path routing inquiry */
  276         {       
  277                 struct ccb_pathinq *cpi = &ccb->cpi;
  278 
  279                 cpi->version_num = 1; /* XXX??? */
  280                 cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
  281                 cpi->target_sprt = 0;
  282                 cpi->hba_misc = 0;
  283                 cpi->hba_eng_cnt = 0;
  284                 cpi->max_target = 7;
  285                 cpi->max_lun = 7;
  286                 cpi->initiator_id = aic->initiator;
  287                 cpi->bus_id = cam_sim_bus(sim);
  288                 cpi->base_transfer_speed = 3300;
  289                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
  290                 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
  291                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
  292                 cpi->unit_number = cam_sim_unit(sim);
  293                 cpi->transport = XPORT_SPI;
  294                 cpi->transport_version = 2;
  295                 cpi->protocol = PROTO_SCSI;
  296                 cpi->protocol_version = SCSI_REV_2;
  297                 cpi->ccb_h.status = CAM_REQ_CMP;
  298                 xpt_done(ccb);
  299                 break;
  300         }
  301         default:
  302                 ccb->ccb_h.status = CAM_REQ_INVALID;
  303                 xpt_done(ccb);
  304                 break;
  305         }
  306 }
  307 
  308 static void
  309 aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
  310 {
  311         struct aic_scb *scb = (struct aic_scb *)arg;
  312         union ccb *ccb = scb->ccb;
  313         struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr;
  314         int s;
  315 
  316         s = splcam();
  317 
  318         if (ccb->ccb_h.status != CAM_REQ_INPROG) {
  319                 splx(s);
  320                 aic_free_scb(aic, scb);
  321                 xpt_done(ccb);
  322                 return;
  323         }
  324 
  325         scb->flags |= SCB_ACTIVE;
  326         ccb->ccb_h.status |= CAM_SIM_QUEUED;
  327         TAILQ_INSERT_TAIL(&aic->pending_ccbs, &ccb->ccb_h, sim_links.tqe);
  328 
  329         ccb->ccb_h.timeout_ch = timeout(aic_timeout, (caddr_t)scb,
  330                 (ccb->ccb_h.timeout * hz) / 1000);
  331 
  332         aic_start(aic);
  333         splx(s);
  334 }
  335 
  336 /*
  337  * Start another command if the controller is not busy.
  338  */
  339 static void
  340 aic_start(struct aic_softc *aic)
  341 {
  342         struct ccb_hdr *ccb_h;
  343         struct aic_tinfo *ti;
  344 
  345         if (aic->state != AIC_IDLE)
  346                 return;
  347 
  348         TAILQ_FOREACH(ccb_h, &aic->pending_ccbs, sim_links.tqe) {
  349                 ti = &aic->tinfo[ccb_h->target_id];
  350                 if ((ti->lubusy & (1 << ccb_h->target_lun)) == 0) {
  351                         TAILQ_REMOVE(&aic->pending_ccbs, ccb_h, sim_links.tqe);
  352                         aic->nexus = (struct aic_scb *)ccb_h->ccb_scb_ptr;
  353                         aic_select(aic);
  354                         return;
  355                 }
  356         }
  357 
  358         CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_start: idle\n"));
  359 
  360         aic_outb(aic, SIMODE0, ENSELDI);
  361         aic_outb(aic, SIMODE1, ENSCSIRST);
  362         aic_outb(aic, SCSISEQ, ENRESELI);
  363 }
  364 
  365 /*
  366  * Start a selection.
  367  */
  368 static void
  369 aic_select(struct aic_softc *aic)
  370 {
  371         struct aic_scb *scb = aic->nexus;
  372 
  373         CAM_DEBUG(scb->ccb->ccb_h.path, CAM_DEBUG_TRACE,
  374                   ("aic_select - ccb %p\n", scb->ccb));
  375 
  376         aic->state = AIC_SELECTING;
  377 
  378         aic_outb(aic, DMACNTRL1, 0);
  379         aic_outb(aic, SCSIID, aic->initiator << OID_S | scb->target);
  380         aic_outb(aic, SXFRCTL1, STIMO_256ms | ENSTIMER |
  381             (aic->flags & AIC_PARITY_ENABLE ? ENSPCHK : 0));
  382 
  383         aic_outb(aic, SIMODE0, ENSELDI|ENSELDO);
  384         aic_outb(aic, SIMODE1, ENSCSIRST|ENSELTIMO);
  385         aic_outb(aic, SCSISEQ, ENRESELI|ENSELO|ENAUTOATNO);
  386 }
  387 
  388 /*
  389  * We have successfully selected a target, prepare for the information
  390  * transfer phases.
  391  */
  392 static void
  393 aic_selected(struct aic_softc *aic)
  394 {
  395         struct aic_scb *scb = aic->nexus;
  396         union ccb *ccb = scb->ccb;
  397         struct aic_tinfo *ti = &aic->tinfo[scb->target];
  398 
  399         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
  400                   ("aic_selected - ccb %p\n", ccb));
  401 
  402         aic->state = AIC_HASNEXUS;
  403 
  404         if (scb->flags & SCB_DEVICE_RESET) {
  405                 aic->msg_buf[0] = MSG_BUS_DEV_RESET;
  406                 aic->msg_len = 1;
  407                 aic->msg_outq = AIC_MSG_MSGBUF;
  408         } else {
  409                 aic->msg_outq = AIC_MSG_IDENTIFY;
  410                 if ((ti->flags & TINFO_TAG_ENB) != 0 &&
  411                     (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0)
  412                         aic->msg_outq |= AIC_MSG_TAG_Q;
  413                 else
  414                         ti->lubusy |= 1 << scb->lun;
  415                 if ((ti->flags & TINFO_SDTR_NEGO) != 0)
  416                         aic->msg_outq |= AIC_MSG_SDTR;
  417         }
  418 
  419         aic_outb(aic, CLRSINT0, CLRSELDO);
  420         aic_outb(aic, CLRSINT1, CLRBUSFREE);
  421         aic_outb(aic, SCSISEQ, ENAUTOATNP);
  422         aic_outb(aic, SIMODE0, 0);
  423         aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
  424         aic_outb(aic, SCSIRATE, ti->scsirate);
  425 }
  426 
  427 /*
  428  * We are re-selected by a target, save the target id and wait for the
  429  * target to further identify itself.
  430  */
  431 static void
  432 aic_reselected(struct aic_softc *aic)
  433 {
  434         u_int8_t selid;
  435 
  436         CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reselected\n"));
  437 
  438         /*
  439          * If we have started a selection, it must have lost out in
  440          * the arbitration, put the command back to the pending queue.
  441          */
  442         if (aic->nexus) {
  443                 TAILQ_INSERT_HEAD(&aic->pending_ccbs,
  444                     &aic->nexus->ccb->ccb_h, sim_links.tqe);
  445                 aic->nexus = NULL;
  446         }
  447 
  448         selid = aic_inb(aic, SELID) & ~(1 << aic->initiator);
  449         if (selid & (selid - 1)) {
  450                 /* this should never have happened */
  451                 printf("aic_reselected: invalid selid %x\n", selid);
  452                 aic_reset(aic, /*initiate_reset*/TRUE);
  453                 return;
  454         }
  455 
  456         aic->state = AIC_RESELECTED;
  457         aic->target = ffs(selid) - 1;
  458         aic->lun = -1;
  459 
  460         aic_outb(aic, CLRSINT0, CLRSELDI);
  461         aic_outb(aic, CLRSINT1, CLRBUSFREE);
  462         aic_outb(aic, SIMODE0, 0);
  463         aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
  464         aic_outb(aic, SCSISEQ, ENAUTOATNP);
  465         aic_outb(aic, SCSIRATE, aic->tinfo[aic->target].scsirate);
  466 }
  467 
  468 /*
  469  * Raise ATNO to signal the target that we have a message for it.
  470  */
  471 static __inline void
  472 aic_sched_msgout(struct aic_softc *aic, u_int8_t msg)
  473 {
  474         if (msg) {
  475                 aic->msg_buf[0] = msg;
  476                 aic->msg_len = 1;
  477         }
  478         aic->msg_outq |= AIC_MSG_MSGBUF;
  479         aic_outb(aic, SCSISIGO, aic_inb(aic, SCSISIGI) | ATNO);
  480 }
  481 
  482 /*
  483  * Wait for SPIORDY (SCSI PIO ready) flag, or a phase change.
  484  */
  485 static __inline int
  486 aic_spiordy(struct aic_softc *aic)
  487 {
  488         while (!(aic_inb(aic, DMASTAT) & INTSTAT) &&
  489             !(aic_inb(aic, SSTAT0) & SPIORDY))
  490                 ;
  491         return !(aic_inb(aic, DMASTAT) & INTSTAT);
  492 }
  493 
  494 /*
  495  * Reestablish a disconnected nexus.
  496  */
  497 static void
  498 aic_reconnect(struct aic_softc *aic, int tag)
  499 {
  500         struct aic_scb *scb;
  501         struct ccb_hdr *ccb_h;
  502 
  503         CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reconnect\n"));
  504 
  505         /* Find the nexus */
  506         scb = NULL;
  507         TAILQ_FOREACH(ccb_h, &aic->nexus_ccbs, sim_links.tqe) {
  508                 scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
  509                 if (scb->target == aic->target && scb->lun == aic->lun &&
  510                     (tag == -1 || scb->tag == tag))
  511                         break;
  512         }
  513 
  514         /* ABORT if nothing is found */
  515         if (!ccb_h) {
  516                 if (tag == -1)
  517                         aic_sched_msgout(aic, MSG_ABORT);
  518                 else
  519                         aic_sched_msgout(aic, MSG_ABORT_TAG);
  520                 xpt_async(AC_UNSOL_RESEL, aic->path, NULL);
  521                 return;
  522         }
  523 
  524         /* Reestablish the nexus */
  525         TAILQ_REMOVE(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
  526         aic->nexus = scb;
  527         scb->flags &= ~SCB_DISCONNECTED;
  528         aic->state = AIC_HASNEXUS;
  529 }
  530 
  531 /*
  532  * Read messages.
  533  */
  534 static void
  535 aic_msgin(struct aic_softc *aic)
  536 {
  537         int msglen;
  538 
  539         CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_msgin\n"));
  540 
  541         aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
  542         aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
  543 
  544         aic->flags &= ~AIC_DROP_MSGIN;
  545         aic->msg_len = 0;
  546         do {
  547                 /*
  548                  * If a parity error is detected, drop the remaining
  549                  * bytes and inform the target so it could resend
  550                  * the messages.
  551                  */
  552                 if (aic_inb(aic, SSTAT1) & SCSIPERR) {
  553                         aic_outb(aic, CLRSINT1, CLRSCSIPERR);
  554                         aic->flags |= AIC_DROP_MSGIN;
  555                         aic_sched_msgout(aic, MSG_PARITY_ERROR);
  556                 }
  557                 if ((aic->flags & AIC_DROP_MSGIN)) {
  558                         aic_inb(aic, SCSIDAT);
  559                         continue;
  560                 }
  561                 /* read the message byte without ACKing on it */
  562                 aic->msg_buf[aic->msg_len++] = aic_inb(aic, SCSIBUS);
  563                 if (aic->msg_buf[0] == MSG_EXTENDED) {
  564                         if (aic->msg_len < 2) {
  565                                 (void) aic_inb(aic, SCSIDAT);
  566                                 continue;
  567                         }
  568                         switch (aic->msg_buf[2]) {
  569                         case MSG_EXT_SDTR:
  570                                 msglen = MSG_EXT_SDTR_LEN;
  571                                 break;
  572                         case MSG_EXT_WDTR:
  573                                 msglen = MSG_EXT_WDTR_LEN;
  574                                 break;
  575                         default:
  576                                 msglen = 0;
  577                                 break;
  578                         }
  579                         if (aic->msg_buf[1] != msglen) {
  580                                 aic->flags |= AIC_DROP_MSGIN;
  581                                 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
  582                         }
  583                         msglen += 2;
  584                 } else if (aic->msg_buf[0] >= 0x20 && aic->msg_buf[0] <= 0x2f)
  585                         msglen = 2;
  586                 else
  587                         msglen = 1;
  588                 /*
  589                  * If we have a complete message, handle it before the final
  590                  * ACK (in case we decide to reject the message).
  591                  */
  592                 if (aic->msg_len == msglen) {
  593                         aic_handle_msgin(aic);
  594                         aic->msg_len = 0;
  595                 }
  596                 /* ACK on the message byte */
  597                 (void) aic_inb(aic, SCSIDAT);
  598         } while (aic_spiordy(aic));
  599 
  600         aic_outb(aic, SXFRCTL0, CHEN);
  601         aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
  602 }
  603 
  604 /*
  605  * Handle a message.
  606  */
  607 static void
  608 aic_handle_msgin(struct aic_softc *aic)
  609 {
  610         struct aic_scb *scb;
  611         struct ccb_hdr *ccb_h;
  612         struct aic_tinfo *ti;
  613         struct ccb_trans_settings neg;
  614         struct ccb_trans_settings_spi *spi = &neg.xport_specific.spi;
  615 
  616         if (aic->state == AIC_RESELECTED) {
  617                 if (!MSG_ISIDENTIFY(aic->msg_buf[0])) {
  618                         aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
  619                         return;
  620                 }
  621                 aic->lun = aic->msg_buf[0] & MSG_IDENTIFY_LUNMASK;
  622                 if (aic->tinfo[aic->target].lubusy & (1 << aic->lun))
  623                         aic_reconnect(aic, -1);
  624                 else
  625                         aic->state = AIC_RECONNECTING;
  626                 return;
  627         }
  628 
  629         if (aic->state == AIC_RECONNECTING) {
  630                 if (aic->msg_buf[0] != MSG_SIMPLE_Q_TAG) {
  631                         aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
  632                         return;
  633                 }
  634                 aic_reconnect(aic, aic->msg_buf[1]);
  635                 return;
  636         }
  637 
  638         switch (aic->msg_buf[0]) {
  639         case MSG_CMDCOMPLETE: {
  640                 struct ccb_scsiio *csio;
  641                 scb = aic->nexus;
  642                 ccb_h = &scb->ccb->ccb_h;
  643                 csio = &scb->ccb->csio;
  644                 if ((scb->flags & SCB_SENSE) != 0) {
  645                         /* auto REQUEST SENSE command */
  646                         scb->flags &= ~SCB_SENSE;
  647                         csio->sense_resid = scb->data_len;
  648                         if (scb->status == SCSI_STATUS_OK) {
  649                                 ccb_h->status |=
  650                                     CAM_SCSI_STATUS_ERROR|CAM_AUTOSNS_VALID;
  651                                 /*scsi_sense_print(csio);*/
  652                         } else {
  653                                 ccb_h->status |= CAM_AUTOSENSE_FAIL;
  654                                 printf("ccb %p sense failed %x\n",
  655                                     ccb_h, scb->status);
  656                         }
  657                 } else {
  658                         csio->scsi_status = scb->status;
  659                         csio->resid = scb->data_len;
  660                         if (scb->status == SCSI_STATUS_OK) {
  661                                 /* everything goes well */
  662                                 ccb_h->status |= CAM_REQ_CMP;
  663                         } else if ((ccb_h->flags & CAM_DIS_AUTOSENSE) == 0 &&
  664                             (csio->scsi_status == SCSI_STATUS_CHECK_COND ||
  665                              csio->scsi_status == SCSI_STATUS_CMD_TERMINATED)) {
  666                                 /* try to retrieve sense information */
  667                                 scb->flags |= SCB_SENSE;
  668                                 aic->flags |= AIC_BUSFREE_OK;
  669                                 return;
  670                         } else
  671                                 ccb_h->status |= CAM_SCSI_STATUS_ERROR;
  672                 }
  673                 aic_done(aic, scb);
  674                 aic->flags |= AIC_BUSFREE_OK;
  675                 break;
  676         }
  677         case MSG_EXTENDED:
  678                 switch (aic->msg_buf[2]) {
  679                 case MSG_EXT_SDTR:
  680                         scb = aic->nexus;
  681                         ti = &aic->tinfo[scb->target];
  682                         if (ti->flags & TINFO_SDTR_SENT) {
  683                                 ti->current.period = aic->msg_buf[3];
  684                                 ti->current.offset = aic->msg_buf[4];
  685                         } else {
  686                                 ti->current.period = aic->msg_buf[3] =
  687                                         max(ti->goal.period, aic->msg_buf[3]);
  688                                 ti->current.offset = aic->msg_buf[4] =
  689                                         min(ti->goal.offset, aic->msg_buf[4]);
  690                                 /*
  691                                  * The target initiated the negotiation,
  692                                  * send back a response.
  693                                  */
  694                                 aic_sched_msgout(aic, 0);
  695                         }
  696                         ti->flags &= ~(TINFO_SDTR_SENT|TINFO_SDTR_NEGO);
  697                         ti->scsirate = ti->current.offset ? ti->current.offset |
  698                             ((ti->current.period * 4 + 49) / 50 - 2) << 4 : 0;
  699                         aic_outb(aic, SCSIRATE, ti->scsirate);
  700                         memset(&neg, 0, sizeof (neg));
  701                         neg.protocol = PROTO_SCSI;
  702                         neg.protocol_version = SCSI_REV_2;
  703                         neg.transport = XPORT_SPI;
  704                         neg.transport_version = 2;
  705                         spi->sync_period = ti->goal.period = ti->current.period;
  706                         spi->sync_offset = ti->goal.offset = ti->current.offset;
  707                         spi->valid = CTS_SPI_VALID_SYNC_RATE
  708                                   | CTS_SPI_VALID_SYNC_OFFSET;
  709                         ccb_h = &scb->ccb->ccb_h;
  710                         xpt_setup_ccb(&neg.ccb_h, ccb_h->path, 1);
  711                         xpt_async(AC_TRANSFER_NEG, ccb_h->path, &neg);
  712                         break;
  713                 case MSG_EXT_WDTR:
  714                 default:
  715                         aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
  716                         break;
  717                 }
  718                 break;
  719         case MSG_DISCONNECT:
  720                 scb = aic->nexus;
  721                 ccb_h = &scb->ccb->ccb_h;
  722                 TAILQ_INSERT_TAIL(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
  723                 scb->flags |= SCB_DISCONNECTED;
  724                 aic->flags |= AIC_BUSFREE_OK;
  725                 aic->nexus = NULL;
  726                 CAM_DEBUG(ccb_h->path, CAM_DEBUG_TRACE, ("disconnected\n"));
  727                 break;
  728         case MSG_MESSAGE_REJECT:
  729                 switch (aic->msg_outq & -aic->msg_outq) {
  730                 case AIC_MSG_TAG_Q:
  731                         scb = aic->nexus;
  732                         ti = &aic->tinfo[scb->target];
  733                         ti->flags &= ~TINFO_TAG_ENB;
  734                         ti->lubusy |= 1 << scb->lun;
  735                         break;
  736                 case AIC_MSG_SDTR:
  737                         scb = aic->nexus;
  738                         ti = &aic->tinfo[scb->target];
  739                         ti->current.period = ti->goal.period = 0;
  740                         ti->current.offset = ti->goal.offset = 0;
  741                         ti->flags &= ~(TINFO_SDTR_SENT|TINFO_SDTR_NEGO);
  742                         ti->scsirate = 0;
  743                         aic_outb(aic, SCSIRATE, ti->scsirate);
  744                         memset(&neg, 0, sizeof (neg));
  745                         neg.protocol = PROTO_SCSI;
  746                         neg.protocol_version = SCSI_REV_2;
  747                         neg.transport = XPORT_SPI;
  748                         neg.transport_version = 2;
  749                         spi->sync_period = ti->current.period;
  750                         spi->sync_offset = ti->current.offset;
  751                         spi->valid = CTS_SPI_VALID_SYNC_RATE
  752                                   | CTS_SPI_VALID_SYNC_OFFSET;
  753                         ccb_h = &scb->ccb->ccb_h;
  754                         xpt_setup_ccb(&neg.ccb_h, ccb_h->path, 1);
  755                         xpt_async(AC_TRANSFER_NEG, ccb_h->path, &neg);
  756                         break;
  757                 default:
  758                         break;
  759                 }
  760                 break;
  761         case MSG_SAVEDATAPOINTER:
  762                 break;  
  763         case MSG_RESTOREPOINTERS:
  764                 break;
  765         case MSG_NOOP:
  766                 break;
  767         default:
  768                 aic_sched_msgout(aic, MSG_MESSAGE_REJECT);
  769                 break;
  770         }
  771 }
  772 
  773 /*
  774  * Send messages.
  775  */
  776 static void
  777 aic_msgout(struct aic_softc *aic)
  778 {
  779         struct aic_scb *scb;
  780         union ccb *ccb;
  781         struct aic_tinfo *ti;
  782         int msgidx = 0;
  783 
  784         CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_msgout\n"));
  785 
  786         aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
  787         aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
  788 
  789         /*
  790          * If the previous phase is also the message out phase,
  791          * we need to retransmit all the messages, probably
  792          * because the target has detected a parity error during
  793          * the past transmission.
  794          */
  795         if (aic->prev_phase == PH_MSGOUT)
  796                 aic->msg_outq = aic->msg_sent;
  797 
  798         do {
  799                 int q = aic->msg_outq;
  800                 if (msgidx > 0 && msgidx == aic->msg_len) {
  801                         /* complete message sent, start the next one */
  802                         q &= -q;
  803                         aic->msg_sent |= q;
  804                         aic->msg_outq ^= q;
  805                         q = aic->msg_outq;
  806                         msgidx = 0;
  807                 }
  808                 if (msgidx == 0) {
  809                         /* setup the message */
  810                         switch (q & -q) {
  811                         case AIC_MSG_IDENTIFY:
  812                                 scb = aic->nexus;
  813                                 ccb = scb->ccb;
  814                                 ti = &aic->tinfo[scb->target];
  815                                 aic->msg_buf[0] = MSG_IDENTIFY(scb->lun,
  816                                     (ti->flags & TINFO_DISC_ENB) &&
  817                                     !(ccb->ccb_h.flags & CAM_DIS_DISCONNECT));
  818                                 aic->msg_len = 1;
  819                                 break;
  820                         case AIC_MSG_TAG_Q:
  821                                 scb = aic->nexus;
  822                                 ccb = scb->ccb;
  823                                 aic->msg_buf[0] = ccb->csio.tag_action;
  824                                 aic->msg_buf[1] = scb->tag;
  825                                 aic->msg_len = 2;
  826                                 break;
  827                         case AIC_MSG_SDTR:
  828                                 scb = aic->nexus;
  829                                 ti = &aic->tinfo[scb->target];
  830                                 aic->msg_buf[0] = MSG_EXTENDED;
  831                                 aic->msg_buf[1] = MSG_EXT_SDTR_LEN;
  832                                 aic->msg_buf[2] = MSG_EXT_SDTR;
  833                                 aic->msg_buf[3] = ti->goal.period;
  834                                 aic->msg_buf[4] = ti->goal.offset;
  835                                 aic->msg_len = MSG_EXT_SDTR_LEN + 2;
  836                                 ti->flags |= TINFO_SDTR_SENT;
  837                                 break;
  838                         case AIC_MSG_MSGBUF:
  839                                 /* a single message already in the buffer */
  840                                 if (aic->msg_buf[0] == MSG_BUS_DEV_RESET ||
  841                                     aic->msg_buf[0] == MSG_ABORT ||
  842                                     aic->msg_buf[0] == MSG_ABORT_TAG)
  843                                         aic->flags |= AIC_BUSFREE_OK;
  844                                 break;
  845                         }
  846                 }
  847                 /*
  848                  * If this is the last message byte of all messages,
  849                  * clear ATNO to signal transmission complete.
  850                  */
  851                 if ((q & (q - 1)) == 0 && msgidx == aic->msg_len - 1)
  852                         aic_outb(aic, CLRSINT1, CLRATNO);
  853                 /* transmit the message byte */
  854                 aic_outb(aic, SCSIDAT, aic->msg_buf[msgidx++]);
  855         } while (aic_spiordy(aic));
  856 
  857         aic_outb(aic, SXFRCTL0, CHEN);
  858         aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
  859 }
  860 
  861 /*
  862  * Read data bytes.
  863  */
  864 static void
  865 aic_datain(struct aic_softc *aic)
  866 {
  867         struct aic_scb *scb = aic->nexus;
  868         u_int8_t dmastat, dmacntrl0;
  869         int n;
  870 
  871         CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_datain\n"));
  872 
  873         aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
  874         aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
  875 
  876         dmacntrl0 = ENDMA;
  877         if (aic->flags & AIC_DWIO_ENABLE)
  878                 dmacntrl0 |= DWORDPIO;
  879         aic_outb(aic, DMACNTRL0, dmacntrl0);
  880 
  881         while (scb->data_len > 0) {
  882                 for (;;) {
  883                         /* wait for the fifo to fill up or a phase change */
  884                         dmastat = aic_inb(aic, DMASTAT);
  885                         if (dmastat & (INTSTAT|DFIFOFULL))
  886                                 break;
  887                 }
  888                 if (dmastat & DFIFOFULL) {
  889                         n = FIFOSIZE;
  890                 } else {
  891                         /*
  892                          * No more data, wait for the remaining bytes in
  893                          * the scsi fifo to be transfer to the host fifo.
  894                          */
  895                         while (!(aic_inb(aic, SSTAT2) & SEMPTY))
  896                                 ;
  897                         n = aic_inb(aic, FIFOSTAT);
  898                 }
  899                 n = imin(scb->data_len, n);
  900                 if (aic->flags & AIC_DWIO_ENABLE) {
  901                         if (n >= 12) {
  902                                 aic_insl(aic, DMADATALONG, scb->data_ptr, n>>2);
  903                                 scb->data_ptr += n & ~3;
  904                                 scb->data_len -= n & ~3;
  905                                 n &= 3;
  906                         }
  907                 } else {
  908                         if (n >= 8) {
  909                                 aic_insw(aic, DMADATA, scb->data_ptr, n >> 1);
  910                                 scb->data_ptr += n & ~1;
  911                                 scb->data_len -= n & ~1;
  912                                 n &= 1;
  913                         }
  914                 }
  915                 if (n) {
  916                         aic_outb(aic, DMACNTRL0, ENDMA|B8MODE);
  917                         aic_insb(aic, DMADATA, scb->data_ptr, n);
  918                         scb->data_ptr += n;
  919                         scb->data_len -= n;
  920                         aic_outb(aic, DMACNTRL0, dmacntrl0);
  921                 }
  922 
  923                 if (dmastat & INTSTAT)
  924                         break;
  925         }
  926 
  927         aic_outb(aic, SXFRCTL0, CHEN);
  928         aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
  929 }
  930 
  931 /*
  932  * Send data bytes.
  933  */
  934 static void
  935 aic_dataout(struct aic_softc *aic)
  936 {
  937         struct aic_scb *scb = aic->nexus;
  938         u_int8_t dmastat, dmacntrl0, sstat2;
  939         int n;
  940 
  941         CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_dataout\n"));
  942 
  943         aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
  944         aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
  945 
  946         dmacntrl0 = ENDMA|WRITE;
  947         if (aic->flags & AIC_DWIO_ENABLE)
  948                 dmacntrl0 |= DWORDPIO;
  949         aic_outb(aic, DMACNTRL0, dmacntrl0);
  950 
  951         while (scb->data_len > 0) {
  952                 for (;;) {
  953                         /* wait for the fifo to clear up or a phase change */
  954                         dmastat = aic_inb(aic, DMASTAT);
  955                         if (dmastat & (INTSTAT|DFIFOEMP))
  956                                 break;
  957                 }
  958                 if (dmastat & INTSTAT)
  959                         break;
  960                 n = imin(scb->data_len, FIFOSIZE);
  961                 if (aic->flags & AIC_DWIO_ENABLE) {
  962                         if (n >= 12) {
  963                                 aic_outsl(aic, DMADATALONG, scb->data_ptr,n>>2);
  964                                 scb->data_ptr += n & ~3;
  965                                 scb->data_len -= n & ~3;
  966                                 n &= 3;
  967                         }
  968                 } else {
  969                         if (n >= 8) {
  970                                 aic_outsw(aic, DMADATA, scb->data_ptr, n >> 1);
  971                                 scb->data_ptr += n & ~1;
  972                                 scb->data_len -= n & ~1;
  973                                 n &= 1;
  974                         }
  975                 }
  976                 if (n) {
  977                         aic_outb(aic, DMACNTRL0, ENDMA|WRITE|B8MODE);
  978                         aic_outsb(aic, DMADATA, scb->data_ptr, n);
  979                         scb->data_ptr += n;
  980                         scb->data_len -= n;
  981                         aic_outb(aic, DMACNTRL0, dmacntrl0);
  982                 }
  983         }
  984 
  985         for (;;) {
  986                 /* wait until all bytes in the fifos are transmitted */
  987                 dmastat = aic_inb(aic, DMASTAT);
  988                 sstat2 = aic_inb(aic, SSTAT2);
  989                 if ((dmastat & DFIFOEMP) && (sstat2 & SEMPTY))
  990                         break;
  991                 if (dmastat & INTSTAT) {
  992                         /* adjust for untransmitted bytes */
  993                         n = aic_inb(aic, FIFOSTAT) + (sstat2 & 0xf);
  994                         scb->data_ptr -= n;
  995                         scb->data_len += n;
  996                         /* clear the fifo */
  997                         aic_outb(aic, SXFRCTL0, CHEN|CLRCH);
  998                         aic_outb(aic, DMACNTRL0, RSTFIFO);
  999                         break;
 1000                 }
 1001         }
 1002 
 1003         aic_outb(aic, SXFRCTL0, CHEN);
 1004         aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
 1005 }
 1006 
 1007 /*
 1008  * Send the scsi command.
 1009  */
 1010 static void
 1011 aic_cmd(struct aic_softc *aic)
 1012 {
 1013         struct aic_scb *scb = aic->nexus;
 1014         struct scsi_request_sense sense_cmd;
 1015 
 1016         CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_cmd\n"));
 1017 
 1018         if (scb->flags & SCB_SENSE) {
 1019                 /* autosense request */
 1020                 sense_cmd.opcode = REQUEST_SENSE;
 1021                 sense_cmd.byte2 = scb->lun << 5;
 1022                 sense_cmd.length = scb->ccb->csio.sense_len;
 1023                 sense_cmd.control = 0;
 1024                 sense_cmd.unused[0] = 0;
 1025                 sense_cmd.unused[1] = 0;
 1026                 scb->cmd_ptr = (u_int8_t *)&sense_cmd;
 1027                 scb->cmd_len = sizeof(sense_cmd);
 1028                 scb->data_ptr = (u_int8_t *)&scb->ccb->csio.sense_data;
 1029                 scb->data_len = scb->ccb->csio.sense_len;
 1030         }
 1031 
 1032         aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
 1033         aic_outb(aic, DMACNTRL0, ENDMA|WRITE);
 1034         aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
 1035         aic_outsw(aic, DMADATA, (u_int16_t *)scb->cmd_ptr, scb->cmd_len >> 1);
 1036         while ((aic_inb(aic, SSTAT2) & SEMPTY) == 0 &&
 1037             (aic_inb(aic, DMASTAT) & INTSTAT) == 0)
 1038                 ;
 1039         aic_outb(aic, SXFRCTL0, CHEN);
 1040         aic_outb(aic, SIMODE1, ENSCSIRST|ENBUSFREE|ENREQINIT);
 1041 }
 1042 
 1043 /*
 1044  * Finish off a command. The caller is responsible to remove the ccb
 1045  * from any queue.
 1046  */
 1047 static void
 1048 aic_done(struct aic_softc *aic, struct aic_scb *scb)
 1049 {
 1050         union ccb *ccb = scb->ccb;
 1051 
 1052         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
 1053                   ("aic_done - ccb %p status %x resid %d\n",
 1054                    ccb, ccb->ccb_h.status, ccb->csio.resid));
 1055 
 1056         untimeout(aic_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch);
 1057 
 1058         if ((scb->flags & SCB_DEVICE_RESET) != 0 &&
 1059             ccb->ccb_h.func_code != XPT_RESET_DEV) {
 1060                 struct cam_path *path;
 1061                 struct ccb_hdr *ccb_h;
 1062                 cam_status error;
 1063 
 1064                 error = xpt_create_path(&path, /*periph*/NULL,
 1065                                         cam_sim_path(aic->sim),
 1066                                         scb->target,
 1067                                         CAM_LUN_WILDCARD);
 1068 
 1069                 if (error == CAM_REQ_CMP) {
 1070                         xpt_async(AC_SENT_BDR, path, NULL);
 1071                         xpt_free_path(path);
 1072                 }
 1073 
 1074                 ccb_h = TAILQ_FIRST(&aic->pending_ccbs);
 1075                 while (ccb_h != NULL) {
 1076                         struct aic_scb *pending_scb;
 1077 
 1078                         pending_scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
 1079                         if (ccb_h->target_id == scb->target) {
 1080                                 ccb_h->status |= CAM_BDR_SENT;
 1081                                 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
 1082                                 TAILQ_REMOVE(&aic->pending_ccbs,
 1083                                     &pending_scb->ccb->ccb_h, sim_links.tqe);
 1084                                 aic_done(aic, pending_scb);
 1085                         } else {
 1086                                 ccb_h->timeout_ch =
 1087                                     timeout(aic_timeout, (caddr_t)pending_scb,
 1088                                         (ccb_h->timeout * hz) / 1000);
 1089                                 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
 1090                         }
 1091                 }
 1092 
 1093                 ccb_h = TAILQ_FIRST(&aic->nexus_ccbs);
 1094                 while (ccb_h != NULL) {
 1095                         struct aic_scb *nexus_scb;
 1096 
 1097                         nexus_scb = (struct aic_scb *)ccb_h->ccb_scb_ptr;
 1098                         if (ccb_h->target_id == scb->target) {
 1099                                 ccb_h->status |= CAM_BDR_SENT;
 1100                                 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
 1101                                 TAILQ_REMOVE(&aic->nexus_ccbs,
 1102                                     &nexus_scb->ccb->ccb_h, sim_links.tqe);
 1103                                 aic_done(aic, nexus_scb);
 1104                         } else {
 1105                                 ccb_h->timeout_ch =
 1106                                     timeout(aic_timeout, (caddr_t)nexus_scb,
 1107                                         (ccb_h->timeout * hz) / 1000);
 1108                                 ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe);
 1109                         }
 1110                 }
 1111         }
 1112 
 1113         if (aic->nexus == scb || scb->flags & SCB_DISCONNECTED)
 1114                 aic->tinfo[scb->target].lubusy &= ~(1 << scb->lun);
 1115         
 1116         if (aic->nexus == scb) {
 1117                 aic->nexus = NULL;
 1118         }
 1119         aic_free_scb(aic, scb);
 1120         xpt_done(ccb);
 1121 }
 1122 
 1123 static void
 1124 aic_poll(struct cam_sim *sim)
 1125 {
 1126         aic_intr(cam_sim_softc(sim));
 1127 }
 1128 
 1129 static void
 1130 aic_timeout(void *arg)
 1131 {
 1132         struct aic_scb *scb = (struct aic_scb *)arg;
 1133         union ccb *ccb = scb->ccb;
 1134         struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr;
 1135         int s;
 1136 
 1137         xpt_print_path(ccb->ccb_h.path);
 1138         printf("ccb %p - timed out", ccb);
 1139         if (aic->nexus && aic->nexus != scb)
 1140                 printf(", nexus %p", aic->nexus->ccb);
 1141         printf(", phase 0x%x, state %d\n", aic_inb(aic, SCSISIGI), aic->state);
 1142 
 1143         s = splcam();
 1144 
 1145         if ((scb->flags & SCB_ACTIVE) == 0) {
 1146                 splx(s);
 1147                 xpt_print_path(ccb->ccb_h.path);
 1148                 printf("ccb %p - timed out already completed\n", ccb);
 1149                 return;
 1150         }
 1151 
 1152         if ((scb->flags & SCB_DEVICE_RESET) == 0 && aic->nexus == scb) {
 1153                 struct ccb_hdr *ccb_h = &scb->ccb->ccb_h;
 1154 
 1155                 if ((ccb_h->status & CAM_RELEASE_SIMQ) == 0) {
 1156                         xpt_freeze_simq(aic->sim, /*count*/1);
 1157                         ccb_h->status |= CAM_RELEASE_SIMQ;
 1158                 }
 1159 
 1160                 TAILQ_FOREACH(ccb_h, &aic->pending_ccbs, sim_links.tqe) {
 1161                         untimeout(aic_timeout, (caddr_t)ccb_h->ccb_scb_ptr,
 1162                             ccb_h->timeout_ch);
 1163                 }
 1164 
 1165                 TAILQ_FOREACH(ccb_h, &aic->nexus_ccbs, sim_links.tqe) {
 1166                         untimeout(aic_timeout, (caddr_t)ccb_h->ccb_scb_ptr,
 1167                             ccb_h->timeout_ch);
 1168                 }
 1169 
 1170                 scb->flags |= SCB_DEVICE_RESET;
 1171                 ccb->ccb_h.timeout_ch =
 1172                     timeout(aic_timeout, (caddr_t)scb, 5 * hz);
 1173                 aic_sched_msgout(aic, MSG_BUS_DEV_RESET);
 1174         } else {
 1175                 if (aic->nexus == scb) {
 1176                         ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
 1177                         aic_done(aic, scb);
 1178                 }
 1179                 aic_reset(aic, /*initiate_reset*/TRUE);
 1180         }
 1181 
 1182         splx(s);
 1183 }
 1184 
 1185 void
 1186 aic_intr(void *arg)
 1187 {
 1188         struct aic_softc *aic = (struct aic_softc *)arg;
 1189         u_int8_t sstat0, sstat1;
 1190         union ccb *ccb;
 1191         struct aic_scb *scb;
 1192 
 1193         if (!(aic_inb(aic, DMASTAT) & INTSTAT))
 1194                 return;
 1195 
 1196         aic_outb(aic, DMACNTRL0, 0);
 1197 
 1198         sstat0 = aic_inb(aic, SSTAT0);
 1199         sstat1 = aic_inb(aic, SSTAT1);
 1200 
 1201         if ((sstat1 & SCSIRSTI) != 0) {
 1202                 /* a device-initiated bus reset */
 1203                 aic_outb(aic, CLRSINT1, CLRSCSIRSTI);
 1204                 aic_reset(aic, /*initiate_reset*/FALSE);
 1205                 return;
 1206         }
 1207 
 1208         if ((sstat1 & SCSIPERR) != 0) {
 1209                 aic_outb(aic, CLRSINT1, CLRSCSIPERR);
 1210                 aic_sched_msgout(aic, MSG_PARITY_ERROR);
 1211                 aic_outb(aic, DMACNTRL0, INTEN);
 1212                 return;
 1213         }
 1214 
 1215         if (aic_inb(aic, SSTAT4)) {
 1216                 aic_outb(aic, CLRSERR, CLRSYNCERR|CLRFWERR|CLRFRERR);
 1217                 aic_reset(aic, /*initiate_reset*/TRUE);
 1218                 return;
 1219         }
 1220 
 1221         if (aic->state <= AIC_SELECTING) {
 1222                 if ((sstat0 & SELDI) != 0) {
 1223                         aic_reselected(aic);
 1224                         aic_outb(aic, DMACNTRL0, INTEN);
 1225                         return;
 1226                 }
 1227 
 1228                 if ((sstat0 & SELDO) != 0) {
 1229                         aic_selected(aic);
 1230                         aic_outb(aic, DMACNTRL0, INTEN);
 1231                         return;
 1232                 }
 1233 
 1234                 if ((sstat1 & SELTO) != 0) {
 1235                         scb = aic->nexus;
 1236                         ccb = scb->ccb;
 1237                         ccb->ccb_h.status = CAM_SEL_TIMEOUT;
 1238                         aic_done(aic, scb);
 1239                         while ((sstat1 & BUSFREE) == 0)
 1240                                 sstat1 = aic_inb(aic, SSTAT1);
 1241                         aic->flags |= AIC_BUSFREE_OK;
 1242                 }
 1243         }
 1244 
 1245         if ((sstat1 & BUSFREE) != 0) {
 1246                 aic_outb(aic, SCSISEQ, 0);
 1247                 aic_outb(aic, CLRSINT0, sstat0);
 1248                 aic_outb(aic, CLRSINT1, sstat1);
 1249                 if ((scb = aic->nexus)) {
 1250                         if ((aic->flags & AIC_BUSFREE_OK) == 0) {
 1251                                 ccb = scb->ccb;
 1252                                 ccb->ccb_h.status = CAM_UNEXP_BUSFREE;
 1253                                 aic_done(aic, scb);
 1254                         } else if (scb->flags & SCB_DEVICE_RESET) {
 1255                                 ccb = scb->ccb;
 1256                                 if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
 1257                                         xpt_async(AC_SENT_BDR,
 1258                                             ccb->ccb_h.path, NULL);
 1259                                         ccb->ccb_h.status |= CAM_REQ_CMP;
 1260                                 } else
 1261                                         ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
 1262                                 aic_done(aic, scb);
 1263                         } else if (scb->flags & SCB_SENSE) {
 1264                                 /* autosense request */
 1265                                 aic->flags &= ~AIC_BUSFREE_OK;
 1266                                 aic->tinfo[scb->target].lubusy &=
 1267                                     ~(1 << scb->lun);
 1268                                 aic_select(aic);
 1269                                 aic_outb(aic, DMACNTRL0, INTEN);
 1270                                 return;
 1271                         }
 1272                 }
 1273                 aic->flags &= ~AIC_BUSFREE_OK;
 1274                 aic->state = AIC_IDLE;
 1275                 aic_start(aic);
 1276                 aic_outb(aic, DMACNTRL0, INTEN);
 1277                 return;
 1278         }
 1279 
 1280         if ((sstat1 & REQINIT) != 0) {
 1281                 u_int8_t phase = aic_inb(aic, SCSISIGI) & PH_MASK;
 1282                 aic_outb(aic, SCSISIGO, phase);
 1283                 aic_outb(aic, CLRSINT1, CLRPHASECHG);
 1284 
 1285                 switch (phase) {
 1286                 case PH_MSGOUT:
 1287                         aic_msgout(aic);
 1288                         break;
 1289                 case PH_MSGIN:
 1290                         aic_msgin(aic);
 1291                         break;
 1292                 case PH_STAT:
 1293                         scb = aic->nexus;
 1294                         ccb = scb->ccb;
 1295                         aic_outb(aic, DMACNTRL0, 0);
 1296                         aic_outb(aic, SXFRCTL0, CHEN|SPIOEN);
 1297                         scb->status = aic_inb(aic, SCSIDAT);
 1298                         aic_outb(aic, SXFRCTL0, CHEN);
 1299                         break;
 1300                 case PH_CMD:
 1301                         aic_cmd(aic);
 1302                         break;
 1303                 case PH_DATAIN:
 1304                         aic_datain(aic);
 1305                         break;
 1306                 case PH_DATAOUT:
 1307                         aic_dataout(aic);
 1308                         break;
 1309                 }
 1310                 aic->prev_phase = phase;
 1311                 aic_outb(aic, DMACNTRL0, INTEN);
 1312                 return;
 1313         }
 1314 
 1315         printf("aic_intr: unexpected intr sstat0 %x sstat1 %x\n",
 1316                 sstat0, sstat1);
 1317         aic_outb(aic, DMACNTRL0, INTEN);
 1318 }
 1319 
 1320 /*
 1321  * Reset ourselves.
 1322  */
 1323 static void
 1324 aic_chip_reset(struct aic_softc *aic)
 1325 {
 1326         /*
 1327          * Doc. recommends to clear these two registers before
 1328          * operations commence
 1329          */
 1330         aic_outb(aic, SCSITEST, 0);
 1331         aic_outb(aic, TEST, 0);
 1332 
 1333         /* Reset SCSI-FIFO and abort any transfers */
 1334         aic_outb(aic, SXFRCTL0, CHEN|CLRCH|CLRSTCNT);
 1335 
 1336         /* Reset HOST-FIFO */
 1337         aic_outb(aic, DMACNTRL0, RSTFIFO);
 1338         aic_outb(aic, DMACNTRL1, 0);
 1339 
 1340         /* Disable all selection features */
 1341         aic_outb(aic, SCSISEQ, 0);
 1342         aic_outb(aic, SXFRCTL1, 0);
 1343 
 1344         /* Disable interrupts */
 1345         aic_outb(aic, SIMODE0, 0);
 1346         aic_outb(aic, SIMODE1, 0);
 1347 
 1348         /* Clear interrupts */
 1349         aic_outb(aic, CLRSINT0, 0x7f);
 1350         aic_outb(aic, CLRSINT1, 0xef);
 1351 
 1352         /* Disable synchronous transfers */
 1353         aic_outb(aic, SCSIRATE, 0);
 1354 
 1355         /* Haven't seen ant errors (yet) */
 1356         aic_outb(aic, CLRSERR, 0x07);
 1357 
 1358         /* Set our SCSI-ID */
 1359         aic_outb(aic, SCSIID, aic->initiator << OID_S);
 1360         aic_outb(aic, BRSTCNTRL, EISA_BRST_TIM);
 1361 }
 1362 
 1363 /*
 1364  * Reset the SCSI bus
 1365  */
 1366 static void
 1367 aic_scsi_reset(struct aic_softc *aic)
 1368 {
 1369         aic_outb(aic, SCSISEQ, SCSIRSTO);
 1370         DELAY(500);
 1371         aic_outb(aic, SCSISEQ, 0);
 1372         DELAY(50);
 1373 }
 1374 
 1375 /*
 1376  * Reset. Abort all pending commands.
 1377  */
 1378 static void
 1379 aic_reset(struct aic_softc *aic, int initiate_reset)
 1380 {
 1381         struct ccb_hdr *ccb_h;
 1382 
 1383         CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_reset\n"));
 1384 
 1385         if (initiate_reset)
 1386                 aic_scsi_reset(aic);
 1387         aic_chip_reset(aic);
 1388 
 1389         xpt_async(AC_BUS_RESET, aic->path, NULL);
 1390 
 1391         while ((ccb_h = TAILQ_FIRST(&aic->pending_ccbs)) != NULL) {
 1392                 TAILQ_REMOVE(&aic->pending_ccbs, ccb_h, sim_links.tqe);
 1393                 ccb_h->status |= CAM_SCSI_BUS_RESET;
 1394                 aic_done(aic, (struct aic_scb *)ccb_h->ccb_scb_ptr);
 1395         }
 1396 
 1397         while ((ccb_h = TAILQ_FIRST(&aic->nexus_ccbs)) != NULL) {
 1398                 TAILQ_REMOVE(&aic->nexus_ccbs, ccb_h, sim_links.tqe);
 1399                 ccb_h->status |= CAM_SCSI_BUS_RESET;
 1400                 aic_done(aic, (struct aic_scb *)ccb_h->ccb_scb_ptr);
 1401         }
 1402 
 1403         if (aic->nexus) {
 1404                 ccb_h = &aic->nexus->ccb->ccb_h;
 1405                 ccb_h->status |= CAM_SCSI_BUS_RESET;
 1406                 aic_done(aic, aic->nexus);
 1407         }
 1408 
 1409         aic->state = AIC_IDLE;
 1410         aic_outb(aic, DMACNTRL0, INTEN);
 1411 }
 1412 
 1413 static char *aic_chip_names[] = {
 1414         "AIC6260", "AIC6360", "AIC6370", "GM82C700",
 1415 };
 1416 
 1417 static struct {
 1418         int type;
 1419         char *idstring;
 1420 } aic_chip_ids[] = {
 1421         { AIC6360, IDSTRING_AIC6360 },
 1422         { AIC6370, IDSTRING_AIC6370 },
 1423         { GM82C700, IDSTRING_GM82C700 },
 1424 };
 1425 
 1426 static void
 1427 aic_init(struct aic_softc *aic)
 1428 {
 1429         struct aic_scb *scb;
 1430         struct aic_tinfo *ti;
 1431         u_int8_t porta, portb;
 1432         char chip_id[33];
 1433         int i;
 1434 
 1435         TAILQ_INIT(&aic->pending_ccbs);
 1436         TAILQ_INIT(&aic->nexus_ccbs);
 1437         aic->nexus = NULL;
 1438         aic->state = AIC_IDLE;
 1439         aic->prev_phase = -1;
 1440         aic->flags = 0;
 1441 
 1442         aic_chip_reset(aic);
 1443         aic_scsi_reset(aic);
 1444 
 1445         /* determine the chip type from its ID string */
 1446         aic->chip_type = AIC6260;
 1447         aic_insb(aic, ID, chip_id, sizeof(chip_id) - 1);
 1448         chip_id[sizeof(chip_id) - 1] = '\0';
 1449         for (i = 0; i < sizeof(aic_chip_ids) / sizeof(aic_chip_ids[0]); i++) {
 1450                 if (!strcmp(chip_id, aic_chip_ids[i].idstring)) {
 1451                         aic->chip_type = aic_chip_ids[i].type;
 1452                         break;
 1453                 }
 1454         }
 1455 
 1456         porta = aic_inb(aic, PORTA);
 1457         portb = aic_inb(aic, PORTB);
 1458 
 1459         aic->initiator = PORTA_ID(porta);
 1460         if (PORTA_PARITY(porta))
 1461                 aic->flags |= AIC_PARITY_ENABLE;
 1462         if (PORTB_DISC(portb))
 1463                 aic->flags |= AIC_DISC_ENABLE;
 1464         if (PORTB_DMA(portb))
 1465                 aic->flags |= AIC_DMA_ENABLE;
 1466 
 1467         /*
 1468          * We can do fast SCSI (10MHz clock rate) if bit 4 of portb
 1469          * is set and we've got a 6360.  The 6260 can only do standard
 1470          * 5MHz SCSI.
 1471          */
 1472         if (aic->chip_type > AIC6260 || aic_inb(aic, REV)) {
 1473                 if (PORTB_FSYNC(portb))
 1474                         aic->flags |= AIC_FAST_ENABLE;
 1475                 aic->flags |= AIC_DWIO_ENABLE;
 1476         }
 1477 
 1478         if (aic->flags & AIC_FAST_ENABLE)
 1479                 aic->max_period = AIC_FAST_SYNC_PERIOD;
 1480         else
 1481                 aic->max_period = AIC_SYNC_PERIOD;
 1482         aic->min_period = AIC_MIN_SYNC_PERIOD;
 1483         
 1484         free_scbs = NULL;
 1485         for (i = 255; i >= 0; i--) {
 1486                 scb = &aic->scbs[i];
 1487                 scb->tag = i;
 1488                 aic_free_scb(aic, scb);
 1489         }
 1490 
 1491         for (i = 0; i < 8; i++) {
 1492                 if (i == aic->initiator)
 1493                         continue;
 1494                 ti = &aic->tinfo[i];
 1495                 bzero(ti, sizeof(*ti));
 1496                 ti->flags = TINFO_TAG_ENB;
 1497                 if (aic->flags & AIC_DISC_ENABLE)
 1498                         ti->flags |= TINFO_DISC_ENB;
 1499                 ti->user.period = aic->max_period;
 1500                 ti->user.offset = AIC_SYNC_OFFSET;
 1501                 ti->scsirate = 0;
 1502         }
 1503 
 1504         aic_outb(aic, DMACNTRL0, INTEN);
 1505 }
 1506 
 1507 int
 1508 aic_probe(struct aic_softc *aic)
 1509 {
 1510         int i;
 1511 
 1512         /* Remove aic6360 from possible powerdown mode */
 1513         aic_outb(aic, DMACNTRL0, 0);
 1514 
 1515 #define STSIZE  16
 1516         aic_outb(aic, DMACNTRL1, 0);    /* Reset stack pointer */
 1517         for (i = 0; i < STSIZE; i++)
 1518                 aic_outb(aic, STACK, i);
 1519 
 1520         /* See if we can pull out the same sequence */
 1521         aic_outb(aic, DMACNTRL1, 0);
 1522         for (i = 0; i < STSIZE && aic_inb(aic, STACK) == i; i++)
 1523                 ;
 1524         if (i != STSIZE)
 1525                 return (ENXIO);
 1526 #undef  STSIZE
 1527         return (0);
 1528 }
 1529 
 1530 int
 1531 aic_attach(struct aic_softc *aic)
 1532 {
 1533         struct cam_devq *devq;
 1534 
 1535         /*
 1536          * Create the device queue for our SIM.
 1537          */
 1538         devq = cam_simq_alloc(256);
 1539         if (devq == NULL)
 1540                 return (ENOMEM);
 1541 
 1542         /*
 1543          * Construct our SIM entry
 1544          */
 1545         aic->sim = cam_sim_alloc(aic_action, aic_poll, "aic", aic,
 1546                                  aic->unit, &Giant, 2, 256, devq);
 1547         if (aic->sim == NULL) {
 1548                 cam_simq_free(devq);
 1549                 return (ENOMEM);
 1550         }
 1551 
 1552         if (xpt_bus_register(aic->sim, aic->dev, 0) != CAM_SUCCESS) {
 1553                 cam_sim_free(aic->sim, /*free_devq*/TRUE);
 1554                 return (ENXIO);
 1555         }
 1556 
 1557         if (xpt_create_path(&aic->path, /*periph*/NULL,
 1558                             cam_sim_path(aic->sim), CAM_TARGET_WILDCARD,
 1559                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
 1560                 xpt_bus_deregister(cam_sim_path(aic->sim));
 1561                 cam_sim_free(aic->sim, /*free_devq*/TRUE);
 1562                 return (ENXIO);
 1563         }
 1564 
 1565         aic_init(aic);
 1566 
 1567         printf("aic%d: %s", aic->unit, aic_chip_names[aic->chip_type]);
 1568         if (aic->flags & AIC_DMA_ENABLE)
 1569                 printf(", dma");
 1570         if (aic->flags & AIC_DISC_ENABLE)
 1571                 printf(", disconnection");
 1572         if (aic->flags & AIC_PARITY_ENABLE)
 1573                 printf(", parity check");
 1574         if (aic->flags & AIC_FAST_ENABLE)
 1575                 printf(", fast SCSI");
 1576         printf("\n");
 1577         return (0);
 1578 }
 1579 
 1580 int
 1581 aic_detach(struct aic_softc *aic)
 1582 {
 1583         xpt_async(AC_LOST_DEVICE, aic->path, NULL);
 1584         xpt_free_path(aic->path);
 1585         xpt_bus_deregister(cam_sim_path(aic->sim));
 1586         cam_sim_free(aic->sim, /*free_devq*/TRUE);
 1587         return (0);
 1588 }

Cache object: ac7da93ccc74fac95b39c7dcb9eac950


[ 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.