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

Cache object: 2e0e00ccf087eaee89bc237f4e9f33d5


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