]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hfa/hfa_freebsd.c
This commit was generated by cvs2svn to compensate for changes in r156952,
[FreeBSD/FreeBSD.git] / sys / dev / hfa / hfa_freebsd.c
1 /*-
2  * Copyright (c) 2002 Matthew N. Dodd <winter@jurai.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 /*
30  *
31  * ===================================
32  * HARP  |  Host ATM Research Platform
33  * ===================================
34  *
35  *
36  * This Host ATM Research Platform ("HARP") file (the "Software") is
37  * made available by Network Computing Services, Inc. ("NetworkCS")
38  * "AS IS".  NetworkCS does not provide maintenance, improvements or
39  * support of any kind.
40  *
41  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
42  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
43  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
44  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
45  * In no event shall NetworkCS be responsible for any damages, including
46  * but not limited to consequential damages, arising from or relating to
47  * any use of the Software or related support.
48  *
49  * Copyright 1994-1998 Network Computing Services, Inc.
50  *
51  * Copies of this Software may be made, however, the above copyright
52  * notice must be reproduced on all copies.
53  *
54  */
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/socket.h>
59 #include <sys/socketvar.h>
60 #include <sys/kernel.h>
61 #include <sys/lock.h>
62 #include <sys/malloc.h>
63 #include <sys/socket.h>
64 #include <sys/sysctl.h>
65
66 #include <sys/bus.h>
67 #include <sys/conf.h>
68
69 #include <sys/module.h>
70 #include <machine/bus.h>
71 #include <machine/resource.h>
72 #include <sys/rman.h>
73
74 #include <net/if.h>
75 #include <netatm/port.h>
76 #include <netatm/queue.h>
77 #include <netatm/atm.h>
78 #include <netatm/atm_sys.h>
79 #include <netatm/atm_sap.h>
80 #include <netatm/atm_cm.h>
81 #include <netatm/atm_if.h>
82 #include <netatm/atm_stack.h>
83 #include <netatm/atm_pcb.h>
84 #include <netatm/atm_var.h>
85
86 #include <dev/hfa/fore.h>
87 #include <dev/hfa/fore_aali.h>
88 #include <dev/hfa/fore_slave.h>
89 #include <dev/hfa/fore_stats.h>
90 #include <dev/hfa/fore_var.h>
91 #include <dev/hfa/fore_include.h>
92
93 #include <dev/hfa/hfa_freebsd.h>
94
95 devclass_t hfa_devclass;
96
97 static int hfa_modevent(module_t, int, void *);
98
99 SYSCTL_DECL(_hw_atm);
100
101 /*
102  * Sysctl handler for the traffic shaping option
103  */
104 static int
105 hfa_sysctl_shape(SYSCTL_HANDLER_ARGS)
106 {
107         struct hfa_softc *sc = arg1;
108         int error;
109         u_int new;
110
111         error = SYSCTL_OUT(req, &sc->fup.fu_shape , sizeof(sc->fup.fu_shape));
112         if (error != 0 || req->newptr == NULL) {
113                 return (error);
114         }
115
116         error = SYSCTL_IN(req, &new, sizeof(new));
117         if (error != 0) {
118                 return (error);
119         }
120
121         if (new > FUS_SHAPE_ALL) {
122                 return (EINVAL);
123         }
124
125         sc->fup.fu_shape = new;
126         return (0);
127 }
128
129 int
130 hfa_alloc (device_t dev)
131 {
132         struct hfa_softc *sc;
133         int error;
134
135         sc = (struct hfa_softc *)device_get_softc(dev);
136         error = 0;
137
138         sc->mem = bus_alloc_resource_any(dev, sc->mem_type, &sc->mem_rid,
139                                            RF_ACTIVE);
140         if (sc->mem == NULL) {
141                 device_printf(dev, "Unable to allocate memory resource.\n");
142                 error = ENXIO;
143                 goto fail;
144         }
145
146         sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
147                                         RF_SHAREABLE | RF_ACTIVE);
148         if (sc->irq == NULL) {
149                 device_printf(dev, "Unable to allocate interrupt resource.\n");
150                 error = ENXIO;
151                 goto fail;
152         }
153
154         /*
155          * Make the sysctl tree
156          */
157         if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
158             SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO,
159             device_get_nameunit(dev), CTLFLAG_RW, 0, "")) == NULL)
160                 goto fail;
161
162         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
163             OID_AUTO, "shape", CTLFLAG_RW | CTLTYPE_UINT, sc, 0,
164             hfa_sysctl_shape, "IU", "traffic shaping") == NULL)
165                 goto fail;
166
167         mtx_init(&sc->mtx, device_get_nameunit(dev), "Interrupt lock", MTX_DEF|MTX_RECURSE);
168
169 fail:
170         return (error);
171 }
172
173 int
174 hfa_free (device_t dev)
175 {
176         struct hfa_softc *sc;
177
178         sc = (struct hfa_softc *)device_get_softc(dev);
179
180         if (sc->mem)
181                 bus_release_resource(dev, sc->mem_type, sc->mem_rid, sc->mem);
182         if (sc->irq_ih)
183                 bus_teardown_intr(dev, sc->irq, sc->irq_ih);
184         if (sc->irq)
185                 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
186
187         /*
188          * Destroy the mutex.
189          */
190         if (mtx_initialized(&sc->mtx) != 0)
191                  mtx_destroy(&sc->mtx);
192
193         return (0);
194 }
195
196 int
197 hfa_attach (device_t dev)
198 {
199         struct hfa_softc *sc;
200         Fore_unit *fup;
201         int error;
202         int err_count;
203
204         sc = (struct hfa_softc *)device_get_softc(dev);
205         fup = &sc->fup;
206         error = 0;
207         err_count = BOOT_LOOPS;
208
209         /*
210          * Start initializing it
211          */
212         fup->fu_unit = device_get_unit(dev);
213         fup->fu_mtu = FORE_IFF_MTU;
214         fup->fu_vcc_zone = fore_vcc_zone;
215         fup->fu_nif_zone = fore_nif_zone;
216         fup->fu_ioctl = fore_atm_ioctl;
217         fup->fu_instvcc = fore_instvcc;
218         fup->fu_openvcc = fore_openvcc;
219         fup->fu_closevcc = fore_closevcc;
220         fup->fu_output = fore_output;
221         fup->fu_softc = (void *)sc;
222
223         callout_handle_init(&fup->fu_thandle);
224
225         /*
226          * Poke the hardware - boot the CP and prepare it for downloading
227          */
228         hfa_reset(dev);
229
230         /*
231          * Wait for the monitor to perform self-test
232          */
233         while (CP_READ(fup->fu_mon->mon_bstat) != BOOT_MONREADY) {
234                  if (CP_READ(fup->fu_mon->mon_bstat) == BOOT_FAILTEST) {
235                           device_printf(dev, "failed self-test\n");
236                           goto fail;
237                  } else if ( --err_count == 0 ) {
238                           device_printf(dev, "unable to boot - status=0x%lx\n",
239                                    (u_long)CP_READ(fup->fu_mon->mon_bstat));
240                           goto fail;
241                  }
242                  DELAY ( BOOT_DELAY );
243         }
244
245         /*
246          * Setup the adapter config info - at least as much as we can
247          */
248         fup->fu_config.ac_vendor = VENDOR_FORE;
249         fup->fu_config.ac_vendapi = VENDAPI_FORE_1;
250         fup->fu_config.ac_media = MEDIA_OC3C;
251         fup->fu_pif.pif_pcr = ATM_PCR_OC3C;
252
253         /*
254          * Save device ram info for user-level programs
255          */
256         fup->fu_config.ac_ram = (long)fup->fu_ram;
257         fup->fu_config.ac_ramsize = fup->fu_ramsize;
258
259         /*
260          * Set device capabilities
261          */
262         fup->fu_pif.pif_maxvpi = FORE_MAX_VPI;
263         fup->fu_pif.pif_maxvci = FORE_MAX_VCI;
264
265         /*
266          * Register this interface with ATM core services
267          */
268         error = atm_physif_register((Cmn_unit *)fup, FORE_DEV_NAME, fore_services);
269         if (error)
270                  goto fail;
271
272         fore_units[device_get_unit(dev)] = fup;
273         fore_nunits++;
274
275         /*
276          * Initialize the CP microcode program.
277          */
278         fore_initialize(fup);
279
280 fail:
281         return (error);
282 }
283
284 int
285 hfa_detach (device_t dev)
286 {
287         struct hfa_softc *sc;
288         Fore_unit *fup;
289         int error;
290
291         sc = (struct hfa_softc *)device_get_softc(dev);
292         fup = &sc->fup;
293         error = 0;
294
295         /*
296          * De-Register this interface with ATM core services
297          */
298         error = atm_physif_deregister((Cmn_unit *)fup);
299
300         /*
301          * Reset the board and return it to cold_start state.
302          * Hopefully, this will prevent use of resources as
303          * we're trying to free things up.
304          */
305         hfa_reset(dev);
306
307         /*
308          * Lock out all device interrupts
309          */
310         DEVICE_LOCK((Cmn_unit *)fup);
311
312         /*
313          * Remove any pending timeout()'s
314          */
315         (void)untimeout((KTimeout_ret(*)(void *))fore_initialize,
316                  (void *)fup, fup->fu_thandle);
317
318         hfa_free(dev);
319
320         DEVICE_UNLOCK((Cmn_unit *)fup);
321
322         /*
323          * Free any Fore-specific device resources
324          */
325         fore_interface_free(fup);
326
327         return (error);
328 }
329
330 void
331 hfa_intr (void * arg)
332 {
333         struct hfa_softc *sc;
334
335         sc = (struct hfa_softc *)arg;
336
337         HFA_LOCK(sc);
338         fore_intr(&sc->fup);
339         HFA_UNLOCK(sc);
340
341         return;
342 }
343
344 void
345 hfa_reset (device_t dev)
346 {
347         struct hfa_softc *sc;
348         Fore_unit *fup;
349
350         sc = (struct hfa_softc *)device_get_softc(dev);
351         fup = &sc->fup;
352         HFA_LOCK(sc);
353
354         /*
355          * Reset the board and return it to cold_start state
356          */
357         if (fup->fu_mon)
358                 fup->fu_mon->mon_bstat = CP_WRITE(BOOT_COLDSTART);
359
360         if (fup->fu_ctlreg) {
361
362                 switch (fup->fu_config.ac_device) {
363                 case DEV_FORE_ESA200E:
364
365                         break;
366
367                 case DEV_FORE_SBA200E:
368                         /*
369                          * Reset i960 by setting and clearing RESET
370                          */
371                         SBA200E_HCR_INIT(*fup->fu_ctlreg, SBA200E_RESET);
372                         SBA200E_HCR_CLR(*fup->fu_ctlreg, SBA200E_RESET);
373                         break;
374
375                 case DEV_FORE_SBA200:
376                         /*
377                          * Reset i960 by setting and clearing RESET
378                          *
379                          * SBA200 will NOT reset if bit is OR'd in!
380                          */
381                         *fup->fu_ctlreg = SBA200_RESET;
382                         *fup->fu_ctlreg = SBA200_RESET_CLR;
383                         break;
384
385                 case DEV_FORE_PCA200E:
386                         /*
387                          * Reset i960 by setting and clearing RESET
388                          */
389                         PCA200E_HCR_INIT(*fup->fu_ctlreg, PCA200E_RESET);
390                         DELAY(10000);
391                         PCA200E_HCR_CLR(*fup->fu_ctlreg, PCA200E_RESET);
392                         break;
393                 default:
394                         break;
395                 }
396         }
397
398         HFA_UNLOCK(sc);
399         return;
400 }
401
402 static int       
403 hfa_modevent (module_t mod, int type, void *data)
404 {
405         int error;
406
407         error = 0;
408
409         switch (type) {
410         case MOD_LOAD:
411                 /*
412                 * Verify software version
413                 */
414                 if (atm_version != ATM_VERSION) {
415                         printf("hfa: version mismatch: fore=%d.%d kernel=%d.%d\n",
416                                 ATM_VERS_MAJ(ATM_VERSION),
417                                 ATM_VERS_MIN(ATM_VERSION),
418                                 ATM_VERS_MAJ(atm_version),
419                                 ATM_VERS_MIN(atm_version));
420                         error = EINVAL;
421                         break;
422                 }
423
424                 fore_nif_zone = uma_zcreate("fore nif", sizeof(struct atm_nif), NULL,
425                     NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
426                 if (fore_nif_zone == NULL)
427                         panic("hfa_modevent:uma_zcreate nif");
428                 uma_zone_set_max(fore_nif_zone, 52);
429
430                 fore_vcc_zone = uma_zcreate("fore vcc", sizeof(Fore_vcc), NULL,
431                     NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
432                 if (fore_vcc_zone == NULL)
433                         panic("hfa_modevent: uma_zcreate vcc");
434                 uma_zone_set_max(fore_vcc_zone, 100);
435         
436                 /*
437                 * Start up watchdog timer
438                 */
439                 atm_timeout(&fore_timer, ATM_HZ * FORE_TIME_TICK, fore_timeout);
440
441                 break;
442         case MOD_UNLOAD:
443                 /*
444                  * Stop watchdog timer
445                  */
446                 atm_untimeout(&fore_timer);
447
448                 uma_zdestroy(fore_nif_zone);
449                 uma_zdestroy(fore_vcc_zone);
450
451                 break;
452         default:
453                 return (EOPNOTSUPP);
454                 break;
455         }
456
457         return (error);
458 }
459
460 static moduledata_t hfa_moduledata = {
461         "hfa",
462         hfa_modevent,
463         NULL
464 };
465 DECLARE_MODULE(hfa, hfa_moduledata, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
466 MODULE_VERSION(hfa, 1);