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