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