Merge from vendor branch OPENSSH:
[dragonfly.git] / sys / dev / atm / hfa / fore_intr.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/dev/hfa/fore_intr.c,v 1.3 1999/08/28 00:41:50 peter Exp $
27  *      @(#) $DragonFly: src/sys/dev/atm/hfa/fore_intr.c,v 1.4 2003/08/07 21:16:49 dillon Exp $
28  */
29
30 /*
31  * FORE Systems 200-Series Adapter Support
32  * ---------------------------------------
33  *
34  * Interrupt processing
35  *
36  */
37
38 #include "fore_include.h"
39
40 #if defined(sun)
41 /*
42  * Polling interrupt routine
43  * 
44  * Polling interrupts are handled by calling all interrupt service 
45  * routines for a given level until someone claims to have "handled" the 
46  * interrupt.
47  *
48  * Called at interrupt level.
49  *
50  * Arguments:
51  *      none
52  *
53  * Returns:
54  *      1               an interrupt has been serviced
55  *      0               no interrupts serviced
56  *
57  */
58 int
59 fore_poll()
60 {
61         int     serviced = 0;
62         int     unit;
63
64         /*
65          * See if any of our devices are interrupting
66          */
67         for ( unit = 0; unit < fore_nunits; unit++ )
68         {
69                 Fore_unit       *fup = fore_units[unit];
70
71                 if (fup == NULL)
72                         continue;
73
74                 serviced += fore_intr((void *)fup);
75         }
76
77         /*
78          * Indicate if we handled an interrupt
79          */
80         return (serviced ? 1 : 0);
81 }
82 #endif  /* defined(sun) */
83
84
85 /*
86  * Device interrupt routine
87  * 
88  * Called at interrupt level.
89  *
90  * Arguments:
91  *      arg             pointer to device unit structure
92  *
93  * Returns:
94  *      1               device interrupt was serviced
95  *      0               no interrupts serviced
96  *
97  */
98 #if (defined(BSD) && (BSD <= 199306))
99 int
100 #else
101 void
102 #endif
103 fore_intr(arg)
104         void    *arg;
105 {
106         Fore_unit       *fup = arg;
107         Aali    *aap;
108 #if (defined(BSD) && (BSD <= 199306))
109         int     serviced = 0;
110 #endif
111
112         /*
113          * Try to prevent stuff happening after we've paniced
114          */
115         if (panicstr) {
116                 goto done;
117         }
118
119         /*
120          * Get to the microcode shared memory interface
121          */
122         if ((aap = fup->fu_aali) == NULL)
123                 goto done;
124
125         /*
126          * Has this card issued an interrupt??
127          */
128 #ifdef FORE_PCI
129         if (*fup->fu_psr) {
130 #else
131         if (aap->aali_intr_sent) {
132 #endif
133
134                 /*
135                  * Indicate that we've serviced an interrupt. 
136                  */
137 #if (defined(BSD) && (BSD <= 199306))
138                 serviced = 1;
139 #endif
140
141                 /*
142                  * Clear the device interrupt
143                  */
144                 switch (fup->fu_config.ac_device) {
145
146 #ifdef FORE_SBUS
147                 case DEV_FORE_SBA200E:
148                         SBA200E_HCR_SET(*fup->fu_ctlreg, SBA200E_CLR_SBUS_INTR);
149                         break;
150
151                 case DEV_FORE_SBA200:
152                         *fup->fu_ctlreg = SBA200_CLR_SBUS_INTR;
153                         break;
154 #endif
155 #ifdef FORE_PCI
156                 case DEV_FORE_PCA200E:
157                         PCA200E_HCR_SET(*fup->fu_ctlreg, PCA200E_CLR_HBUS_INT);
158                         break;
159 #endif
160                 default:
161                         panic("fore_intr: unknown device type");
162                 }
163                 aap->aali_intr_sent = CP_WRITE(0);
164
165                 /*
166                  * Reset the watchdog timer
167                  */
168                 fup->fu_timer = FORE_WATCHDOG;
169
170                 /*
171                  * Device initialization handled separately
172                  */
173                 if ((fup->fu_flags & CUF_INITED) == 0) {
174
175                         /*
176                          * We're just initializing device now, so see if
177                          * the initialization command has completed
178                          */
179                         if (CP_READ(aap->aali_init.init_status) & 
180                                                 QSTAT_COMPLETED)
181                                 fore_initialize_complete(fup);
182
183                         /*
184                          * If we're still not inited, none of the host
185                          * queues are setup yet
186                          */
187                         if ((fup->fu_flags & CUF_INITED) == 0)
188                                 goto done;
189                 }
190
191                 /*
192                  * Drain the queues of completed work
193                  */
194                 fore_cmd_drain(fup);
195                 fore_recv_drain(fup);
196                 fore_xmit_drain(fup);
197
198                 /*
199                  * Supply more buffers to the CP
200                  */
201                 fore_buf_supply(fup);
202         }
203
204 done:
205 #if (defined(BSD) && (BSD <= 199306))
206         return(serviced);
207 #else
208         return;
209 #endif
210 }
211
212
213 /*
214  * Watchdog timeout routine
215  * 
216  * Called when we haven't heard from the card in a while.  Just in case
217  * we missed an interrupt, we'll drain the queues and try to resupply the
218  * CP with more receive buffers.  If the CP is partially wedged, hopefully
219  * this will be enough to get it going again.
220  *
221  * Called with interrupts locked out.
222  *
223  * Arguments:
224  *      fup             pointer to device unit structure
225  *
226  * Returns:
227  *      none
228  *
229  */
230 void
231 fore_watchdog(fup)
232         Fore_unit       *fup;
233 {
234         /*
235          * Try to prevent stuff happening after we've paniced
236          */
237         if (panicstr) {
238                 return;
239         }
240
241         /*
242          * Reset the watchdog timer
243          */
244         fup->fu_timer = FORE_WATCHDOG;
245
246         /*
247          * If the device is initialized, nudge it (wink, wink)
248          */
249         if (fup->fu_flags & CUF_INITED) {
250
251                 /*
252                  * Drain the queues of completed work
253                  */
254                 fore_cmd_drain(fup);
255                 fore_recv_drain(fup);
256                 fore_xmit_drain(fup);
257
258                 /*
259                  * Supply more buffers to the CP
260                  */
261                 fore_buf_supply(fup);
262         }
263
264         return;
265 }