[BACK]Return to aic7xxx_inline.h CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/aic7xxx_inline.h, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: aic7xxx_inline.h,v 1.14 2007/05/14 01:37:49 deraadt 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: ahc_pause_bug_fix(struct ahc_softc *ahc)
                     78: {
                     79:        if ((ahc->features & AHC_ULTRA2) != 0)
                     80:                (void)ahc_inb(ahc, CCSCBCTL);
                     81: }
                     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: ahc_is_paused(struct ahc_softc *ahc)
                     89: {
                     90:        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: ahc_pause(struct ahc_softc *ahc)
                    102: {
                    103:        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:        while (ahc_is_paused(ahc) == 0)
                    110:                ;
                    111:
                    112:        ahc_pause_bug_fix(ahc);
                    113: }
                    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: ahc_unpause(struct ahc_softc *ahc)
                    127: {
                    128:        if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
                    129:                ahc_outb(ahc, HCNTRL, ahc->unpause);
                    130: }
                    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: ahc_freeze_untagged_queues(struct ahc_softc *ahc)
                    144: {
                    145:        if ((ahc->flags & AHC_SCB_BTT) == 0)
                    146:                ahc->untagged_queue_lock++;
                    147: }
                    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: ahc_release_untagged_queues(struct ahc_softc *ahc)
                    157: {
                    158:        if ((ahc->flags & AHC_SCB_BTT) == 0) {
                    159:                ahc->untagged_queue_lock--;
                    160:                if (ahc->untagged_queue_lock == 0)
                    161:                        ahc_run_untagged_queues(ahc);
                    162:        }
                    163: }
                    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: ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr)
                    188: {
                    189:        int sg_index;
                    190:
                    191:        sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg);
                    192:        /* sg_list_phys points to entry 1, not 0 */
                    193:        sg_index++;
                    194:
                    195:        return (&scb->sg_list[sg_index]);
                    196: }
                    197:
                    198: IO_INLINE uint32_t
                    199: 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:        sg_index = sg - &scb->sg_list[1];
                    205:
                    206:        return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list)));
                    207: }
                    208:
                    209: IO_INLINE uint32_t
                    210: ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
                    211: {
                    212:        return (ahc->scb_data->hscb_busaddr
                    213:                + (sizeof(struct hardware_scb) * index));
                    214: }
                    215:
                    216: IO_INLINE void
                    217: ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
                    218: {
                    219:        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: }
                    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: ahc_name(struct ahc_softc *ahc)
                    239: {
                    240:        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*
                    262:                        ahc_get_scb(struct ahc_softc *ahc);
                    263: IO_INLINE void         ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
                    264: IO_INLINE struct scb *ahc_lookup_scb(struct ahc_softc *ahc, u_int tag);
                    265: IO_INLINE void         ahc_swap_with_next_hscb(struct ahc_softc *ahc,
                    266:                                                struct scb *scb);
                    267: IO_INLINE void         ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb);
                    268: IO_INLINE struct scsi_sense_data *
                    269:                        ahc_get_sense_buf(struct ahc_softc *ahc,
                    270:                                          struct scb *scb);
                    271: IO_INLINE uint32_t
                    272:                        ahc_get_sense_bufaddr(struct ahc_softc *ahc,
                    273:                                              struct scb *scb);
                    274:
                    275: #ifdef IO_EXPAND
                    276:
                    277: /*
                    278:  * Determine whether the sequencer reported a residual
                    279:  * for this SCB/transaction.
                    280:  */
                    281: IO_INLINE void
                    282: ahc_update_residual(struct ahc_softc *ahc, struct scb *scb)
                    283: {
                    284:        uint32_t sgptr;
                    285:
                    286:        sgptr = aic_le32toh(scb->hscb->sgptr);
                    287:        if ((sgptr & SG_RESID_VALID) != 0)
                    288:                ahc_calc_residual(ahc, scb);
                    289: }
                    290:
                    291: /*
                    292:  * Return pointers to the transfer negotiation information
                    293:  * for the specified our_id/remote_id pair.
                    294:  */
                    295: IO_INLINE struct ahc_initiator_tinfo *
                    296: ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
                    297:                    u_int remote_id, struct ahc_tmode_tstate **tstate)
                    298: {
                    299:        /*
                    300:         * Transfer data structures are stored from the perspective
                    301:         * of the target role.  Since the parameters for a connection
                    302:         * in the initiator role to a given target are the same as
                    303:         * when the roles are reversed, we pretend we are the target.
                    304:         */
                    305:        /*if (channel == 'B')
                    306:          our_id += 8;*/
                    307:        *tstate = ahc->enabled_targets[our_id];
                    308:        return (&(*tstate)->transinfo[remote_id]);
                    309: }
                    310:
                    311: IO_INLINE uint16_t
                    312: ahc_inw(struct ahc_softc *ahc, u_int port)
                    313: {
                    314:        return ((ahc_inb(ahc, port+1) << 8) | ahc_inb(ahc, port));
                    315: }
                    316:
                    317: IO_INLINE void
                    318: ahc_outw(struct ahc_softc *ahc, u_int port, u_int value)
                    319: {
                    320:        ahc_outb(ahc, port, value & 0xFF);
                    321:        ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
                    322: }
                    323:
                    324: IO_INLINE uint32_t
                    325: ahc_inl(struct ahc_softc *ahc, u_int port)
                    326: {
                    327:        return ((ahc_inb(ahc, port))
                    328:              | (ahc_inb(ahc, port+1) << 8)
                    329:              | (ahc_inb(ahc, port+2) << 16)
                    330:              | (ahc_inb(ahc, port+3) << 24));
                    331: }
                    332:
                    333: IO_INLINE void
                    334: ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value)
                    335: {
                    336:        ahc_outb(ahc, port, (value) & 0xFF);
                    337:        ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF);
                    338:        ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF);
                    339:        ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF);
                    340: }
                    341:
                    342: /*
                    343:  * Get a free scb. If there are none, see if we can allocate a new SCB.
                    344:  */
                    345: IO_INLINE struct scb *
                    346: ahc_get_scb(struct ahc_softc *ahc)
                    347: {
                    348:        struct scb *scb;
                    349:
                    350:        scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
                    351:
                    352:        if (scb != NULL)
                    353:                SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
                    354:
                    355:        return (scb);
                    356: }
                    357:
                    358: /*
                    359:  * Return an SCB resource to the free list.
                    360:  */
                    361: IO_INLINE void
                    362: ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
                    363: {
                    364:        struct hardware_scb *hscb;
                    365:
                    366:        hscb = scb->hscb;
                    367:        /* Clean up for the next user */
                    368:        ahc->scb_data->scbindex[hscb->tag] = NULL;
                    369:        scb->flags = SCB_FLAG_NONE;
                    370:        hscb->control = 0;
                    371:
                    372:        SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
                    373:
                    374:        /* Notify the OSM that a resource is now available. */
                    375:        ahc_platform_scb_free(ahc, scb);
                    376: }
                    377:
                    378:
                    379: IO_INLINE struct scb *
                    380: ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
                    381: {
                    382:        struct scb* scb;
                    383:
                    384:        scb = ahc->scb_data->scbindex[tag];
                    385:        if (scb != NULL)
                    386:                ahc_sync_scb(ahc, scb,
                    387:                             BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
                    388:        return (scb);
                    389: }
                    390:
                    391:
                    392: IO_INLINE void
                    393: ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb)
                    394: {
                    395:        struct hardware_scb *q_hscb;
                    396:        u_int  saved_tag;
                    397:
                    398:        /*
                    399:         * Our queuing method is a bit tricky.  The card
                    400:         * knows in advance which HSCB to download, and we
                    401:         * can't disappoint it.  To achieve this, the next
                    402:         * SCB to download is saved off in ahc->next_queued_scb.
                    403:         * When we are called to queue "an arbitrary scb",
                    404:         * we copy the contents of the incoming HSCB to the one
                    405:         * the sequencer knows about, swap HSCB pointers and
                    406:         * finally assign the SCB to the tag indexed location
                    407:         * in the scb_array.  This makes sure that we can still
                    408:         * locate the correct SCB by SCB_TAG.
                    409:         */
                    410:        q_hscb = ahc->next_queued_scb->hscb;
                    411:        saved_tag = q_hscb->tag;
                    412:        memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
                    413:        if ((scb->flags & SCB_CDB32_PTR) != 0) {
                    414:                q_hscb->shared_data.cdb_ptr =
                    415:                    aic_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
                    416:                              + offsetof(struct hardware_scb, cdb32));
                    417:        }
                    418:        q_hscb->tag = saved_tag;
                    419:        q_hscb->next = scb->hscb->tag;
                    420:
                    421:        /* Now swap HSCB pointers. */
                    422:        ahc->next_queued_scb->hscb = scb->hscb;
                    423:        scb->hscb = q_hscb;
                    424:
                    425:        /* Now define the mapping from tag to SCB in the scbindex */
                    426:        ahc->scb_data->scbindex[scb->hscb->tag] = scb;
                    427: }
                    428:
                    429: /*
                    430:  * Tell the sequencer about a new transaction to execute.
                    431:  */
                    432: IO_INLINE void
                    433: ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
                    434: {
                    435:        ahc_swap_with_next_hscb(ahc, scb);
                    436:
                    437:        if (scb->hscb->tag == SCB_LIST_NULL
                    438:         || scb->hscb->next == SCB_LIST_NULL)
                    439:                panic("Attempt to queue invalid SCB tag %x:%x",
                    440:                      scb->hscb->tag, scb->hscb->next);
                    441:
                    442:        /*
                    443:         * Setup data "oddness".
                    444:         */
                    445:        scb->hscb->lun &= LID;
                    446:        if (ahc_get_transfer_length(scb) & 0x1)
                    447:                scb->hscb->lun |= SCB_XFERLEN_ODD;
                    448:
                    449:        /*
                    450:         * Keep a history of SCBs we've downloaded in the qinfifo.
                    451:         */
                    452:        ahc->qinfifo[ahc->qinfifonext] = scb->hscb->tag;
                    453:        ahc_dmamap_sync(ahc, ahc->parent_dmat, ahc->shared_data_dmamap,
                    454:                        /*offset*/ahc->qinfifonext+256, /*len*/1,
                    455:                        BUS_DMASYNC_PREWRITE);
                    456:        ahc->qinfifonext++;
                    457:
                    458:        /*
                    459:         * Make sure our data is consistent from the
                    460:         * perspective of the adapter.
                    461:         */
                    462:        ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
                    463:
                    464:        /* Tell the adapter about the newly queued SCB */
                    465:        if ((ahc->features & AHC_QUEUE_REGS) != 0) {
                    466:                ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
                    467:        } else {
                    468:                if ((ahc->features & AHC_AUTOPAUSE) == 0)
                    469:                        ahc_pause(ahc);
                    470:                ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
                    471:                if ((ahc->features & AHC_AUTOPAUSE) == 0)
                    472:                        ahc_unpause(ahc);
                    473:        }
                    474: }
                    475:
                    476:
                    477: IO_INLINE struct scsi_sense_data *
                    478: ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb)
                    479: {
                    480:        int offset;
                    481:
                    482:        offset = scb - ahc->scb_data->scbarray;
                    483:        return (&ahc->scb_data->sense[offset]);
                    484: }
                    485:
                    486: IO_INLINE uint32_t
                    487: ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
                    488: {
                    489:        int offset;
                    490:
                    491:        offset = scb - ahc->scb_data->scbarray;
                    492:        return (ahc->scb_data->sense_busaddr
                    493:              + (offset * sizeof(struct scsi_sense_data)));
                    494: }
                    495: #endif /* IO_EXPAND */
                    496:
                    497: /************************** Interrupt Processing ******************************/
                    498: IO_INLINE void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op);
                    499: IO_INLINE void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op);
                    500: IO_INLINE u_int        ahc_check_cmdcmpltqueues(struct ahc_softc *ahc);
                    501: IO_INLINE int  ahc_intr(struct ahc_softc *ahc);
                    502:
                    503: #ifdef IO_EXPAND
                    504: IO_INLINE void
                    505: ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
                    506: {
                    507:        ahc_dmamap_sync(ahc, ahc->parent_dmat, ahc->shared_data_dmamap,
                    508:                        /*offset*/0, /*len*/256, op);
                    509: }
                    510:
                    511: IO_INLINE void
                    512: ahc_sync_tqinfifo(struct ahc_softc *ahc, int op)
                    513: {
                    514: #ifdef AHC_TARGET_MODE
                    515:        if ((ahc->flags & AHC_TARGETROLE) != 0) {
                    516:          ahc_dmamap_sync(ahc, ahc->parent_dmat /*shared_data_dmat*/,
                    517:                                ahc->shared_data_dmamap,
                    518:                                ahc_targetcmd_offset(ahc, 0),
                    519:                                sizeof(struct target_cmd) * AHC_TMODE_CMDS,
                    520:                                op);
                    521:        }
                    522: #endif
                    523: }
                    524:
                    525: /*
                    526:  * See if the firmware has posted any completed commands
                    527:  * into our in-core command complete fifos.
                    528:  */
                    529: #define AHC_RUN_QOUTFIFO 0x1
                    530: #define AHC_RUN_TQINFIFO 0x2
                    531: IO_INLINE u_int
                    532: ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
                    533: {
                    534:        u_int retval;
                    535:
                    536:        retval = 0;
                    537:        ahc_dmamap_sync(ahc, ahc->parent_dmat /*shared_data_dmat*/, ahc->shared_data_dmamap,
                    538:                        /*offset*/ahc->qoutfifonext, /*len*/1,
                    539:                        BUS_DMASYNC_POSTREAD);
                    540:        if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
                    541:                retval |= AHC_RUN_QOUTFIFO;
                    542: #ifdef AHC_TARGET_MODE
                    543:        if ((ahc->flags & AHC_TARGETROLE) != 0
                    544:            && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) {
                    545:          ahc_dmamap_sync(ahc, ahc->parent_dmat /*shared_data_dmat*/,
                    546:                          ahc->shared_data_dmamap,
                    547:                          ahc_targetcmd_offset(ahc, ahc->tqinfifonext),
                    548:                          /*len*/sizeof(struct target_cmd),
                    549:                          BUS_DMASYNC_POSTREAD);
                    550:                if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
                    551:                        retval |= AHC_RUN_TQINFIFO;
                    552:        }
                    553: #endif
                    554:        return (retval);
                    555: }
                    556:
                    557:
                    558: /*
                    559:  * Catch an interrupt from the adapter
                    560:  */
                    561: IO_INLINE int
                    562: ahc_intr(struct ahc_softc *ahc)
                    563: {
                    564:        u_int   intstat;
                    565:
                    566:        if ((ahc->pause & INTEN) == 0) {
                    567:                /*
                    568:                 * Our interrupt is not enabled on the chip
                    569:                 * and may be disabled for re-entrancy reasons,
                    570:                 * so just return.  This is likely just a shared
                    571:                 * interrupt.
                    572:                 */
                    573:                return (0);
                    574:        }
                    575:        /*
                    576:         * Instead of directly reading the interrupt status register,
                    577:         * infer the cause of the interrupt by checking our in-core
                    578:         * completion queues.  This avoids a costly PCI bus read in
                    579:         * most cases.
                    580:         */
                    581:        if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
                    582:            && (ahc_check_cmdcmpltqueues(ahc) != 0))
                    583:                 intstat = CMDCMPLT;
                    584:         else {
                    585:                 intstat = ahc_inb(ahc, INTSTAT);
                    586:         }
                    587:
                    588:         if (intstat & CMDCMPLT) {
                    589:                ahc_outb(ahc, CLRINT, CLRCMDINT);
                    590:
                    591:                /*
                    592:                 * Ensure that the chip sees that we've cleared
                    593:                 * this interrupt before we walk the output fifo.
                    594:                 * Otherwise, we may, due to posted bus writes,
                    595:                 * clear the interrupt after we finish the scan,
                    596:                 * and after the sequencer has added new entries
                    597:                 * and asserted the interrupt again.
                    598:                 */
                    599:                ahc_flush_device_writes(ahc);
                    600:                ahc_run_qoutfifo(ahc);
                    601: #ifdef AHC_TARGET_MODE
                    602:                if ((ahc->flags & AHC_TARGETROLE) != 0)
                    603:                        ahc_run_tqinfifo(ahc, /*paused*/FALSE);
                    604: #endif
                    605:        }
                    606:
                    607:        if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
                    608:                /* Hot eject */
                    609:                return 1;
                    610:
                    611:        if ((intstat & INT_PEND) == 0) {
                    612: #if AHC_PCI_CONFIG > 0
                    613:                if (ahc->unsolicited_ints > 500) {
                    614:                        ahc->unsolicited_ints = 0;
                    615:                        if ((ahc->chip & AHC_PCI) != 0
                    616:                         && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
                    617:                                ahc->bus_intr(ahc);
                    618:                }
                    619:                ahc->unsolicited_ints++;
                    620: #endif
                    621:                return 0;
                    622:        }
                    623:        ahc->unsolicited_ints = 0;
                    624:
                    625:        if (intstat & BRKADRINT) {
                    626:                ahc_handle_brkadrint(ahc);
                    627:                /* Fatal error, no more interrupts to handle. */
                    628:                return 1;
                    629:        }
                    630:
                    631:        if ((intstat & (SEQINT|SCSIINT)) != 0)
                    632:                ahc_pause_bug_fix(ahc);
                    633:
                    634:        if ((intstat & SEQINT) != 0)
                    635:                ahc_handle_seqint(ahc, intstat);
                    636:
                    637:        if ((intstat & SCSIINT) != 0)
                    638:                ahc_handle_scsiint(ahc, intstat);
                    639:
                    640:        return (1);
                    641: }
                    642:
                    643: #endif /* IO_EXPAND */
                    644:
                    645: #endif  /* _AIC7XXX_INLINE_H_ */

CVSweb