if_patm_attach.c revision 156949
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 156949 2006-03-21 14:54:42Z harti $");
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 | INTR_MPSAFE,
445	    patm_intr, 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
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);
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
1077