LCOV - code coverage report
Current view: top level - dev/ic - aic7xxx_openbsd.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 337 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13