Initial import from FreeBSD RELENG_4:
[games.git] / sys / dev / atm / hea / eni_if.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_if.c,v 1.5 1999/08/28 00:41:44 peter Exp $
27  *
28  */
29
30 /*
31  * Efficient ENI Adapter Support
32  * -----------------------------
33  *
34  * Network interface layer support
35  *
36  */
37
38 #include <netatm/kern_include.h>
39
40 #include <dev/hea/eni_stats.h>
41 #include <dev/hea/eni.h>
42 #include <dev/hea/eni_suni.h>
43 #include <dev/hea/eni_var.h>
44
45 #ifndef lint
46 __RCSID("@(#) $FreeBSD: src/sys/dev/hea/eni_if.c,v 1.5 1999/08/28 00:41:44 peter Exp $");
47 #endif
48
49 static void     eni_get_stats __P((Eni_unit *));
50
51 /*
52  * SUNI statistics counters take one of three forms:
53  *      single byte value       (0x0 - 0xff)
54  *      two byte value          (0x0 - 0xffff)
55  *      two + 1/2 (three) byte value
56  *                              (0x0 - 0x0fffff)
57  */
58 #define READ_ONE(x)     ( (eup->eu_suni[(x)] & 0xff) )
59
60 #define READ_TWO(x)     ( (eup->eu_suni[(x)+1] & 0xff) << 8 | \
61                           (eup->eu_suni[(x)] & 0xff) )
62
63 #define READ_THREE(x)   ( (eup->eu_suni[(x)+2] & 0xf) << 16 | \
64                           (eup->eu_suni[(x)+1] & 0xff) << 8 | \
65                           (eup->eu_suni[(x)] & 0xff) )
66
67 /*
68  * Do an initial read of the error counters without saving them.
69  * In effect, this will "zero" our idea of the number of errors
70  * which have occurred since the driver was loaded.
71  *
72  * Arguments:
73  *      eup             pointer to per unit structure
74  *
75  * Returns:
76  *      none
77  *
78  */
79 void
80 eni_zero_stats ( eup )
81         Eni_unit *eup;
82 {
83         int     val;
84
85         /*
86          * Write the SUNI master control register which
87          * will cause all the statistics counters to be
88          * loaded.
89          */
90         eup->eu_suni[SUNI_MASTER_REG] = eup->eu_suni[SUNI_MASTER_REG];
91
92         /*
93          * Delay to allow for counter load time...
94          */
95         DELAY ( SUNI_DELAY );
96
97         /*
98          * Statistics counters contain the number of events
99          * since the last time the counter was read.
100          */
101         val = READ_TWO ( SUNI_SECT_BIP_REG );           /* oc3_sect_bip8 */
102         val = READ_TWO ( SUNI_PATH_BIP_REG );           /* oc3_path_bip8 */
103         val = READ_THREE ( SUNI_LINE_BIP_REG );         /* oc3_line_bip24 */
104         val = READ_THREE ( SUNI_LINE_FEBE_REG );        /* oc3_line_febe */
105         val = READ_TWO ( SUNI_PATH_FEBE_REG );          /* oc3_path_febe */
106         val = READ_ONE ( SUNI_HECS_REG );               /* oc3_hec_corr */
107         val = READ_ONE ( SUNI_UHECS_REG );              /* oc3_hec_uncorr */
108 }
109
110 /*
111  * Retrieve SUNI stats
112  *
113  * Arguments:
114  *      eup             pointer to per unit structure
115  *
116  * Returns:
117  *      none
118  *
119  */
120 static void
121 eni_get_stats ( eup )
122         Eni_unit        *eup;
123 {
124         /*
125          * Write the SUNI master control register which
126          * will cause all the statistics counters to be
127          * loaded.
128          */
129         eup->eu_suni[SUNI_MASTER_REG] = eup->eu_suni[SUNI_MASTER_REG];
130
131         /*
132          * Delay to allow for counter load time...
133          */
134         DELAY ( 10 );
135
136         /*
137          * Statistics counters contain the number of events
138          * since the last time the counter was read.
139          */
140         eup->eu_stats.eni_st_oc3.oc3_sect_bip8 +=
141                         READ_TWO ( SUNI_SECT_BIP_REG );
142         eup->eu_stats.eni_st_oc3.oc3_path_bip8 +=
143                         READ_TWO ( SUNI_PATH_BIP_REG );
144         eup->eu_stats.eni_st_oc3.oc3_line_bip24 +=
145                         READ_THREE ( SUNI_LINE_BIP_REG );
146         eup->eu_stats.eni_st_oc3.oc3_line_febe +=
147                         READ_THREE ( SUNI_LINE_FEBE_REG );
148         eup->eu_stats.eni_st_oc3.oc3_path_febe +=
149                         READ_TWO ( SUNI_PATH_FEBE_REG );
150         eup->eu_stats.eni_st_oc3.oc3_hec_corr +=
151                         READ_ONE ( SUNI_HECS_REG );
152         eup->eu_stats.eni_st_oc3.oc3_hec_uncorr +=
153                         READ_ONE ( SUNI_UHECS_REG );
154 }
155
156 /*
157  * Handle netatm core service interface ioctl requests
158  *
159  * Called at splnet.
160  *
161  * Arguments:
162  *      code            ioctl function (sub)code
163  *      data            data to/from ioctl
164  *      arg             optional code-specific argument
165  *
166  * Returns:
167  *      0               request processed successfully
168  *      error           request failed - reason code
169  *
170  */
171 int
172 eni_atm_ioctl ( code, data, arg )
173         int code;
174         caddr_t data;
175         caddr_t arg;
176 {
177         struct atminfreq        *aip = (struct atminfreq *)data;
178         struct atm_pif          *pip = (struct atm_pif *)arg;
179         Eni_unit                *eup = (Eni_unit *)pip;
180         caddr_t                 buf = aip->air_buf_addr;
181         struct air_vinfo_rsp    *avr;
182         int                     count, len, buf_len = aip->air_buf_len;
183         int                     err = 0;
184         char                    ifname[2*IFNAMSIZ];
185
186         ATM_DEBUG2("eni_atm_ioctl: code=%d, opcode=%d\n",
187                 code, aip->air_opcode );
188
189         switch ( aip->air_opcode ) {
190
191         case AIOCS_INF_VST:
192                 /*
193                  * Get vendor statistics
194                  */
195                 if ( eup == NULL )
196                         return ( ENXIO );
197                 snprintf ( ifname, sizeof(ifname),
198                     "%s%d", pip->pif_name, pip->pif_unit );
199
200                 /*
201                  * Cast response structure onto user's buffer
202                  */
203                 avr = (struct air_vinfo_rsp *)buf;
204
205                 /*
206                  * How large is the response structure
207                  */
208                 len = sizeof(struct air_vinfo_rsp);
209
210                 /*
211                  * Sanity check - enough room for response structure?
212                  */
213                 if ( buf_len < len )
214                         return ( ENOSPC );
215
216                 /*
217                  * Copy interface name into response structure
218                  */
219                 if ((err = copyout(ifname, avr->avsp_intf, IFNAMSIZ)) != 0)
220                         break;
221
222                 /*
223                  * Advance the buffer address and decrement the size
224                  */
225                 buf += len;
226                 buf_len -= len;
227
228                 /*
229                  * Get the vendor stats (SUNI) from the hardware
230                  */
231                 eni_get_stats ( eup );
232                 /*
233                  * Stick as much of it as we have room for
234                  * into the response
235                  */
236                 count = MIN ( sizeof(Eni_stats), buf_len );
237
238                 /*
239                  * Copy stats into user's buffer. Return value is
240                  * amount of data copied.
241                  */
242                 if ((err = copyout((void *)&eup->eu_stats, buf, count)) != 0)
243                                 break;
244                 buf += count;
245                 buf_len -= count;
246                 if ( count < sizeof(Eni_stats) )
247                         err = ENOSPC;
248
249                 /*
250                  * Record amount we're returning as vendor info...
251                  */
252                 if ((err = copyout(&count, &avr->avsp_len, sizeof(int))) != 0)
253                         break;
254
255                 /*
256                  * Update the reply pointers and length
257                  */
258                 aip->air_buf_addr = buf;
259                 aip->air_buf_len = buf_len;
260                 break;
261
262         default:
263                 err = ENOSYS;           /* Operation not supported */
264                 break;
265         }
266
267         return ( err );
268
269 }
270