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

          Line data    Source code
       1             : /*      $OpenBSD: aic7xxx_inline.h,v 1.17 2016/08/17 01:17:54 krw Exp $ */
       2             : /*      $NetBSD: aic7xxx_inline.h,v 1.4 2003/11/02 11:07:44 wiz Exp $   */
       3             : 
       4             : /*
       5             :  * Inline routines shareable across OS platforms.
       6             :  *
       7             :  * Copyright (c) 1994-2001 Justin T. Gibbs.
       8             :  * Copyright (c) 2000-2001 Adaptec Inc.
       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. Redistributions in binary form must reproduce at minimum a disclaimer
      18             :  *    substantially similar to the "NO WARRANTY" disclaimer below
      19             :  *    ("Disclaimer") and any redistribution must be conditioned upon
      20             :  *    including a substantially similar Disclaimer requirement for further
      21             :  *    binary redistribution.
      22             :  * 3. Neither the names of the above-listed copyright holders nor the names
      23             :  *    of any contributors may be used to endorse or promote products derived
      24             :  *    from this software without specific prior written permission.
      25             :  *
      26             :  * Alternatively, this software may be distributed under the terms of the
      27             :  * GNU General Public License ("GPL") version 2 as published by the Free
      28             :  * Software Foundation.
      29             :  *
      30             :  * NO WARRANTY
      31             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      32             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      33             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
      34             :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      35             :  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      36             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      37             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      38             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      39             :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
      40             :  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      41             :  * POSSIBILITY OF SUCH DAMAGES.
      42             :  *
      43             :  * //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#39 $
      44             :  *
      45             :  * $FreeBSD: /repoman/r/ncvs/src/sys/dev/aic7xxx/aic7xxx_inline.h,v 1.20 2003/01/20 20:44:55 gibbs Exp $
      46             :  */
      47             : /*
      48             :  * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc. - April 2003
      49             :  */
      50             : 
      51             : #ifndef _AIC7XXX_INLINE_H_
      52             : #define _AIC7XXX_INLINE_H_
      53             : 
      54             : #ifdef SMALL_KERNEL
      55             : #define IO_INLINE
      56             : #else
      57             : #define IO_INLINE       static __inline
      58             : #define IO_EXPAND
      59             : #endif
      60             : 
      61             : /************************* Sequencer Execution Control ************************/
      62             : IO_INLINE void ahc_pause_bug_fix(struct ahc_softc *ahc);
      63             : IO_INLINE int  ahc_is_paused(struct ahc_softc *ahc);
      64             : IO_INLINE void ahc_pause(struct ahc_softc *ahc);
      65             : IO_INLINE void ahc_unpause(struct ahc_softc *ahc);
      66             : 
      67             : #ifdef IO_EXPAND
      68             : /*
      69             :  * Work around any chip bugs related to halting sequencer execution.
      70             :  * On Ultra2 controllers, we must clear the CIOBUS stretch signal by
      71             :  * reading a register that will set this signal and deassert it.
      72             :  * Without this workaround, if the chip is paused, by an interrupt or
      73             :  * manual pause while accessing scb ram, accesses to certain registers
      74             :  * will hang the system (infinite pci retries).
      75             :  */
      76             : IO_INLINE void
      77           0 : ahc_pause_bug_fix(struct ahc_softc *ahc)
      78             : {
      79           0 :         if ((ahc->features & AHC_ULTRA2) != 0)
      80           0 :                 (void)ahc_inb(ahc, CCSCBCTL);
      81           0 : }
      82             : 
      83             : /*
      84             :  * Determine whether the sequencer has halted code execution.
      85             :  * Returns non-zero status if the sequencer is stopped.
      86             :  */
      87             : IO_INLINE int
      88           0 : ahc_is_paused(struct ahc_softc *ahc)
      89             : {
      90           0 :         return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
      91             : }
      92             : 
      93             : /*
      94             :  * Request that the sequencer stop and wait, indefinitely, for it
      95             :  * to stop.  The sequencer will only acknowledge that it is paused
      96             :  * once it has reached an instruction boundary and PAUSEDIS is
      97             :  * cleared in the SEQCTL register.  The sequencer may use PAUSEDIS
      98             :  * for critical sections.
      99             :  */
     100             : IO_INLINE void
     101           0 : ahc_pause(struct ahc_softc *ahc)
     102             : {
     103           0 :         ahc_outb(ahc, HCNTRL, ahc->pause);
     104             : 
     105             :         /*
     106             :          * Since the sequencer can disable pausing in a critical section, we
     107             :          * must loop until it actually stops.
     108             :          */
     109           0 :         while (ahc_is_paused(ahc) == 0)
     110             :                 ;
     111             : 
     112           0 :         ahc_pause_bug_fix(ahc);
     113           0 : }
     114             : 
     115             : /*
     116             :  * Allow the sequencer to continue program execution.
     117             :  * We check here to ensure that no additional interrupt
     118             :  * sources that would cause the sequencer to halt have been
     119             :  * asserted.  If, for example, a SCSI bus reset is detected
     120             :  * while we are fielding a different, pausing, interrupt type,
     121             :  * we don't want to release the sequencer before going back
     122             :  * into our interrupt handler and dealing with this new
     123             :  * condition.
     124             :  */
     125             : IO_INLINE void
     126           0 : ahc_unpause(struct ahc_softc *ahc)
     127             : {
     128           0 :         if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
     129           0 :                 ahc_outb(ahc, HCNTRL, ahc->unpause);
     130           0 : }
     131             : #endif /* IO_EXPAND */
     132             : 
     133             : /*********************** Untagged Transaction Routines ************************/
     134             : IO_INLINE void  ahc_freeze_untagged_queues(struct ahc_softc *ahc);
     135             : IO_INLINE void  ahc_release_untagged_queues(struct ahc_softc *ahc);
     136             : 
     137             : #ifdef IO_EXPAND
     138             : /*
     139             :  * Block our completion routine from starting the next untagged
     140             :  * transaction for this target or target lun.
     141             :  */
     142             : IO_INLINE void
     143           0 : ahc_freeze_untagged_queues(struct ahc_softc *ahc)
     144             : {
     145           0 :         if ((ahc->flags & AHC_SCB_BTT) == 0)
     146           0 :                 ahc->untagged_queue_lock++;
     147           0 : }
     148             : 
     149             : /*
     150             :  * Allow the next untagged transaction for this target or target lun
     151             :  * to be executed.  We use a counting semaphore to allow the lock
     152             :  * to be acquired recursively.  Once the count drops to zero, the
     153             :  * transaction queues will be run.
     154             :  */
     155             : IO_INLINE void
     156           0 : ahc_release_untagged_queues(struct ahc_softc *ahc)
     157             : {
     158           0 :         if ((ahc->flags & AHC_SCB_BTT) == 0) {
     159           0 :                 ahc->untagged_queue_lock--;
     160           0 :                 if (ahc->untagged_queue_lock == 0)
     161           0 :                         ahc_run_untagged_queues(ahc);
     162             :         }
     163           0 : }
     164             : #endif /* IO_EXPAND */
     165             : 
     166             : 
     167             : /************************** Memory mapping routines ***************************/
     168             : IO_INLINE struct ahc_dma_seg *
     169             :                         ahc_sg_bus_to_virt(struct scb *scb,
     170             :                                            uint32_t sg_busaddr);
     171             : IO_INLINE uint32_t
     172             :                         ahc_sg_virt_to_bus(struct scb *scb,
     173             :                                            struct ahc_dma_seg *sg);
     174             : IO_INLINE uint32_t
     175             :                         ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index);
     176             : IO_INLINE void          ahc_sync_scb(struct ahc_softc *ahc,
     177             :                                            struct scb *scb, int op);
     178             : #ifdef AHC_TARGET_MODE
     179             : IO_INLINE uint32_t
     180             :                         ahc_targetcmd_offset(struct ahc_softc *ahc,
     181             :                                              u_int index);
     182             : #endif
     183             : 
     184             : #ifdef IO_EXPAND
     185             : 
     186             : IO_INLINE struct ahc_dma_seg *
     187           0 : ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr)
     188             : {
     189             :         int sg_index;
     190             : 
     191           0 :         sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg);
     192             :         /* sg_list_phys points to entry 1, not 0 */
     193           0 :         sg_index++;
     194             : 
     195           0 :         return (&scb->sg_list[sg_index]);
     196             : }
     197             : 
     198             : IO_INLINE uint32_t
     199           0 : ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg)
     200             : {
     201             :         int sg_index;
     202             : 
     203             :         /* sg_list_phys points to entry 1, not 0 */
     204           0 :         sg_index = sg - &scb->sg_list[1];
     205             : 
     206           0 :         return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list)));
     207             : }
     208             : 
     209             : IO_INLINE uint32_t
     210           0 : ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
     211             : {
     212           0 :         return (ahc->scb_data->hscb_busaddr
     213           0 :                 + (sizeof(struct hardware_scb) * index));
     214             : }
     215             : 
     216             : IO_INLINE void
     217           0 : ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
     218             : {
     219           0 :         ahc_dmamap_sync(ahc, ahc->parent_dmat,
     220             :                         ahc->scb_data->hscb_dmamap,
     221             :                         /*offset*/(scb->hscb - ahc->scb_data->hscbs) * sizeof(*scb->hscb),
     222             :                         /*len*/sizeof(*scb->hscb), op);
     223           0 : }
     224             : 
     225             : #ifdef AHC_TARGET_MODE
     226             : IO_INLINE uint32_t
     227             : ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index)
     228             : {
     229             :         return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo);
     230             : }
     231             : #endif /* AHC_TARGET_MODE */
     232             : #endif /* IO_EXPAND */
     233             : 
     234             : /******************************** Debugging ***********************************/
     235             : static __inline char *ahc_name(struct ahc_softc *ahc);
     236             : 
     237             : static __inline char *
     238           0 : ahc_name(struct ahc_softc *ahc)
     239             : {
     240           0 :         return (ahc->name);
     241             : }
     242             : 
     243             : /*********************** Miscellaneous Support Functions ***********************/
     244             : 
     245             : IO_INLINE void  ahc_update_residual(struct ahc_softc *ahc,
     246             :                                             struct scb *scb);
     247             : IO_INLINE struct ahc_initiator_tinfo *
     248             :                         ahc_fetch_transinfo(struct ahc_softc *ahc,
     249             :                                             char channel, u_int our_id,
     250             :                                             u_int remote_id,
     251             :                                             struct ahc_tmode_tstate **tstate);
     252             : 
     253             : IO_INLINE uint16_t
     254             :                         ahc_inw(struct ahc_softc *ahc, u_int port);
     255             : IO_INLINE void  ahc_outw(struct ahc_softc *ahc, u_int port,
     256             :                                  u_int value);
     257             : IO_INLINE uint32_t
     258             :                         ahc_inl(struct ahc_softc *ahc, u_int port);
     259             : IO_INLINE void  ahc_outl(struct ahc_softc *ahc, u_int port,
     260             :                                  uint32_t value);
     261             : IO_INLINE struct scb *ahc_lookup_scb(struct ahc_softc *ahc, u_int tag);
     262             : IO_INLINE void          ahc_swap_with_next_hscb(struct ahc_softc *ahc,
     263             :                                                 struct scb *scb);
     264             : IO_INLINE void          ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb);
     265             : IO_INLINE struct scsi_sense_data *
     266             :                         ahc_get_sense_buf(struct ahc_softc *ahc,
     267             :                                           struct scb *scb);
     268             : IO_INLINE uint32_t
     269             :                         ahc_get_sense_bufaddr(struct ahc_softc *ahc,
     270             :                                               struct scb *scb);
     271             : 
     272             : #ifdef IO_EXPAND
     273             : 
     274             : /*
     275             :  * Determine whether the sequencer reported a residual
     276             :  * for this SCB/transaction.
     277             :  */
     278             : IO_INLINE void
     279           0 : ahc_update_residual(struct ahc_softc *ahc, struct scb *scb)
     280             : {
     281             :         uint32_t sgptr;
     282             : 
     283           0 :         sgptr = aic_le32toh(scb->hscb->sgptr);
     284           0 :         if ((sgptr & SG_RESID_VALID) != 0)
     285           0 :                 ahc_calc_residual(ahc, scb);
     286           0 : }
     287             : 
     288             : /*
     289             :  * Return pointers to the transfer negotiation information
     290             :  * for the specified our_id/remote_id pair.
     291             :  */
     292             : IO_INLINE struct ahc_initiator_tinfo *
     293           0 : ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
     294             :                     u_int remote_id, struct ahc_tmode_tstate **tstate)
     295             : {
     296             :         /*
     297             :          * Transfer data structures are stored from the perspective
     298             :          * of the target role.  Since the parameters for a connection
     299             :          * in the initiator role to a given target are the same as
     300             :          * when the roles are reversed, we pretend we are the target.
     301             :          */
     302           0 :         if (channel == 'B')
     303           0 :                 our_id += 8;
     304           0 :         *tstate = ahc->enabled_targets[our_id];
     305           0 :         return (&(*tstate)->transinfo[remote_id]);
     306             : }
     307             : 
     308             : IO_INLINE uint16_t
     309           0 : ahc_inw(struct ahc_softc *ahc, u_int port)
     310             : {
     311           0 :         return ((ahc_inb(ahc, port+1) << 8) | ahc_inb(ahc, port));
     312             : }
     313             : 
     314             : IO_INLINE void
     315           0 : ahc_outw(struct ahc_softc *ahc, u_int port, u_int value)
     316             : {
     317           0 :         ahc_outb(ahc, port, value & 0xFF);
     318           0 :         ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
     319           0 : }
     320             : 
     321             : IO_INLINE uint32_t
     322           0 : ahc_inl(struct ahc_softc *ahc, u_int port)
     323             : {
     324           0 :         return ((ahc_inb(ahc, port))
     325           0 :               | (ahc_inb(ahc, port+1) << 8)
     326           0 :               | (ahc_inb(ahc, port+2) << 16)
     327           0 :               | (ahc_inb(ahc, port+3) << 24));
     328             : }
     329             : 
     330             : IO_INLINE void
     331           0 : ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value)
     332             : {
     333           0 :         ahc_outb(ahc, port, (value) & 0xFF);
     334           0 :         ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF);
     335           0 :         ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF);
     336           0 :         ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF);
     337           0 : }
     338             : 
     339             : IO_INLINE struct scb *
     340           0 : ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
     341             : {
     342             :         struct scb* scb;
     343             : 
     344           0 :         scb = ahc->scb_data->scbindex[tag];
     345           0 :         if (scb != NULL)
     346           0 :                 ahc_sync_scb(ahc, scb,
     347             :                              BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
     348           0 :         return (scb);
     349             : }
     350             : 
     351             : 
     352             : IO_INLINE void
     353           0 : ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb)
     354             : {
     355             :         struct hardware_scb *q_hscb;
     356             :         u_int  saved_tag;
     357             : 
     358             :         /*
     359             :          * Our queuing method is a bit tricky.  The card
     360             :          * knows in advance which HSCB to download, and we
     361             :          * can't disappoint it.  To achieve this, the next
     362             :          * SCB to download is saved off in ahc->next_queued_scb.
     363             :          * When we are called to queue "an arbitrary scb",
     364             :          * we copy the contents of the incoming HSCB to the one
     365             :          * the sequencer knows about, swap HSCB pointers and
     366             :          * finally assign the SCB to the tag indexed location
     367             :          * in the scb_array.  This makes sure that we can still
     368             :          * locate the correct SCB by SCB_TAG.
     369             :          */
     370           0 :         q_hscb = ahc->next_queued_scb->hscb;
     371           0 :         saved_tag = q_hscb->tag;
     372           0 :         memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
     373           0 :         if ((scb->flags & SCB_CDB32_PTR) != 0) {
     374           0 :                 q_hscb->shared_data.cdb_ptr =
     375           0 :                     aic_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
     376             :                               + offsetof(struct hardware_scb, cdb32));
     377           0 :         }
     378           0 :         q_hscb->tag = saved_tag;
     379           0 :         q_hscb->next = scb->hscb->tag;
     380             : 
     381             :         /* Now swap HSCB pointers. */
     382           0 :         ahc->next_queued_scb->hscb = scb->hscb;
     383           0 :         scb->hscb = q_hscb;
     384             : 
     385             :         /* Now define the mapping from tag to SCB in the scbindex */
     386           0 :         ahc->scb_data->scbindex[scb->hscb->tag] = scb;
     387           0 : }
     388             : 
     389             : /*
     390             :  * Tell the sequencer about a new transaction to execute.
     391             :  */
     392             : IO_INLINE void
     393           0 : ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
     394             : {
     395           0 :         ahc_swap_with_next_hscb(ahc, scb);
     396             : 
     397           0 :         if (scb->hscb->tag == SCB_LIST_NULL
     398           0 :          || scb->hscb->next == SCB_LIST_NULL)
     399           0 :                 panic("Attempt to queue invalid SCB tag %x:%x",
     400           0 :                       scb->hscb->tag, scb->hscb->next);
     401             : 
     402             :         /*
     403             :          * Setup data "oddness".
     404             :          */
     405           0 :         scb->hscb->lun &= LID;
     406           0 :         if (ahc_get_transfer_length(scb) & 0x1)
     407           0 :                 scb->hscb->lun |= SCB_XFERLEN_ODD;
     408             : 
     409             :         /*
     410             :          * Keep a history of SCBs we've downloaded in the qinfifo.
     411             :          */
     412           0 :         ahc->qinfifo[ahc->qinfifonext] = scb->hscb->tag;
     413           0 :         ahc_dmamap_sync(ahc, ahc->parent_dmat, ahc->shared_data_dmamap,
     414             :                         /*offset*/ahc->qinfifonext+256, /*len*/1,
     415             :                         BUS_DMASYNC_PREWRITE);
     416           0 :         ahc->qinfifonext++;
     417             : 
     418             :         /*
     419             :          * Make sure our data is consistent from the
     420             :          * perspective of the adapter.
     421             :          */
     422           0 :         ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
     423             : 
     424             :         /* Tell the adapter about the newly queued SCB */
     425           0 :         if ((ahc->features & AHC_QUEUE_REGS) != 0) {
     426           0 :                 ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
     427           0 :         } else {
     428           0 :                 if ((ahc->features & AHC_AUTOPAUSE) == 0)
     429           0 :                         ahc_pause(ahc);
     430           0 :                 ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
     431           0 :                 if ((ahc->features & AHC_AUTOPAUSE) == 0)
     432           0 :                         ahc_unpause(ahc);
     433             :         }
     434           0 : }
     435             : 
     436             : 
     437             : IO_INLINE struct scsi_sense_data *
     438           0 : ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb)
     439             : {
     440             :         int offset;
     441             : 
     442           0 :         offset = scb - ahc->scb_data->scbarray;
     443           0 :         return (&ahc->scb_data->sense[offset]);
     444             : }
     445             : 
     446             : IO_INLINE uint32_t
     447           0 : ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
     448             : {
     449             :         int offset;
     450             : 
     451           0 :         offset = scb - ahc->scb_data->scbarray;
     452           0 :         return (ahc->scb_data->sense_busaddr
     453           0 :               + (offset * sizeof(struct scsi_sense_data)));
     454             : }
     455             : #endif /* IO_EXPAND */
     456             : 
     457             : /************************** Interrupt Processing ******************************/
     458             : IO_INLINE void  ahc_sync_qoutfifo(struct ahc_softc *ahc, int op);
     459             : IO_INLINE void  ahc_sync_tqinfifo(struct ahc_softc *ahc, int op);
     460             : IO_INLINE u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc);
     461             : IO_INLINE int   ahc_intr(struct ahc_softc *ahc);
     462             : 
     463             : #ifdef IO_EXPAND
     464             : IO_INLINE void
     465           0 : ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
     466             : {
     467           0 :         ahc_dmamap_sync(ahc, ahc->parent_dmat, ahc->shared_data_dmamap,
     468             :                         /*offset*/0, /*len*/256, op);
     469           0 : }
     470             : 
     471             : IO_INLINE void
     472           0 : ahc_sync_tqinfifo(struct ahc_softc *ahc, int op)
     473             : {
     474             : #ifdef AHC_TARGET_MODE
     475             :         if ((ahc->flags & AHC_TARGETROLE) != 0) {
     476             :           ahc_dmamap_sync(ahc, ahc->parent_dmat /*shared_data_dmat*/,
     477             :                                 ahc->shared_data_dmamap,
     478             :                                 ahc_targetcmd_offset(ahc, 0),
     479             :                                 sizeof(struct target_cmd) * AHC_TMODE_CMDS,
     480             :                                 op);
     481             :         }
     482             : #endif
     483           0 : }
     484             : 
     485             : /*
     486             :  * See if the firmware has posted any completed commands
     487             :  * into our in-core command complete fifos.
     488             :  */
     489             : #define AHC_RUN_QOUTFIFO 0x1
     490             : #define AHC_RUN_TQINFIFO 0x2
     491             : IO_INLINE u_int
     492           0 : ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
     493             : {
     494             :         u_int retval;
     495             : 
     496             :         retval = 0;
     497           0 :         ahc_dmamap_sync(ahc, ahc->parent_dmat /*shared_data_dmat*/, ahc->shared_data_dmamap,
     498             :                         /*offset*/ahc->qoutfifonext, /*len*/1,
     499             :                         BUS_DMASYNC_POSTREAD);
     500           0 :         if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
     501           0 :                 retval |= AHC_RUN_QOUTFIFO;
     502             : #ifdef AHC_TARGET_MODE
     503             :         if ((ahc->flags & AHC_TARGETROLE) != 0
     504             :             && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) {
     505             :           ahc_dmamap_sync(ahc, ahc->parent_dmat /*shared_data_dmat*/,
     506             :                           ahc->shared_data_dmamap,
     507             :                           ahc_targetcmd_offset(ahc, ahc->tqinfifonext),
     508             :                           /*len*/sizeof(struct target_cmd),
     509             :                           BUS_DMASYNC_POSTREAD);
     510             :                 if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
     511             :                         retval |= AHC_RUN_TQINFIFO;
     512             :         }
     513             : #endif
     514           0 :         return (retval);
     515             : }
     516             : 
     517             : 
     518             : /*
     519             :  * Catch an interrupt from the adapter
     520             :  */
     521             : IO_INLINE int
     522           0 : ahc_intr(struct ahc_softc *ahc)
     523             : {
     524             :         u_int   intstat;
     525             : 
     526           0 :         if ((ahc->pause & INTEN) == 0) {
     527             :                 /*
     528             :                  * Our interrupt is not enabled on the chip
     529             :                  * and may be disabled for re-entrancy reasons,
     530             :                  * so just return.  This is likely just a shared
     531             :                  * interrupt.
     532             :                  */
     533           0 :                 return (0);
     534             :         }
     535             :         /*
     536             :          * Instead of directly reading the interrupt status register,
     537             :          * infer the cause of the interrupt by checking our in-core
     538             :          * completion queues.  This avoids a costly PCI bus read in
     539             :          * most cases.
     540             :          */
     541           0 :         if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
     542           0 :             && (ahc_check_cmdcmpltqueues(ahc) != 0))
     543           0 :                 intstat = CMDCMPLT;
     544             :         else {
     545           0 :                 intstat = ahc_inb(ahc, INTSTAT);
     546             :         }
     547             : 
     548           0 :         if (intstat & CMDCMPLT) {
     549           0 :                 ahc_outb(ahc, CLRINT, CLRCMDINT);
     550             : 
     551             :                 /*
     552             :                  * Ensure that the chip sees that we've cleared
     553             :                  * this interrupt before we walk the output fifo.
     554             :                  * Otherwise, we may, due to posted bus writes,
     555             :                  * clear the interrupt after we finish the scan,
     556             :                  * and after the sequencer has added new entries
     557             :                  * and asserted the interrupt again.
     558             :                  */
     559           0 :                 ahc_flush_device_writes(ahc);
     560           0 :                 ahc_run_qoutfifo(ahc);
     561             : #ifdef AHC_TARGET_MODE
     562             :                 if ((ahc->flags & AHC_TARGETROLE) != 0)
     563             :                         ahc_run_tqinfifo(ahc, /*paused*/FALSE);
     564             : #endif
     565           0 :         }
     566             : 
     567           0 :         if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
     568             :                 /* Hot eject */
     569           0 :                 return 1;
     570             : 
     571           0 :         if ((intstat & INT_PEND) == 0) {
     572             : #if AHC_PCI_CONFIG > 0
     573           0 :                 if (ahc->unsolicited_ints > 500) {
     574           0 :                         ahc->unsolicited_ints = 0;
     575           0 :                         if ((ahc->chip & AHC_PCI) != 0
     576           0 :                          && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
     577           0 :                                 ahc->bus_intr(ahc);
     578             :                 }
     579           0 :                 ahc->unsolicited_ints++;
     580             : #endif
     581           0 :                 return 0;
     582             :         }
     583           0 :         ahc->unsolicited_ints = 0;
     584             : 
     585           0 :         if (intstat & BRKADRINT) {
     586           0 :                 ahc_handle_brkadrint(ahc);
     587             :                 /* Fatal error, no more interrupts to handle. */
     588           0 :                 return 1;
     589             :         }
     590             : 
     591           0 :         if ((intstat & (SEQINT|SCSIINT)) != 0)
     592           0 :                 ahc_pause_bug_fix(ahc);
     593             : 
     594           0 :         if ((intstat & SEQINT) != 0)
     595           0 :                 ahc_handle_seqint(ahc, intstat);
     596             : 
     597           0 :         if ((intstat & SCSIINT) != 0)
     598           0 :                 ahc_handle_scsiint(ahc, intstat);
     599             : 
     600           0 :         return (1);
     601           0 : }
     602             : 
     603             : #endif  /* IO_EXPAND */
     604             : 
     605             : #endif  /* _AIC7XXX_INLINE_H_ */

Generated by: LCOV version 1.13