if_patm_attach.c revision 119137
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#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/patm/if_patm_attach.c 119137 2003-08-19 17:51:11Z sam $");
33
34#include "opt_inet.h"
35#include "opt_natm.h"
36
37#include <sys/types.h>
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/malloc.h>
41#include <sys/kernel.h>
42#include <sys/bus.h>
43#include <sys/errno.h>
44#include <sys/conf.h>
45#include <sys/module.h>
46#include <sys/lock.h>
47#include <sys/mutex.h>
48#include <sys/sysctl.h>
49#include <sys/queue.h>
50#include <sys/condvar.h>
51#include <vm/uma.h>
52
53#include <sys/sockio.h>
54#include <sys/mbuf.h>
55#include <sys/socket.h>
56
57#include <net/if.h>
58#include <net/if_media.h>
59#include <net/if_atm.h>
60#include <net/route.h>
61#ifdef ENABLE_BPF
62#include <net/bpf.h>
63#endif
64#include <netinet/in.h>
65#include <netinet/if_atm.h>
66
67#include <machine/bus.h>
68#include <machine/resource.h>
69#include <sys/bus.h>
70#include <sys/rman.h>
71#include <sys/mbpool.h>
72#include <pci/pcireg.h>
73#include <pci/pcivar.h>
74
75#include <dev/utopia/utopia.h>
76#include <dev/patm/idt77252reg.h>
77#include <dev/patm/if_patmvar.h>
78
79MODULE_DEPEND(patm, utopia, 1, 1, 1);
80MODULE_DEPEND(patm, pci, 1, 1, 1);
81MODULE_DEPEND(patm, atm, 1, 1, 1);
82MODULE_DEPEND(patm, libmbpool, 1, 1, 1);
83
84devclass_t patm_devclass;
85
86static int patm_probe(device_t dev);
87static int patm_attach(device_t dev);
88static int patm_detach(device_t dev);
89static device_method_t patm_methods[] = {
90	DEVMETHOD(device_probe,		patm_probe),
91	DEVMETHOD(device_attach,	patm_attach),
92	DEVMETHOD(device_detach,	patm_detach),
93	{0,0}
94};
95static driver_t patm_driver = {
96	"patm",
97	patm_methods,
98	sizeof(struct patm_softc),
99};
100DRIVER_MODULE(patm, pci, patm_driver, patm_devclass, NULL, 0);
101
102static const struct {
103	u_int	devid;
104	const char *desc;
105} devs[] = {
106	{ PCI_DEVICE_IDT77252,	"NICStAR (77222/77252) ATM adapter" },
107	{ PCI_DEVICE_IDT77v252,	"NICStAR (77v252) ATM adapter" },
108	{ PCI_DEVICE_IDT77v222,	"NICStAR (77v222) ATM adapter" },
109	{ 0, NULL }
110};
111
112SYSCTL_DECL(_hw_atm);
113
114static int patm_phy_readregs(struct ifatm *, u_int, uint8_t *, u_int *);
115static int patm_phy_writereg(struct ifatm *, u_int, u_int, u_int);
116static const struct utopia_methods patm_utopia_methods = {
117	patm_phy_readregs,
118	patm_phy_writereg
119};
120
121static void patm_destroy(struct patm_softc *sc);
122
123static int patm_sysctl_istats(SYSCTL_HANDLER_ARGS);
124static int patm_sysctl_eeprom(SYSCTL_HANDLER_ARGS);
125
126static void patm_read_eeprom(struct patm_softc *sc);
127static int patm_sq_init(struct patm_softc *sc);
128static int patm_rbuf_init(struct patm_softc *sc);
129static int patm_txmap_init(struct patm_softc *sc);
130
131static void patm_env_getuint(struct patm_softc *, u_int *, const char *);
132
133#ifdef PATM_DEBUG
134static int patm_sysctl_regs(SYSCTL_HANDLER_ARGS);
135static int patm_sysctl_tsq(SYSCTL_HANDLER_ARGS);
136int patm_dump_vc(u_int unit, u_int vc) __unused;
137int patm_dump_regs(u_int unit) __unused;
138int patm_dump_sram(u_int unit, u_int from, u_int words) __unused;
139#endif
140
141/*
142 * Probe for a IDT77252 controller
143 */
144static int
145patm_probe(device_t dev)
146{
147	u_int i;
148
149	if (pci_get_vendor(dev) == PCI_VENDOR_IDT) {
150		for (i = 0; devs[i].desc != NULL; i++)
151			if (pci_get_device(dev) == devs[i].devid) {
152				device_set_desc(dev, devs[i].desc);
153				return (0);
154			}
155	}
156	return (ENXIO);
157}
158
159/*
160 * Attach
161 */
162static int
163patm_attach(device_t dev)
164{
165	struct patm_softc *sc;
166	int error;
167	struct ifnet *ifp;
168	int rid;
169	u_int a;
170
171	static const struct idt_mmap idt_mmap[4] = IDT_MMAP;
172
173	sc = device_get_softc(dev);
174
175	sc->dev = dev;
176#ifdef IATM_DEBUG
177	sc->debug = IATM_DEBUG;
178#endif
179	sc->ifatm.mib.device = ATM_DEVICE_IDTABR25;
180	sc->ifatm.mib.serial = 0;
181	sc->ifatm.mib.hw_version = 0;
182	sc->ifatm.mib.sw_version = 0;
183	sc->ifatm.mib.vpi_bits = PATM_VPI_BITS;
184	sc->ifatm.mib.vci_bits = 0;	/* set below */;
185	sc->ifatm.mib.max_vpcs = 0;
186	sc->ifatm.mib.max_vccs = 0;	/* set below */
187	sc->ifatm.mib.media = IFM_ATM_UNKNOWN;
188	sc->ifatm.phy = &sc->utopia;
189
190	ifp = &sc->ifatm.ifnet;
191	ifp->if_softc = sc;
192	ifp->if_unit = device_get_unit(dev);
193	ifp->if_name = "patm";
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(dev, SYS_RES_MEMORY, &rid,
223	    0, ~0, 1, 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(dev, SYS_RES_IRQ, &sc->irqid,
237	    0, ~0, 1, 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 */
457static int
458patm_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 */
483static void
484patm_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 */
564static void
565patm_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 */
590static int
591patm_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 */
614static int
615patm_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 */
636static void
637patm_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 */
696static int
697patm_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 */
722static int
723patm_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 */
751static int
752patm_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 */
811static int
812patm_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 */
889static int
890patm_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 */
935static int
936patm_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 */
960static int
961patm_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 */
982static struct patm_softc *
983patm_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
1001int
1002patm_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
1032int
1033patm_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
1047int
1048patm_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
1068