9b2c9dcaf1978b30b82937c972f5eb3d8fb92238
[dragonfly.git] / sys / dev / atm / hea / eni_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/hea/eni_intr.c,v 1.4 1999/08/28 00:41:44 peter Exp $
27  *      @(#) $DragonFly: src/sys/dev/atm/hea/eni_intr.c,v 1.6 2005/02/01 00:51:49 joerg Exp $
28  */
29
30 /*
31  * Efficient ENI Adapter Support
32  * -----------------------------
33  *
34  * Interrupt processing
35  *
36  */
37
38 #include <netproto/atm/kern_include.h>
39
40 #include "eni_stats.h"
41 #include "eni.h"
42 #include "eni_suni.h"
43 #include "eni_var.h"
44
45 static void     eni_suni_intr (Eni_unit *);
46
47 /*
48  * SUNI Interrupt processing
49  *
50  * Currently, we don't do anything more then clear the interrupt
51  * for the SUNI chip.
52  *
53  * Arguments:
54  *      eup             pointer to device unit structure
55  *
56  * Returns:
57  *      none
58  *
59  */
60 static void
61 eni_suni_intr ( eup )
62         Eni_unit *eup;
63 {
64         int     SuniInt;
65         int     val;
66
67         SuniInt = eup->eu_suni[SUNI_IS_REG];
68         
69         /* RSOPI */
70         if ( SuniInt & SUNI_RSOPI )
71                 val = eup->eu_suni[SUNI_RSOP_REG];
72
73         /* RLOPI */
74         if ( SuniInt & SUNI_RLOPI )
75                 val = eup->eu_suni[SUNI_RLOP_REG];
76
77         /* RPOPI */
78         if ( SuniInt & SUNI_RPOPI )
79                 val = eup->eu_suni[SUNI_RPOP_IS_REG];
80
81         /* RACPI */
82         if ( SuniInt & SUNI_RACPI )
83                 val = eup->eu_suni[SUNI_RACP_REG];
84
85         /* TACPI */
86         if ( SuniInt & SUNI_TACPI )
87                 val = eup->eu_suni[SUNI_TACP_REG];
88
89         /* TROOLI */
90         if ( SuniInt & SUNI_TROOLI )
91                 val = eup->eu_suni[SUNI_CLOCK_REG];
92
93         /* LCDI */
94                 /* Cleared when reading Master Interrupt Status Reg */
95
96         /* RDOOLI */
97         if ( SuniInt & SUNI_RDOOLI )
98                 val = eup->eu_suni[SUNI_CLOCK_REG];
99
100         return;
101 }
102
103 /*
104  * Device interrupt routine
105  *
106  * Service an interrupt from this device
107  *
108  * Arguments:
109  *      eup             pointer to device unit structure
110  *
111  * Returns:
112  *      none
113  *
114  */
115 void
116 eni_intr ( arg )
117         void *arg;
118 {
119         Eni_unit        *eup = (Eni_unit *)arg;
120
121         /*
122          * Read and acknowledge any interrupts
123          */
124         u_long  mask = eup->eu_midway[MIDWAY_ISA];
125         /*
126          * Read the error statistics counter
127          */
128         u_long  sval = eup->eu_midway[MIDWAY_STAT];
129
130         /*
131          * Update statistics from adapter
132          */
133         eup->eu_trash += ( sval >> 16 );
134         eup->eu_ovfl += ( sval & 0xffff );
135
136         /*
137          * We handle any DMA completes first so
138          * that we can free resources for use
139          * during transmit and especially receive
140          */
141         /*
142          * Handle RX DMA Complete
143          */
144         if ( mask & ENI_INT_RX_DMA ) {
145                 eni_recv_drain ( eup );
146         }
147
148         /*
149          * Handle TX DMA Complete
150          */
151         if ( mask & ENI_INT_TX_DMA ) {
152                 eni_xmit_drain ( eup );
153         }
154
155         /*
156          * Look for any PDUs in service list
157          */
158         if ( mask & ENI_INT_SERVICE ) {
159                 eni_do_service ( eup );
160         }
161
162         /*
163          * Handle miscelaneous interrupts
164          */
165         if ( mask & ENI_INT_STAT ) {                    /* STAT_OVFL */
166                 log ( LOG_INFO, "eni_intr: stat_ovfl: 0x%lx\n", sval );
167         }
168         if ( mask & ENI_INT_SUNI ) {                    /* SUNI_INTR */
169                 eni_suni_intr ( eup );
170         }
171         if ( mask & ENI_INT_DMA_ERR ) {                 /* DMA Error */
172                 log ( LOG_ERR,
173                         "eni_intr: DMA Error\n" );
174                 /*
175                  * We don't know how to recover from DMA errors
176                  * yet. The adapter has disabled any further
177                  * processing and we're going to leave it like
178                  * that.
179                  */
180                 return;                                 /* Leave now */
181         }
182         if ( mask & ENI_INT_IDEN ) {
183                 log ( LOG_ERR,
184                         "eni_intr: TX DMA Ident mismatch\n" );
185                 /*
186                  * Something in the TX buffer has really gotten messed
187                  * up. Since this is most likely a driver bug, and
188                  * the adapter has shut everything down, leave it
189                  * like that.
190                  */
191                 return;                                 /* Leave now */
192         }
193         if ( mask & ENI_INT_DMA_OVFL )
194                 eup->eu_stats.eni_st_drv.drv_xm_dmaovfl++;
195         if ( mask & ENI_INT_DMA_LERR ) {
196                 log ( LOG_ERR,
197                         "eni_intr: DMA LERR\n" );
198                 return;
199         }
200 }
201