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