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