]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/patm/if_patm_attach.c
This commit was generated by cvs2svn to compensate for changes in r138296,
[FreeBSD/FreeBSD.git] / sys / dev / patm / if_patm_attach.c
1 /*
2  * Copyright (c) 2003
3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * Author: Hartmut Brandt <harti@freebsd.org>
28  *
29  * Driver for IDT77252 based cards like ProSum's.
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include "opt_inet.h"
36 #include "opt_natm.h"
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/malloc.h>
42 #include <sys/kernel.h>
43 #include <sys/bus.h>
44 #include <sys/errno.h>
45 #include <sys/conf.h>
46 #include <sys/module.h>
47 #include <sys/lock.h>
48 #include <sys/mutex.h>
49 #include <sys/sysctl.h>
50 #include <sys/queue.h>
51 #include <sys/condvar.h>
52 #include <vm/uma.h>
53
54 #include <sys/sockio.h>
55 #include <sys/mbuf.h>
56 #include <sys/socket.h>
57
58 #include <net/if.h>
59 #include <net/if_media.h>
60 #include <net/if_atm.h>
61 #include <net/route.h>
62 #ifdef ENABLE_BPF
63 #include <net/bpf.h>
64 #endif
65 #include <netinet/in.h>
66 #include <netinet/if_atm.h>
67
68 #include <machine/bus.h>
69 #include <machine/resource.h>
70 #include <sys/bus.h>
71 #include <sys/rman.h>
72 #include <sys/mbpool.h>
73 #include <dev/pci/pcireg.h>
74 #include <dev/pci/pcivar.h>
75
76 #include <dev/utopia/utopia.h>
77 #include <dev/patm/idt77252reg.h>
78 #include <dev/patm/if_patmvar.h>
79
80 MODULE_DEPEND(patm, utopia, 1, 1, 1);
81 MODULE_DEPEND(patm, pci, 1, 1, 1);
82 MODULE_DEPEND(patm, atm, 1, 1, 1);
83 MODULE_DEPEND(patm, libmbpool, 1, 1, 1);
84
85 devclass_t patm_devclass;
86
87 static int patm_probe(device_t dev);
88 static int patm_attach(device_t dev);
89 static int patm_detach(device_t dev);
90 static device_method_t patm_methods[] = {
91         DEVMETHOD(device_probe,         patm_probe),
92         DEVMETHOD(device_attach,        patm_attach),
93         DEVMETHOD(device_detach,        patm_detach),
94         {0,0}
95 };
96 static driver_t patm_driver = {
97         "patm",
98         patm_methods,
99         sizeof(struct patm_softc),
100 };
101 DRIVER_MODULE(patm, pci, patm_driver, patm_devclass, NULL, 0);
102
103 static const struct {
104         u_int   devid;
105         const char *desc;
106 } devs[] = {
107         { PCI_DEVICE_IDT77252,  "NICStAR (77222/77252) ATM adapter" },
108         { PCI_DEVICE_IDT77v252, "NICStAR (77v252) ATM adapter" },
109         { PCI_DEVICE_IDT77v222, "NICStAR (77v222) ATM adapter" },
110         { 0, NULL }
111 };
112
113 SYSCTL_DECL(_hw_atm);
114
115 static int patm_phy_readregs(struct ifatm *, u_int, uint8_t *, u_int *);
116 static int patm_phy_writereg(struct ifatm *, u_int, u_int, u_int);
117 static const struct utopia_methods patm_utopia_methods = {
118         patm_phy_readregs,
119         patm_phy_writereg
120 };
121
122 static void patm_destroy(struct patm_softc *sc);
123
124 static int patm_sysctl_istats(SYSCTL_HANDLER_ARGS);
125 static int patm_sysctl_eeprom(SYSCTL_HANDLER_ARGS);
126
127 static void patm_read_eeprom(struct patm_softc *sc);
128 static int patm_sq_init(struct patm_softc *sc);
129 static int patm_rbuf_init(struct patm_softc *sc);
130 static int patm_txmap_init(struct patm_softc *sc);
131
132 static void patm_env_getuint(struct patm_softc *, u_int *, const char *);
133
134 #ifdef PATM_DEBUG
135 static int patm_sysctl_regs(SYSCTL_HANDLER_ARGS);
136 static int patm_sysctl_tsq(SYSCTL_HANDLER_ARGS);
137 int patm_dump_vc(u_int unit, u_int vc) __unused;
138 int patm_dump_regs(u_int unit) __unused;
139 int patm_dump_sram(u_int unit, u_int from, u_int words) __unused;
140 #endif
141
142 /*
143  * Probe for a IDT77252 controller
144  */
145 static int
146 patm_probe(device_t dev)
147 {
148         u_int i;
149
150         if (pci_get_vendor(dev) == PCI_VENDOR_IDT) {
151                 for (i = 0; devs[i].desc != NULL; i++)
152                         if (pci_get_device(dev) == devs[i].devid) {
153                                 device_set_desc(dev, devs[i].desc);
154                                 return (0);
155                         }
156         }
157         return (ENXIO);
158 }
159
160 /*
161  * Attach
162  */
163 static int
164 patm_attach(device_t dev)
165 {
166         struct patm_softc *sc;
167         int error;
168         struct ifnet *ifp;
169         int rid;
170         u_int a;
171
172         static const struct idt_mmap idt_mmap[4] = IDT_MMAP;
173
174         sc = device_get_softc(dev);
175
176         sc->dev = dev;
177 #ifdef IATM_DEBUG
178         sc->debug = IATM_DEBUG;
179 #endif
180         sc->ifatm.mib.device = ATM_DEVICE_IDTABR25;
181         sc->ifatm.mib.serial = 0;
182         sc->ifatm.mib.hw_version = 0;
183         sc->ifatm.mib.sw_version = 0;
184         sc->ifatm.mib.vpi_bits = PATM_VPI_BITS;
185         sc->ifatm.mib.vci_bits = 0;     /* set below */;
186         sc->ifatm.mib.max_vpcs = 0;
187         sc->ifatm.mib.max_vccs = 0;     /* set below */
188         sc->ifatm.mib.media = IFM_ATM_UNKNOWN;
189         sc->ifatm.phy = &sc->utopia;
190
191         ifp = &sc->ifatm.ifnet;
192         ifp->if_softc = sc;
193         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
194         ifp->if_flags = IFF_SIMPLEX;
195         ifp->if_watchdog = NULL;
196         ifp->if_init = patm_init;
197         ifp->if_ioctl = patm_ioctl;
198         ifp->if_start = patm_start;
199         ifp->if_watchdog = NULL;
200
201         /* do this early so we can destroy unconditionally */
202         mtx_init(&sc->mtx, device_get_nameunit(dev),
203             MTX_NETWORK_LOCK, MTX_DEF);
204         mtx_init(&sc->tst_lock, "tst lock", NULL, MTX_DEF);
205         cv_init(&sc->vcc_cv, "vcc_close");
206
207         callout_init(&sc->tst_callout, CALLOUT_MPSAFE);
208
209         sysctl_ctx_init(&sc->sysctl_ctx);
210
211         /*
212          * Get revision
213          */
214         sc->revision = pci_read_config(dev, PCIR_REVID, 4) & 0xf;
215
216         /*
217          * Enable PCI bus master and memory
218          */
219         pci_enable_busmaster(dev);
220
221         rid = IDT_PCI_REG_MEMBASE;
222         sc->memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
223             RF_ACTIVE);
224         if (sc->memres == NULL) {
225                 patm_printf(sc, "could not map memory\n");
226                 error = ENXIO;
227                 goto fail;
228         }
229         sc->memh = rman_get_bushandle(sc->memres);
230         sc->memt = rman_get_bustag(sc->memres);
231
232         /*
233          * Allocate the interrupt (enable it later)
234          */
235         sc->irqid = 0;
236         sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
237             RF_SHAREABLE | RF_ACTIVE);
238         if (sc->irqres == 0) {
239                 patm_printf(sc, "could not allocate irq\n");
240                 error = ENXIO;
241                 goto fail;
242         }
243
244         /*
245          * Construct the sysctl tree
246          */
247         error = ENOMEM;
248         if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
249             SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO,
250             device_get_nameunit(dev), CTLFLAG_RD, 0, "")) == NULL)
251                 goto fail;
252
253         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
254             OID_AUTO, "istats", CTLFLAG_RD, sc, 0, patm_sysctl_istats,
255             "S", "internal statistics") == NULL)
256                 goto fail;
257
258         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
259             OID_AUTO, "eeprom", CTLFLAG_RD, sc, 0, patm_sysctl_eeprom,
260             "S", "EEPROM contents") == NULL)
261                 goto fail;
262
263         if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
264             OID_AUTO, "lbuf_max", CTLFLAG_RD, &sc->lbuf_max,
265             0, "maximum number of large receive buffers") == NULL)
266                 goto fail;
267         patm_env_getuint(sc, &sc->lbuf_max, "lbuf_max");
268
269         if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
270             OID_AUTO, "max_txmaps", CTLFLAG_RW, &sc->tx_maxmaps,
271             0, "maximum number of TX DMA maps") == NULL)
272                 goto fail;
273         patm_env_getuint(sc, &sc->tx_maxmaps, "tx_maxmaps");
274
275 #ifdef PATM_DEBUG
276         if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
277             OID_AUTO, "debug", CTLFLAG_RW, &sc->debug,
278             0, "debug flags") == NULL)
279                 goto fail;
280         sc->debug = PATM_DEBUG;
281         patm_env_getuint(sc, &sc->debug, "debug");
282
283         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
284             OID_AUTO, "regs", CTLFLAG_RD, sc, 0, patm_sysctl_regs,
285             "S", "registers") == NULL)
286                 goto fail;
287
288         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
289             OID_AUTO, "tsq", CTLFLAG_RD, sc, 0, patm_sysctl_tsq,
290             "S", "TSQ") == NULL)
291                 goto fail;
292 #endif
293
294         patm_reset(sc);
295
296         /*
297          * Detect and attach the phy.
298          */
299         patm_debug(sc, ATTACH, "attaching utopia");
300         sc->ifatm.phy = &sc->utopia;
301         utopia_attach(&sc->utopia, &sc->ifatm, &sc->media, &sc->mtx,
302             &sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
303             &patm_utopia_methods);
304
305         /*
306          * Start the PHY because we need the autodetection
307          */
308         patm_debug(sc, ATTACH, "starting utopia");
309         mtx_lock(&sc->mtx);
310         utopia_start(&sc->utopia);
311         utopia_reset(&sc->utopia);
312         mtx_unlock(&sc->mtx);
313
314         /* Read EEPROM */
315         patm_read_eeprom(sc);
316
317         /* analyze it */
318         if (strncmp(sc->eeprom + PATM_PROATM_NAME_OFFSET, PATM_PROATM_NAME,
319             strlen(PATM_PROATM_NAME)) == 0) {
320                 if (sc->utopia.chip->type == UTP_TYPE_IDT77105) {
321                         sc->ifatm.mib.device = ATM_DEVICE_PROATM25;
322                         sc->ifatm.mib.pcr = ATM_RATE_25_6M;
323                         sc->ifatm.mib.media = IFM_ATM_UTP_25;
324                         sc->flags |= PATM_25M;
325                         patm_printf(sc, "ProATM 25 interface; ");
326
327                 } else {
328                         /* cannot really know which media */
329                         sc->ifatm.mib.device = ATM_DEVICE_PROATM155;
330                         sc->ifatm.mib.pcr = ATM_RATE_155M;
331                         sc->ifatm.mib.media = IFM_ATM_MM_155;
332                         patm_printf(sc, "ProATM 155 interface; ");
333                 }
334
335                 bcopy(sc->eeprom + PATM_PROATM_MAC_OFFSET, sc->ifatm.mib.esi,
336                     sizeof(sc->ifatm.mib.esi));
337
338         } else {
339                 if (sc->utopia.chip->type == UTP_TYPE_IDT77105) {
340                         sc->ifatm.mib.device = ATM_DEVICE_IDTABR25;
341                         sc->ifatm.mib.pcr = ATM_RATE_25_6M;
342                         sc->ifatm.mib.media = IFM_ATM_UTP_25;
343                         sc->flags |= PATM_25M;
344                         patm_printf(sc, "IDT77252 25MBit interface; ");
345
346                 } else {
347                         /* cannot really know which media */
348                         sc->ifatm.mib.device = ATM_DEVICE_IDTABR155;
349                         sc->ifatm.mib.pcr = ATM_RATE_155M;
350                         sc->ifatm.mib.media = IFM_ATM_MM_155;
351                         patm_printf(sc, "IDT77252 155MBit interface; ");
352                 }
353
354                 bcopy(sc->eeprom + PATM_IDT_MAC_OFFSET, sc->ifatm.mib.esi,
355                     sizeof(sc->ifatm.mib.esi));
356         }
357         printf("idt77252 Rev. %c; %s PHY\n", 'A' + sc->revision,
358             sc->utopia.chip->name);
359
360         utopia_reset_media(&sc->utopia);
361         utopia_init_media(&sc->utopia);
362
363         /*
364          * Determine RAM size
365          */
366         for (a = 0; a < 0x20000; a++)
367                 patm_sram_write(sc, a, 0);
368         patm_sram_write(sc, 0, 0xdeadbeef);
369         if (patm_sram_read(sc, 0x4004) == 0xdeadbeef)
370                 sc->mmap = &idt_mmap[0];
371         else if (patm_sram_read(sc, 0x8000) == 0xdeadbeef)
372                 sc->mmap = &idt_mmap[1];
373         else if (patm_sram_read(sc, 0x20000) == 0xdeadbeef)
374                 sc->mmap = &idt_mmap[2];
375         else
376                 sc->mmap = &idt_mmap[3];
377
378         sc->ifatm.mib.vci_bits = sc->mmap->vcbits - sc->ifatm.mib.vpi_bits;
379         sc->ifatm.mib.max_vccs = sc->mmap->max_conn;
380         patm_sram_write(sc, 0, 0);
381         patm_printf(sc, "%uK x 32 SRAM; %u connections\n", sc->mmap->sram,
382             sc->mmap->max_conn);
383
384         /* initialize status queues */
385         error = patm_sq_init(sc);
386         if (error != 0)
387                 goto fail;
388
389         /* get TST */
390         sc->tst_soft = malloc(sizeof(uint32_t) * sc->mmap->tst_size,
391             M_DEVBUF, M_WAITOK);
392
393         /* allocate all the receive buffer stuff */
394         error = patm_rbuf_init(sc);
395         if (error != 0)
396                 goto fail;
397
398         /*
399          * Allocate SCD tag
400          *
401          * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with
402          * bus_dmamem_alloc()
403          */
404         error = bus_dma_tag_create(NULL, PAGE_SIZE, 0,
405             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
406             NULL, NULL, sizeof(struct patm_scd), 1,
407             sizeof(struct patm_scd), 0, NULL, NULL, &sc->scd_tag);
408         if (error) {
409                 patm_printf(sc, "SCD DMA tag create %d\n", error);
410                 goto fail;
411         }
412         LIST_INIT(&sc->scd_list);
413
414         /* allocate VCC zone and pointers */
415         if ((sc->vcc_zone = uma_zcreate("PATM vccs", sizeof(struct patm_vcc),
416             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0)) == NULL) {
417                 patm_printf(sc, "cannot allocate zone for vccs\n");
418                 goto fail;
419         }
420         sc->vccs = malloc(sizeof(sc->vccs[0]) * sc->mmap->max_conn,
421             M_DEVBUF, M_WAITOK | M_ZERO);
422
423         /* allocate transmission resources */
424         error = patm_txmap_init(sc);
425         if (error != 0)
426                 goto fail;
427
428         /* poll while we are not running */
429         sc->utopia.flags |= UTP_FL_POLL_CARRIER;
430
431         patm_debug(sc, ATTACH, "attaching interface");
432         atm_ifattach(ifp);
433
434 #ifdef ENABLE_BPF
435         bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
436 #endif
437
438         patm_debug(sc, ATTACH, "attaching interrupt handler");
439         error = bus_setup_intr(dev, sc->irqres, INTR_TYPE_NET, patm_intr,
440             sc, &sc->ih);
441         if (error != 0) {
442                 patm_printf(sc, "could not setup interrupt\n");
443                 atm_ifdetach(&sc->ifatm.ifnet);
444                 goto fail;
445         }
446
447         return (0);
448
449   fail:
450         patm_destroy(sc);
451         return (error);
452 }
453
454 /*
455  * Detach
456  */
457 static int
458 patm_detach(device_t dev)
459 {
460         struct patm_softc *sc;
461
462         sc = (struct patm_softc *)device_get_softc(dev);
463
464         mtx_lock(&sc->mtx);
465         patm_stop(sc);
466         if (sc->utopia.state & UTP_ST_ATTACHED) {
467                 patm_debug(sc, ATTACH, "detaching utopia");
468                 utopia_stop(&sc->utopia);
469                 utopia_detach(&sc->utopia);
470         }
471         mtx_unlock(&sc->mtx);
472
473         atm_ifdetach(&sc->ifatm.ifnet);
474
475         patm_destroy(sc);
476
477         return (0);
478 }
479
480 /*
481  * Destroy everything. Assume we are stopped.
482  */
483 static void
484 patm_destroy(struct patm_softc *sc)
485 {
486         u_int i;
487         struct patm_txmap *map;
488
489         if (sc->ih != NULL)
490                 bus_teardown_intr(sc->dev, sc->irqres, sc->ih);
491
492         if (sc->tx_mapzone != NULL) {
493                 /* all maps must be free */
494                 while ((map = SLIST_FIRST(&sc->tx_maps_free)) != NULL) {
495                         bus_dmamap_destroy(sc->tx_tag, map->map);
496                         SLIST_REMOVE_HEAD(&sc->tx_maps_free, link);
497                         uma_zfree(sc->tx_mapzone, map);
498                 }
499                 uma_zdestroy(sc->tx_mapzone);
500         }
501
502         if (sc->scd_tag != NULL)
503                 bus_dma_tag_destroy(sc->scd_tag);
504
505         if (sc->tx_tag != NULL)
506                 bus_dma_tag_destroy(sc->scd_tag);
507
508         if (sc->vccs != NULL) {
509                 for (i = 0; i < sc->mmap->max_conn; i++)
510                         if (sc->vccs[i] != NULL)
511                                 uma_zfree(sc->vcc_zone, sc->vccs[i]);
512                 free(sc->vccs, M_DEVBUF);
513         }
514         if (sc->vcc_zone != NULL)
515                 uma_zdestroy(sc->vcc_zone);
516
517         if (sc->lbufs != NULL) {
518                 for (i = 0; i < sc->lbuf_max; i++)
519                         bus_dmamap_destroy(sc->lbuf_tag, sc->lbufs[i].map);
520                 free(sc->lbufs, M_DEVBUF);
521         }
522
523         if (sc->lbuf_tag != NULL)
524                 bus_dma_tag_destroy(sc->lbuf_tag);
525
526         if (sc->sbuf_pool != NULL)
527                 mbp_destroy(sc->sbuf_pool);
528         if (sc->vbuf_pool != NULL)
529                 mbp_destroy(sc->vbuf_pool);
530
531         if (sc->sbuf_tag != NULL)
532                 bus_dma_tag_destroy(sc->sbuf_tag);
533
534         if (sc->tst_soft != NULL)
535                 free(sc->tst_soft, M_DEVBUF);
536
537         /*
538          * Free all status queue memory resources
539          */
540         if (sc->tsq != NULL) {
541                 bus_dmamap_unload(sc->sq_tag, sc->sq_map);
542                 bus_dmamem_free(sc->sq_tag, sc->tsq, sc->sq_map);
543                 bus_dma_tag_destroy(sc->sq_tag);
544         }
545
546         if (sc->irqres != NULL)
547                 bus_release_resource(sc->dev, SYS_RES_IRQ,
548                     sc->irqid, sc->irqres);
549         if (sc->memres != NULL)
550                 bus_release_resource(sc->dev, SYS_RES_MEMORY,
551                     IDT_PCI_REG_MEMBASE, sc->memres);
552
553         /* this was initialize unconditionally */
554         sysctl_ctx_free(&sc->sysctl_ctx);
555         cv_destroy(&sc->vcc_cv);
556         mtx_destroy(&sc->tst_lock);
557         mtx_destroy(&sc->mtx);
558 }
559
560 /*
561  * Try to find a variable in the environment and parse it as an unsigned
562  * integer.
563  */
564 static void
565 patm_env_getuint(struct patm_softc *sc, u_int *var, const char *name)
566 {
567         char full[IFNAMSIZ + 3 + 20];
568         char *val, *end;
569         u_long u;
570
571         snprintf(full, sizeof(full), "hw.%s.%s",
572             device_get_nameunit(sc->dev), name);
573
574         if ((val = getenv(full)) != NULL) {
575                 u = strtoul(val, &end, 0);
576                 if (end > val && *end == '\0') {
577                         if (bootverbose)
578                                 patm_printf(sc, "%s=%lu\n", full, u);
579                         *var = u;
580                 }
581                 freeenv(val);
582         }
583 }
584
585 /*
586  * Sysctl handler for internal statistics
587  *
588  * LOCK: unlocked, needed
589  */
590 static int
591 patm_sysctl_istats(SYSCTL_HANDLER_ARGS)
592 {
593         struct patm_softc *sc = arg1;
594         uint32_t *ret;
595         int error;
596
597         ret = malloc(sizeof(sc->stats), M_TEMP, M_WAITOK);
598
599         mtx_lock(&sc->mtx);
600         bcopy(&sc->stats, ret, sizeof(sc->stats));
601         mtx_unlock(&sc->mtx);
602
603         error = SYSCTL_OUT(req, ret, sizeof(sc->stats));
604         free(ret, M_TEMP);
605
606         return (error);
607 }
608
609 /*
610  * Sysctl handler for EEPROM
611  *
612  * LOCK: unlocked, needed
613  */
614 static int
615 patm_sysctl_eeprom(SYSCTL_HANDLER_ARGS)
616 {
617         struct patm_softc *sc = arg1;
618         void *ret;
619         int error;
620
621         ret = malloc(sizeof(sc->eeprom), M_TEMP, M_WAITOK);
622
623         mtx_lock(&sc->mtx);
624         bcopy(sc->eeprom, ret, sizeof(sc->eeprom));
625         mtx_unlock(&sc->mtx);
626
627         error = SYSCTL_OUT(req, ret, sizeof(sc->eeprom));
628         free(ret, M_TEMP);
629
630         return (error);
631 }
632
633 /*
634  * Read the EEPROM. We assume that this is a XIRCOM 25020
635  */
636 static void
637 patm_read_eeprom(struct patm_softc *sc)
638 {
639         u_int gp;
640         uint8_t byte;
641         int i, addr;
642
643         static const uint32_t tab[] = {
644                 /* CS transition to reset the chip */
645                 IDT_GP_EECS | IDT_GP_EESCLK,    0,
646                 /* read command 0x03 */
647                 IDT_GP_EESCLK,                  0,
648                 IDT_GP_EESCLK,                  0,
649                 IDT_GP_EESCLK,                  0,
650                 IDT_GP_EESCLK,                  0,
651                 IDT_GP_EESCLK,                  0,
652                 IDT_GP_EESCLK,                  IDT_GP_EEDO,
653                 IDT_GP_EESCLK | IDT_GP_EEDO,    IDT_GP_EEDO,
654                 IDT_GP_EESCLK | IDT_GP_EEDO,    0,
655                 /* address 0x00 */
656                 IDT_GP_EESCLK,                  0,
657                 IDT_GP_EESCLK,                  0,
658                 IDT_GP_EESCLK,                  0,
659                 IDT_GP_EESCLK,                  0,
660                 IDT_GP_EESCLK,                  0,
661                 IDT_GP_EESCLK,                  0,
662                 IDT_GP_EESCLK,                  0,
663                 IDT_GP_EESCLK,                  0,
664         };
665
666         /* go to a known state (chip enabled) */
667         gp = patm_nor_read(sc, IDT_NOR_GP);
668         gp &= ~(IDT_GP_EESCLK | IDT_GP_EECS | IDT_GP_EEDO);
669
670         for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
671                 patm_nor_write(sc, IDT_NOR_GP, gp | tab[i]);
672                 DELAY(40);
673         }
674
675         /* read out the prom */
676         for (addr = 0; addr < 256; addr++) {
677                 byte = 0;
678                 for (i = 0; i < 8; i++) {
679                         byte <<= 1;
680                         if (patm_nor_read(sc, IDT_NOR_GP) & IDT_GP_EEDI)
681                                 byte |= 1;
682                         /* rising CLK */
683                         patm_nor_write(sc, IDT_NOR_GP, gp | IDT_GP_EESCLK);
684                         DELAY(40);
685                         /* falling clock */
686                         patm_nor_write(sc, IDT_NOR_GP, gp);
687                         DELAY(40);
688                 }
689                 sc->eeprom[addr] = byte;
690         }
691 }
692
693 /*
694  * PHY access read
695  */
696 static int
697 patm_phy_readregs(struct ifatm *ifatm, u_int reg, uint8_t *val, u_int *n)
698 {
699         struct patm_softc *sc = ifatm->ifnet.if_softc;
700         u_int cnt = *n;
701
702         if (reg >= 0x100)
703                 return (EINVAL);
704
705         patm_cmd_wait(sc);
706         while (reg < 0x100 && cnt > 0) {
707                 patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_RUTIL(1, 0, reg));
708                 patm_cmd_wait(sc);
709                 *val = patm_nor_read(sc, IDT_NOR_D0);
710                 patm_debug(sc, PHY, "phy(%02x)=%02x", reg, *val);
711                 val++;
712                 reg++;
713                 cnt--;
714         }
715         *n = *n - cnt;
716         return (0);
717 }
718
719 /*
720  * Write PHY reg
721  */
722 static int
723 patm_phy_writereg(struct ifatm *ifatm, u_int reg, u_int mask, u_int val)
724 {
725         struct patm_softc *sc = ifatm->ifnet.if_softc;
726         u_int old, new;
727
728         if (reg >= 0x100)
729                 return (EINVAL);
730
731         patm_cmd_wait(sc);
732         patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_RUTIL(1, 0, reg));
733         patm_cmd_wait(sc);
734
735         old = patm_nor_read(sc, IDT_NOR_D0);
736         new = (old & ~mask) | (val & mask);
737         patm_debug(sc, PHY, "phy(%02x) %02x -> %02x", reg, old, new);
738             
739         patm_nor_write(sc, IDT_NOR_D0, new);
740         patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_WUTIL(1, 0, reg));
741         patm_cmd_wait(sc);
742
743         return (0);
744 }
745
746 /*
747  * Allocate a large chunk of DMA able memory for the transmit
748  * and receive status queues. We align this to a page boundary
749  * to ensure the alignment.
750  */
751 static int
752 patm_sq_init(struct patm_softc *sc)
753 {
754         int error;
755         void *p;
756
757         /* compute size of the two queues */
758         sc->sq_size = IDT_TSQ_SIZE * IDT_TSQE_SIZE +
759             PATM_RSQ_SIZE * IDT_RSQE_SIZE +
760             IDT_RAWHND_SIZE;
761
762         patm_debug(sc, ATTACH,
763             "allocating status queues (%zu) ...", sc->sq_size);
764
765         /*
766          * allocate tag
767          * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with
768          * bus_dmamem_alloc()
769          */
770         error = bus_dma_tag_create(NULL, PATM_SQ_ALIGNMENT, 0,
771             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
772             NULL, NULL, sc->sq_size, 1, sc->sq_size,
773             0, NULL, NULL, &sc->sq_tag);
774         if (error) {
775                 patm_printf(sc, "memory DMA tag create %d\n", error);
776                 return (error);
777         }
778
779         /* allocate memory */
780         error = bus_dmamem_alloc(sc->sq_tag, &p, 0, &sc->sq_map);
781         if (error) {
782                 patm_printf(sc, "memory DMA alloc %d\n", error);
783                 bus_dma_tag_destroy(sc->sq_tag);
784                 return (error);
785         }
786
787         /* map it */
788         sc->tsq_phy = 0x1fff;
789         error = bus_dmamap_load(sc->sq_tag, sc->sq_map, p,
790             sc->sq_size, patm_load_callback, &sc->tsq_phy, BUS_DMA_NOWAIT);
791         if (error) {
792                 patm_printf(sc, "memory DMA map load %d\n", error);
793                 bus_dmamem_free(sc->sq_tag, p, sc->sq_map);
794                 bus_dma_tag_destroy(sc->sq_tag);
795                 return (error);
796         }
797
798         /* set queue start */
799         sc->tsq = p;
800         sc->rsq = (void *)((char *)p + IDT_TSQ_SIZE * IDT_TSQE_SIZE);
801         sc->rsq_phy = sc->tsq_phy + IDT_TSQ_SIZE * IDT_TSQE_SIZE;
802         sc->rawhnd = (void *)((char *)sc->rsq + PATM_RSQ_SIZE * IDT_RSQE_SIZE);
803         sc->rawhnd_phy = sc->rsq_phy + PATM_RSQ_SIZE * IDT_RSQE_SIZE;
804
805         return (0);
806 }
807
808 /*
809  * Initialize all receive buffer stuff
810  */
811 static int
812 patm_rbuf_init(struct patm_softc *sc)
813 {
814         u_int i;
815         int error;
816
817         patm_debug(sc, ATTACH, "allocating Rx buffer resources ...");
818         /*
819          * Create a tag for small buffers. We allocate these page wise.
820          * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with
821          * bus_dmamem_alloc()
822          */
823         if ((error = bus_dma_tag_create(NULL, PAGE_SIZE, 0,
824             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
825             SMBUF_PAGE_SIZE, 1, SMBUF_PAGE_SIZE, 0,
826             NULL, NULL, &sc->sbuf_tag)) != 0) {
827                 patm_printf(sc, "sbuf DMA tag create %d\n", error);
828                 return (error);
829         }
830
831         error = mbp_create(&sc->sbuf_pool, "patm sbufs", sc->sbuf_tag,
832             SMBUF_MAX_PAGES, SMBUF_PAGE_SIZE, SMBUF_CHUNK_SIZE);
833         if (error != 0) {
834                 patm_printf(sc, "smbuf pool create %d\n", error);
835                 return (error);
836         }
837
838         error = mbp_create(&sc->vbuf_pool, "patm vbufs", sc->sbuf_tag,
839             VMBUF_MAX_PAGES, SMBUF_PAGE_SIZE, VMBUF_CHUNK_SIZE);
840         if (error != 0) {
841                 patm_printf(sc, "vmbuf pool create %d\n", error);
842                 return (error);
843         }
844
845         /*
846          * Create a tag for large buffers.
847          * Don't use BUS_DMA_ALLOCNOW, because it makes no sense with multiple
848          * maps using one tag. Rather use BUS_DMA_NOWAIT when loading the map
849          * to prevent EINPROGRESS.
850          */
851         if ((error = bus_dma_tag_create(NULL, 4, 0,
852             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
853             MCLBYTES, 1, MCLBYTES, 0, 
854             NULL, NULL, &sc->lbuf_tag)) != 0) {
855                 patm_printf(sc, "lbuf DMA tag create %d\n", error);
856                 return (error);
857         }
858
859         if (sc->lbuf_max < IDT_FBQ_SIZE)
860                 sc->lbuf_max = LMBUF_MAX;
861         sc->lbufs = malloc(sizeof(sc->lbufs[0]) * sc->lbuf_max,
862             M_DEVBUF, M_ZERO | M_WAITOK);
863
864         SLIST_INIT(&sc->lbuf_free_list);
865         for (i = 0; i < sc->lbuf_max; i++) {
866                 struct lmbuf *b = &sc->lbufs[i];
867
868                 error = bus_dmamap_create(sc->lbuf_tag, 0, &b->map);
869                 if (error) {
870                         /* must deallocate here, because a test for NULL
871                          * does not work on most archs */
872                         while (i-- > 0)
873                                 bus_dmamap_destroy(sc->lbuf_tag,
874                                     sc->lbufs[i].map);
875                         free(sc->lbufs, M_DEVBUF);
876                         sc->lbufs = NULL;
877                         return (error);
878                 }
879                 b->handle = i;
880                 SLIST_INSERT_HEAD(&sc->lbuf_free_list, b, link);
881         }
882
883         return (0);
884 }
885
886 /*
887  * Allocate everything needed for the transmission maps.
888  */
889 static int
890 patm_txmap_init(struct patm_softc *sc)
891 {
892         int error;
893         struct patm_txmap *map;
894
895         /* get transmission tag */
896         error = bus_dma_tag_create(NULL, 1, 0,
897             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
898             NULL, NULL, 65536, IDT_SCQ_SIZE - 1, 65536,
899             0, NULL, NULL, &sc->tx_tag);
900         if (error) {
901                 patm_printf(sc, "cannot allocate TX tag %d\n", error);
902                 return (error);
903         }
904
905         if ((sc->tx_mapzone = uma_zcreate("PATM tx maps",
906             sizeof(struct patm_txmap), NULL, NULL, NULL, NULL,
907             UMA_ALIGN_PTR, 0)) == NULL)
908                 return (ENOMEM);
909
910         if (sc->tx_maxmaps < PATM_CFG_TXMAPS_MAX)
911                 sc->tx_maxmaps = PATM_CFG_TXMAPS_MAX;
912         sc->tx_nmaps = PATM_CFG_TXMAPS_INIT;
913
914         for (sc->tx_nmaps = 0; sc->tx_nmaps < PATM_CFG_TXMAPS_INIT;
915             sc->tx_nmaps++) {
916                 map = uma_zalloc(sc->tx_mapzone, M_WAITOK);
917                 error = bus_dmamap_create(sc->tx_tag, 0, &map->map);
918                 if (error) {
919                         uma_zfree(sc->tx_mapzone, map);
920                         return (ENOMEM);
921                 }
922                 SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link);
923         }
924
925         return (0);
926 }
927
928 #ifdef PATM_DEBUG
929
930 /*
931  * Sysctl handler for REGS
932  *
933  * LOCK: unlocked, needed
934  */
935 static int
936 patm_sysctl_regs(SYSCTL_HANDLER_ARGS)
937 {
938         struct patm_softc *sc = arg1;
939         uint32_t *ret;
940         int error, i;
941
942         ret = malloc(IDT_NOR_END, M_TEMP, M_WAITOK);
943
944         mtx_lock(&sc->mtx);
945         for (i = 0; i < IDT_NOR_END; i += 4)
946                 ret[i / 4] = patm_nor_read(sc, i);
947         mtx_unlock(&sc->mtx);
948
949         error = SYSCTL_OUT(req, ret, IDT_NOR_END);
950         free(ret, M_TEMP);
951
952         return (error);
953 }
954
955 /*
956  * Sysctl handler for TSQ
957  *
958  * LOCK: unlocked, needed
959  */
960 static int
961 patm_sysctl_tsq(SYSCTL_HANDLER_ARGS)
962 {
963         struct patm_softc *sc = arg1;
964         void *ret;
965         int error;
966
967         ret = malloc(IDT_TSQ_SIZE * IDT_TSQE_SIZE, M_TEMP, M_WAITOK);
968
969         mtx_lock(&sc->mtx);
970         memcpy(ret, sc->tsq, IDT_TSQ_SIZE * IDT_TSQE_SIZE);
971         mtx_unlock(&sc->mtx);
972
973         error = SYSCTL_OUT(req, ret, IDT_TSQ_SIZE * IDT_TSQE_SIZE);
974         free(ret, M_TEMP);
975
976         return (error);
977 }
978
979 /*
980  * debugging
981  */
982 static struct patm_softc *
983 patm_dump_unit(u_int unit)
984 {
985         devclass_t dc;
986         struct patm_softc *sc;
987
988         dc = devclass_find("patm");
989         if (dc == NULL) {
990                 printf("%s: can't find devclass\n", __func__);
991                 return (NULL);
992         }
993         sc = devclass_get_softc(dc, unit);
994         if (sc == NULL) {
995                 printf("%s: invalid unit number: %d\n", __func__, unit);
996                 return (NULL);
997         }
998         return (sc);
999 }
1000
1001 int
1002 patm_dump_vc(u_int unit, u_int vc)
1003 {
1004         struct patm_softc *sc;
1005         uint32_t tct[8];
1006         uint32_t rct[4];
1007         uint32_t scd[12];
1008         u_int i;
1009
1010         if ((sc = patm_dump_unit(unit)) == NULL)
1011                 return (0);
1012
1013         for (i = 0; i < 8; i++)
1014                 tct[i] = patm_sram_read(sc, vc * 8 + i);
1015         for (i = 0; i < 4; i++)
1016                 rct[i] = patm_sram_read(sc, sc->mmap->rct + vc * 4 + i);
1017         for (i = 0; i < 12; i++)
1018                 scd[i] = patm_sram_read(sc, (tct[0] & 0x7ffff) + i);
1019
1020         printf("TCT%3u: %08x %08x %08x %08x  %08x %08x %08x %08x\n", vc,
1021             tct[0], tct[1], tct[2], tct[3], tct[4], tct[5], tct[6], tct[7]);
1022         printf("RCT%3u: %08x %08x %08x %08x\n", vc,
1023             rct[0], rct[1], rct[2], rct[3]);
1024         printf("SCD%3u: %08x %08x %08x %08x  %08x %08x %08x %08x\n", vc,
1025             scd[0], scd[1], scd[2], scd[3], scd[4], scd[5], scd[6], scd[7]);
1026         printf("        %08x %08x %08x %08x\n",
1027             scd[8], scd[9], scd[10], scd[11]);
1028
1029         return (0);
1030 }
1031
1032 int
1033 patm_dump_regs(u_int unit)
1034 {
1035         struct patm_softc *sc;
1036         u_int i;
1037
1038         if ((sc = patm_dump_unit(unit)) == NULL)
1039                 return (0);
1040
1041         for (i = 0; i <= IDT_NOR_DNOW; i += 4)
1042                 printf("%x: %08x\n", i, patm_nor_read(sc, i));
1043
1044         return (0);
1045 }
1046
1047 int
1048 patm_dump_sram(u_int unit, u_int from, u_int words)
1049 {
1050         struct patm_softc *sc;
1051         u_int i;
1052
1053         if ((sc = patm_dump_unit(unit)) == NULL)
1054                 return (0);
1055
1056         for (i = 0; i < words; i++) {
1057                 if (i % 8 == 0)
1058                         printf("%05x:", from + i);
1059                 printf(" %08x", patm_sram_read(sc, from + i));
1060                 if (i % 8 == 7)
1061                         printf("\n");
1062         }
1063         if (i % 8 != 0)
1064                 printf("\n");
1065         return (0);
1066 }
1067 #endif