1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Inline routines shareable across OS platforms. 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Copyright (c) 1994-2001 Justin T. Gibbs. 5*1da177e4SLinus Torvalds * Copyright (c) 2000-2003 Adaptec Inc. 6*1da177e4SLinus Torvalds * All rights reserved. 7*1da177e4SLinus Torvalds * 8*1da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or without 9*1da177e4SLinus Torvalds * modification, are permitted provided that the following conditions 10*1da177e4SLinus Torvalds * are met: 11*1da177e4SLinus Torvalds * 1. Redistributions of source code must retain the above copyright 12*1da177e4SLinus Torvalds * notice, this list of conditions, and the following disclaimer, 13*1da177e4SLinus Torvalds * without modification. 14*1da177e4SLinus Torvalds * 2. Redistributions in binary form must reproduce at minimum a disclaimer 15*1da177e4SLinus Torvalds * substantially similar to the "NO WARRANTY" disclaimer below 16*1da177e4SLinus Torvalds * ("Disclaimer") and any redistribution must be conditioned upon 17*1da177e4SLinus Torvalds * including a substantially similar Disclaimer requirement for further 18*1da177e4SLinus Torvalds * binary redistribution. 19*1da177e4SLinus Torvalds * 3. Neither the names of the above-listed copyright holders nor the names 20*1da177e4SLinus Torvalds * of any contributors may be used to endorse or promote products derived 21*1da177e4SLinus Torvalds * from this software without specific prior written permission. 22*1da177e4SLinus Torvalds * 23*1da177e4SLinus Torvalds * Alternatively, this software may be distributed under the terms of the 24*1da177e4SLinus Torvalds * GNU General Public License ("GPL") version 2 as published by the Free 25*1da177e4SLinus Torvalds * Software Foundation. 26*1da177e4SLinus Torvalds * 27*1da177e4SLinus Torvalds * NO WARRANTY 28*1da177e4SLinus Torvalds * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29*1da177e4SLinus Torvalds * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30*1da177e4SLinus Torvalds * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 31*1da177e4SLinus Torvalds * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32*1da177e4SLinus Torvalds * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33*1da177e4SLinus Torvalds * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34*1da177e4SLinus Torvalds * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35*1da177e4SLinus Torvalds * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 36*1da177e4SLinus Torvalds * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 37*1da177e4SLinus Torvalds * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38*1da177e4SLinus Torvalds * POSSIBILITY OF SUCH DAMAGES. 39*1da177e4SLinus Torvalds * 40*1da177e4SLinus Torvalds * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#51 $ 41*1da177e4SLinus Torvalds * 42*1da177e4SLinus Torvalds * $FreeBSD$ 43*1da177e4SLinus Torvalds */ 44*1da177e4SLinus Torvalds 45*1da177e4SLinus Torvalds #ifndef _AIC79XX_INLINE_H_ 46*1da177e4SLinus Torvalds #define _AIC79XX_INLINE_H_ 47*1da177e4SLinus Torvalds 48*1da177e4SLinus Torvalds /******************************** Debugging ***********************************/ 49*1da177e4SLinus Torvalds static __inline char *ahd_name(struct ahd_softc *ahd); 50*1da177e4SLinus Torvalds 51*1da177e4SLinus Torvalds static __inline char * 52*1da177e4SLinus Torvalds ahd_name(struct ahd_softc *ahd) 53*1da177e4SLinus Torvalds { 54*1da177e4SLinus Torvalds return (ahd->name); 55*1da177e4SLinus Torvalds } 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds /************************ Sequencer Execution Control *************************/ 58*1da177e4SLinus Torvalds static __inline void ahd_known_modes(struct ahd_softc *ahd, 59*1da177e4SLinus Torvalds ahd_mode src, ahd_mode dst); 60*1da177e4SLinus Torvalds static __inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd, 61*1da177e4SLinus Torvalds ahd_mode src, 62*1da177e4SLinus Torvalds ahd_mode dst); 63*1da177e4SLinus Torvalds static __inline void ahd_extract_mode_state(struct ahd_softc *ahd, 64*1da177e4SLinus Torvalds ahd_mode_state state, 65*1da177e4SLinus Torvalds ahd_mode *src, ahd_mode *dst); 66*1da177e4SLinus Torvalds static __inline void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, 67*1da177e4SLinus Torvalds ahd_mode dst); 68*1da177e4SLinus Torvalds static __inline void ahd_update_modes(struct ahd_softc *ahd); 69*1da177e4SLinus Torvalds static __inline void ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode, 70*1da177e4SLinus Torvalds ahd_mode dstmode, const char *file, 71*1da177e4SLinus Torvalds int line); 72*1da177e4SLinus Torvalds static __inline ahd_mode_state ahd_save_modes(struct ahd_softc *ahd); 73*1da177e4SLinus Torvalds static __inline void ahd_restore_modes(struct ahd_softc *ahd, 74*1da177e4SLinus Torvalds ahd_mode_state state); 75*1da177e4SLinus Torvalds static __inline int ahd_is_paused(struct ahd_softc *ahd); 76*1da177e4SLinus Torvalds static __inline void ahd_pause(struct ahd_softc *ahd); 77*1da177e4SLinus Torvalds static __inline void ahd_unpause(struct ahd_softc *ahd); 78*1da177e4SLinus Torvalds 79*1da177e4SLinus Torvalds static __inline void 80*1da177e4SLinus Torvalds ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) 81*1da177e4SLinus Torvalds { 82*1da177e4SLinus Torvalds ahd->src_mode = src; 83*1da177e4SLinus Torvalds ahd->dst_mode = dst; 84*1da177e4SLinus Torvalds ahd->saved_src_mode = src; 85*1da177e4SLinus Torvalds ahd->saved_dst_mode = dst; 86*1da177e4SLinus Torvalds } 87*1da177e4SLinus Torvalds 88*1da177e4SLinus Torvalds static __inline ahd_mode_state 89*1da177e4SLinus Torvalds ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) 90*1da177e4SLinus Torvalds { 91*1da177e4SLinus Torvalds return ((src << SRC_MODE_SHIFT) | (dst << DST_MODE_SHIFT)); 92*1da177e4SLinus Torvalds } 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds static __inline void 95*1da177e4SLinus Torvalds ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state, 96*1da177e4SLinus Torvalds ahd_mode *src, ahd_mode *dst) 97*1da177e4SLinus Torvalds { 98*1da177e4SLinus Torvalds *src = (state & SRC_MODE) >> SRC_MODE_SHIFT; 99*1da177e4SLinus Torvalds *dst = (state & DST_MODE) >> DST_MODE_SHIFT; 100*1da177e4SLinus Torvalds } 101*1da177e4SLinus Torvalds 102*1da177e4SLinus Torvalds static __inline void 103*1da177e4SLinus Torvalds ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) 104*1da177e4SLinus Torvalds { 105*1da177e4SLinus Torvalds if (ahd->src_mode == src && ahd->dst_mode == dst) 106*1da177e4SLinus Torvalds return; 107*1da177e4SLinus Torvalds #ifdef AHD_DEBUG 108*1da177e4SLinus Torvalds if (ahd->src_mode == AHD_MODE_UNKNOWN 109*1da177e4SLinus Torvalds || ahd->dst_mode == AHD_MODE_UNKNOWN) 110*1da177e4SLinus Torvalds panic("Setting mode prior to saving it.\n"); 111*1da177e4SLinus Torvalds if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) 112*1da177e4SLinus Torvalds printf("%s: Setting mode 0x%x\n", ahd_name(ahd), 113*1da177e4SLinus Torvalds ahd_build_mode_state(ahd, src, dst)); 114*1da177e4SLinus Torvalds #endif 115*1da177e4SLinus Torvalds ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst)); 116*1da177e4SLinus Torvalds ahd->src_mode = src; 117*1da177e4SLinus Torvalds ahd->dst_mode = dst; 118*1da177e4SLinus Torvalds } 119*1da177e4SLinus Torvalds 120*1da177e4SLinus Torvalds static __inline void 121*1da177e4SLinus Torvalds ahd_update_modes(struct ahd_softc *ahd) 122*1da177e4SLinus Torvalds { 123*1da177e4SLinus Torvalds ahd_mode_state mode_ptr; 124*1da177e4SLinus Torvalds ahd_mode src; 125*1da177e4SLinus Torvalds ahd_mode dst; 126*1da177e4SLinus Torvalds 127*1da177e4SLinus Torvalds mode_ptr = ahd_inb(ahd, MODE_PTR); 128*1da177e4SLinus Torvalds #ifdef AHD_DEBUG 129*1da177e4SLinus Torvalds if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) 130*1da177e4SLinus Torvalds printf("Reading mode 0x%x\n", mode_ptr); 131*1da177e4SLinus Torvalds #endif 132*1da177e4SLinus Torvalds ahd_extract_mode_state(ahd, mode_ptr, &src, &dst); 133*1da177e4SLinus Torvalds ahd_known_modes(ahd, src, dst); 134*1da177e4SLinus Torvalds } 135*1da177e4SLinus Torvalds 136*1da177e4SLinus Torvalds static __inline void 137*1da177e4SLinus Torvalds ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode, 138*1da177e4SLinus Torvalds ahd_mode dstmode, const char *file, int line) 139*1da177e4SLinus Torvalds { 140*1da177e4SLinus Torvalds #ifdef AHD_DEBUG 141*1da177e4SLinus Torvalds if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0 142*1da177e4SLinus Torvalds || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) { 143*1da177e4SLinus Torvalds panic("%s:%s:%d: Mode assertion failed.\n", 144*1da177e4SLinus Torvalds ahd_name(ahd), file, line); 145*1da177e4SLinus Torvalds } 146*1da177e4SLinus Torvalds #endif 147*1da177e4SLinus Torvalds } 148*1da177e4SLinus Torvalds 149*1da177e4SLinus Torvalds static __inline ahd_mode_state 150*1da177e4SLinus Torvalds ahd_save_modes(struct ahd_softc *ahd) 151*1da177e4SLinus Torvalds { 152*1da177e4SLinus Torvalds if (ahd->src_mode == AHD_MODE_UNKNOWN 153*1da177e4SLinus Torvalds || ahd->dst_mode == AHD_MODE_UNKNOWN) 154*1da177e4SLinus Torvalds ahd_update_modes(ahd); 155*1da177e4SLinus Torvalds 156*1da177e4SLinus Torvalds return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode)); 157*1da177e4SLinus Torvalds } 158*1da177e4SLinus Torvalds 159*1da177e4SLinus Torvalds static __inline void 160*1da177e4SLinus Torvalds ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state) 161*1da177e4SLinus Torvalds { 162*1da177e4SLinus Torvalds ahd_mode src; 163*1da177e4SLinus Torvalds ahd_mode dst; 164*1da177e4SLinus Torvalds 165*1da177e4SLinus Torvalds ahd_extract_mode_state(ahd, state, &src, &dst); 166*1da177e4SLinus Torvalds ahd_set_modes(ahd, src, dst); 167*1da177e4SLinus Torvalds } 168*1da177e4SLinus Torvalds 169*1da177e4SLinus Torvalds #define AHD_ASSERT_MODES(ahd, source, dest) \ 170*1da177e4SLinus Torvalds ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__); 171*1da177e4SLinus Torvalds 172*1da177e4SLinus Torvalds /* 173*1da177e4SLinus Torvalds * Determine whether the sequencer has halted code execution. 174*1da177e4SLinus Torvalds * Returns non-zero status if the sequencer is stopped. 175*1da177e4SLinus Torvalds */ 176*1da177e4SLinus Torvalds static __inline int 177*1da177e4SLinus Torvalds ahd_is_paused(struct ahd_softc *ahd) 178*1da177e4SLinus Torvalds { 179*1da177e4SLinus Torvalds return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0); 180*1da177e4SLinus Torvalds } 181*1da177e4SLinus Torvalds 182*1da177e4SLinus Torvalds /* 183*1da177e4SLinus Torvalds * Request that the sequencer stop and wait, indefinitely, for it 184*1da177e4SLinus Torvalds * to stop. The sequencer will only acknowledge that it is paused 185*1da177e4SLinus Torvalds * once it has reached an instruction boundary and PAUSEDIS is 186*1da177e4SLinus Torvalds * cleared in the SEQCTL register. The sequencer may use PAUSEDIS 187*1da177e4SLinus Torvalds * for critical sections. 188*1da177e4SLinus Torvalds */ 189*1da177e4SLinus Torvalds static __inline void 190*1da177e4SLinus Torvalds ahd_pause(struct ahd_softc *ahd) 191*1da177e4SLinus Torvalds { 192*1da177e4SLinus Torvalds ahd_outb(ahd, HCNTRL, ahd->pause); 193*1da177e4SLinus Torvalds 194*1da177e4SLinus Torvalds /* 195*1da177e4SLinus Torvalds * Since the sequencer can disable pausing in a critical section, we 196*1da177e4SLinus Torvalds * must loop until it actually stops. 197*1da177e4SLinus Torvalds */ 198*1da177e4SLinus Torvalds while (ahd_is_paused(ahd) == 0) 199*1da177e4SLinus Torvalds ; 200*1da177e4SLinus Torvalds } 201*1da177e4SLinus Torvalds 202*1da177e4SLinus Torvalds /* 203*1da177e4SLinus Torvalds * Allow the sequencer to continue program execution. 204*1da177e4SLinus Torvalds * We check here to ensure that no additional interrupt 205*1da177e4SLinus Torvalds * sources that would cause the sequencer to halt have been 206*1da177e4SLinus Torvalds * asserted. If, for example, a SCSI bus reset is detected 207*1da177e4SLinus Torvalds * while we are fielding a different, pausing, interrupt type, 208*1da177e4SLinus Torvalds * we don't want to release the sequencer before going back 209*1da177e4SLinus Torvalds * into our interrupt handler and dealing with this new 210*1da177e4SLinus Torvalds * condition. 211*1da177e4SLinus Torvalds */ 212*1da177e4SLinus Torvalds static __inline void 213*1da177e4SLinus Torvalds ahd_unpause(struct ahd_softc *ahd) 214*1da177e4SLinus Torvalds { 215*1da177e4SLinus Torvalds /* 216*1da177e4SLinus Torvalds * Automatically restore our modes to those saved 217*1da177e4SLinus Torvalds * prior to the first change of the mode. 218*1da177e4SLinus Torvalds */ 219*1da177e4SLinus Torvalds if (ahd->saved_src_mode != AHD_MODE_UNKNOWN 220*1da177e4SLinus Torvalds && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) { 221*1da177e4SLinus Torvalds if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0) 222*1da177e4SLinus Torvalds ahd_reset_cmds_pending(ahd); 223*1da177e4SLinus Torvalds ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); 224*1da177e4SLinus Torvalds } 225*1da177e4SLinus Torvalds 226*1da177e4SLinus Torvalds if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0) 227*1da177e4SLinus Torvalds ahd_outb(ahd, HCNTRL, ahd->unpause); 228*1da177e4SLinus Torvalds 229*1da177e4SLinus Torvalds ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN); 230*1da177e4SLinus Torvalds } 231*1da177e4SLinus Torvalds 232*1da177e4SLinus Torvalds /*********************** Scatter Gather List Handling *************************/ 233*1da177e4SLinus Torvalds static __inline void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, 234*1da177e4SLinus Torvalds void *sgptr, dma_addr_t addr, 235*1da177e4SLinus Torvalds bus_size_t len, int last); 236*1da177e4SLinus Torvalds static __inline void ahd_setup_scb_common(struct ahd_softc *ahd, 237*1da177e4SLinus Torvalds struct scb *scb); 238*1da177e4SLinus Torvalds static __inline void ahd_setup_data_scb(struct ahd_softc *ahd, 239*1da177e4SLinus Torvalds struct scb *scb); 240*1da177e4SLinus Torvalds static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd, 241*1da177e4SLinus Torvalds struct scb *scb); 242*1da177e4SLinus Torvalds 243*1da177e4SLinus Torvalds static __inline void * 244*1da177e4SLinus Torvalds ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, 245*1da177e4SLinus Torvalds void *sgptr, dma_addr_t addr, bus_size_t len, int last) 246*1da177e4SLinus Torvalds { 247*1da177e4SLinus Torvalds scb->sg_count++; 248*1da177e4SLinus Torvalds if (sizeof(dma_addr_t) > 4 249*1da177e4SLinus Torvalds && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) { 250*1da177e4SLinus Torvalds struct ahd_dma64_seg *sg; 251*1da177e4SLinus Torvalds 252*1da177e4SLinus Torvalds sg = (struct ahd_dma64_seg *)sgptr; 253*1da177e4SLinus Torvalds sg->addr = ahd_htole64(addr); 254*1da177e4SLinus Torvalds sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); 255*1da177e4SLinus Torvalds return (sg + 1); 256*1da177e4SLinus Torvalds } else { 257*1da177e4SLinus Torvalds struct ahd_dma_seg *sg; 258*1da177e4SLinus Torvalds 259*1da177e4SLinus Torvalds sg = (struct ahd_dma_seg *)sgptr; 260*1da177e4SLinus Torvalds sg->addr = ahd_htole32(addr & 0xFFFFFFFF); 261*1da177e4SLinus Torvalds sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000) 262*1da177e4SLinus Torvalds | (last ? AHD_DMA_LAST_SEG : 0)); 263*1da177e4SLinus Torvalds return (sg + 1); 264*1da177e4SLinus Torvalds } 265*1da177e4SLinus Torvalds } 266*1da177e4SLinus Torvalds 267*1da177e4SLinus Torvalds static __inline void 268*1da177e4SLinus Torvalds ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb) 269*1da177e4SLinus Torvalds { 270*1da177e4SLinus Torvalds /* XXX Handle target mode SCBs. */ 271*1da177e4SLinus Torvalds scb->crc_retry_count = 0; 272*1da177e4SLinus Torvalds if ((scb->flags & SCB_PACKETIZED) != 0) { 273*1da177e4SLinus Torvalds /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */ 274*1da177e4SLinus Torvalds scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE; 275*1da177e4SLinus Torvalds } else { 276*1da177e4SLinus Torvalds if (ahd_get_transfer_length(scb) & 0x01) 277*1da177e4SLinus Torvalds scb->hscb->task_attribute = SCB_XFERLEN_ODD; 278*1da177e4SLinus Torvalds else 279*1da177e4SLinus Torvalds scb->hscb->task_attribute = 0; 280*1da177e4SLinus Torvalds } 281*1da177e4SLinus Torvalds 282*1da177e4SLinus Torvalds if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR 283*1da177e4SLinus Torvalds || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0) 284*1da177e4SLinus Torvalds scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr = 285*1da177e4SLinus Torvalds ahd_htole32(scb->sense_busaddr); 286*1da177e4SLinus Torvalds } 287*1da177e4SLinus Torvalds 288*1da177e4SLinus Torvalds static __inline void 289*1da177e4SLinus Torvalds ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb) 290*1da177e4SLinus Torvalds { 291*1da177e4SLinus Torvalds /* 292*1da177e4SLinus Torvalds * Copy the first SG into the "current" data ponter area. 293*1da177e4SLinus Torvalds */ 294*1da177e4SLinus Torvalds if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { 295*1da177e4SLinus Torvalds struct ahd_dma64_seg *sg; 296*1da177e4SLinus Torvalds 297*1da177e4SLinus Torvalds sg = (struct ahd_dma64_seg *)scb->sg_list; 298*1da177e4SLinus Torvalds scb->hscb->dataptr = sg->addr; 299*1da177e4SLinus Torvalds scb->hscb->datacnt = sg->len; 300*1da177e4SLinus Torvalds } else { 301*1da177e4SLinus Torvalds struct ahd_dma_seg *sg; 302*1da177e4SLinus Torvalds uint32_t *dataptr_words; 303*1da177e4SLinus Torvalds 304*1da177e4SLinus Torvalds sg = (struct ahd_dma_seg *)scb->sg_list; 305*1da177e4SLinus Torvalds dataptr_words = (uint32_t*)&scb->hscb->dataptr; 306*1da177e4SLinus Torvalds dataptr_words[0] = sg->addr; 307*1da177e4SLinus Torvalds dataptr_words[1] = 0; 308*1da177e4SLinus Torvalds if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { 309*1da177e4SLinus Torvalds uint64_t high_addr; 310*1da177e4SLinus Torvalds 311*1da177e4SLinus Torvalds high_addr = ahd_le32toh(sg->len) & 0x7F000000; 312*1da177e4SLinus Torvalds scb->hscb->dataptr |= ahd_htole64(high_addr << 8); 313*1da177e4SLinus Torvalds } 314*1da177e4SLinus Torvalds scb->hscb->datacnt = sg->len; 315*1da177e4SLinus Torvalds } 316*1da177e4SLinus Torvalds /* 317*1da177e4SLinus Torvalds * Note where to find the SG entries in bus space. 318*1da177e4SLinus Torvalds * We also set the full residual flag which the 319*1da177e4SLinus Torvalds * sequencer will clear as soon as a data transfer 320*1da177e4SLinus Torvalds * occurs. 321*1da177e4SLinus Torvalds */ 322*1da177e4SLinus Torvalds scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID); 323*1da177e4SLinus Torvalds } 324*1da177e4SLinus Torvalds 325*1da177e4SLinus Torvalds static __inline void 326*1da177e4SLinus Torvalds ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb) 327*1da177e4SLinus Torvalds { 328*1da177e4SLinus Torvalds scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL); 329*1da177e4SLinus Torvalds scb->hscb->dataptr = 0; 330*1da177e4SLinus Torvalds scb->hscb->datacnt = 0; 331*1da177e4SLinus Torvalds } 332*1da177e4SLinus Torvalds 333*1da177e4SLinus Torvalds /************************** Memory mapping routines ***************************/ 334*1da177e4SLinus Torvalds static __inline size_t ahd_sg_size(struct ahd_softc *ahd); 335*1da177e4SLinus Torvalds static __inline void * 336*1da177e4SLinus Torvalds ahd_sg_bus_to_virt(struct ahd_softc *ahd, 337*1da177e4SLinus Torvalds struct scb *scb, 338*1da177e4SLinus Torvalds uint32_t sg_busaddr); 339*1da177e4SLinus Torvalds static __inline uint32_t 340*1da177e4SLinus Torvalds ahd_sg_virt_to_bus(struct ahd_softc *ahd, 341*1da177e4SLinus Torvalds struct scb *scb, 342*1da177e4SLinus Torvalds void *sg); 343*1da177e4SLinus Torvalds static __inline void ahd_sync_scb(struct ahd_softc *ahd, 344*1da177e4SLinus Torvalds struct scb *scb, int op); 345*1da177e4SLinus Torvalds static __inline void ahd_sync_sglist(struct ahd_softc *ahd, 346*1da177e4SLinus Torvalds struct scb *scb, int op); 347*1da177e4SLinus Torvalds static __inline void ahd_sync_sense(struct ahd_softc *ahd, 348*1da177e4SLinus Torvalds struct scb *scb, int op); 349*1da177e4SLinus Torvalds static __inline uint32_t 350*1da177e4SLinus Torvalds ahd_targetcmd_offset(struct ahd_softc *ahd, 351*1da177e4SLinus Torvalds u_int index); 352*1da177e4SLinus Torvalds 353*1da177e4SLinus Torvalds static __inline size_t 354*1da177e4SLinus Torvalds ahd_sg_size(struct ahd_softc *ahd) 355*1da177e4SLinus Torvalds { 356*1da177e4SLinus Torvalds if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) 357*1da177e4SLinus Torvalds return (sizeof(struct ahd_dma64_seg)); 358*1da177e4SLinus Torvalds return (sizeof(struct ahd_dma_seg)); 359*1da177e4SLinus Torvalds } 360*1da177e4SLinus Torvalds 361*1da177e4SLinus Torvalds static __inline void * 362*1da177e4SLinus Torvalds ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr) 363*1da177e4SLinus Torvalds { 364*1da177e4SLinus Torvalds dma_addr_t sg_offset; 365*1da177e4SLinus Torvalds 366*1da177e4SLinus Torvalds /* sg_list_phys points to entry 1, not 0 */ 367*1da177e4SLinus Torvalds sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd)); 368*1da177e4SLinus Torvalds return ((uint8_t *)scb->sg_list + sg_offset); 369*1da177e4SLinus Torvalds } 370*1da177e4SLinus Torvalds 371*1da177e4SLinus Torvalds static __inline uint32_t 372*1da177e4SLinus Torvalds ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg) 373*1da177e4SLinus Torvalds { 374*1da177e4SLinus Torvalds dma_addr_t sg_offset; 375*1da177e4SLinus Torvalds 376*1da177e4SLinus Torvalds /* sg_list_phys points to entry 1, not 0 */ 377*1da177e4SLinus Torvalds sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list) 378*1da177e4SLinus Torvalds - ahd_sg_size(ahd); 379*1da177e4SLinus Torvalds 380*1da177e4SLinus Torvalds return (scb->sg_list_busaddr + sg_offset); 381*1da177e4SLinus Torvalds } 382*1da177e4SLinus Torvalds 383*1da177e4SLinus Torvalds static __inline void 384*1da177e4SLinus Torvalds ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op) 385*1da177e4SLinus Torvalds { 386*1da177e4SLinus Torvalds ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat, 387*1da177e4SLinus Torvalds scb->hscb_map->dmamap, 388*1da177e4SLinus Torvalds /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr, 389*1da177e4SLinus Torvalds /*len*/sizeof(*scb->hscb), op); 390*1da177e4SLinus Torvalds } 391*1da177e4SLinus Torvalds 392*1da177e4SLinus Torvalds static __inline void 393*1da177e4SLinus Torvalds ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op) 394*1da177e4SLinus Torvalds { 395*1da177e4SLinus Torvalds if (scb->sg_count == 0) 396*1da177e4SLinus Torvalds return; 397*1da177e4SLinus Torvalds 398*1da177e4SLinus Torvalds ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat, 399*1da177e4SLinus Torvalds scb->sg_map->dmamap, 400*1da177e4SLinus Torvalds /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd), 401*1da177e4SLinus Torvalds /*len*/ahd_sg_size(ahd) * scb->sg_count, op); 402*1da177e4SLinus Torvalds } 403*1da177e4SLinus Torvalds 404*1da177e4SLinus Torvalds static __inline void 405*1da177e4SLinus Torvalds ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op) 406*1da177e4SLinus Torvalds { 407*1da177e4SLinus Torvalds ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat, 408*1da177e4SLinus Torvalds scb->sense_map->dmamap, 409*1da177e4SLinus Torvalds /*offset*/scb->sense_busaddr, 410*1da177e4SLinus Torvalds /*len*/AHD_SENSE_BUFSIZE, op); 411*1da177e4SLinus Torvalds } 412*1da177e4SLinus Torvalds 413*1da177e4SLinus Torvalds static __inline uint32_t 414*1da177e4SLinus Torvalds ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index) 415*1da177e4SLinus Torvalds { 416*1da177e4SLinus Torvalds return (((uint8_t *)&ahd->targetcmds[index]) 417*1da177e4SLinus Torvalds - (uint8_t *)ahd->qoutfifo); 418*1da177e4SLinus Torvalds } 419*1da177e4SLinus Torvalds 420*1da177e4SLinus Torvalds /*********************** Miscelaneous Support Functions ***********************/ 421*1da177e4SLinus Torvalds static __inline void ahd_complete_scb(struct ahd_softc *ahd, 422*1da177e4SLinus Torvalds struct scb *scb); 423*1da177e4SLinus Torvalds static __inline void ahd_update_residual(struct ahd_softc *ahd, 424*1da177e4SLinus Torvalds struct scb *scb); 425*1da177e4SLinus Torvalds static __inline struct ahd_initiator_tinfo * 426*1da177e4SLinus Torvalds ahd_fetch_transinfo(struct ahd_softc *ahd, 427*1da177e4SLinus Torvalds char channel, u_int our_id, 428*1da177e4SLinus Torvalds u_int remote_id, 429*1da177e4SLinus Torvalds struct ahd_tmode_tstate **tstate); 430*1da177e4SLinus Torvalds static __inline uint16_t 431*1da177e4SLinus Torvalds ahd_inw(struct ahd_softc *ahd, u_int port); 432*1da177e4SLinus Torvalds static __inline void ahd_outw(struct ahd_softc *ahd, u_int port, 433*1da177e4SLinus Torvalds u_int value); 434*1da177e4SLinus Torvalds static __inline uint32_t 435*1da177e4SLinus Torvalds ahd_inl(struct ahd_softc *ahd, u_int port); 436*1da177e4SLinus Torvalds static __inline void ahd_outl(struct ahd_softc *ahd, u_int port, 437*1da177e4SLinus Torvalds uint32_t value); 438*1da177e4SLinus Torvalds static __inline uint64_t 439*1da177e4SLinus Torvalds ahd_inq(struct ahd_softc *ahd, u_int port); 440*1da177e4SLinus Torvalds static __inline void ahd_outq(struct ahd_softc *ahd, u_int port, 441*1da177e4SLinus Torvalds uint64_t value); 442*1da177e4SLinus Torvalds static __inline u_int ahd_get_scbptr(struct ahd_softc *ahd); 443*1da177e4SLinus Torvalds static __inline void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr); 444*1da177e4SLinus Torvalds static __inline u_int ahd_get_hnscb_qoff(struct ahd_softc *ahd); 445*1da177e4SLinus Torvalds static __inline void ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value); 446*1da177e4SLinus Torvalds static __inline u_int ahd_get_hescb_qoff(struct ahd_softc *ahd); 447*1da177e4SLinus Torvalds static __inline void ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value); 448*1da177e4SLinus Torvalds static __inline u_int ahd_get_snscb_qoff(struct ahd_softc *ahd); 449*1da177e4SLinus Torvalds static __inline void ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value); 450*1da177e4SLinus Torvalds static __inline u_int ahd_get_sescb_qoff(struct ahd_softc *ahd); 451*1da177e4SLinus Torvalds static __inline void ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value); 452*1da177e4SLinus Torvalds static __inline u_int ahd_get_sdscb_qoff(struct ahd_softc *ahd); 453*1da177e4SLinus Torvalds static __inline void ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value); 454*1da177e4SLinus Torvalds static __inline u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset); 455*1da177e4SLinus Torvalds static __inline u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset); 456*1da177e4SLinus Torvalds static __inline uint32_t 457*1da177e4SLinus Torvalds ahd_inl_scbram(struct ahd_softc *ahd, u_int offset); 458*1da177e4SLinus Torvalds static __inline uint64_t 459*1da177e4SLinus Torvalds ahd_inq_scbram(struct ahd_softc *ahd, u_int offset); 460*1da177e4SLinus Torvalds static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd, 461*1da177e4SLinus Torvalds struct scb *scb); 462*1da177e4SLinus Torvalds static __inline void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb); 463*1da177e4SLinus Torvalds static __inline uint8_t * 464*1da177e4SLinus Torvalds ahd_get_sense_buf(struct ahd_softc *ahd, 465*1da177e4SLinus Torvalds struct scb *scb); 466*1da177e4SLinus Torvalds static __inline uint32_t 467*1da177e4SLinus Torvalds ahd_get_sense_bufaddr(struct ahd_softc *ahd, 468*1da177e4SLinus Torvalds struct scb *scb); 469*1da177e4SLinus Torvalds 470*1da177e4SLinus Torvalds static __inline void 471*1da177e4SLinus Torvalds ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) 472*1da177e4SLinus Torvalds { 473*1da177e4SLinus Torvalds uint32_t sgptr; 474*1da177e4SLinus Torvalds 475*1da177e4SLinus Torvalds sgptr = ahd_le32toh(scb->hscb->sgptr); 476*1da177e4SLinus Torvalds if ((sgptr & SG_STATUS_VALID) != 0) 477*1da177e4SLinus Torvalds ahd_handle_scb_status(ahd, scb); 478*1da177e4SLinus Torvalds else 479*1da177e4SLinus Torvalds ahd_done(ahd, scb); 480*1da177e4SLinus Torvalds } 481*1da177e4SLinus Torvalds 482*1da177e4SLinus Torvalds /* 483*1da177e4SLinus Torvalds * Determine whether the sequencer reported a residual 484*1da177e4SLinus Torvalds * for this SCB/transaction. 485*1da177e4SLinus Torvalds */ 486*1da177e4SLinus Torvalds static __inline void 487*1da177e4SLinus Torvalds ahd_update_residual(struct ahd_softc *ahd, struct scb *scb) 488*1da177e4SLinus Torvalds { 489*1da177e4SLinus Torvalds uint32_t sgptr; 490*1da177e4SLinus Torvalds 491*1da177e4SLinus Torvalds sgptr = ahd_le32toh(scb->hscb->sgptr); 492*1da177e4SLinus Torvalds if ((sgptr & SG_STATUS_VALID) != 0) 493*1da177e4SLinus Torvalds ahd_calc_residual(ahd, scb); 494*1da177e4SLinus Torvalds } 495*1da177e4SLinus Torvalds 496*1da177e4SLinus Torvalds /* 497*1da177e4SLinus Torvalds * Return pointers to the transfer negotiation information 498*1da177e4SLinus Torvalds * for the specified our_id/remote_id pair. 499*1da177e4SLinus Torvalds */ 500*1da177e4SLinus Torvalds static __inline struct ahd_initiator_tinfo * 501*1da177e4SLinus Torvalds ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id, 502*1da177e4SLinus Torvalds u_int remote_id, struct ahd_tmode_tstate **tstate) 503*1da177e4SLinus Torvalds { 504*1da177e4SLinus Torvalds /* 505*1da177e4SLinus Torvalds * Transfer data structures are stored from the perspective 506*1da177e4SLinus Torvalds * of the target role. Since the parameters for a connection 507*1da177e4SLinus Torvalds * in the initiator role to a given target are the same as 508*1da177e4SLinus Torvalds * when the roles are reversed, we pretend we are the target. 509*1da177e4SLinus Torvalds */ 510*1da177e4SLinus Torvalds if (channel == 'B') 511*1da177e4SLinus Torvalds our_id += 8; 512*1da177e4SLinus Torvalds *tstate = ahd->enabled_targets[our_id]; 513*1da177e4SLinus Torvalds return (&(*tstate)->transinfo[remote_id]); 514*1da177e4SLinus Torvalds } 515*1da177e4SLinus Torvalds 516*1da177e4SLinus Torvalds #define AHD_COPY_COL_IDX(dst, src) \ 517*1da177e4SLinus Torvalds do { \ 518*1da177e4SLinus Torvalds dst->hscb->scsiid = src->hscb->scsiid; \ 519*1da177e4SLinus Torvalds dst->hscb->lun = src->hscb->lun; \ 520*1da177e4SLinus Torvalds } while (0) 521*1da177e4SLinus Torvalds 522*1da177e4SLinus Torvalds static __inline uint16_t 523*1da177e4SLinus Torvalds ahd_inw(struct ahd_softc *ahd, u_int port) 524*1da177e4SLinus Torvalds { 525*1da177e4SLinus Torvalds return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port)); 526*1da177e4SLinus Torvalds } 527*1da177e4SLinus Torvalds 528*1da177e4SLinus Torvalds static __inline void 529*1da177e4SLinus Torvalds ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) 530*1da177e4SLinus Torvalds { 531*1da177e4SLinus Torvalds ahd_outb(ahd, port, value & 0xFF); 532*1da177e4SLinus Torvalds ahd_outb(ahd, port+1, (value >> 8) & 0xFF); 533*1da177e4SLinus Torvalds } 534*1da177e4SLinus Torvalds 535*1da177e4SLinus Torvalds static __inline uint32_t 536*1da177e4SLinus Torvalds ahd_inl(struct ahd_softc *ahd, u_int port) 537*1da177e4SLinus Torvalds { 538*1da177e4SLinus Torvalds return ((ahd_inb(ahd, port)) 539*1da177e4SLinus Torvalds | (ahd_inb(ahd, port+1) << 8) 540*1da177e4SLinus Torvalds | (ahd_inb(ahd, port+2) << 16) 541*1da177e4SLinus Torvalds | (ahd_inb(ahd, port+3) << 24)); 542*1da177e4SLinus Torvalds } 543*1da177e4SLinus Torvalds 544*1da177e4SLinus Torvalds static __inline void 545*1da177e4SLinus Torvalds ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value) 546*1da177e4SLinus Torvalds { 547*1da177e4SLinus Torvalds ahd_outb(ahd, port, (value) & 0xFF); 548*1da177e4SLinus Torvalds ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF); 549*1da177e4SLinus Torvalds ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF); 550*1da177e4SLinus Torvalds ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF); 551*1da177e4SLinus Torvalds } 552*1da177e4SLinus Torvalds 553*1da177e4SLinus Torvalds static __inline uint64_t 554*1da177e4SLinus Torvalds ahd_inq(struct ahd_softc *ahd, u_int port) 555*1da177e4SLinus Torvalds { 556*1da177e4SLinus Torvalds return ((ahd_inb(ahd, port)) 557*1da177e4SLinus Torvalds | (ahd_inb(ahd, port+1) << 8) 558*1da177e4SLinus Torvalds | (ahd_inb(ahd, port+2) << 16) 559*1da177e4SLinus Torvalds | (ahd_inb(ahd, port+3) << 24) 560*1da177e4SLinus Torvalds | (((uint64_t)ahd_inb(ahd, port+4)) << 32) 561*1da177e4SLinus Torvalds | (((uint64_t)ahd_inb(ahd, port+5)) << 40) 562*1da177e4SLinus Torvalds | (((uint64_t)ahd_inb(ahd, port+6)) << 48) 563*1da177e4SLinus Torvalds | (((uint64_t)ahd_inb(ahd, port+7)) << 56)); 564*1da177e4SLinus Torvalds } 565*1da177e4SLinus Torvalds 566*1da177e4SLinus Torvalds static __inline void 567*1da177e4SLinus Torvalds ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value) 568*1da177e4SLinus Torvalds { 569*1da177e4SLinus Torvalds ahd_outb(ahd, port, value & 0xFF); 570*1da177e4SLinus Torvalds ahd_outb(ahd, port+1, (value >> 8) & 0xFF); 571*1da177e4SLinus Torvalds ahd_outb(ahd, port+2, (value >> 16) & 0xFF); 572*1da177e4SLinus Torvalds ahd_outb(ahd, port+3, (value >> 24) & 0xFF); 573*1da177e4SLinus Torvalds ahd_outb(ahd, port+4, (value >> 32) & 0xFF); 574*1da177e4SLinus Torvalds ahd_outb(ahd, port+5, (value >> 40) & 0xFF); 575*1da177e4SLinus Torvalds ahd_outb(ahd, port+6, (value >> 48) & 0xFF); 576*1da177e4SLinus Torvalds ahd_outb(ahd, port+7, (value >> 56) & 0xFF); 577*1da177e4SLinus Torvalds } 578*1da177e4SLinus Torvalds 579*1da177e4SLinus Torvalds static __inline u_int 580*1da177e4SLinus Torvalds ahd_get_scbptr(struct ahd_softc *ahd) 581*1da177e4SLinus Torvalds { 582*1da177e4SLinus Torvalds AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), 583*1da177e4SLinus Torvalds ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK)); 584*1da177e4SLinus Torvalds return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8)); 585*1da177e4SLinus Torvalds } 586*1da177e4SLinus Torvalds 587*1da177e4SLinus Torvalds static __inline void 588*1da177e4SLinus Torvalds ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr) 589*1da177e4SLinus Torvalds { 590*1da177e4SLinus Torvalds AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), 591*1da177e4SLinus Torvalds ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK)); 592*1da177e4SLinus Torvalds ahd_outb(ahd, SCBPTR, scbptr & 0xFF); 593*1da177e4SLinus Torvalds ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF); 594*1da177e4SLinus Torvalds } 595*1da177e4SLinus Torvalds 596*1da177e4SLinus Torvalds static __inline u_int 597*1da177e4SLinus Torvalds ahd_get_hnscb_qoff(struct ahd_softc *ahd) 598*1da177e4SLinus Torvalds { 599*1da177e4SLinus Torvalds return (ahd_inw_atomic(ahd, HNSCB_QOFF)); 600*1da177e4SLinus Torvalds } 601*1da177e4SLinus Torvalds 602*1da177e4SLinus Torvalds static __inline void 603*1da177e4SLinus Torvalds ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value) 604*1da177e4SLinus Torvalds { 605*1da177e4SLinus Torvalds ahd_outw_atomic(ahd, HNSCB_QOFF, value); 606*1da177e4SLinus Torvalds } 607*1da177e4SLinus Torvalds 608*1da177e4SLinus Torvalds static __inline u_int 609*1da177e4SLinus Torvalds ahd_get_hescb_qoff(struct ahd_softc *ahd) 610*1da177e4SLinus Torvalds { 611*1da177e4SLinus Torvalds return (ahd_inb(ahd, HESCB_QOFF)); 612*1da177e4SLinus Torvalds } 613*1da177e4SLinus Torvalds 614*1da177e4SLinus Torvalds static __inline void 615*1da177e4SLinus Torvalds ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value) 616*1da177e4SLinus Torvalds { 617*1da177e4SLinus Torvalds ahd_outb(ahd, HESCB_QOFF, value); 618*1da177e4SLinus Torvalds } 619*1da177e4SLinus Torvalds 620*1da177e4SLinus Torvalds static __inline u_int 621*1da177e4SLinus Torvalds ahd_get_snscb_qoff(struct ahd_softc *ahd) 622*1da177e4SLinus Torvalds { 623*1da177e4SLinus Torvalds u_int oldvalue; 624*1da177e4SLinus Torvalds 625*1da177e4SLinus Torvalds AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); 626*1da177e4SLinus Torvalds oldvalue = ahd_inw(ahd, SNSCB_QOFF); 627*1da177e4SLinus Torvalds ahd_outw(ahd, SNSCB_QOFF, oldvalue); 628*1da177e4SLinus Torvalds return (oldvalue); 629*1da177e4SLinus Torvalds } 630*1da177e4SLinus Torvalds 631*1da177e4SLinus Torvalds static __inline void 632*1da177e4SLinus Torvalds ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value) 633*1da177e4SLinus Torvalds { 634*1da177e4SLinus Torvalds AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); 635*1da177e4SLinus Torvalds ahd_outw(ahd, SNSCB_QOFF, value); 636*1da177e4SLinus Torvalds } 637*1da177e4SLinus Torvalds 638*1da177e4SLinus Torvalds static __inline u_int 639*1da177e4SLinus Torvalds ahd_get_sescb_qoff(struct ahd_softc *ahd) 640*1da177e4SLinus Torvalds { 641*1da177e4SLinus Torvalds AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); 642*1da177e4SLinus Torvalds return (ahd_inb(ahd, SESCB_QOFF)); 643*1da177e4SLinus Torvalds } 644*1da177e4SLinus Torvalds 645*1da177e4SLinus Torvalds static __inline void 646*1da177e4SLinus Torvalds ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value) 647*1da177e4SLinus Torvalds { 648*1da177e4SLinus Torvalds AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); 649*1da177e4SLinus Torvalds ahd_outb(ahd, SESCB_QOFF, value); 650*1da177e4SLinus Torvalds } 651*1da177e4SLinus Torvalds 652*1da177e4SLinus Torvalds static __inline u_int 653*1da177e4SLinus Torvalds ahd_get_sdscb_qoff(struct ahd_softc *ahd) 654*1da177e4SLinus Torvalds { 655*1da177e4SLinus Torvalds AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); 656*1da177e4SLinus Torvalds return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8)); 657*1da177e4SLinus Torvalds } 658*1da177e4SLinus Torvalds 659*1da177e4SLinus Torvalds static __inline void 660*1da177e4SLinus Torvalds ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value) 661*1da177e4SLinus Torvalds { 662*1da177e4SLinus Torvalds AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); 663*1da177e4SLinus Torvalds ahd_outb(ahd, SDSCB_QOFF, value & 0xFF); 664*1da177e4SLinus Torvalds ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF); 665*1da177e4SLinus Torvalds } 666*1da177e4SLinus Torvalds 667*1da177e4SLinus Torvalds static __inline u_int 668*1da177e4SLinus Torvalds ahd_inb_scbram(struct ahd_softc *ahd, u_int offset) 669*1da177e4SLinus Torvalds { 670*1da177e4SLinus Torvalds u_int value; 671*1da177e4SLinus Torvalds 672*1da177e4SLinus Torvalds /* 673*1da177e4SLinus Torvalds * Workaround PCI-X Rev A. hardware bug. 674*1da177e4SLinus Torvalds * After a host read of SCB memory, the chip 675*1da177e4SLinus Torvalds * may become confused into thinking prefetch 676*1da177e4SLinus Torvalds * was required. This starts the discard timer 677*1da177e4SLinus Torvalds * running and can cause an unexpected discard 678*1da177e4SLinus Torvalds * timer interrupt. The work around is to read 679*1da177e4SLinus Torvalds * a normal register prior to the exhaustion of 680*1da177e4SLinus Torvalds * the discard timer. The mode pointer register 681*1da177e4SLinus Torvalds * has no side effects and so serves well for 682*1da177e4SLinus Torvalds * this purpose. 683*1da177e4SLinus Torvalds * 684*1da177e4SLinus Torvalds * Razor #528 685*1da177e4SLinus Torvalds */ 686*1da177e4SLinus Torvalds value = ahd_inb(ahd, offset); 687*1da177e4SLinus Torvalds if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0) 688*1da177e4SLinus Torvalds ahd_inb(ahd, MODE_PTR); 689*1da177e4SLinus Torvalds return (value); 690*1da177e4SLinus Torvalds } 691*1da177e4SLinus Torvalds 692*1da177e4SLinus Torvalds static __inline u_int 693*1da177e4SLinus Torvalds ahd_inw_scbram(struct ahd_softc *ahd, u_int offset) 694*1da177e4SLinus Torvalds { 695*1da177e4SLinus Torvalds return (ahd_inb_scbram(ahd, offset) 696*1da177e4SLinus Torvalds | (ahd_inb_scbram(ahd, offset+1) << 8)); 697*1da177e4SLinus Torvalds } 698*1da177e4SLinus Torvalds 699*1da177e4SLinus Torvalds static __inline uint32_t 700*1da177e4SLinus Torvalds ahd_inl_scbram(struct ahd_softc *ahd, u_int offset) 701*1da177e4SLinus Torvalds { 702*1da177e4SLinus Torvalds return (ahd_inw_scbram(ahd, offset) 703*1da177e4SLinus Torvalds | (ahd_inw_scbram(ahd, offset+2) << 16)); 704*1da177e4SLinus Torvalds } 705*1da177e4SLinus Torvalds 706*1da177e4SLinus Torvalds static __inline uint64_t 707*1da177e4SLinus Torvalds ahd_inq_scbram(struct ahd_softc *ahd, u_int offset) 708*1da177e4SLinus Torvalds { 709*1da177e4SLinus Torvalds return (ahd_inl_scbram(ahd, offset) 710*1da177e4SLinus Torvalds | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32); 711*1da177e4SLinus Torvalds } 712*1da177e4SLinus Torvalds 713*1da177e4SLinus Torvalds static __inline struct scb * 714*1da177e4SLinus Torvalds ahd_lookup_scb(struct ahd_softc *ahd, u_int tag) 715*1da177e4SLinus Torvalds { 716*1da177e4SLinus Torvalds struct scb* scb; 717*1da177e4SLinus Torvalds 718*1da177e4SLinus Torvalds if (tag >= AHD_SCB_MAX) 719*1da177e4SLinus Torvalds return (NULL); 720*1da177e4SLinus Torvalds scb = ahd->scb_data.scbindex[tag]; 721*1da177e4SLinus Torvalds if (scb != NULL) 722*1da177e4SLinus Torvalds ahd_sync_scb(ahd, scb, 723*1da177e4SLinus Torvalds BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 724*1da177e4SLinus Torvalds return (scb); 725*1da177e4SLinus Torvalds } 726*1da177e4SLinus Torvalds 727*1da177e4SLinus Torvalds static __inline void 728*1da177e4SLinus Torvalds ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) 729*1da177e4SLinus Torvalds { 730*1da177e4SLinus Torvalds struct hardware_scb *q_hscb; 731*1da177e4SLinus Torvalds uint32_t saved_hscb_busaddr; 732*1da177e4SLinus Torvalds 733*1da177e4SLinus Torvalds /* 734*1da177e4SLinus Torvalds * Our queuing method is a bit tricky. The card 735*1da177e4SLinus Torvalds * knows in advance which HSCB (by address) to download, 736*1da177e4SLinus Torvalds * and we can't disappoint it. To achieve this, the next 737*1da177e4SLinus Torvalds * HSCB to download is saved off in ahd->next_queued_hscb. 738*1da177e4SLinus Torvalds * When we are called to queue "an arbitrary scb", 739*1da177e4SLinus Torvalds * we copy the contents of the incoming HSCB to the one 740*1da177e4SLinus Torvalds * the sequencer knows about, swap HSCB pointers and 741*1da177e4SLinus Torvalds * finally assign the SCB to the tag indexed location 742*1da177e4SLinus Torvalds * in the scb_array. This makes sure that we can still 743*1da177e4SLinus Torvalds * locate the correct SCB by SCB_TAG. 744*1da177e4SLinus Torvalds */ 745*1da177e4SLinus Torvalds q_hscb = ahd->next_queued_hscb; 746*1da177e4SLinus Torvalds saved_hscb_busaddr = q_hscb->hscb_busaddr; 747*1da177e4SLinus Torvalds memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); 748*1da177e4SLinus Torvalds q_hscb->hscb_busaddr = saved_hscb_busaddr; 749*1da177e4SLinus Torvalds q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; 750*1da177e4SLinus Torvalds 751*1da177e4SLinus Torvalds /* Now swap HSCB pointers. */ 752*1da177e4SLinus Torvalds ahd->next_queued_hscb = scb->hscb; 753*1da177e4SLinus Torvalds scb->hscb = q_hscb; 754*1da177e4SLinus Torvalds 755*1da177e4SLinus Torvalds /* Now define the mapping from tag to SCB in the scbindex */ 756*1da177e4SLinus Torvalds ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; 757*1da177e4SLinus Torvalds } 758*1da177e4SLinus Torvalds 759*1da177e4SLinus Torvalds /* 760*1da177e4SLinus Torvalds * Tell the sequencer about a new transaction to execute. 761*1da177e4SLinus Torvalds */ 762*1da177e4SLinus Torvalds static __inline void 763*1da177e4SLinus Torvalds ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb) 764*1da177e4SLinus Torvalds { 765*1da177e4SLinus Torvalds ahd_swap_with_next_hscb(ahd, scb); 766*1da177e4SLinus Torvalds 767*1da177e4SLinus Torvalds if (SCBID_IS_NULL(SCB_GET_TAG(scb))) 768*1da177e4SLinus Torvalds panic("Attempt to queue invalid SCB tag %x\n", 769*1da177e4SLinus Torvalds SCB_GET_TAG(scb)); 770*1da177e4SLinus Torvalds 771*1da177e4SLinus Torvalds /* 772*1da177e4SLinus Torvalds * Keep a history of SCBs we've downloaded in the qinfifo. 773*1da177e4SLinus Torvalds */ 774*1da177e4SLinus Torvalds ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb); 775*1da177e4SLinus Torvalds ahd->qinfifonext++; 776*1da177e4SLinus Torvalds 777*1da177e4SLinus Torvalds if (scb->sg_count != 0) 778*1da177e4SLinus Torvalds ahd_setup_data_scb(ahd, scb); 779*1da177e4SLinus Torvalds else 780*1da177e4SLinus Torvalds ahd_setup_noxfer_scb(ahd, scb); 781*1da177e4SLinus Torvalds ahd_setup_scb_common(ahd, scb); 782*1da177e4SLinus Torvalds 783*1da177e4SLinus Torvalds /* 784*1da177e4SLinus Torvalds * Make sure our data is consistent from the 785*1da177e4SLinus Torvalds * perspective of the adapter. 786*1da177e4SLinus Torvalds */ 787*1da177e4SLinus Torvalds ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 788*1da177e4SLinus Torvalds 789*1da177e4SLinus Torvalds #ifdef AHD_DEBUG 790*1da177e4SLinus Torvalds if ((ahd_debug & AHD_SHOW_QUEUE) != 0) { 791*1da177e4SLinus Torvalds uint64_t host_dataptr; 792*1da177e4SLinus Torvalds 793*1da177e4SLinus Torvalds host_dataptr = ahd_le64toh(scb->hscb->dataptr); 794*1da177e4SLinus Torvalds printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n", 795*1da177e4SLinus Torvalds ahd_name(ahd), 796*1da177e4SLinus Torvalds SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr), 797*1da177e4SLinus Torvalds (u_int)((host_dataptr >> 32) & 0xFFFFFFFF), 798*1da177e4SLinus Torvalds (u_int)(host_dataptr & 0xFFFFFFFF), 799*1da177e4SLinus Torvalds ahd_le32toh(scb->hscb->datacnt)); 800*1da177e4SLinus Torvalds } 801*1da177e4SLinus Torvalds #endif 802*1da177e4SLinus Torvalds /* Tell the adapter about the newly queued SCB */ 803*1da177e4SLinus Torvalds ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); 804*1da177e4SLinus Torvalds } 805*1da177e4SLinus Torvalds 806*1da177e4SLinus Torvalds static __inline uint8_t * 807*1da177e4SLinus Torvalds ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb) 808*1da177e4SLinus Torvalds { 809*1da177e4SLinus Torvalds return (scb->sense_data); 810*1da177e4SLinus Torvalds } 811*1da177e4SLinus Torvalds 812*1da177e4SLinus Torvalds static __inline uint32_t 813*1da177e4SLinus Torvalds ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb) 814*1da177e4SLinus Torvalds { 815*1da177e4SLinus Torvalds return (scb->sense_busaddr); 816*1da177e4SLinus Torvalds } 817*1da177e4SLinus Torvalds 818*1da177e4SLinus Torvalds /************************** Interrupt Processing ******************************/ 819*1da177e4SLinus Torvalds static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op); 820*1da177e4SLinus Torvalds static __inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op); 821*1da177e4SLinus Torvalds static __inline u_int ahd_check_cmdcmpltqueues(struct ahd_softc *ahd); 822*1da177e4SLinus Torvalds static __inline int ahd_intr(struct ahd_softc *ahd); 823*1da177e4SLinus Torvalds 824*1da177e4SLinus Torvalds static __inline void 825*1da177e4SLinus Torvalds ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) 826*1da177e4SLinus Torvalds { 827*1da177e4SLinus Torvalds ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, 828*1da177e4SLinus Torvalds /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op); 829*1da177e4SLinus Torvalds } 830*1da177e4SLinus Torvalds 831*1da177e4SLinus Torvalds static __inline void 832*1da177e4SLinus Torvalds ahd_sync_tqinfifo(struct ahd_softc *ahd, int op) 833*1da177e4SLinus Torvalds { 834*1da177e4SLinus Torvalds #ifdef AHD_TARGET_MODE 835*1da177e4SLinus Torvalds if ((ahd->flags & AHD_TARGETROLE) != 0) { 836*1da177e4SLinus Torvalds ahd_dmamap_sync(ahd, ahd->shared_data_dmat, 837*1da177e4SLinus Torvalds ahd->shared_data_dmamap, 838*1da177e4SLinus Torvalds ahd_targetcmd_offset(ahd, 0), 839*1da177e4SLinus Torvalds sizeof(struct target_cmd) * AHD_TMODE_CMDS, 840*1da177e4SLinus Torvalds op); 841*1da177e4SLinus Torvalds } 842*1da177e4SLinus Torvalds #endif 843*1da177e4SLinus Torvalds } 844*1da177e4SLinus Torvalds 845*1da177e4SLinus Torvalds /* 846*1da177e4SLinus Torvalds * See if the firmware has posted any completed commands 847*1da177e4SLinus Torvalds * into our in-core command complete fifos. 848*1da177e4SLinus Torvalds */ 849*1da177e4SLinus Torvalds #define AHD_RUN_QOUTFIFO 0x1 850*1da177e4SLinus Torvalds #define AHD_RUN_TQINFIFO 0x2 851*1da177e4SLinus Torvalds static __inline u_int 852*1da177e4SLinus Torvalds ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) 853*1da177e4SLinus Torvalds { 854*1da177e4SLinus Torvalds u_int retval; 855*1da177e4SLinus Torvalds 856*1da177e4SLinus Torvalds retval = 0; 857*1da177e4SLinus Torvalds ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, 858*1da177e4SLinus Torvalds /*offset*/ahd->qoutfifonext, /*len*/2, 859*1da177e4SLinus Torvalds BUS_DMASYNC_POSTREAD); 860*1da177e4SLinus Torvalds if ((ahd->qoutfifo[ahd->qoutfifonext] 861*1da177e4SLinus Torvalds & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) 862*1da177e4SLinus Torvalds retval |= AHD_RUN_QOUTFIFO; 863*1da177e4SLinus Torvalds #ifdef AHD_TARGET_MODE 864*1da177e4SLinus Torvalds if ((ahd->flags & AHD_TARGETROLE) != 0 865*1da177e4SLinus Torvalds && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { 866*1da177e4SLinus Torvalds ahd_dmamap_sync(ahd, ahd->shared_data_dmat, 867*1da177e4SLinus Torvalds ahd->shared_data_dmamap, 868*1da177e4SLinus Torvalds ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), 869*1da177e4SLinus Torvalds /*len*/sizeof(struct target_cmd), 870*1da177e4SLinus Torvalds BUS_DMASYNC_POSTREAD); 871*1da177e4SLinus Torvalds if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0) 872*1da177e4SLinus Torvalds retval |= AHD_RUN_TQINFIFO; 873*1da177e4SLinus Torvalds } 874*1da177e4SLinus Torvalds #endif 875*1da177e4SLinus Torvalds return (retval); 876*1da177e4SLinus Torvalds } 877*1da177e4SLinus Torvalds 878*1da177e4SLinus Torvalds /* 879*1da177e4SLinus Torvalds * Catch an interrupt from the adapter 880*1da177e4SLinus Torvalds */ 881*1da177e4SLinus Torvalds static __inline int 882*1da177e4SLinus Torvalds ahd_intr(struct ahd_softc *ahd) 883*1da177e4SLinus Torvalds { 884*1da177e4SLinus Torvalds u_int intstat; 885*1da177e4SLinus Torvalds 886*1da177e4SLinus Torvalds if ((ahd->pause & INTEN) == 0) { 887*1da177e4SLinus Torvalds /* 888*1da177e4SLinus Torvalds * Our interrupt is not enabled on the chip 889*1da177e4SLinus Torvalds * and may be disabled for re-entrancy reasons, 890*1da177e4SLinus Torvalds * so just return. This is likely just a shared 891*1da177e4SLinus Torvalds * interrupt. 892*1da177e4SLinus Torvalds */ 893*1da177e4SLinus Torvalds return (0); 894*1da177e4SLinus Torvalds } 895*1da177e4SLinus Torvalds 896*1da177e4SLinus Torvalds /* 897*1da177e4SLinus Torvalds * Instead of directly reading the interrupt status register, 898*1da177e4SLinus Torvalds * infer the cause of the interrupt by checking our in-core 899*1da177e4SLinus Torvalds * completion queues. This avoids a costly PCI bus read in 900*1da177e4SLinus Torvalds * most cases. 901*1da177e4SLinus Torvalds */ 902*1da177e4SLinus Torvalds if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0 903*1da177e4SLinus Torvalds && (ahd_check_cmdcmpltqueues(ahd) != 0)) 904*1da177e4SLinus Torvalds intstat = CMDCMPLT; 905*1da177e4SLinus Torvalds else 906*1da177e4SLinus Torvalds intstat = ahd_inb(ahd, INTSTAT); 907*1da177e4SLinus Torvalds 908*1da177e4SLinus Torvalds if ((intstat & INT_PEND) == 0) 909*1da177e4SLinus Torvalds return (0); 910*1da177e4SLinus Torvalds 911*1da177e4SLinus Torvalds if (intstat & CMDCMPLT) { 912*1da177e4SLinus Torvalds ahd_outb(ahd, CLRINT, CLRCMDINT); 913*1da177e4SLinus Torvalds 914*1da177e4SLinus Torvalds /* 915*1da177e4SLinus Torvalds * Ensure that the chip sees that we've cleared 916*1da177e4SLinus Torvalds * this interrupt before we walk the output fifo. 917*1da177e4SLinus Torvalds * Otherwise, we may, due to posted bus writes, 918*1da177e4SLinus Torvalds * clear the interrupt after we finish the scan, 919*1da177e4SLinus Torvalds * and after the sequencer has added new entries 920*1da177e4SLinus Torvalds * and asserted the interrupt again. 921*1da177e4SLinus Torvalds */ 922*1da177e4SLinus Torvalds if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { 923*1da177e4SLinus Torvalds if (ahd_is_paused(ahd)) { 924*1da177e4SLinus Torvalds /* 925*1da177e4SLinus Torvalds * Potentially lost SEQINT. 926*1da177e4SLinus Torvalds * If SEQINTCODE is non-zero, 927*1da177e4SLinus Torvalds * simulate the SEQINT. 928*1da177e4SLinus Torvalds */ 929*1da177e4SLinus Torvalds if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT) 930*1da177e4SLinus Torvalds intstat |= SEQINT; 931*1da177e4SLinus Torvalds } 932*1da177e4SLinus Torvalds } else { 933*1da177e4SLinus Torvalds ahd_flush_device_writes(ahd); 934*1da177e4SLinus Torvalds } 935*1da177e4SLinus Torvalds ahd_run_qoutfifo(ahd); 936*1da177e4SLinus Torvalds ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++; 937*1da177e4SLinus Torvalds ahd->cmdcmplt_total++; 938*1da177e4SLinus Torvalds #ifdef AHD_TARGET_MODE 939*1da177e4SLinus Torvalds if ((ahd->flags & AHD_TARGETROLE) != 0) 940*1da177e4SLinus Torvalds ahd_run_tqinfifo(ahd, /*paused*/FALSE); 941*1da177e4SLinus Torvalds #endif 942*1da177e4SLinus Torvalds } 943*1da177e4SLinus Torvalds 944*1da177e4SLinus Torvalds /* 945*1da177e4SLinus Torvalds * Handle statuses that may invalidate our cached 946*1da177e4SLinus Torvalds * copy of INTSTAT separately. 947*1da177e4SLinus Torvalds */ 948*1da177e4SLinus Torvalds if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) { 949*1da177e4SLinus Torvalds /* Hot eject. Do nothing */ 950*1da177e4SLinus Torvalds } else if (intstat & HWERRINT) { 951*1da177e4SLinus Torvalds ahd_handle_hwerrint(ahd); 952*1da177e4SLinus Torvalds } else if ((intstat & (PCIINT|SPLTINT)) != 0) { 953*1da177e4SLinus Torvalds ahd->bus_intr(ahd); 954*1da177e4SLinus Torvalds } else { 955*1da177e4SLinus Torvalds 956*1da177e4SLinus Torvalds if ((intstat & SEQINT) != 0) 957*1da177e4SLinus Torvalds ahd_handle_seqint(ahd, intstat); 958*1da177e4SLinus Torvalds 959*1da177e4SLinus Torvalds if ((intstat & SCSIINT) != 0) 960*1da177e4SLinus Torvalds ahd_handle_scsiint(ahd, intstat); 961*1da177e4SLinus Torvalds } 962*1da177e4SLinus Torvalds return (1); 963*1da177e4SLinus Torvalds } 964*1da177e4SLinus Torvalds 965*1da177e4SLinus Torvalds #endif /* _AIC79XX_INLINE_H_ */ 966