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

Cache object: 4a3dab512791b0d9fe7976de0bf1d10c


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