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