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/ic/aic7xxx_openbsd.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 /*      $OpenBSD: aic7xxx_openbsd.c,v 1.72 2022/04/16 19:19:58 naddy Exp $      */
    2 /*      $NetBSD: aic7xxx_osm.c,v 1.14 2003/11/02 11:07:44 wiz Exp $     */
    3 
    4 /*
    5  * Bus independent OpenBSD shim for the aic7xxx based adaptec SCSI controllers
    6  *
    7  * Copyright (c) 1994-2001 Justin T. Gibbs.
    8  * Copyright (c) 2001-2002 Steve Murphree, Jr.
    9  * All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions, and the following disclaimer,
   16  *    without modification.
   17  * 2. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * Alternatively, this software may be distributed under the terms of the
   21  * GNU Public License ("GPL").
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  * //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.c#12 $
   36  *
   37  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_osm.c,v 1.31 2002/11/30 19:08:58 scottl Exp $
   38  */
   39 /*
   40  * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc. - April 2003
   41  */
   42 
   43 #include <dev/ic/aic7xxx_openbsd.h>
   44 #include <dev/ic/aic7xxx_inline.h>
   45 
   46 #ifndef AHC_TMODE_ENABLE
   47 #define AHC_TMODE_ENABLE 0
   48 #endif
   49 
   50 
   51 void    ahc_action(struct scsi_xfer *);
   52 void    ahc_execute_scb(void *, bus_dma_segment_t *, int);
   53 int     ahc_poll(struct ahc_softc *, int);
   54 void    ahc_setup_data(struct ahc_softc *, struct scsi_xfer *, struct scb *);
   55 
   56 void    ahc_adapter_req_set_xfer_mode(struct ahc_softc *, struct scb *);
   57 
   58 
   59 struct cfdriver ahc_cd = {
   60         NULL, "ahc", DV_DULL
   61 };
   62 
   63 static const struct scsi_adapter ahc_switch = {
   64         ahc_action, NULL, NULL, NULL, NULL
   65 };
   66 
   67 /*
   68  * Attach all the sub-devices we can find
   69  */
   70 int
   71 ahc_attach(struct ahc_softc *ahc)
   72 {
   73         struct scsibus_attach_args saa;
   74         int s;
   75 
   76         s = splbio();
   77 
   78 #ifndef DEBUG
   79         if (bootverbose) {
   80                 char ahc_info[256];
   81                 ahc_controller_info(ahc, ahc_info, sizeof ahc_info);
   82                 printf("%s: %s\n", ahc->sc_dev.dv_xname, ahc_info);
   83         }
   84 #endif
   85 
   86         ahc_intr_enable(ahc, TRUE);
   87 
   88         if (ahc->flags & AHC_RESET_BUS_A)
   89                 ahc_reset_channel(ahc, 'A', TRUE);
   90         if ((ahc->features & AHC_TWIN) && ahc->flags & AHC_RESET_BUS_B)
   91                 ahc_reset_channel(ahc, 'B', TRUE);
   92 
   93         saa.saa_adapter_buswidth = (ahc->features & AHC_WIDE) ? 16 :8;
   94         saa.saa_adapter_softc = ahc;
   95         saa.saa_adapter = &ahc_switch;
   96         saa.saa_luns = saa.saa_adapter_buswidth = 8;
   97         saa.saa_openings = 16;
   98         saa.saa_pool = &ahc->sc_iopool;
   99         saa.saa_quirks = saa.saa_flags = 0;
  100         saa.saa_wwpn = saa.saa_wwnn = 0;
  101         if ((ahc->flags & AHC_PRIMARY_CHANNEL) == 0) {
  102                 saa.saa_adapter_target = ahc->our_id;
  103                 ahc->sc_child = (struct scsibus_softc *)config_found(
  104                     (void *)&ahc->sc_dev, &saa, scsiprint);
  105                 if (ahc->features & AHC_TWIN) {
  106                         saa.saa_adapter_target = ahc->our_id_b;
  107                         ahc->sc_child_b = (struct scsibus_softc *)config_found(
  108                             (void *)&ahc->sc_dev, &saa, scsiprint);
  109                 }
  110         } else {
  111                 if (ahc->features & AHC_TWIN) {
  112                         saa.saa_adapter_target = ahc->our_id_b;
  113                         ahc->sc_child = (struct scsibus_softc *)config_found(
  114                             (void *)&ahc->sc_dev, &saa, scsiprint);
  115                 }
  116                 saa.saa_adapter_target = ahc->our_id;
  117                 ahc->sc_child_b = (struct scsibus_softc *)config_found(
  118                     (void *)&ahc->sc_dev, &saa, scsiprint);
  119         }
  120 
  121         splx(s);
  122         return (1);
  123 }
  124 
  125 /*
  126  * Catch an interrupt from the adapter
  127  */
  128 int
  129 ahc_platform_intr(void *arg)
  130 {
  131         struct  ahc_softc *ahc = (struct ahc_softc *)arg;
  132 
  133         bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
  134             0, ahc->scb_data->hscb_dmamap->dm_mapsize,
  135             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  136 
  137         return ahc_intr(ahc);
  138 }
  139 
  140 /*
  141  * We have an scb which has been processed by the
  142  * adaptor, now we look to see how the operation
  143  * went.
  144  */
  145 void
  146 ahc_done(struct ahc_softc *ahc, struct scb *scb)
  147 {
  148         struct scsi_xfer *xs = scb->xs;
  149 
  150         bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
  151             0, ahc->scb_data->hscb_dmamap->dm_mapsize,
  152             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  153 
  154         LIST_REMOVE(scb, pending_links);
  155         if ((scb->flags & SCB_UNTAGGEDQ) != 0) {
  156                 struct scb_tailq *untagged_q;
  157                 int target_offset;
  158 
  159                 target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
  160                 untagged_q = &ahc->untagged_queues[target_offset];
  161                 TAILQ_REMOVE(untagged_q, scb, links.tqe);
  162                 scb->flags &= ~SCB_UNTAGGEDQ;
  163                 ahc_run_untagged_queue(ahc, untagged_q);
  164         }
  165 
  166         timeout_del(&xs->stimeout);
  167 
  168         if (xs->datalen) {
  169                 int op;
  170 
  171                 if ((xs->flags & SCSI_DATA_IN) != 0)
  172                         op = BUS_DMASYNC_POSTREAD;
  173                 else
  174                         op = BUS_DMASYNC_POSTWRITE;
  175                 bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0,
  176                                 scb->dmamap->dm_mapsize, op);
  177                 bus_dmamap_unload(ahc->parent_dmat, scb->dmamap);
  178         }
  179 
  180         /* Translate the CAM status code to a SCSI error code. */
  181         switch (xs->error) {
  182         case CAM_SCSI_STATUS_ERROR:
  183         case CAM_REQ_INPROG:
  184         case CAM_REQ_CMP:
  185                 switch (xs->status) {
  186                 case SCSI_TASKSET_FULL:
  187                 case SCSI_BUSY:
  188                         xs->error = XS_BUSY;
  189                         break;
  190                 case SCSI_CHECK:
  191                 case SCSI_TERMINATED:
  192                         if ((scb->flags & SCB_SENSE) == 0) {
  193                                 /* CHECK on CHECK? */
  194                                 xs->error = XS_DRIVER_STUFFUP;
  195                         } else
  196                                 xs->error = XS_NOERROR;
  197                         break;
  198                 default:
  199                         xs->error = XS_NOERROR;
  200                         break;
  201                 }
  202                 break;
  203         case CAM_REQUEUE_REQ:
  204         case CAM_BUSY:
  205                 xs->error = XS_BUSY;
  206                 break;
  207         case CAM_CMD_TIMEOUT:
  208                 xs->error = XS_TIMEOUT;
  209                 break;
  210         case CAM_BDR_SENT:
  211         case CAM_SCSI_BUS_RESET:
  212                 xs->error = XS_RESET;
  213                 break;
  214         case CAM_SEL_TIMEOUT:
  215                 xs->error = XS_SELTIMEOUT;
  216                 break;
  217         default:
  218                 xs->error = XS_DRIVER_STUFFUP;
  219                 break;
  220         }
  221 
  222         /* Don't clobber any existing error state */
  223         if (xs->error != XS_NOERROR) {
  224           /* Don't clobber any existing error state */
  225         } else if ((scb->flags & SCB_SENSE) != 0) {
  226                 /*
  227                  * We performed autosense retrieval.
  228                  *
  229                  * Zero any sense not transferred by the
  230                  * device.  The SCSI spec mandates that any
  231                  * untransferred data should be assumed to be
  232                  * zero.  Complete the 'bounce' of sense information
  233                  * through buffers accessible via bus-space by
  234                  * copying it into the clients csio.
  235                  */
  236                 memset(&xs->sense, 0, sizeof(struct scsi_sense_data));
  237                 memcpy(&xs->sense, ahc_get_sense_buf(ahc, scb),
  238                     aic_le32toh(scb->sg_list->len) & AHC_SG_LEN_MASK);
  239                 xs->error = XS_SENSE;
  240         }
  241 
  242         scsi_done(xs);
  243 }
  244 
  245 void
  246 ahc_action(struct scsi_xfer *xs)
  247 {
  248         struct ahc_softc *ahc;
  249         struct scb *scb;
  250         struct hardware_scb *hscb;
  251         u_int target_id;
  252         u_int our_id;
  253 
  254 #ifdef AHC_DEBUG
  255         printf("%s: ahc_action\n", ahc_name(ahc));
  256 #endif
  257         ahc = xs->sc_link->bus->sb_adapter_softc;
  258 
  259         target_id = xs->sc_link->target;
  260         our_id = SCSI_SCSI_ID(ahc, xs->sc_link);
  261 
  262         /*
  263          * get the scb to use.
  264          */
  265         scb = xs->io;
  266 
  267         /* Clean up for the next user */
  268         scb->flags = SCB_FLAG_NONE;
  269 
  270         hscb = scb->hscb;
  271         hscb->control = 0;
  272         ahc->scb_data->scbindex[hscb->tag] = NULL;
  273 
  274 #ifdef AHC_DEBUG
  275         printf("%s: start scb(%p)\n", ahc_name(ahc), scb);
  276 #endif
  277         scb->xs = xs;
  278         timeout_set(&xs->stimeout, ahc_timeout, scb);
  279 
  280         /*
  281          * Put all the arguments for the xfer in the scb
  282          */
  283         hscb->control = 0;
  284         hscb->scsiid = BUILD_SCSIID(ahc, xs->sc_link, target_id, our_id);
  285         hscb->lun = xs->sc_link->lun;
  286         if (xs->xs_control & XS_CTL_RESET) {
  287                 hscb->cdb_len = 0;
  288                 scb->flags |= SCB_DEVICE_RESET;
  289                 hscb->control |= MK_MESSAGE;
  290                 ahc_execute_scb(scb, NULL, 0);
  291                 return;
  292         }
  293 
  294         ahc_setup_data(ahc, xs, scb);
  295 }
  296 
  297 void
  298 ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
  299 {
  300         struct  scb *scb;
  301         struct  scsi_xfer *xs;
  302         struct  ahc_softc *ahc;
  303         struct  ahc_initiator_tinfo *tinfo;
  304         struct  ahc_tmode_tstate *tstate;
  305 
  306         u_int   mask;
  307         int     s;
  308 
  309         scb = (struct scb *)arg;
  310         xs = scb->xs;
  311         xs->error = CAM_REQ_INPROG;
  312         xs->status = 0;
  313         ahc = xs->sc_link->bus->sb_adapter_softc;
  314 
  315         if (nsegments != 0) {
  316                 struct    ahc_dma_seg *sg;
  317                 bus_dma_segment_t *end_seg;
  318                 int op;
  319 
  320                 end_seg = dm_segs + nsegments;
  321 
  322                 /* Copy the segments into our SG list */
  323                 sg = scb->sg_list;
  324                 while (dm_segs < end_seg) {
  325                         uint32_t len;
  326 
  327                         sg->addr = aic_htole32(dm_segs->ds_addr);
  328                         len = dm_segs->ds_len
  329                             | ((dm_segs->ds_addr >> 8) & 0x7F000000);
  330                         sg->len = aic_htole32(len);
  331                         sg++;
  332                         dm_segs++;
  333                 }
  334 
  335                 /*
  336                  * Note where to find the SG entries in bus space.
  337                  * We also set the full residual flag which the
  338                  * sequencer will clear as soon as a data transfer
  339                  * occurs.
  340                  */
  341                 scb->hscb->sgptr = aic_htole32(scb->sg_list_phys|SG_FULL_RESID);
  342 
  343                 if ((xs->flags & SCSI_DATA_IN) != 0)
  344                         op = BUS_DMASYNC_PREREAD;
  345                 else
  346                         op = BUS_DMASYNC_PREWRITE;
  347 
  348                 bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0,
  349                                 scb->dmamap->dm_mapsize, op);
  350 
  351                 sg--;
  352                 sg->len |= aic_htole32(AHC_DMA_LAST_SEG);
  353 
  354                 bus_dmamap_sync(ahc->parent_dmat, scb->sg_map->sg_dmamap,
  355                     0, scb->sg_map->sg_dmamap->dm_mapsize,
  356                     BUS_DMASYNC_PREWRITE);
  357 
  358                 /* Copy the first SG into the "current" data pointer area */
  359                 scb->hscb->dataptr = scb->sg_list->addr;
  360                 scb->hscb->datacnt = scb->sg_list->len;
  361         } else {
  362                 scb->hscb->sgptr = aic_htole32(SG_LIST_NULL);
  363                 scb->hscb->dataptr = 0;
  364                 scb->hscb->datacnt = 0;
  365         }
  366 
  367         scb->sg_count = nsegments;
  368 
  369         s = splbio();
  370 
  371         tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid),
  372                                     SCSIID_OUR_ID(scb->hscb->scsiid),
  373                                     SCSIID_TARGET(ahc, scb->hscb->scsiid),
  374                                     &tstate);
  375 
  376         mask = SCB_GET_TARGET_MASK(ahc, scb);
  377         scb->hscb->scsirate = tinfo->scsirate;
  378         scb->hscb->scsioffset = tinfo->curr.offset;
  379 
  380         if ((tstate->ultraenb & mask) != 0)
  381                 scb->hscb->control |= ULTRAENB;
  382 
  383         if ((tstate->discenable & mask) != 0)
  384                 scb->hscb->control |= DISCENB;
  385 
  386         if ((tstate->auto_negotiate & mask) != 0) {
  387                 scb->flags |= SCB_AUTO_NEGOTIATE;
  388                 scb->hscb->control |= MK_MESSAGE;
  389         }
  390 
  391         if ((tstate->tagenable & mask) != 0)
  392                 scb->hscb->control |= TAG_ENB;
  393 
  394         bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
  395             0, ahc->scb_data->hscb_dmamap->dm_mapsize,
  396             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  397 
  398         LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
  399 
  400         if (!(xs->flags & SCSI_POLL))
  401                 timeout_add_msec(&xs->stimeout, xs->timeout);
  402 
  403         /*
  404          * We only allow one untagged transaction
  405          * per target in the initiator role unless
  406          * we are storing a full busy target *lun*
  407          * table in SCB space.
  408          *
  409          * This really should not be of any
  410          * concern, as we take care to avoid this
  411          * in ahc_done().  XXX smurph
  412          */
  413         if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0
  414             && (ahc->flags & AHC_SCB_BTT) == 0) {
  415                 struct scb_tailq *untagged_q;
  416                 int target_offset;
  417 
  418                 target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
  419                 untagged_q = &(ahc->untagged_queues[target_offset]);
  420                 TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
  421                 scb->flags |= SCB_UNTAGGEDQ;
  422                 if (TAILQ_FIRST(untagged_q) != scb) {
  423                         if (xs->flags & SCSI_POLL)
  424                                 goto poll;
  425                         else {
  426                                 splx(s);
  427                                 return;
  428                         }
  429                 }
  430         }
  431         scb->flags |= SCB_ACTIVE;
  432 
  433         if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
  434                 /* Define a mapping from our tag to the SCB. */
  435                 ahc->scb_data->scbindex[scb->hscb->tag] = scb;
  436                 ahc_pause(ahc);
  437                 if ((ahc->flags & AHC_PAGESCBS) == 0)
  438                         ahc_outb(ahc, SCBPTR, scb->hscb->tag);
  439                 ahc_outb(ahc, TARG_IMMEDIATE_SCB, scb->hscb->tag);
  440                 ahc_unpause(ahc);
  441         } else {
  442                 ahc_queue_scb(ahc, scb);
  443         }
  444 
  445         if (!(xs->flags & SCSI_POLL)) {
  446                 if (ahc->inited_target[xs->sc_link->target] == 0) {
  447                         struct  ahc_devinfo devinfo;
  448 
  449                         ahc_adapter_req_set_xfer_mode(ahc, scb);
  450                         ahc_scb_devinfo(ahc, &devinfo, scb);
  451                         ahc_update_neg_request(ahc, &devinfo, tstate, tinfo,
  452                             AHC_NEG_IF_NON_ASYNC);
  453 
  454                         ahc->inited_target[xs->sc_link->target] = 1;
  455                 }
  456                 splx(s);
  457                 return;
  458         }
  459 
  460         /*
  461          * If we can't use interrupts, poll for completion
  462          */
  463 poll:
  464 #ifdef AHC_DEBUG
  465         printf("%s: cmd_poll\n", ahc_name(ahc));
  466 #endif
  467 
  468         do {
  469                 if (ahc_poll(ahc, xs->timeout)) {
  470                         if (!(xs->flags & SCSI_SILENT))
  471                                 printf("cmd fail\n");
  472                         ahc_timeout(scb);
  473                         break;
  474                 }
  475         } while (!(xs->flags & ITSDONE));
  476 
  477         splx(s);
  478 }
  479 
  480 int
  481 ahc_poll(struct ahc_softc *ahc, int wait)
  482 {
  483         while (--wait) {
  484                 DELAY(1000);
  485                 if (ahc_inb(ahc, INTSTAT) & INT_PEND)
  486                         break;
  487         }
  488 
  489         if (wait == 0) {
  490                 printf("%s: board is not responding\n", ahc_name(ahc));
  491                 return (EIO);
  492         }
  493 
  494         ahc_intr((void *)ahc);
  495         return (0);
  496 }
  497 
  498 void
  499 ahc_setup_data(struct ahc_softc *ahc, struct scsi_xfer *xs,
  500                struct scb *scb)
  501 {
  502         struct hardware_scb *hscb;
  503 
  504         hscb = scb->hscb;
  505         xs->resid = xs->status = 0;
  506         xs->error = CAM_REQ_INPROG;
  507 
  508         hscb->cdb_len = xs->cmdlen;
  509         if (hscb->cdb_len > sizeof(hscb->cdb32)) {
  510                 xs->error = XS_DRIVER_STUFFUP;
  511                 scsi_done(xs);
  512                 return;
  513         }
  514 
  515         if (hscb->cdb_len > 12) {
  516                 memcpy(hscb->cdb32, &xs->cmd, hscb->cdb_len);
  517                 scb->flags |= SCB_CDB32_PTR;
  518         } else {
  519                 memcpy(hscb->shared_data.cdb, &xs->cmd, hscb->cdb_len);
  520         }
  521 
  522         /* Only use S/G if there is a transfer */
  523         if (xs->datalen) {
  524                 int error;
  525 
  526                 error = bus_dmamap_load(ahc->parent_dmat,
  527                                         scb->dmamap, xs->data,
  528                                         xs->datalen, NULL,
  529                                         (xs->flags & SCSI_NOSLEEP) ?
  530                                         BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
  531                 if (error) {
  532 #ifdef AHC_DEBUG
  533                         printf("%s: in ahc_setup_data(): bus_dmamap_load() "
  534                                "= %d\n",
  535                                ahc_name(ahc), error);
  536 #endif
  537                         xs->error = XS_DRIVER_STUFFUP;
  538                         scsi_done(xs);
  539                         return;
  540                 }
  541                 ahc_execute_scb(scb, scb->dmamap->dm_segs,
  542                     scb->dmamap->dm_nsegs);
  543         } else {
  544                 ahc_execute_scb(scb, NULL, 0);
  545         }
  546 }
  547 
  548 void
  549 ahc_timeout(void *arg)
  550 {
  551         struct  scb *scb, *list_scb;
  552         struct  ahc_softc *ahc;
  553         int     s;
  554         int     found;
  555         char    channel;
  556 
  557         scb = arg;
  558         ahc = scb->xs->sc_link->bus->sb_adapter_softc;
  559 
  560         s = splbio();
  561 
  562 #ifdef AHC_DEBUG
  563         printf("%s: SCB %d timed out\n", ahc_name(ahc), scb->hscb->tag);
  564         ahc_dump_card_state(ahc);
  565 #endif
  566 
  567         ahc_pause(ahc);
  568 
  569         if (scb->flags & SCB_ACTIVE) {
  570                 channel = SCB_GET_CHANNEL(ahc, scb);
  571                 ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
  572                 /*
  573                  * Go through all of our pending SCBs and remove
  574                  * any scheduled timeouts for them. They're about to be
  575                  * aborted so no need for them to timeout.
  576                  */
  577                 LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) {
  578                         if (list_scb->xs)
  579                                 timeout_del(&list_scb->xs->stimeout);
  580                 }
  581                 found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE);
  582 #ifdef AHC_DEBUG
  583                 printf("%s: Issued Channel %c Bus Reset %d SCBs aborted\n",
  584                     ahc_name(ahc), channel, found);
  585 #endif
  586         }
  587 
  588         ahc_unpause(ahc);
  589         splx(s);
  590 }
  591 
  592 
  593 void
  594 ahc_platform_set_tags(struct ahc_softc *ahc,
  595                       struct ahc_devinfo *devinfo, int alg)
  596 {
  597         struct ahc_tmode_tstate *tstate;
  598 
  599         ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
  600                             devinfo->target, &tstate);
  601 
  602         /* XXXX Need to check quirks before doing this! XXXX */
  603 
  604         switch (alg) {
  605         case AHC_QUEUE_BASIC:
  606         case AHC_QUEUE_TAGGED:
  607                 tstate->tagenable |= devinfo->target_mask;
  608                 break;
  609         case AHC_QUEUE_NONE:
  610                 tstate->tagenable &= ~devinfo->target_mask;
  611                 break;
  612         }
  613 }
  614 
  615 int
  616 ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc)
  617 {
  618         return (0);
  619 }
  620 
  621 void
  622 ahc_send_async(struct ahc_softc *ahc, char channel, u_int target, u_int lun,
  623                 ac_code code, void *opt_arg)
  624 {
  625         /* Nothing to do here for OpenBSD */
  626 }
  627 
  628 void
  629 ahc_adapter_req_set_xfer_mode(struct ahc_softc *ahc, struct scb *scb)
  630 {
  631         struct ahc_initiator_tinfo *tinfo;
  632         struct ahc_tmode_tstate *tstate;
  633         struct ahc_syncrate *syncrate;
  634         struct ahc_devinfo devinfo;
  635         u_int16_t quirks;
  636         u_int width, ppr_options, period, offset;
  637         int s;
  638 
  639         s = splbio();
  640 
  641         ahc_scb_devinfo(ahc, &devinfo, scb);
  642         quirks = scb->xs->sc_link->quirks;
  643         tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
  644             devinfo.our_scsiid, devinfo.target, &tstate);
  645 
  646         tstate->discenable |= (ahc->user_discenable & devinfo.target_mask);
  647 
  648         if (quirks & SDEV_NOTAGS)
  649                 tstate->tagenable &= ~devinfo.target_mask;
  650         else if (ahc->user_tagenable & devinfo.target_mask)
  651                 tstate->tagenable |= devinfo.target_mask;
  652 
  653         if (quirks & SDEV_NOWIDE)
  654                 width = MSG_EXT_WDTR_BUS_8_BIT;
  655         else
  656                 width = MSG_EXT_WDTR_BUS_16_BIT;
  657 
  658         ahc_validate_width(ahc, NULL, &width, ROLE_UNKNOWN);
  659         if (width > tinfo->user.width)
  660                 width = tinfo->user.width;
  661         ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE);
  662 
  663         if (quirks & SDEV_NOSYNC) {
  664                 period = 0;
  665                 offset = 0;
  666         } else {
  667                 period = tinfo->user.period;
  668                 offset = tinfo->user.offset;
  669         }
  670 
  671         /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */
  672         ppr_options = tinfo->user.ppr_options;
  673         /* XXX Other reasons to avoid ppr? XXX */
  674         if (width < MSG_EXT_WDTR_BUS_16_BIT)
  675                 ppr_options = 0;
  676 
  677         if ((tstate->discenable & devinfo.target_mask) == 0 ||
  678             (tstate->tagenable & devinfo.target_mask) == 0)
  679                 ppr_options &= ~MSG_EXT_PPR_PROT_IUS;
  680 
  681         syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
  682             AHC_SYNCRATE_MAX);
  683         ahc_validate_offset(ahc, NULL, syncrate, &offset, width,
  684             ROLE_UNKNOWN);
  685 
  686         if (offset == 0) {
  687                 period = 0;
  688                 ppr_options = 0;
  689         }
  690 
  691         if (ppr_options != 0 && tinfo->user.transport_version >= 3) {
  692                 tinfo->goal.transport_version = tinfo->user.transport_version;
  693                 tinfo->curr.transport_version = tinfo->user.transport_version;
  694         }
  695 
  696         ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset, ppr_options,
  697             AHC_TRANS_GOAL, FALSE);
  698 
  699         splx(s);
  700 }
  701 
  702 /*
  703  * Get a free scb. If there are none, see if we can allocate a new SCB.
  704  */
  705 void *
  706 ahc_scb_alloc(void *xahc)
  707 {
  708         struct ahc_softc *ahc = xahc;
  709         struct scb *scb;
  710 
  711         mtx_enter(&ahc->sc_scb_mtx);
  712         scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
  713 
  714         if (scb != NULL)
  715                 SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
  716 
  717         mtx_leave(&ahc->sc_scb_mtx);
  718 
  719         return (scb);
  720 }
  721 
  722 /*
  723  * Return an SCB resource to the free list.
  724  */
  725 void
  726 ahc_scb_free(void *xahc, void *io)
  727 {
  728         struct ahc_softc *ahc = xahc;
  729         struct scb *scb = io;
  730         struct hardware_scb *hscb;
  731 
  732         hscb = scb->hscb;
  733         /* Clean up for the next user */
  734         ahc->scb_data->scbindex[hscb->tag] = NULL;
  735         scb->flags = SCB_FLAG_NONE;
  736         hscb->control = 0;
  737 
  738         mtx_enter(&ahc->sc_scb_mtx);
  739         SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
  740         mtx_leave(&ahc->sc_scb_mtx);
  741 
  742         /* Notify the OSM that a resource is now available. */
  743         ahc_platform_scb_free(ahc, scb);
  744 }

Cache object: 53cdd7e82b6e83c4fdc0c7e77c4c4e22


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