root/dev/ic/aic7xxx_openbsd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ahc_attach
  2. ahc_platform_intr
  3. ahc_done
  4. ahc_minphys
  5. ahc_action
  6. ahc_execute_scb
  7. ahc_poll
  8. ahc_setup_data
  9. ahc_timeout
  10. ahc_platform_set_tags
  11. ahc_platform_alloc
  12. ahc_platform_free
  13. ahc_softc_comp
  14. ahc_send_async
  15. ahc_adapter_req_set_xfer_mode

    1 /*      $OpenBSD: aic7xxx_openbsd.c,v 1.35 2007/08/04 14:37:34 krw 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 <sys/cdefs.h>
   44 /* __KERNEL_RCSID(0, "$NetBSD: aic7xxx_osm.c,v 1.14 2003/11/02 11:07:44 wiz Exp $"); */
   45 
   46 #include <dev/ic/aic7xxx_openbsd.h>
   47 #include <dev/ic/aic7xxx_inline.h>
   48 
   49 #ifndef AHC_TMODE_ENABLE
   50 #define AHC_TMODE_ENABLE 0
   51 #endif
   52 
   53 
   54 int     ahc_action(struct scsi_xfer *);
   55 int     ahc_execute_scb(void *, bus_dma_segment_t *, int);
   56 int     ahc_poll(struct ahc_softc *, int);
   57 int     ahc_setup_data(struct ahc_softc *, struct scsi_xfer *, struct scb *);
   58 
   59 void    ahc_minphys(struct buf *);
   60 void    ahc_adapter_req_set_xfer_mode(struct ahc_softc *, struct scb *);
   61 
   62 
   63 struct cfdriver ahc_cd = {
   64         NULL, "ahc", DV_DULL
   65 };
   66 
   67 static struct scsi_adapter ahc_switch =
   68 {
   69         ahc_action,
   70         ahc_minphys,
   71         0,
   72         0,
   73 };
   74 
   75 /* the below structure is so we have a default dev struct for our link struct */
   76 static struct scsi_device ahc_dev =
   77 {
   78         NULL, /* Use default error handler */
   79         NULL, /* have a queue, served by this */
   80         NULL, /* have no async handler */
   81         NULL, /* Use default 'done' routine */
   82 };
   83 
   84 /*
   85  * Attach all the sub-devices we can find
   86  */
   87 int
   88 ahc_attach(struct ahc_softc *ahc)
   89 {
   90         struct scsibus_attach_args saa;
   91         int s;
   92 
   93         s = splbio();
   94 
   95         /*
   96          * fill in the prototype scsi_links.
   97          */
   98         ahc->sc_channel.adapter_target = ahc->our_id;
   99         if (ahc->features & AHC_WIDE)
  100                 ahc->sc_channel.adapter_buswidth = 16;
  101         ahc->sc_channel.adapter_softc = ahc;
  102         ahc->sc_channel.adapter = &ahc_switch;
  103         ahc->sc_channel.openings = 16;
  104         ahc->sc_channel.device = &ahc_dev;
  105 
  106         if (ahc->features & AHC_TWIN) {
  107                 /* Configure the second scsi bus */
  108                 ahc->sc_channel_b = ahc->sc_channel;
  109                 ahc->sc_channel_b.adapter_target = ahc->our_id_b;
  110         }
  111 
  112 #ifndef DEBUG           
  113         if (bootverbose) {
  114                 char ahc_info[256];
  115                 ahc_controller_info(ahc, ahc_info, sizeof ahc_info);
  116                 printf("%s: %s\n", ahc->sc_dev.dv_xname, ahc_info);
  117         }
  118 #endif
  119 
  120         ahc_intr_enable(ahc, TRUE);
  121 
  122         if (ahc->flags & AHC_RESET_BUS_A)
  123                 ahc_reset_channel(ahc, 'A', TRUE);
  124         if ((ahc->features & AHC_TWIN) && ahc->flags & AHC_RESET_BUS_B)
  125                 ahc_reset_channel(ahc, 'B', TRUE);
  126 
  127         bzero(&saa, sizeof(saa));
  128         if ((ahc->flags & AHC_PRIMARY_CHANNEL) == 0) {
  129                 saa.saa_sc_link = &ahc->sc_channel;
  130                 ahc->sc_child = config_found((void *)&ahc->sc_dev,
  131                     &saa, scsiprint);
  132                 if (ahc->features & AHC_TWIN) {
  133                         saa.saa_sc_link = &ahc->sc_channel_b;
  134                         ahc->sc_child_b = config_found((void *)&ahc->sc_dev,
  135                             &saa, scsiprint);
  136                 }
  137         } else {
  138                 if (ahc->features & AHC_TWIN) {
  139                         saa.saa_sc_link = &ahc->sc_channel_b;
  140                         ahc->sc_child = config_found((void *)&ahc->sc_dev,
  141                             &saa, scsiprint);
  142                 }
  143                 saa.saa_sc_link = &ahc->sc_channel;
  144                 ahc->sc_child_b = config_found((void *)&ahc->sc_dev,
  145                     &saa, scsiprint);
  146         }
  147 
  148         splx(s);
  149         return (1);
  150 }
  151 
  152 /*
  153  * Catch an interrupt from the adapter
  154  */
  155 int
  156 ahc_platform_intr(void *arg)
  157 {
  158         struct  ahc_softc *ahc = (struct ahc_softc *)arg;
  159 
  160         bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
  161             0, ahc->scb_data->hscb_dmamap->dm_mapsize,
  162             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  163 
  164         return ahc_intr(ahc);
  165 }
  166 
  167 /*
  168  * We have an scb which has been processed by the
  169  * adaptor, now we look to see how the operation
  170  * went.
  171  */
  172 void
  173 ahc_done(struct ahc_softc *ahc, struct scb *scb)
  174 {
  175         struct scsi_xfer *xs = scb->xs;
  176         int s;
  177 
  178         bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
  179             0, ahc->scb_data->hscb_dmamap->dm_mapsize,
  180             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  181 
  182         LIST_REMOVE(scb, pending_links);
  183         if ((scb->flags & SCB_UNTAGGEDQ) != 0) {
  184                 struct scb_tailq *untagged_q;
  185                 int target_offset;
  186 
  187                 target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
  188                 untagged_q = &ahc->untagged_queues[target_offset];
  189                 TAILQ_REMOVE(untagged_q, scb, links.tqe);
  190                 scb->flags &= ~SCB_UNTAGGEDQ;
  191                 ahc_run_untagged_queue(ahc, untagged_q);
  192         }
  193 
  194         timeout_del(&xs->stimeout);
  195 
  196         if (xs->datalen) {
  197                 int op;
  198 
  199                 if ((xs->flags & SCSI_DATA_IN) != 0)
  200                         op = BUS_DMASYNC_POSTREAD;
  201                 else
  202                         op = BUS_DMASYNC_POSTWRITE;
  203                 bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0,
  204                                 scb->dmamap->dm_mapsize, op);
  205                 bus_dmamap_unload(ahc->parent_dmat, scb->dmamap);
  206         }
  207 
  208         /* Translate the CAM status code to a SCSI error code. */
  209         switch (xs->error) {
  210         case CAM_SCSI_STATUS_ERROR:
  211         case CAM_REQ_INPROG:
  212         case CAM_REQ_CMP:
  213                 switch (xs->status) {
  214                 case SCSI_TASKSET_FULL:
  215                         /* SCSI Layer won't requeue, so we force infinite
  216                          * retries until queue space is available. XS_BUSY
  217                          * is dangerous because if the NOSLEEP flag is set
  218                          * it can cause the I/O to return EIO. XS_BUSY code
  219                          * falls through to XS_TIMEOUT anyway.
  220                          */
  221                         xs->error = XS_TIMEOUT;
  222                         xs->retries++;
  223                         break;
  224                 case SCSI_BUSY:
  225                         xs->error = XS_BUSY;
  226                         break;
  227                 case SCSI_CHECK:
  228                 case SCSI_TERMINATED:
  229                         if ((scb->flags & SCB_SENSE) == 0) {
  230                                 /* CHECK on CHECK? */
  231                                 xs->error = XS_DRIVER_STUFFUP;
  232                         } else
  233                                 xs->error = XS_NOERROR;
  234                         break;
  235                 default:
  236                         xs->error = XS_NOERROR;
  237                         break;
  238                 }
  239                 break;
  240         case CAM_BUSY:
  241                 xs->error = XS_BUSY;
  242                 break;
  243         case CAM_CMD_TIMEOUT:
  244                 xs->error = XS_TIMEOUT;
  245                 break;
  246         case CAM_BDR_SENT:
  247         case CAM_SCSI_BUS_RESET:
  248                 xs->error = XS_RESET;
  249                 break;
  250         case CAM_REQUEUE_REQ:
  251                 xs->error = XS_TIMEOUT;
  252                 xs->retries++;
  253                 break;
  254         case CAM_SEL_TIMEOUT:
  255                 xs->error = XS_SELTIMEOUT;
  256                 break;
  257         default:
  258                 xs->error = XS_DRIVER_STUFFUP;
  259                 break;
  260         }
  261 
  262         /* Don't clobber any existing error state */
  263         if (xs->error != XS_NOERROR) {
  264           /* Don't clobber any existing error state */
  265         } else if ((scb->flags & SCB_SENSE) != 0) {
  266                 /*
  267                  * We performed autosense retrieval.
  268                  *
  269                  * Zero any sense not transferred by the
  270                  * device.  The SCSI spec mandates that any
  271                  * untransferred data should be assumed to be
  272                  * zero.  Complete the 'bounce' of sense information
  273                  * through buffers accessible via bus-space by
  274                  * copying it into the clients csio.
  275                  */
  276                 memset(&xs->sense, 0, sizeof(struct scsi_sense_data));
  277                 memcpy(&xs->sense, ahc_get_sense_buf(ahc, scb),
  278                     aic_le32toh(scb->sg_list->len) & AHC_SG_LEN_MASK);
  279                 xs->error = XS_SENSE;
  280         }
  281 
  282         s = splbio();       
  283         ahc_free_scb(ahc, scb);
  284         splx(s);       
  285 
  286         xs->flags |= ITSDONE;
  287         scsi_done(xs);
  288 }
  289 
  290 void
  291 ahc_minphys(bp)
  292         struct buf *bp;
  293 {
  294         /*
  295          * Even though the card can transfer up to 16megs per command
  296          * we are limited by the number of segments in the dma segment
  297          * list that we can hold.  The worst case is that all pages are
  298          * discontinuous physically, hence the "page per segment" limit
  299          * enforced here.
  300          */
  301         if (bp->b_bcount > ((AHC_NSEG - 1) * PAGE_SIZE)) {
  302                 bp->b_bcount = ((AHC_NSEG - 1) * PAGE_SIZE);
  303         }
  304         minphys(bp);
  305 }
  306 
  307 int32_t
  308 ahc_action(struct scsi_xfer *xs)
  309 {
  310         struct ahc_softc *ahc;
  311         struct scb *scb;
  312         struct hardware_scb *hscb;
  313         u_int target_id;
  314         u_int our_id;
  315         int s;
  316         int dontqueue = 0;
  317 
  318         SC_DEBUG(xs->sc_link, SDEV_DB3, ("ahc_action\n"));
  319         ahc = (struct ahc_softc *)xs->sc_link->adapter_softc;
  320 
  321         /* determine safety of software queueing */
  322         dontqueue = xs->flags & SCSI_POLL;
  323 
  324         target_id = xs->sc_link->target;
  325         our_id = SCSI_SCSI_ID(ahc, xs->sc_link);
  326 
  327         /*
  328          * get an scb to use.
  329          */
  330         s = splbio();
  331         if ((scb = ahc_get_scb(ahc)) == NULL) {
  332                 splx(s);
  333                 return (TRY_AGAIN_LATER);
  334         }
  335         splx(s);
  336 
  337         hscb = scb->hscb;
  338 
  339         SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
  340         scb->xs = xs;
  341         timeout_set(&xs->stimeout, ahc_timeout, scb);
  342 
  343         /*
  344          * Put all the arguments for the xfer in the scb
  345          */
  346         hscb->control = 0;
  347         hscb->scsiid = BUILD_SCSIID(ahc, xs->sc_link, target_id, our_id);
  348         hscb->lun = xs->sc_link->lun;
  349         if (xs->xs_control & XS_CTL_RESET) {
  350                 hscb->cdb_len = 0;
  351                 scb->flags |= SCB_DEVICE_RESET;
  352                 hscb->control |= MK_MESSAGE;
  353                 return (ahc_execute_scb(scb, NULL, 0));
  354         }
  355 
  356         return (ahc_setup_data(ahc, xs, scb));
  357 }
  358 
  359 int
  360 ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
  361 {
  362         struct  scb *scb;
  363         struct  scsi_xfer *xs;
  364         struct  ahc_softc *ahc;
  365         struct  ahc_initiator_tinfo *tinfo;
  366         struct  ahc_tmode_tstate *tstate;
  367 
  368         u_int   mask;
  369         int     s;
  370 
  371         scb = (struct scb *)arg;
  372         xs = scb->xs;
  373         xs->error = CAM_REQ_INPROG;
  374         xs->status = 0;
  375         ahc = (struct ahc_softc *)xs->sc_link->adapter_softc;
  376 
  377         if (nsegments != 0) {
  378                 struct    ahc_dma_seg *sg;
  379                 bus_dma_segment_t *end_seg;
  380                 int op;
  381                 
  382                 end_seg = dm_segs + nsegments;
  383 
  384                 /* Copy the segments into our SG list */
  385                 sg = scb->sg_list;
  386                 while (dm_segs < end_seg) {
  387                         uint32_t len;
  388 
  389                         sg->addr = aic_htole32(dm_segs->ds_addr);
  390                         len = dm_segs->ds_len
  391                             | ((dm_segs->ds_addr >> 8) & 0x7F000000);
  392                         sg->len = aic_htole32(len);
  393                         sg++;
  394                         dm_segs++;
  395                 }
  396 
  397                 /*
  398                  * Note where to find the SG entries in bus space.
  399                  * We also set the full residual flag which the 
  400                  * sequencer will clear as soon as a data transfer
  401                  * occurs.
  402                  */
  403                 scb->hscb->sgptr = aic_htole32(scb->sg_list_phys|SG_FULL_RESID);
  404 
  405                 if ((xs->flags & SCSI_DATA_IN) != 0)
  406                         op = BUS_DMASYNC_PREREAD;
  407                 else
  408                         op = BUS_DMASYNC_PREWRITE;
  409 
  410                 bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0,
  411                                 scb->dmamap->dm_mapsize, op);
  412 
  413                 sg--;
  414                 sg->len |= aic_htole32(AHC_DMA_LAST_SEG);
  415 
  416                 bus_dmamap_sync(ahc->parent_dmat, scb->sg_map->sg_dmamap,
  417                     0, scb->sg_map->sg_dmamap->dm_mapsize,
  418                     BUS_DMASYNC_PREWRITE);
  419 
  420                 /* Copy the first SG into the "current" data pointer area */
  421                 scb->hscb->dataptr = scb->sg_list->addr;
  422                 scb->hscb->datacnt = scb->sg_list->len;
  423         } else {
  424                 scb->hscb->sgptr = aic_htole32(SG_LIST_NULL);
  425                 scb->hscb->dataptr = 0;
  426                 scb->hscb->datacnt = 0;
  427         }
  428 
  429         scb->sg_count = nsegments;
  430 
  431         s = splbio();
  432 
  433         /*
  434          * Last time we need to check if this SCB needs to
  435          * be aborted.
  436          */
  437         if (xs->flags & ITSDONE) {
  438                 if (nsegments != 0)
  439                         bus_dmamap_unload(ahc->parent_dmat, scb->dmamap);
  440 
  441                 ahc_free_scb(ahc, scb);
  442                 splx(s);
  443                 return (COMPLETE);
  444         }
  445 
  446         tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid),
  447                                     SCSIID_OUR_ID(scb->hscb->scsiid),
  448                                     SCSIID_TARGET(ahc, scb->hscb->scsiid),
  449                                     &tstate);
  450 
  451         mask = SCB_GET_TARGET_MASK(ahc, scb);
  452         scb->hscb->scsirate = tinfo->scsirate;
  453         scb->hscb->scsioffset = tinfo->curr.offset;
  454 
  455         if ((tstate->ultraenb & mask) != 0)
  456                 scb->hscb->control |= ULTRAENB;
  457 
  458         if ((tstate->discenable & mask) != 0)
  459                 scb->hscb->control |= DISCENB;
  460 
  461         if ((tstate->auto_negotiate & mask) != 0) {
  462                 scb->flags |= SCB_AUTO_NEGOTIATE;
  463                 scb->hscb->control |= MK_MESSAGE;
  464         }
  465 
  466         if ((tstate->tagenable & mask) != 0)
  467                 scb->hscb->control |= TAG_ENB;
  468 
  469         bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
  470             0, ahc->scb_data->hscb_dmamap->dm_mapsize,
  471             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  472 
  473         LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
  474 
  475         if (!(xs->flags & SCSI_POLL))
  476                 timeout_add(&xs->stimeout, (xs->timeout * hz) / 1000);
  477 
  478         /*
  479          * We only allow one untagged transaction
  480          * per target in the initiator role unless
  481          * we are storing a full busy target *lun*
  482          * table in SCB space.
  483          *
  484          * This really should not be of any
  485          * concern, as we take care to avoid this
  486          * in ahc_done().  XXX smurph
  487          */
  488         if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0
  489             && (ahc->flags & AHC_SCB_BTT) == 0) {
  490                 struct scb_tailq *untagged_q;
  491                 int target_offset;
  492 
  493                 target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
  494                 untagged_q = &(ahc->untagged_queues[target_offset]);
  495                 TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
  496                 scb->flags |= SCB_UNTAGGEDQ;
  497                 if (TAILQ_FIRST(untagged_q) != scb) {
  498                         if (xs->flags & SCSI_POLL)
  499                                 goto poll;
  500                         else {          
  501                                 splx(s);
  502                                 return (SUCCESSFULLY_QUEUED);
  503                         }
  504                 }
  505         }
  506         scb->flags |= SCB_ACTIVE;
  507 
  508         if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
  509                 /* Define a mapping from our tag to the SCB. */
  510                 ahc->scb_data->scbindex[scb->hscb->tag] = scb;
  511                 ahc_pause(ahc);
  512                 if ((ahc->flags & AHC_PAGESCBS) == 0)
  513                         ahc_outb(ahc, SCBPTR, scb->hscb->tag);
  514                 ahc_outb(ahc, TARG_IMMEDIATE_SCB, scb->hscb->tag);
  515                 ahc_unpause(ahc);
  516         } else {
  517                 ahc_queue_scb(ahc, scb);
  518         }
  519 
  520         if (!(xs->flags & SCSI_POLL)) {
  521                 if (ahc->inited_target[xs->sc_link->target] == 0) {
  522                         struct  ahc_devinfo devinfo;
  523 
  524                         ahc_adapter_req_set_xfer_mode(ahc, scb);
  525                         ahc_scb_devinfo(ahc, &devinfo, scb);
  526                         ahc_update_neg_request(ahc, &devinfo, tstate, tinfo,
  527                             AHC_NEG_IF_NON_ASYNC);
  528 
  529                         ahc->inited_target[xs->sc_link->target] = 1;
  530                 }
  531                 splx(s);
  532                 return (SUCCESSFULLY_QUEUED);
  533         }
  534 
  535         /*
  536          * If we can't use interrupts, poll for completion
  537          */
  538 poll:
  539         SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
  540 
  541         do {
  542                 if (ahc_poll(ahc, xs->timeout)) {
  543                         if (!(xs->flags & SCSI_SILENT))
  544                                 printf("cmd fail\n");
  545                         ahc_timeout(scb);
  546                         break;
  547                 }
  548         } while (!(xs->flags & ITSDONE));
  549 
  550         splx(s);
  551         return (COMPLETE);
  552 }
  553 
  554 int
  555 ahc_poll(struct ahc_softc *ahc, int wait)
  556 {
  557         while (--wait) {
  558                 DELAY(1000);
  559                 if (ahc_inb(ahc, INTSTAT) & INT_PEND)
  560                         break;
  561         }
  562 
  563         if (wait == 0) {
  564                 printf("%s: board is not responding\n", ahc_name(ahc));
  565                 return (EIO);
  566         }
  567 
  568         ahc_intr((void *)ahc);
  569         return (0);
  570 }
  571 
  572 int
  573 ahc_setup_data(struct ahc_softc *ahc, struct scsi_xfer *xs,
  574                struct scb *scb)
  575 {
  576         struct hardware_scb *hscb;
  577         int s;
  578 
  579         hscb = scb->hscb;
  580         xs->resid = xs->status = 0;
  581         xs->error = CAM_REQ_INPROG;
  582 
  583         hscb->cdb_len = xs->cmdlen;
  584         if (hscb->cdb_len > sizeof(hscb->cdb32)) {
  585                 s = splbio();
  586                 ahc_free_scb(ahc, scb);
  587                 splx(s);
  588                 xs->error = XS_DRIVER_STUFFUP;
  589                 xs->flags |= ITSDONE;
  590                 scsi_done(xs);
  591                 return (COMPLETE);
  592         }
  593 
  594         if (hscb->cdb_len > 12) {
  595                 memcpy(hscb->cdb32, xs->cmd, hscb->cdb_len);
  596                 scb->flags |= SCB_CDB32_PTR;
  597         } else {
  598                 memcpy(hscb->shared_data.cdb, xs->cmd, hscb->cdb_len);
  599         }
  600                 
  601         /* Only use S/G if there is a transfer */
  602         if (xs->datalen) {
  603                 int error;
  604 
  605                 error = bus_dmamap_load(ahc->parent_dmat,
  606                                         scb->dmamap, xs->data,
  607                                         xs->datalen, NULL,
  608                                         (xs->flags & SCSI_NOSLEEP) ?
  609                                         BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
  610                 if (error) {
  611 #ifdef AHC_DEBUG
  612                         printf("%s: in ahc_setup_data(): bus_dmamap_load() "
  613                                "= %d\n",
  614                                ahc_name(ahc), error);
  615 #endif
  616                         s = splbio();
  617                         ahc_free_scb(ahc, scb);
  618                         splx(s);
  619                         return (TRY_AGAIN_LATER);       /* XXX fvdl */
  620 }
  621                 error = ahc_execute_scb(scb,
  622                                         scb->dmamap->dm_segs,
  623                                         scb->dmamap->dm_nsegs);
  624                 return error;
  625         } else {
  626                 return ahc_execute_scb(scb, NULL, 0);
  627         }
  628 }
  629 
  630 void
  631 ahc_timeout(void *arg)
  632 {
  633         struct  scb *scb, *list_scb;
  634         struct  ahc_softc *ahc;
  635         int     s;
  636         int     found;
  637         char    channel;
  638 
  639         scb = (struct scb *)arg;
  640         ahc = (struct ahc_softc *)scb->xs->sc_link->adapter_softc;
  641 
  642         s = splbio();
  643 
  644 #ifdef AHC_DEBUG
  645         printf("%s: SCB %d timed out\n", ahc_name(ahc), scb->hscb->tag);
  646         ahc_dump_card_state(ahc);
  647 #endif
  648 
  649         ahc_pause(ahc);
  650 
  651         if (scb->flags & SCB_ACTIVE) {
  652                 channel = SCB_GET_CHANNEL(ahc, scb);
  653                 ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
  654                 /*
  655                  * Go through all of our pending SCBs and remove
  656                  * any scheduled timeouts for them. They're about to be
  657                  * aborted so no need for them to timeout.
  658                  */
  659                 LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) {
  660                         if (list_scb->xs)
  661                                 timeout_del(&list_scb->xs->stimeout);
  662                 }
  663                 found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE);
  664 #ifdef AHC_DEBUG
  665                 printf("%s: Issued Channel %c Bus Reset %d SCBs aborted\n",
  666                     ahc_name(ahc), channel, found);
  667 #endif
  668         }
  669 
  670         ahc_unpause(ahc);
  671         splx(s);
  672 }
  673 
  674 
  675 void
  676 ahc_platform_set_tags(struct ahc_softc *ahc,
  677                       struct ahc_devinfo *devinfo, int alg)
  678 {
  679         struct ahc_tmode_tstate *tstate;
  680 
  681         ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
  682                             devinfo->target, &tstate);
  683 
  684         /* XXXX Need to check quirks before doing this! XXXX */
  685 
  686         switch (alg) {
  687         case AHC_QUEUE_BASIC:
  688         case AHC_QUEUE_TAGGED:
  689                 tstate->tagenable |= devinfo->target_mask;
  690                 break;
  691         case AHC_QUEUE_NONE:
  692                 tstate->tagenable &= ~devinfo->target_mask;
  693                 break;
  694         }
  695 }
  696 
  697 int
  698 ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
  699 {
  700         if (sizeof(struct ahc_platform_data) > 0) {
  701                 ahc->platform_data = malloc(sizeof(struct ahc_platform_data),
  702                     M_DEVBUF, M_NOWAIT);
  703                 if (ahc->platform_data == NULL)
  704                         return (ENOMEM);
  705                 bzero(ahc->platform_data, sizeof(struct ahc_platform_data));
  706         }
  707 
  708         return (0);
  709 }
  710 
  711 void
  712 ahc_platform_free(struct ahc_softc *ahc)
  713 {
  714         if (sizeof(struct ahc_platform_data) > 0)
  715                 free(ahc->platform_data, M_DEVBUF);
  716 }
  717 
  718 int
  719 ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc)
  720 {
  721         return (0);
  722 }
  723 
  724 void
  725 ahc_send_async(struct ahc_softc *ahc, char channel, u_int target, u_int lun,
  726                 ac_code code, void *opt_arg)
  727 {
  728         /* Nothing to do here for OpenBSD */
  729 }
  730 
  731 void
  732 ahc_adapter_req_set_xfer_mode(struct ahc_softc *ahc, struct scb *scb)
  733 {
  734         struct ahc_initiator_tinfo *tinfo;
  735         struct ahc_tmode_tstate *tstate;
  736         struct ahc_syncrate *syncrate;
  737         struct ahc_devinfo devinfo;
  738         u_int16_t quirks;
  739         u_int width, ppr_options, period, offset;
  740         int s;
  741 
  742         s = splbio();
  743 
  744         ahc_scb_devinfo(ahc, &devinfo, scb);
  745         quirks = scb->xs->sc_link->quirks;
  746         tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
  747             devinfo.our_scsiid, devinfo.target, &tstate);
  748 
  749         tstate->discenable |= (ahc->user_discenable & devinfo.target_mask);
  750 
  751         if (quirks & SDEV_NOTAGS)
  752                 tstate->tagenable &= ~devinfo.target_mask;
  753         else if (ahc->user_tagenable & devinfo.target_mask)
  754                 tstate->tagenable |= devinfo.target_mask;
  755 
  756         if (quirks & SDEV_NOWIDE)
  757                 width = MSG_EXT_WDTR_BUS_8_BIT;
  758         else
  759                 width = MSG_EXT_WDTR_BUS_16_BIT;
  760 
  761         ahc_validate_width(ahc, NULL, &width, ROLE_UNKNOWN);
  762         if (width > tinfo->user.width)
  763                 width = tinfo->user.width;
  764         ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE);
  765 
  766         if (quirks & SDEV_NOSYNC) {
  767                 period = 0;
  768                 offset = 0;
  769         } else {
  770                 period = tinfo->user.period;
  771                 offset = tinfo->user.offset;
  772         }
  773 
  774         /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */ 
  775         ppr_options = tinfo->user.ppr_options;
  776         /* XXX Other reasons to avoid ppr? XXX */
  777         if (width < MSG_EXT_WDTR_BUS_16_BIT)
  778                 ppr_options = 0;
  779 
  780         if ((tstate->discenable & devinfo.target_mask) == 0 ||
  781             (tstate->tagenable & devinfo.target_mask) == 0)
  782                 ppr_options &= ~MSG_EXT_PPR_PROT_IUS;
  783 
  784         syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
  785             AHC_SYNCRATE_MAX);
  786         ahc_validate_offset(ahc, NULL, syncrate, &offset, width,
  787             ROLE_UNKNOWN);
  788 
  789         if (offset == 0) {
  790                 period = 0;
  791                 ppr_options = 0;
  792         }
  793 
  794         if (ppr_options != 0 && tinfo->user.transport_version >= 3) {
  795                 tinfo->goal.transport_version = tinfo->user.transport_version;
  796                 tinfo->curr.transport_version = tinfo->user.transport_version;
  797         }
  798 
  799         ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset, ppr_options,
  800             AHC_TRANS_GOAL, FALSE);
  801 
  802         splx(s);
  803 }

/* [<][>][^][v][top][bottom][index][help] */