1098ca2bdSWarner Losh /*- 2717d4247SJustin T. Gibbs * Inline routines shareable across OS platforms. 3717d4247SJustin T. Gibbs * 4718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 5718cf2ccSPedro F. Giffuni * 664a3876fSJustin T. Gibbs * Copyright (c) 1994-2001 Justin T. Gibbs. 78f214efcSJustin T. Gibbs * Copyright (c) 2000-2001 Adaptec Inc. 8717d4247SJustin T. Gibbs * All rights reserved. 9717d4247SJustin T. Gibbs * 10717d4247SJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 11717d4247SJustin T. Gibbs * modification, are permitted provided that the following conditions 12717d4247SJustin T. Gibbs * are met: 13717d4247SJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 14717d4247SJustin T. Gibbs * notice, this list of conditions, and the following disclaimer, 15717d4247SJustin T. Gibbs * without modification. 168f214efcSJustin T. Gibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer 178f214efcSJustin T. Gibbs * substantially similar to the "NO WARRANTY" disclaimer below 188f214efcSJustin T. Gibbs * ("Disclaimer") and any redistribution must be conditioned upon 198f214efcSJustin T. Gibbs * including a substantially similar Disclaimer requirement for further 208f214efcSJustin T. Gibbs * binary redistribution. 218f214efcSJustin T. Gibbs * 3. Neither the names of the above-listed copyright holders nor the names 228f214efcSJustin T. Gibbs * of any contributors may be used to endorse or promote products derived 238f214efcSJustin T. Gibbs * from this software without specific prior written permission. 24717d4247SJustin T. Gibbs * 25717d4247SJustin T. Gibbs * Alternatively, this software may be distributed under the terms of the 268f214efcSJustin T. Gibbs * GNU General Public License ("GPL") version 2 as published by the Free 278f214efcSJustin T. Gibbs * Software Foundation. 28717d4247SJustin T. Gibbs * 298f214efcSJustin T. Gibbs * NO WARRANTY 308f214efcSJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 318f214efcSJustin T. Gibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 328f214efcSJustin T. Gibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 338f214efcSJustin T. Gibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 348f214efcSJustin T. Gibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35717d4247SJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36717d4247SJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 378f214efcSJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 388f214efcSJustin T. Gibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 398f214efcSJustin T. Gibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 408f214efcSJustin T. Gibbs * POSSIBILITY OF SUCH DAMAGES. 41717d4247SJustin T. Gibbs * 42b3b25f2cSJustin T. Gibbs * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#47 $ 43717d4247SJustin T. Gibbs */ 44717d4247SJustin T. Gibbs 45717d4247SJustin T. Gibbs #ifndef _AIC7XXX_INLINE_H_ 46717d4247SJustin T. Gibbs #define _AIC7XXX_INLINE_H_ 47717d4247SJustin T. Gibbs 48717d4247SJustin T. Gibbs /************************* Sequencer Execution Control ************************/ 49717d4247SJustin T. Gibbs static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc); 50cd036e89SJustin T. Gibbs static __inline int ahc_is_paused(struct ahc_softc *ahc); 516fb77fefSJustin T. Gibbs static __inline void ahc_pause(struct ahc_softc *ahc); 526fb77fefSJustin T. Gibbs static __inline void ahc_unpause(struct ahc_softc *ahc); 53717d4247SJustin T. Gibbs 54717d4247SJustin T. Gibbs /* 55717d4247SJustin T. Gibbs * Work around any chip bugs related to halting sequencer execution. 56717d4247SJustin T. Gibbs * On Ultra2 controllers, we must clear the CIOBUS stretch signal by 57717d4247SJustin T. Gibbs * reading a register that will set this signal and deassert it. 58717d4247SJustin T. Gibbs * Without this workaround, if the chip is paused, by an interrupt or 59717d4247SJustin T. Gibbs * manual pause while accessing scb ram, accesses to certain registers 60717d4247SJustin T. Gibbs * will hang the system (infinite pci retries). 61717d4247SJustin T. Gibbs */ 62717d4247SJustin T. Gibbs static __inline void 63717d4247SJustin T. Gibbs ahc_pause_bug_fix(struct ahc_softc *ahc) 64717d4247SJustin T. Gibbs { 65717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) 66717d4247SJustin T. Gibbs (void)ahc_inb(ahc, CCSCBCTL); 67717d4247SJustin T. Gibbs } 68717d4247SJustin T. Gibbs 69717d4247SJustin T. Gibbs /* 70717d4247SJustin T. Gibbs * Determine whether the sequencer has halted code execution. 71717d4247SJustin T. Gibbs * Returns non-zero status if the sequencer is stopped. 72717d4247SJustin T. Gibbs */ 73717d4247SJustin T. Gibbs static __inline int 746fb77fefSJustin T. Gibbs ahc_is_paused(struct ahc_softc *ahc) 75717d4247SJustin T. Gibbs { 76717d4247SJustin T. Gibbs return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0); 77717d4247SJustin T. Gibbs } 78717d4247SJustin T. Gibbs 79717d4247SJustin T. Gibbs /* 80717d4247SJustin T. Gibbs * Request that the sequencer stop and wait, indefinitely, for it 81717d4247SJustin T. Gibbs * to stop. The sequencer will only acknowledge that it is paused 82717d4247SJustin T. Gibbs * once it has reached an instruction boundary and PAUSEDIS is 83717d4247SJustin T. Gibbs * cleared in the SEQCTL register. The sequencer may use PAUSEDIS 84717d4247SJustin T. Gibbs * for critical sections. 85717d4247SJustin T. Gibbs */ 86717d4247SJustin T. Gibbs static __inline void 876fb77fefSJustin T. Gibbs ahc_pause(struct ahc_softc *ahc) 88717d4247SJustin T. Gibbs { 89717d4247SJustin T. Gibbs ahc_outb(ahc, HCNTRL, ahc->pause); 90717d4247SJustin T. Gibbs 91717d4247SJustin T. Gibbs /* 92717d4247SJustin T. Gibbs * Since the sequencer can disable pausing in a critical section, we 93717d4247SJustin T. Gibbs * must loop until it actually stops. 94717d4247SJustin T. Gibbs */ 956fb77fefSJustin T. Gibbs while (ahc_is_paused(ahc) == 0) 96717d4247SJustin T. Gibbs ; 97717d4247SJustin T. Gibbs 98717d4247SJustin T. Gibbs ahc_pause_bug_fix(ahc); 99717d4247SJustin T. Gibbs } 100717d4247SJustin T. Gibbs 101717d4247SJustin T. Gibbs /* 102717d4247SJustin T. Gibbs * Allow the sequencer to continue program execution. 103717d4247SJustin T. Gibbs * We check here to ensure that no additional interrupt 104717d4247SJustin T. Gibbs * sources that would cause the sequencer to halt have been 105717d4247SJustin T. Gibbs * asserted. If, for example, a SCSI bus reset is detected 106717d4247SJustin T. Gibbs * while we are fielding a different, pausing, interrupt type, 107717d4247SJustin T. Gibbs * we don't want to release the sequencer before going back 108717d4247SJustin T. Gibbs * into our interrupt handler and dealing with this new 109717d4247SJustin T. Gibbs * condition. 110717d4247SJustin T. Gibbs */ 111717d4247SJustin T. Gibbs static __inline void 1126fb77fefSJustin T. Gibbs ahc_unpause(struct ahc_softc *ahc) 113717d4247SJustin T. Gibbs { 114717d4247SJustin T. Gibbs if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0) 115717d4247SJustin T. Gibbs ahc_outb(ahc, HCNTRL, ahc->unpause); 116717d4247SJustin T. Gibbs } 117717d4247SJustin T. Gibbs 118717d4247SJustin T. Gibbs /*********************** Untagged Transaction Routines ************************/ 119717d4247SJustin T. Gibbs static __inline void ahc_freeze_untagged_queues(struct ahc_softc *ahc); 120717d4247SJustin T. Gibbs static __inline void ahc_release_untagged_queues(struct ahc_softc *ahc); 121717d4247SJustin T. Gibbs 122717d4247SJustin T. Gibbs /* 123717d4247SJustin T. Gibbs * Block our completion routine from starting the next untagged 124717d4247SJustin T. Gibbs * transaction for this target or target lun. 125717d4247SJustin T. Gibbs */ 126717d4247SJustin T. Gibbs static __inline void 127717d4247SJustin T. Gibbs ahc_freeze_untagged_queues(struct ahc_softc *ahc) 128717d4247SJustin T. Gibbs { 129a5847d5cSJustin T. Gibbs if ((ahc->flags & AHC_SCB_BTT) == 0) 130717d4247SJustin T. Gibbs ahc->untagged_queue_lock++; 131717d4247SJustin T. Gibbs } 132717d4247SJustin T. Gibbs 133717d4247SJustin T. Gibbs /* 134717d4247SJustin T. Gibbs * Allow the next untagged transaction for this target or target lun 135717d4247SJustin T. Gibbs * to be executed. We use a counting semaphore to allow the lock 136717d4247SJustin T. Gibbs * to be acquired recursively. Once the count drops to zero, the 137717d4247SJustin T. Gibbs * transaction queues will be run. 138717d4247SJustin T. Gibbs */ 139717d4247SJustin T. Gibbs static __inline void 140717d4247SJustin T. Gibbs ahc_release_untagged_queues(struct ahc_softc *ahc) 141717d4247SJustin T. Gibbs { 142a5847d5cSJustin T. Gibbs if ((ahc->flags & AHC_SCB_BTT) == 0) { 143717d4247SJustin T. Gibbs ahc->untagged_queue_lock--; 144717d4247SJustin T. Gibbs if (ahc->untagged_queue_lock == 0) 145717d4247SJustin T. Gibbs ahc_run_untagged_queues(ahc); 146717d4247SJustin T. Gibbs } 147717d4247SJustin T. Gibbs } 148717d4247SJustin T. Gibbs 149717d4247SJustin T. Gibbs /************************** Memory mapping routines ***************************/ 150717d4247SJustin T. Gibbs static __inline struct ahc_dma_seg * 151717d4247SJustin T. Gibbs ahc_sg_bus_to_virt(struct scb *scb, 152717d4247SJustin T. Gibbs uint32_t sg_busaddr); 153717d4247SJustin T. Gibbs static __inline uint32_t 154717d4247SJustin T. Gibbs ahc_sg_virt_to_bus(struct scb *scb, 155717d4247SJustin T. Gibbs struct ahc_dma_seg *sg); 156717d4247SJustin T. Gibbs static __inline uint32_t 157717d4247SJustin T. Gibbs ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index); 158cd036e89SJustin T. Gibbs static __inline void ahc_sync_scb(struct ahc_softc *ahc, 159cd036e89SJustin T. Gibbs struct scb *scb, int op); 160cd036e89SJustin T. Gibbs static __inline void ahc_sync_sglist(struct ahc_softc *ahc, 161cd036e89SJustin T. Gibbs struct scb *scb, int op); 162cd036e89SJustin T. Gibbs static __inline uint32_t 163cd036e89SJustin T. Gibbs ahc_targetcmd_offset(struct ahc_softc *ahc, 164cd036e89SJustin T. Gibbs u_int index); 165717d4247SJustin T. Gibbs 166717d4247SJustin T. Gibbs static __inline struct ahc_dma_seg * 167717d4247SJustin T. Gibbs ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr) 168717d4247SJustin T. Gibbs { 169717d4247SJustin T. Gibbs int sg_index; 170717d4247SJustin T. Gibbs 171717d4247SJustin T. Gibbs sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg); 172717d4247SJustin T. Gibbs /* sg_list_phys points to entry 1, not 0 */ 173717d4247SJustin T. Gibbs sg_index++; 174717d4247SJustin T. Gibbs 175717d4247SJustin T. Gibbs return (&scb->sg_list[sg_index]); 176717d4247SJustin T. Gibbs } 177717d4247SJustin T. Gibbs 178717d4247SJustin T. Gibbs static __inline uint32_t 179717d4247SJustin T. Gibbs ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg) 180717d4247SJustin T. Gibbs { 181717d4247SJustin T. Gibbs int sg_index; 182717d4247SJustin T. Gibbs 183717d4247SJustin T. Gibbs /* sg_list_phys points to entry 1, not 0 */ 184717d4247SJustin T. Gibbs sg_index = sg - &scb->sg_list[1]; 185717d4247SJustin T. Gibbs 186717d4247SJustin T. Gibbs return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list))); 187717d4247SJustin T. Gibbs } 188717d4247SJustin T. Gibbs 189717d4247SJustin T. Gibbs static __inline uint32_t 190717d4247SJustin T. Gibbs ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index) 191717d4247SJustin T. Gibbs { 192717d4247SJustin T. Gibbs return (ahc->scb_data->hscb_busaddr 193717d4247SJustin T. Gibbs + (sizeof(struct hardware_scb) * index)); 194717d4247SJustin T. Gibbs } 195717d4247SJustin T. Gibbs 196cd036e89SJustin T. Gibbs static __inline void 197cd036e89SJustin T. Gibbs ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op) 198cd036e89SJustin T. Gibbs { 199b3b25f2cSJustin T. Gibbs aic_dmamap_sync(ahc, ahc->scb_data->hscb_dmat, 200cd036e89SJustin T. Gibbs ahc->scb_data->hscb_dmamap, 201cd036e89SJustin T. Gibbs /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb), 202cd036e89SJustin T. Gibbs /*len*/sizeof(*scb->hscb), op); 203cd036e89SJustin T. Gibbs } 204cd036e89SJustin T. Gibbs 205cd036e89SJustin T. Gibbs static __inline void 206cd036e89SJustin T. Gibbs ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op) 207cd036e89SJustin T. Gibbs { 208cd036e89SJustin T. Gibbs if (scb->sg_count == 0) 209cd036e89SJustin T. Gibbs return; 210cd036e89SJustin T. Gibbs 211b3b25f2cSJustin T. Gibbs aic_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap, 212cd036e89SJustin T. Gibbs /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr) 213cd036e89SJustin T. Gibbs * sizeof(struct ahc_dma_seg), 214cd036e89SJustin T. Gibbs /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op); 215cd036e89SJustin T. Gibbs } 216cd036e89SJustin T. Gibbs 217cd036e89SJustin T. Gibbs static __inline uint32_t 218cd036e89SJustin T. Gibbs ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index) 219cd036e89SJustin T. Gibbs { 220*b5e0cc2fSKyle Evans return (((uint8_t *)&ahc->targetcmds[index]) - (uint8_t *)ahc->targetcmds); 221cd036e89SJustin T. Gibbs } 222cd036e89SJustin T. Gibbs 223717d4247SJustin T. Gibbs /******************************** Debugging ***********************************/ 224717d4247SJustin T. Gibbs static __inline char *ahc_name(struct ahc_softc *ahc); 225717d4247SJustin T. Gibbs 226717d4247SJustin T. Gibbs static __inline char * 227717d4247SJustin T. Gibbs ahc_name(struct ahc_softc *ahc) 228717d4247SJustin T. Gibbs { 229717d4247SJustin T. Gibbs return (ahc->name); 230717d4247SJustin T. Gibbs } 231717d4247SJustin T. Gibbs 232594c945aSPedro F. Giffuni /********************** Miscellaneous Support Functions ***********************/ 233717d4247SJustin T. Gibbs 2348f214efcSJustin T. Gibbs static __inline void ahc_update_residual(struct ahc_softc *ahc, 2358f214efcSJustin T. Gibbs struct scb *scb); 236717d4247SJustin T. Gibbs static __inline struct ahc_initiator_tinfo * 237717d4247SJustin T. Gibbs ahc_fetch_transinfo(struct ahc_softc *ahc, 238717d4247SJustin T. Gibbs char channel, u_int our_id, 239717d4247SJustin T. Gibbs u_int remote_id, 240b95de6daSJustin T. Gibbs struct ahc_tmode_tstate **tstate); 24170b41139SJustin T. Gibbs static __inline uint16_t 24270b41139SJustin T. Gibbs ahc_inw(struct ahc_softc *ahc, u_int port); 24370b41139SJustin T. Gibbs static __inline void ahc_outw(struct ahc_softc *ahc, u_int port, 24470b41139SJustin T. Gibbs u_int value); 24570b41139SJustin T. Gibbs static __inline uint32_t 24670b41139SJustin T. Gibbs ahc_inl(struct ahc_softc *ahc, u_int port); 24770b41139SJustin T. Gibbs static __inline void ahc_outl(struct ahc_softc *ahc, u_int port, 24870b41139SJustin T. Gibbs uint32_t value); 24970b41139SJustin T. Gibbs static __inline uint64_t 25070b41139SJustin T. Gibbs ahc_inq(struct ahc_softc *ahc, u_int port); 25170b41139SJustin T. Gibbs static __inline void ahc_outq(struct ahc_softc *ahc, u_int port, 25270b41139SJustin T. Gibbs uint64_t value); 253717d4247SJustin T. Gibbs static __inline struct scb* 254717d4247SJustin T. Gibbs ahc_get_scb(struct ahc_softc *ahc); 255717d4247SJustin T. Gibbs static __inline void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb); 25647c2d60fSJustin T. Gibbs static __inline void ahc_swap_with_next_hscb(struct ahc_softc *ahc, 25747c2d60fSJustin T. Gibbs struct scb *scb); 258717d4247SJustin T. Gibbs static __inline void ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb); 25976150586SJustin T. Gibbs static __inline struct scsi_sense_data * 26076150586SJustin T. Gibbs ahc_get_sense_buf(struct ahc_softc *ahc, 26176150586SJustin T. Gibbs struct scb *scb); 26276150586SJustin T. Gibbs static __inline uint32_t 26376150586SJustin T. Gibbs ahc_get_sense_bufaddr(struct ahc_softc *ahc, 26476150586SJustin T. Gibbs struct scb *scb); 265717d4247SJustin T. Gibbs 266717d4247SJustin T. Gibbs /* 267717d4247SJustin T. Gibbs * Determine whether the sequencer reported a residual 268717d4247SJustin T. Gibbs * for this SCB/transaction. 269717d4247SJustin T. Gibbs */ 27058fb7d8eSJustin T. Gibbs static __inline void 2718f214efcSJustin T. Gibbs ahc_update_residual(struct ahc_softc *ahc, struct scb *scb) 272717d4247SJustin T. Gibbs { 27358fb7d8eSJustin T. Gibbs uint32_t sgptr; 274717d4247SJustin T. Gibbs 275b3b25f2cSJustin T. Gibbs sgptr = aic_le32toh(scb->hscb->sgptr); 27658fb7d8eSJustin T. Gibbs if ((sgptr & SG_RESID_VALID) != 0) 2778f214efcSJustin T. Gibbs ahc_calc_residual(ahc, scb); 278717d4247SJustin T. Gibbs } 279717d4247SJustin T. Gibbs 280717d4247SJustin T. Gibbs /* 281717d4247SJustin T. Gibbs * Return pointers to the transfer negotiation information 282717d4247SJustin T. Gibbs * for the specified our_id/remote_id pair. 283717d4247SJustin T. Gibbs */ 284717d4247SJustin T. Gibbs static __inline struct ahc_initiator_tinfo * 285717d4247SJustin T. Gibbs ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id, 286b95de6daSJustin T. Gibbs u_int remote_id, struct ahc_tmode_tstate **tstate) 287717d4247SJustin T. Gibbs { 288717d4247SJustin T. Gibbs /* 289717d4247SJustin T. Gibbs * Transfer data structures are stored from the perspective 290717d4247SJustin T. Gibbs * of the target role. Since the parameters for a connection 291717d4247SJustin T. Gibbs * in the initiator role to a given target are the same as 292717d4247SJustin T. Gibbs * when the roles are reversed, we pretend we are the target. 293717d4247SJustin T. Gibbs */ 294717d4247SJustin T. Gibbs if (channel == 'B') 295717d4247SJustin T. Gibbs our_id += 8; 296717d4247SJustin T. Gibbs *tstate = ahc->enabled_targets[our_id]; 297717d4247SJustin T. Gibbs return (&(*tstate)->transinfo[remote_id]); 298717d4247SJustin T. Gibbs } 299717d4247SJustin T. Gibbs 30070b41139SJustin T. Gibbs static __inline uint16_t 30170b41139SJustin T. Gibbs ahc_inw(struct ahc_softc *ahc, u_int port) 30270b41139SJustin T. Gibbs { 30370b41139SJustin T. Gibbs return ((ahc_inb(ahc, port+1) << 8) | ahc_inb(ahc, port)); 30470b41139SJustin T. Gibbs } 30570b41139SJustin T. Gibbs 30670b41139SJustin T. Gibbs static __inline void 30770b41139SJustin T. Gibbs ahc_outw(struct ahc_softc *ahc, u_int port, u_int value) 30870b41139SJustin T. Gibbs { 30970b41139SJustin T. Gibbs ahc_outb(ahc, port, value & 0xFF); 31070b41139SJustin T. Gibbs ahc_outb(ahc, port+1, (value >> 8) & 0xFF); 31170b41139SJustin T. Gibbs } 31270b41139SJustin T. Gibbs 31370b41139SJustin T. Gibbs static __inline uint32_t 31470b41139SJustin T. Gibbs ahc_inl(struct ahc_softc *ahc, u_int port) 31570b41139SJustin T. Gibbs { 31670b41139SJustin T. Gibbs return ((ahc_inb(ahc, port)) 31770b41139SJustin T. Gibbs | (ahc_inb(ahc, port+1) << 8) 31870b41139SJustin T. Gibbs | (ahc_inb(ahc, port+2) << 16) 31970b41139SJustin T. Gibbs | (ahc_inb(ahc, port+3) << 24)); 32070b41139SJustin T. Gibbs } 32170b41139SJustin T. Gibbs 32270b41139SJustin T. Gibbs static __inline void 32370b41139SJustin T. Gibbs ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value) 32470b41139SJustin T. Gibbs { 32570b41139SJustin T. Gibbs ahc_outb(ahc, port, (value) & 0xFF); 32670b41139SJustin T. Gibbs ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF); 32770b41139SJustin T. Gibbs ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF); 32870b41139SJustin T. Gibbs ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF); 32970b41139SJustin T. Gibbs } 33070b41139SJustin T. Gibbs 33170b41139SJustin T. Gibbs static __inline uint64_t 33270b41139SJustin T. Gibbs ahc_inq(struct ahc_softc *ahc, u_int port) 33370b41139SJustin T. Gibbs { 33470b41139SJustin T. Gibbs return ((ahc_inb(ahc, port)) 33570b41139SJustin T. Gibbs | (ahc_inb(ahc, port+1) << 8) 33670b41139SJustin T. Gibbs | (ahc_inb(ahc, port+2) << 16) 33770b41139SJustin T. Gibbs | (ahc_inb(ahc, port+3) << 24) 33870b41139SJustin T. Gibbs | (((uint64_t)ahc_inb(ahc, port+4)) << 32) 33970b41139SJustin T. Gibbs | (((uint64_t)ahc_inb(ahc, port+5)) << 40) 34070b41139SJustin T. Gibbs | (((uint64_t)ahc_inb(ahc, port+6)) << 48) 34170b41139SJustin T. Gibbs | (((uint64_t)ahc_inb(ahc, port+7)) << 56)); 34270b41139SJustin T. Gibbs } 34370b41139SJustin T. Gibbs 34470b41139SJustin T. Gibbs static __inline void 34570b41139SJustin T. Gibbs ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value) 34670b41139SJustin T. Gibbs { 34770b41139SJustin T. Gibbs ahc_outb(ahc, port, value & 0xFF); 34870b41139SJustin T. Gibbs ahc_outb(ahc, port+1, (value >> 8) & 0xFF); 34970b41139SJustin T. Gibbs ahc_outb(ahc, port+2, (value >> 16) & 0xFF); 35070b41139SJustin T. Gibbs ahc_outb(ahc, port+3, (value >> 24) & 0xFF); 35170b41139SJustin T. Gibbs ahc_outb(ahc, port+4, (value >> 32) & 0xFF); 35270b41139SJustin T. Gibbs ahc_outb(ahc, port+5, (value >> 40) & 0xFF); 35370b41139SJustin T. Gibbs ahc_outb(ahc, port+6, (value >> 48) & 0xFF); 35470b41139SJustin T. Gibbs ahc_outb(ahc, port+7, (value >> 56) & 0xFF); 35570b41139SJustin T. Gibbs } 35670b41139SJustin T. Gibbs 357717d4247SJustin T. Gibbs /* 358717d4247SJustin T. Gibbs * Get a free scb. If there are none, see if we can allocate a new SCB. 359717d4247SJustin T. Gibbs */ 360717d4247SJustin T. Gibbs static __inline struct scb * 361717d4247SJustin T. Gibbs ahc_get_scb(struct ahc_softc *ahc) 362717d4247SJustin T. Gibbs { 363a49630acSJustin T. Gibbs struct scb *scb; 364717d4247SJustin T. Gibbs 365a49630acSJustin T. Gibbs if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) { 3667628acd8SScott Long if (ahc_alloc_scbs(ahc) == 0) 3677628acd8SScott Long return (NULL); 368a49630acSJustin T. Gibbs scb = SLIST_FIRST(&ahc->scb_data->free_scbs); 369a49630acSJustin T. Gibbs if (scb == NULL) 370a49630acSJustin T. Gibbs return (NULL); 371717d4247SJustin T. Gibbs } 372a49630acSJustin T. Gibbs SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle); 373a49630acSJustin T. Gibbs return (scb); 374717d4247SJustin T. Gibbs } 375717d4247SJustin T. Gibbs 376717d4247SJustin T. Gibbs /* 377717d4247SJustin T. Gibbs * Return an SCB resource to the free list. 378717d4247SJustin T. Gibbs */ 379717d4247SJustin T. Gibbs static __inline void 380717d4247SJustin T. Gibbs ahc_free_scb(struct ahc_softc *ahc, struct scb *scb) 381717d4247SJustin T. Gibbs { 382717d4247SJustin T. Gibbs struct hardware_scb *hscb; 383717d4247SJustin T. Gibbs 384717d4247SJustin T. Gibbs hscb = scb->hscb; 385717d4247SJustin T. Gibbs /* Clean up for the next user */ 386a49630acSJustin T. Gibbs ahc->scb_data->scbindex[hscb->tag] = NULL; 387b3b25f2cSJustin T. Gibbs scb->flags = SCB_FLAG_NONE; 388717d4247SJustin T. Gibbs hscb->control = 0; 389717d4247SJustin T. Gibbs 390717d4247SJustin T. Gibbs SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle); 391a49630acSJustin T. Gibbs 392a49630acSJustin T. Gibbs /* Notify the OSM that a resource is now available. */ 393b3b25f2cSJustin T. Gibbs aic_platform_scb_free(ahc, scb); 394a49630acSJustin T. Gibbs } 395a49630acSJustin T. Gibbs 396a49630acSJustin T. Gibbs static __inline struct scb * 397a49630acSJustin T. Gibbs ahc_lookup_scb(struct ahc_softc *ahc, u_int tag) 398a49630acSJustin T. Gibbs { 399cd036e89SJustin T. Gibbs struct scb* scb; 400a49630acSJustin T. Gibbs 401cd036e89SJustin T. Gibbs scb = ahc->scb_data->scbindex[tag]; 402cd036e89SJustin T. Gibbs if (scb != NULL) 403cd036e89SJustin T. Gibbs ahc_sync_scb(ahc, scb, 404cd036e89SJustin T. Gibbs BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 405cd036e89SJustin T. Gibbs return (scb); 406717d4247SJustin T. Gibbs } 407717d4247SJustin T. Gibbs 408717d4247SJustin T. Gibbs static __inline void 40947c2d60fSJustin T. Gibbs ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb) 410717d4247SJustin T. Gibbs { 411a49630acSJustin T. Gibbs struct hardware_scb *q_hscb; 412a49630acSJustin T. Gibbs u_int saved_tag; 413a49630acSJustin T. Gibbs 414a49630acSJustin T. Gibbs /* 415a49630acSJustin T. Gibbs * Our queuing method is a bit tricky. The card 416a49630acSJustin T. Gibbs * knows in advance which HSCB to download, and we 417a49630acSJustin T. Gibbs * can't disappoint it. To achieve this, the next 418a49630acSJustin T. Gibbs * SCB to download is saved off in ahc->next_queued_scb. 419a49630acSJustin T. Gibbs * When we are called to queue "an arbitrary scb", 420a49630acSJustin T. Gibbs * we copy the contents of the incoming HSCB to the one 421a49630acSJustin T. Gibbs * the sequencer knows about, swap HSCB pointers and 42247c2d60fSJustin T. Gibbs * finally assign the SCB to the tag indexed location 423a49630acSJustin T. Gibbs * in the scb_array. This makes sure that we can still 424a49630acSJustin T. Gibbs * locate the correct SCB by SCB_TAG. 425a49630acSJustin T. Gibbs */ 426a49630acSJustin T. Gibbs q_hscb = ahc->next_queued_scb->hscb; 427a49630acSJustin T. Gibbs saved_tag = q_hscb->tag; 42860754d0bSJustin T. Gibbs memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); 429dd1290f0SJustin T. Gibbs if ((scb->flags & SCB_CDB32_PTR) != 0) { 430dd1290f0SJustin T. Gibbs q_hscb->shared_data.cdb_ptr = 431b3b25f2cSJustin T. Gibbs aic_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag) 4328f214efcSJustin T. Gibbs + offsetof(struct hardware_scb, cdb32)); 433dd1290f0SJustin T. Gibbs } 434a49630acSJustin T. Gibbs q_hscb->tag = saved_tag; 435a49630acSJustin T. Gibbs q_hscb->next = scb->hscb->tag; 436a49630acSJustin T. Gibbs 437a49630acSJustin T. Gibbs /* Now swap HSCB pointers. */ 438a49630acSJustin T. Gibbs ahc->next_queued_scb->hscb = scb->hscb; 439a49630acSJustin T. Gibbs scb->hscb = q_hscb; 440a49630acSJustin T. Gibbs 441a49630acSJustin T. Gibbs /* Now define the mapping from tag to SCB in the scbindex */ 442a49630acSJustin T. Gibbs ahc->scb_data->scbindex[scb->hscb->tag] = scb; 44347c2d60fSJustin T. Gibbs } 44447c2d60fSJustin T. Gibbs 44547c2d60fSJustin T. Gibbs /* 44647c2d60fSJustin T. Gibbs * Tell the sequencer about a new transaction to execute. 44747c2d60fSJustin T. Gibbs */ 44847c2d60fSJustin T. Gibbs static __inline void 44947c2d60fSJustin T. Gibbs ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb) 45047c2d60fSJustin T. Gibbs { 45147c2d60fSJustin T. Gibbs ahc_swap_with_next_hscb(ahc, scb); 452a49630acSJustin T. Gibbs 453dd1290f0SJustin T. Gibbs if (scb->hscb->tag == SCB_LIST_NULL 454dd1290f0SJustin T. Gibbs || scb->hscb->next == SCB_LIST_NULL) 455dd1290f0SJustin T. Gibbs panic("Attempt to queue invalid SCB tag %x:%x\n", 456dd1290f0SJustin T. Gibbs scb->hscb->tag, scb->hscb->next); 457dd1290f0SJustin T. Gibbs 458a49630acSJustin T. Gibbs /* 45992931c12SJustin T. Gibbs * Setup data "oddness". 46092931c12SJustin T. Gibbs */ 46192931c12SJustin T. Gibbs scb->hscb->lun &= LID; 462b3b25f2cSJustin T. Gibbs if (aic_get_transfer_length(scb) & 0x1) 46392931c12SJustin T. Gibbs scb->hscb->lun |= SCB_XFERLEN_ODD; 46492931c12SJustin T. Gibbs 46592931c12SJustin T. Gibbs /* 466a49630acSJustin T. Gibbs * Keep a history of SCBs we've downloaded in the qinfifo. 467a49630acSJustin T. Gibbs */ 468717d4247SJustin T. Gibbs ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag; 469cd036e89SJustin T. Gibbs 470cd036e89SJustin T. Gibbs /* 4719bf327a7SJustin T. Gibbs * Make sure our data is consistent from the 472cd036e89SJustin T. Gibbs * perspective of the adapter. 473cd036e89SJustin T. Gibbs */ 474cd036e89SJustin T. Gibbs ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 475cd036e89SJustin T. Gibbs 476cd036e89SJustin T. Gibbs /* Tell the adapter about the newly queued SCB */ 477717d4247SJustin T. Gibbs if ((ahc->features & AHC_QUEUE_REGS) != 0) { 478717d4247SJustin T. Gibbs ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); 479717d4247SJustin T. Gibbs } else { 480717d4247SJustin T. Gibbs if ((ahc->features & AHC_AUTOPAUSE) == 0) 4816fb77fefSJustin T. Gibbs ahc_pause(ahc); 482717d4247SJustin T. Gibbs ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); 483717d4247SJustin T. Gibbs if ((ahc->features & AHC_AUTOPAUSE) == 0) 4846fb77fefSJustin T. Gibbs ahc_unpause(ahc); 485717d4247SJustin T. Gibbs } 486717d4247SJustin T. Gibbs } 487717d4247SJustin T. Gibbs 48876150586SJustin T. Gibbs static __inline struct scsi_sense_data * 48976150586SJustin T. Gibbs ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb) 49076150586SJustin T. Gibbs { 49176150586SJustin T. Gibbs int offset; 49276150586SJustin T. Gibbs 49376150586SJustin T. Gibbs offset = scb - ahc->scb_data->scbarray; 49476150586SJustin T. Gibbs return (&ahc->scb_data->sense[offset]); 49576150586SJustin T. Gibbs } 49676150586SJustin T. Gibbs 49776150586SJustin T. Gibbs static __inline uint32_t 49876150586SJustin T. Gibbs ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb) 49976150586SJustin T. Gibbs { 50076150586SJustin T. Gibbs int offset; 50176150586SJustin T. Gibbs 50276150586SJustin T. Gibbs offset = scb - ahc->scb_data->scbarray; 50376150586SJustin T. Gibbs return (ahc->scb_data->sense_busaddr 50476150586SJustin T. Gibbs + (offset * sizeof(struct scsi_sense_data))); 50576150586SJustin T. Gibbs } 50676150586SJustin T. Gibbs 507717d4247SJustin T. Gibbs /************************** Interrupt Processing ******************************/ 508cd036e89SJustin T. Gibbs static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op); 509cd036e89SJustin T. Gibbs static __inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op); 51056a7c4a8SJustin T. Gibbs static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc); 5119bf327a7SJustin T. Gibbs static __inline int ahc_intr(struct ahc_softc *ahc); 512717d4247SJustin T. Gibbs 513cd036e89SJustin T. Gibbs static __inline void 514cd036e89SJustin T. Gibbs ahc_sync_qoutfifo(struct ahc_softc *ahc, int op) 515cd036e89SJustin T. Gibbs { 516b3b25f2cSJustin T. Gibbs aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, 517cd036e89SJustin T. Gibbs /*offset*/0, /*len*/256, op); 518cd036e89SJustin T. Gibbs } 519cd036e89SJustin T. Gibbs 520cd036e89SJustin T. Gibbs static __inline void 521cd036e89SJustin T. Gibbs ahc_sync_tqinfifo(struct ahc_softc *ahc, int op) 522cd036e89SJustin T. Gibbs { 523cd036e89SJustin T. Gibbs #ifdef AHC_TARGET_MODE 524cd036e89SJustin T. Gibbs if ((ahc->flags & AHC_TARGETROLE) != 0) { 525b3b25f2cSJustin T. Gibbs aic_dmamap_sync(ahc, ahc->shared_data_dmat, 526cd036e89SJustin T. Gibbs ahc->shared_data_dmamap, 527cd036e89SJustin T. Gibbs ahc_targetcmd_offset(ahc, 0), 528cd036e89SJustin T. Gibbs sizeof(struct target_cmd) * AHC_TMODE_CMDS, 529cd036e89SJustin T. Gibbs op); 530cd036e89SJustin T. Gibbs } 531cd036e89SJustin T. Gibbs #endif 532cd036e89SJustin T. Gibbs } 533cd036e89SJustin T. Gibbs 534717d4247SJustin T. Gibbs /* 53556a7c4a8SJustin T. Gibbs * See if the firmware has posted any completed commands 53656a7c4a8SJustin T. Gibbs * into our in-core command complete fifos. 53756a7c4a8SJustin T. Gibbs */ 53856a7c4a8SJustin T. Gibbs #define AHC_RUN_QOUTFIFO 0x1 53956a7c4a8SJustin T. Gibbs #define AHC_RUN_TQINFIFO 0x2 54056a7c4a8SJustin T. Gibbs static __inline u_int 54156a7c4a8SJustin T. Gibbs ahc_check_cmdcmpltqueues(struct ahc_softc *ahc) 54256a7c4a8SJustin T. Gibbs { 54356a7c4a8SJustin T. Gibbs u_int retval; 54456a7c4a8SJustin T. Gibbs 54556a7c4a8SJustin T. Gibbs retval = 0; 546b3b25f2cSJustin T. Gibbs aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, 547cd036e89SJustin T. Gibbs /*offset*/ahc->qoutfifonext, /*len*/1, 548cd036e89SJustin T. Gibbs BUS_DMASYNC_POSTREAD); 54956a7c4a8SJustin T. Gibbs if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) 55056a7c4a8SJustin T. Gibbs retval |= AHC_RUN_QOUTFIFO; 55156a7c4a8SJustin T. Gibbs #ifdef AHC_TARGET_MODE 5528f214efcSJustin T. Gibbs if ((ahc->flags & AHC_TARGETROLE) != 0 5538f214efcSJustin T. Gibbs && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) { 554b3b25f2cSJustin T. Gibbs aic_dmamap_sync(ahc, ahc->shared_data_dmat, 555cd036e89SJustin T. Gibbs ahc->shared_data_dmamap, 556cd036e89SJustin T. Gibbs ahc_targetcmd_offset(ahc, ahc->tqinfifofnext), 557cd036e89SJustin T. Gibbs /*len*/sizeof(struct target_cmd), 558cd036e89SJustin T. Gibbs BUS_DMASYNC_POSTREAD); 559cd036e89SJustin T. Gibbs if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0) 56056a7c4a8SJustin T. Gibbs retval |= AHC_RUN_TQINFIFO; 561cd036e89SJustin T. Gibbs } 56256a7c4a8SJustin T. Gibbs #endif 56356a7c4a8SJustin T. Gibbs return (retval); 56456a7c4a8SJustin T. Gibbs } 56556a7c4a8SJustin T. Gibbs 56656a7c4a8SJustin T. Gibbs /* 567717d4247SJustin T. Gibbs * Catch an interrupt from the adapter 568717d4247SJustin T. Gibbs */ 5699bf327a7SJustin T. Gibbs static __inline int 570717d4247SJustin T. Gibbs ahc_intr(struct ahc_softc *ahc) 571717d4247SJustin T. Gibbs { 572717d4247SJustin T. Gibbs u_int intstat; 573717d4247SJustin T. Gibbs 574d10a3e08SJustin T. Gibbs if ((ahc->pause & INTEN) == 0) { 575d10a3e08SJustin T. Gibbs /* 576d10a3e08SJustin T. Gibbs * Our interrupt is not enabled on the chip 577d10a3e08SJustin T. Gibbs * and may be disabled for re-entrancy reasons, 578d10a3e08SJustin T. Gibbs * so just return. This is likely just a shared 579d10a3e08SJustin T. Gibbs * interrupt. 580d10a3e08SJustin T. Gibbs */ 5819bf327a7SJustin T. Gibbs return (0); 582d10a3e08SJustin T. Gibbs } 583717d4247SJustin T. Gibbs /* 58456a7c4a8SJustin T. Gibbs * Instead of directly reading the interrupt status register, 58556a7c4a8SJustin T. Gibbs * infer the cause of the interrupt by checking our in-core 58656a7c4a8SJustin T. Gibbs * completion queues. This avoids a costly PCI bus read in 58756a7c4a8SJustin T. Gibbs * most cases. 588717d4247SJustin T. Gibbs */ 5896fb77fefSJustin T. Gibbs if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0 5908f214efcSJustin T. Gibbs && (ahc_check_cmdcmpltqueues(ahc) != 0)) 59156a7c4a8SJustin T. Gibbs intstat = CMDCMPLT; 5926fb77fefSJustin T. Gibbs else { 59356a7c4a8SJustin T. Gibbs intstat = ahc_inb(ahc, INTSTAT); 59456a7c4a8SJustin T. Gibbs } 59556a7c4a8SJustin T. Gibbs 5969bf327a7SJustin T. Gibbs if ((intstat & INT_PEND) == 0) { 597b3b25f2cSJustin T. Gibbs #if AIC_PCI_CONFIG > 0 5989bf327a7SJustin T. Gibbs if (ahc->unsolicited_ints > 500) { 5999bf327a7SJustin T. Gibbs ahc->unsolicited_ints = 0; 6009bf327a7SJustin T. Gibbs if ((ahc->chip & AHC_PCI) != 0 6019bf327a7SJustin T. Gibbs && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0) 6029bf327a7SJustin T. Gibbs ahc->bus_intr(ahc); 6039bf327a7SJustin T. Gibbs } 6049bf327a7SJustin T. Gibbs #endif 6059bf327a7SJustin T. Gibbs ahc->unsolicited_ints++; 6069bf327a7SJustin T. Gibbs return (0); 6079bf327a7SJustin T. Gibbs } 6089bf327a7SJustin T. Gibbs ahc->unsolicited_ints = 0; 6099bf327a7SJustin T. Gibbs 610717d4247SJustin T. Gibbs if (intstat & CMDCMPLT) { 611717d4247SJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRCMDINT); 61256a7c4a8SJustin T. Gibbs 613717d4247SJustin T. Gibbs /* 614717d4247SJustin T. Gibbs * Ensure that the chip sees that we've cleared 615717d4247SJustin T. Gibbs * this interrupt before we walk the output fifo. 616717d4247SJustin T. Gibbs * Otherwise, we may, due to posted bus writes, 617717d4247SJustin T. Gibbs * clear the interrupt after we finish the scan, 618717d4247SJustin T. Gibbs * and after the sequencer has added new entries 619717d4247SJustin T. Gibbs * and asserted the interrupt again. 620717d4247SJustin T. Gibbs */ 621717d4247SJustin T. Gibbs ahc_flush_device_writes(ahc); 622717d4247SJustin T. Gibbs ahc_run_qoutfifo(ahc); 623717d4247SJustin T. Gibbs #ifdef AHC_TARGET_MODE 6248f214efcSJustin T. Gibbs if ((ahc->flags & AHC_TARGETROLE) != 0) 625717d4247SJustin T. Gibbs ahc_run_tqinfifo(ahc, /*paused*/FALSE); 626717d4247SJustin T. Gibbs #endif 627717d4247SJustin T. Gibbs } 628cd036e89SJustin T. Gibbs 6299bf327a7SJustin T. Gibbs /* 6309bf327a7SJustin T. Gibbs * Handle statuses that may invalidate our cached 6319bf327a7SJustin T. Gibbs * copy of INTSTAT separately. 6329bf327a7SJustin T. Gibbs */ 6339bf327a7SJustin T. Gibbs if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) { 6349bf327a7SJustin T. Gibbs /* Hot eject. Do nothing */ 6359bf327a7SJustin T. Gibbs } else if (intstat & BRKADRINT) { 636717d4247SJustin T. Gibbs ahc_handle_brkadrint(ahc); 6379bf327a7SJustin T. Gibbs } else if ((intstat & (SEQINT|SCSIINT)) != 0) { 638717d4247SJustin T. Gibbs ahc_pause_bug_fix(ahc); 639717d4247SJustin T. Gibbs 640717d4247SJustin T. Gibbs if ((intstat & SEQINT) != 0) 641717d4247SJustin T. Gibbs ahc_handle_seqint(ahc, intstat); 642717d4247SJustin T. Gibbs 643717d4247SJustin T. Gibbs if ((intstat & SCSIINT) != 0) 644717d4247SJustin T. Gibbs ahc_handle_scsiint(ahc, intstat); 645717d4247SJustin T. Gibbs } 6469bf327a7SJustin T. Gibbs return (1); 6479bf327a7SJustin T. Gibbs } 648717d4247SJustin T. Gibbs 649717d4247SJustin T. Gibbs #endif /* _AIC7XXX_INLINE_H_ */ 650