2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
27 * Author: Hartmut Brandt <harti@freebsd.org>
31 * This file contains the module and driver infrastructure stuff as well
32 * as a couple of utility functions and the entire initialisation.
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/malloc.h>
45 #include <sys/kernel.h>
47 #include <sys/errno.h>
49 #include <sys/module.h>
50 #include <sys/queue.h>
51 #include <sys/syslog.h>
53 #include <sys/mutex.h>
54 #include <sys/condvar.h>
55 #include <sys/sysctl.h>
58 #include <sys/sockio.h>
60 #include <sys/socket.h>
63 #include <net/if_media.h>
64 #include <net/if_atm.h>
65 #include <net/route.h>
69 #include <netinet/in.h>
70 #include <netinet/if_atm.h>
72 #include <machine/bus.h>
73 #include <machine/resource.h>
76 #include <dev/pci/pcireg.h>
77 #include <dev/pci/pcivar.h>
79 #include <dev/utopia/utopia.h>
80 #include <dev/hatm/if_hatmconf.h>
81 #include <dev/hatm/if_hatmreg.h>
82 #include <dev/hatm/if_hatmvar.h>
96 MODULE_DEPEND(hatm, utopia, 1, 1, 1);
97 MODULE_DEPEND(hatm, pci, 1, 1, 1);
98 MODULE_DEPEND(hatm, atm, 1, 1, 1);
100 #define EEPROM_DELAY 400 /* microseconds */
102 /* Read from EEPROM 0000 0011b */
103 static const uint32_t readtab[] = {
104 HE_REGM_HOST_PROM_SEL | HE_REGM_HOST_PROM_CLOCK,
106 HE_REGM_HOST_PROM_CLOCK,
108 HE_REGM_HOST_PROM_CLOCK,
110 HE_REGM_HOST_PROM_CLOCK,
112 HE_REGM_HOST_PROM_CLOCK,
114 HE_REGM_HOST_PROM_CLOCK,
116 HE_REGM_HOST_PROM_CLOCK,
117 HE_REGM_HOST_PROM_DATA_IN, /* 0 */
118 HE_REGM_HOST_PROM_CLOCK | HE_REGM_HOST_PROM_DATA_IN,
119 HE_REGM_HOST_PROM_DATA_IN, /* 1 */
120 HE_REGM_HOST_PROM_CLOCK | HE_REGM_HOST_PROM_DATA_IN,
121 HE_REGM_HOST_PROM_DATA_IN, /* 1 */
123 static const uint32_t clocktab[] = {
124 0, HE_REGM_HOST_PROM_CLOCK,
125 0, HE_REGM_HOST_PROM_CLOCK,
126 0, HE_REGM_HOST_PROM_CLOCK,
127 0, HE_REGM_HOST_PROM_CLOCK,
128 0, HE_REGM_HOST_PROM_CLOCK,
129 0, HE_REGM_HOST_PROM_CLOCK,
130 0, HE_REGM_HOST_PROM_CLOCK,
131 0, HE_REGM_HOST_PROM_CLOCK,
136 * Convert cell rate to ATM Forum format
139 hatm_cps2atmf(uint32_t pcr)
147 while (pcr > (1024 - 1)) {
151 return ((1 << 14) | (e << 9) | (pcr & 0x1ff));
154 hatm_atmf2cps(uint32_t fcr)
158 return ((1 << ((fcr >> 9) & 0x1f)) * (512 + (fcr & 0x1ff)) / 512
162 /************************************************************
167 * Probe for a HE controller
170 hatm_probe(device_t dev)
174 for (i = 0; hatm_devs[i].name; i++)
175 if (pci_get_vendor(dev) == hatm_devs[i].vid &&
176 pci_get_device(dev) == hatm_devs[i].did) {
177 device_set_desc(dev, hatm_devs[i].name);
184 * Allocate and map DMA-able memory. We support only contiguous mappings.
187 dmaload_helper(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
191 KASSERT(nsegs == 1, ("too many segments for DMA: %d", nsegs));
192 KASSERT(segs[0].ds_addr <= 0xffffffffUL,
193 ("phys addr too large %lx", (u_long)segs[0].ds_addr));
195 *(bus_addr_t *)arg = segs[0].ds_addr;
198 hatm_alloc_dmamem(struct hatm_softc *sc, const char *what, struct dmamem *mem)
205 * Alignement does not work in the bus_dmamem_alloc function below
206 * on FreeBSD. malloc seems to align objects at least to the object
207 * size so increase the size to the alignment if the size is lesser
208 * than the alignemnt.
209 * XXX on sparc64 this is (probably) not needed.
211 if (mem->size < mem->align)
212 mem->size = mem->align;
214 error = bus_dma_tag_create(sc->parent_tag, mem->align, 0,
215 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
216 NULL, NULL, mem->size, 1,
217 BUS_SPACE_MAXSIZE_32BIT, BUS_DMA_ALLOCNOW,
218 NULL, NULL, &mem->tag);
220 if_printf(&sc->ifatm.ifnet, "DMA tag create (%s)\n", what);
224 error = bus_dmamem_alloc(mem->tag, &mem->base, 0, &mem->map);
226 if_printf(&sc->ifatm.ifnet, "DMA mem alloc (%s): %d\n",
228 bus_dma_tag_destroy(mem->tag);
233 error = bus_dmamap_load(mem->tag, mem->map, mem->base, mem->size,
234 dmaload_helper, &mem->paddr, BUS_DMA_NOWAIT);
236 if_printf(&sc->ifatm.ifnet, "DMA map load (%s): %d\n",
238 bus_dmamem_free(mem->tag, mem->base, mem->map);
239 bus_dma_tag_destroy(mem->tag);
244 DBG(sc, DMA, ("%s S/A/V/P 0x%x 0x%x %p 0x%lx", what, mem->size,
245 mem->align, mem->base, (u_long)mem->paddr));
251 * Destroy all the resources of an DMA-able memory region.
254 hatm_destroy_dmamem(struct dmamem *mem)
256 if (mem->base != NULL) {
257 bus_dmamap_unload(mem->tag, mem->map);
258 bus_dmamem_free(mem->tag, mem->base, mem->map);
259 (void)bus_dma_tag_destroy(mem->tag);
265 * Initialize/destroy DMA maps for the large pool 0
268 hatm_destroy_rmaps(struct hatm_softc *sc)
272 DBG(sc, ATTACH, ("destroying rmaps and lbuf pointers..."));
273 if (sc->rmaps != NULL) {
274 for (b = 0; b < sc->lbufs_size; b++)
275 bus_dmamap_destroy(sc->mbuf_tag, sc->rmaps[b]);
276 free(sc->rmaps, M_DEVBUF);
278 if (sc->lbufs != NULL)
279 free(sc->lbufs, M_DEVBUF);
283 hatm_init_rmaps(struct hatm_softc *sc)
288 DBG(sc, ATTACH, ("allocating rmaps and lbuf pointers..."));
289 sc->lbufs = malloc(sizeof(sc->lbufs[0]) * sc->lbufs_size,
290 M_DEVBUF, M_ZERO | M_WAITOK);
292 /* allocate and create the DMA maps for the large pool */
293 sc->rmaps = malloc(sizeof(sc->rmaps[0]) * sc->lbufs_size,
295 for (b = 0; b < sc->lbufs_size; b++) {
296 err = bus_dmamap_create(sc->mbuf_tag, 0, &sc->rmaps[b]);
298 panic("bus_dmamap_create: %d\n", err);
303 * Initialize and destroy small mbuf page pointers and pages
306 hatm_destroy_smbufs(struct hatm_softc *sc)
309 struct mbuf_page *pg;
310 struct mbuf_chunk_hdr *h;
312 if (sc->mbuf_pages != NULL) {
313 for (i = 0; i < sc->mbuf_npages; i++) {
314 pg = sc->mbuf_pages[i];
315 for (b = 0; b < pg->hdr.nchunks; b++) {
316 h = (struct mbuf_chunk_hdr *) ((char *)pg +
317 b * pg->hdr.chunksize + pg->hdr.hdroff);
318 if (h->flags & MBUF_CARD)
319 if_printf(&sc->ifatm.ifnet,
320 "%s -- mbuf page=%u card buf %u\n",
322 if (h->flags & MBUF_USED)
323 if_printf(&sc->ifatm.ifnet,
324 "%s -- mbuf page=%u used buf %u\n",
327 bus_dmamap_unload(sc->mbuf_tag, pg->hdr.map);
328 bus_dmamap_destroy(sc->mbuf_tag, pg->hdr.map);
331 free(sc->mbuf_pages, M_DEVBUF);
336 hatm_init_smbufs(struct hatm_softc *sc)
338 sc->mbuf_pages = malloc(sizeof(sc->mbuf_pages[0]) *
339 sc->mbuf_max_pages, M_DEVBUF, M_WAITOK);
344 * Initialize/destroy TPDs. This is called from attach/detach.
347 hatm_destroy_tpds(struct hatm_softc *sc)
351 if (sc->tpds.base == NULL)
354 DBG(sc, ATTACH, ("releasing TPDs ..."));
355 if (sc->tpd_nfree != sc->tpd_total)
356 if_printf(&sc->ifatm.ifnet, "%u tpds still in use from %u\n",
357 sc->tpd_total - sc->tpd_nfree, sc->tpd_total);
358 while ((t = SLIST_FIRST(&sc->tpd_free)) != NULL) {
359 SLIST_REMOVE_HEAD(&sc->tpd_free, link);
360 bus_dmamap_destroy(sc->tx_tag, t->map);
362 hatm_destroy_dmamem(&sc->tpds);
363 free(sc->tpd_used, M_DEVBUF);
364 DBG(sc, ATTACH, ("... done"));
367 hatm_init_tpds(struct hatm_softc *sc)
373 DBG(sc, ATTACH, ("allocating %u TPDs and maps ...", sc->tpd_total));
374 error = hatm_alloc_dmamem(sc, "TPD memory", &sc->tpds);
376 DBG(sc, ATTACH, ("... dmamem error=%d", error));
380 /* put all the TPDs on the free list and allocate DMA maps */
381 for (i = 0; i < sc->tpd_total; i++) {
385 error = bus_dmamap_create(sc->tx_tag, 0, &t->map);
387 DBG(sc, ATTACH, ("... dmamap error=%d", error));
388 while ((t = SLIST_FIRST(&sc->tpd_free)) != NULL) {
389 SLIST_REMOVE_HEAD(&sc->tpd_free, link);
390 bus_dmamap_destroy(sc->tx_tag, t->map);
392 hatm_destroy_dmamem(&sc->tpds);
396 SLIST_INSERT_HEAD(&sc->tpd_free, t, link);
399 /* allocate and zero bitmap */
400 sc->tpd_used = malloc(sizeof(uint8_t) * (sc->tpd_total + 7) / 8,
401 M_DEVBUF, M_ZERO | M_WAITOK);
402 sc->tpd_nfree = sc->tpd_total;
404 DBG(sc, ATTACH, ("... done"));
410 * Free all the TPDs that where given to the card.
411 * An mbuf chain may be attached to a TPD - free it also and
412 * unload its associated DMA map.
415 hatm_stop_tpds(struct hatm_softc *sc)
420 DBG(sc, ATTACH, ("free TPDs ..."));
421 for (i = 0; i < sc->tpd_total; i++) {
422 if (TPD_TST_USED(sc, i)) {
427 bus_dmamap_unload(sc->tx_tag, t->map);
430 SLIST_INSERT_HEAD(&sc->tpd_free, t, link);
437 * This frees ALL resources of this interface and leaves the structure
438 * in an indeterminate state. This is called just before detaching or
439 * on a failed attach. No lock should be held.
442 hatm_destroy(struct hatm_softc *sc)
446 bus_teardown_intr(sc->dev, sc->irqres, sc->ih);
448 hatm_destroy_rmaps(sc);
449 hatm_destroy_smbufs(sc);
450 hatm_destroy_tpds(sc);
452 if (sc->vcc_zone != NULL) {
453 for (cid = 0; cid < HE_MAX_VCCS; cid++)
454 if (sc->vccs[cid] != NULL)
455 uma_zfree(sc->vcc_zone, sc->vccs[cid]);
456 uma_zdestroy(sc->vcc_zone);
460 * Release all memory allocated to the various queues and
461 * Status pages. These have there own flag which shows whether
462 * they are really allocated.
464 hatm_destroy_dmamem(&sc->irq_0.mem);
465 hatm_destroy_dmamem(&sc->rbp_s0.mem);
466 hatm_destroy_dmamem(&sc->rbp_l0.mem);
467 hatm_destroy_dmamem(&sc->rbp_s1.mem);
468 hatm_destroy_dmamem(&sc->rbrq_0.mem);
469 hatm_destroy_dmamem(&sc->rbrq_1.mem);
470 hatm_destroy_dmamem(&sc->tbrq.mem);
471 hatm_destroy_dmamem(&sc->tpdrq.mem);
472 hatm_destroy_dmamem(&sc->hsp_mem);
474 if (sc->irqres != NULL)
475 bus_release_resource(sc->dev, SYS_RES_IRQ,
476 sc->irqid, sc->irqres);
478 if (sc->tx_tag != NULL)
479 if (bus_dma_tag_destroy(sc->tx_tag))
480 if_printf(&sc->ifatm.ifnet, "mbuf DMA tag busy\n");
482 if (sc->mbuf_tag != NULL)
483 if (bus_dma_tag_destroy(sc->mbuf_tag))
484 if_printf(&sc->ifatm.ifnet, "mbuf DMA tag busy\n");
486 if (sc->parent_tag != NULL)
487 if (bus_dma_tag_destroy(sc->parent_tag))
488 if_printf(&sc->ifatm.ifnet, "parent DMA tag busy\n");
490 if (sc->memres != NULL)
491 bus_release_resource(sc->dev, SYS_RES_MEMORY,
492 sc->memid, sc->memres);
494 sysctl_ctx_free(&sc->sysctl_ctx);
496 cv_destroy(&sc->cv_rcclose);
497 cv_destroy(&sc->vcc_cv);
498 mtx_destroy(&sc->mtx);
505 hatm_reset(struct hatm_softc *sc)
509 WRITE4(sc, HE_REGO_RESET_CNTL, 0x00);
511 WRITE4(sc, HE_REGO_RESET_CNTL, 0xff);
514 while (((v = READ4(sc, HE_REGO_RESET_CNTL)) & HE_REGM_RESET_STATE) == 0) {
516 if (++count == 100) {
517 if_printf(&sc->ifatm.ifnet, "reset failed\n");
529 hatm_init_bus_width(struct hatm_softc *sc)
533 v = READ4(sc, HE_REGO_HOST_CNTL);
535 if (v & HE_REGM_HOST_BUS64) {
537 v1 = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4);
538 v1 |= HE_PCIM_CTL0_64BIT;
539 pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v1, 4);
541 v |= HE_REGM_HOST_DESC_RD64
542 | HE_REGM_HOST_DATA_RD64
543 | HE_REGM_HOST_DATA_WR64;
544 WRITE4(sc, HE_REGO_HOST_CNTL, v);
548 v = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4);
549 v &= ~HE_PCIM_CTL0_64BIT;
550 pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v, 4);
555 * 4.6 Set Host Endianess
558 hatm_init_endianess(struct hatm_softc *sc)
562 v = READ4(sc, HE_REGO_LB_SWAP);
564 #if BYTE_ORDER == BIG_ENDIAN
565 v |= HE_REGM_LBSWAP_INTR_SWAP |
566 HE_REGM_LBSWAP_DESC_WR_SWAP |
567 HE_REGM_LBSWAP_BIG_ENDIAN;
568 v &= ~(HE_REGM_LBSWAP_DATA_WR_SWAP |
569 HE_REGM_LBSWAP_DESC_RD_SWAP |
570 HE_REGM_LBSWAP_DATA_RD_SWAP);
572 v &= ~(HE_REGM_LBSWAP_DATA_WR_SWAP |
573 HE_REGM_LBSWAP_DESC_RD_SWAP |
574 HE_REGM_LBSWAP_DATA_RD_SWAP |
575 HE_REGM_LBSWAP_INTR_SWAP |
576 HE_REGM_LBSWAP_DESC_WR_SWAP |
577 HE_REGM_LBSWAP_BIG_ENDIAN);
581 v |= HE_REGM_LBSWAP_XFER_SIZE;
583 WRITE4(sc, HE_REGO_LB_SWAP, v);
591 hatm_read_prom_byte(struct hatm_softc *sc, u_int addr)
593 uint32_t val, tmp_read, byte_read;
597 val = READ4(sc, HE_REGO_HOST_CNTL);
598 val &= HE_REGM_HOST_PROM_BITS;
601 val |= HE_REGM_HOST_PROM_WREN;
602 WRITE4(sc, HE_REGO_HOST_CNTL, val);
606 for (i = 0; i < sizeof(readtab) / sizeof(readtab[0]); i++) {
607 WRITE4(sc, HE_REGO_HOST_CNTL, val | readtab[i]);
613 for (n = 7, j = 0; n >= 0; n--) {
614 WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++] |
615 (((addr >> n) & 1 ) << HE_REGS_HOST_PROM_DATA_IN));
618 WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++] |
619 (((addr >> n) & 1 ) << HE_REGS_HOST_PROM_DATA_IN));
624 val &= ~HE_REGM_HOST_PROM_WREN;
625 WRITE4(sc, HE_REGO_HOST_CNTL, val);
630 for (n = 7, j = 0; n >= 0; n--) {
631 WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++]);
634 tmp_read = READ4(sc, HE_REGO_HOST_CNTL);
635 byte_read |= (uint8_t)(((tmp_read & HE_REGM_HOST_PROM_DATA_OUT)
636 >> HE_REGS_HOST_PROM_DATA_OUT) << n);
637 WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++]);
641 WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++]);
649 hatm_init_read_eeprom(struct hatm_softc *sc)
655 for (n = count = 0; count < HE_EEPROM_PROD_ID_LEN; count++) {
656 byte = hatm_read_prom_byte(sc, HE_EEPROM_PROD_ID + count);
657 if (n > 0 || byte != ' ')
658 sc->prod_id[n++] = byte;
660 while (n > 0 && sc->prod_id[n-1] == ' ')
662 sc->prod_id[n] = '\0';
664 for (n = count = 0; count < HE_EEPROM_REV_LEN; count++) {
665 byte = hatm_read_prom_byte(sc, HE_EEPROM_REV + count);
666 if (n > 0 || byte != ' ')
669 while (n > 0 && sc->rev[n-1] == ' ')
672 sc->ifatm.mib.hw_version = sc->rev[0];
674 sc->ifatm.mib.serial = hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 0) << 0;
675 sc->ifatm.mib.serial |= hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 1) << 8;
676 sc->ifatm.mib.serial |= hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 2) << 16;
677 sc->ifatm.mib.serial |= hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 3) << 24;
679 v = hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 0) << 0;
680 v |= hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 1) << 8;
681 v |= hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 2) << 16;
682 v |= hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 3) << 24;
685 case HE_MEDIA_UTP155:
686 sc->ifatm.mib.media = IFM_ATM_UTP_155;
687 sc->ifatm.mib.pcr = ATM_RATE_155M;
690 case HE_MEDIA_MMF155:
691 sc->ifatm.mib.media = IFM_ATM_MM_155;
692 sc->ifatm.mib.pcr = ATM_RATE_155M;
695 case HE_MEDIA_MMF622:
696 sc->ifatm.mib.media = IFM_ATM_MM_622;
697 sc->ifatm.mib.device = ATM_DEVICE_HE622;
698 sc->ifatm.mib.pcr = ATM_RATE_622M;
702 case HE_MEDIA_SMF155:
703 sc->ifatm.mib.media = IFM_ATM_SM_155;
704 sc->ifatm.mib.pcr = ATM_RATE_155M;
707 case HE_MEDIA_SMF622:
708 sc->ifatm.mib.media = IFM_ATM_SM_622;
709 sc->ifatm.mib.device = ATM_DEVICE_HE622;
710 sc->ifatm.mib.pcr = ATM_RATE_622M;
715 sc->ifatm.mib.esi[0] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 0);
716 sc->ifatm.mib.esi[1] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 1);
717 sc->ifatm.mib.esi[2] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 2);
718 sc->ifatm.mib.esi[3] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 3);
719 sc->ifatm.mib.esi[4] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 4);
720 sc->ifatm.mib.esi[5] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 5);
724 * Clear unused interrupt queue
727 hatm_clear_irq(struct hatm_softc *sc, u_int group)
729 WRITE4(sc, HE_REGO_IRQ_BASE(group), 0);
730 WRITE4(sc, HE_REGO_IRQ_HEAD(group), 0);
731 WRITE4(sc, HE_REGO_IRQ_CNTL(group), 0);
732 WRITE4(sc, HE_REGO_IRQ_DATA(group), 0);
736 * 4.10 Initialize interrupt queues
739 hatm_init_irq(struct hatm_softc *sc, struct heirq *q, u_int group)
744 hatm_clear_irq(sc, group);
750 q->irq = q->mem.base;
752 q->tailp = q->irq + (q->size - 1);
755 for (i = 0; i < q->size; i++)
756 q->irq[i] = HE_REGM_ITYPE_INVALID;
758 WRITE4(sc, HE_REGO_IRQ_BASE(group), q->mem.paddr);
759 WRITE4(sc, HE_REGO_IRQ_HEAD(group),
760 ((q->size - 1) << HE_REGS_IRQ_HEAD_SIZE) |
761 (q->thresh << HE_REGS_IRQ_HEAD_THRESH));
762 WRITE4(sc, HE_REGO_IRQ_CNTL(group), q->line);
763 WRITE4(sc, HE_REGO_IRQ_DATA(group), 0);
767 * 5.1.3 Initialize connection memory
770 hatm_init_cm(struct hatm_softc *sc)
772 u_int rsra, mlbm, rabr, numbuffs;
773 u_int tsra, tabr, mtpd;
776 for (n = 0; n < HE_CONFIG_TXMEM; n++)
777 WRITE_TCM4(sc, n, 0);
778 for (n = 0; n < HE_CONFIG_RXMEM; n++)
779 WRITE_RCM4(sc, n, 0);
781 numbuffs = sc->r0_numbuffs + sc->r1_numbuffs + sc->tx_numbuffs;
784 mlbm = ((rsra + sc->ifatm.mib.max_vccs * 8) + 0x7ff) & ~0x7ff;
785 rabr = ((mlbm + numbuffs * 2) + 0x7ff) & ~0x7ff;
786 sc->rsrb = ((rabr + 2048) + (2 * sc->ifatm.mib.max_vccs - 1)) &
787 ~(2 * sc->ifatm.mib.max_vccs - 1);
790 sc->tsrb = tsra + sc->ifatm.mib.max_vccs * 8;
791 sc->tsrc = sc->tsrb + sc->ifatm.mib.max_vccs * 4;
792 sc->tsrd = sc->tsrc + sc->ifatm.mib.max_vccs * 2;
793 tabr = sc->tsrd + sc->ifatm.mib.max_vccs * 1;
794 mtpd = ((tabr + 1024) + (16 * sc->ifatm.mib.max_vccs - 1)) &
795 ~(16 * sc->ifatm.mib.max_vccs - 1);
797 DBG(sc, ATTACH, ("rsra=%x mlbm=%x rabr=%x rsrb=%x",
798 rsra, mlbm, rabr, sc->rsrb));
799 DBG(sc, ATTACH, ("tsra=%x tsrb=%x tsrc=%x tsrd=%x tabr=%x mtpd=%x",
800 tsra, sc->tsrb, sc->tsrc, sc->tsrd, tabr, mtpd));
802 WRITE4(sc, HE_REGO_TSRB_BA, sc->tsrb);
803 WRITE4(sc, HE_REGO_TSRC_BA, sc->tsrc);
804 WRITE4(sc, HE_REGO_TSRD_BA, sc->tsrd);
805 WRITE4(sc, HE_REGO_TMABR_BA, tabr);
806 WRITE4(sc, HE_REGO_TPD_BA, mtpd);
808 WRITE4(sc, HE_REGO_RCMRSRB_BA, sc->rsrb);
809 WRITE4(sc, HE_REGO_RCMLBM_BA, mlbm);
810 WRITE4(sc, HE_REGO_RCMABR_BA, rabr);
816 * 5.1.4 Initialize Local buffer Pools
819 hatm_init_rx_buffer_pool(struct hatm_softc *sc,
820 u_int num, /* bank */
821 u_int start, /* start row */
822 u_int numbuffs /* number of entries */
825 u_int row_size; /* bytes per row */
826 uint32_t row_addr; /* start address of this row */
827 u_int lbuf_size; /* bytes per lbuf */
828 u_int lbufs_per_row; /* number of lbufs per memory row */
829 uint32_t lbufd_index; /* index of lbuf descriptor */
830 uint32_t lbufd_addr; /* address of lbuf descriptor */
831 u_int lbuf_row_cnt; /* current lbuf in current row */
832 uint32_t lbuf_addr; /* address of current buffer */
835 row_size = sc->bytes_per_row;;
836 row_addr = start * row_size;
837 lbuf_size = sc->cells_per_lbuf * 48;
838 lbufs_per_row = sc->cells_per_row / sc->cells_per_lbuf;
840 /* descriptor index */
843 /* 2 words per entry */
844 lbufd_addr = READ4(sc, HE_REGO_RCMLBM_BA) + lbufd_index * 2;
846 /* write head of queue */
847 WRITE4(sc, HE_REGO_RLBF_H(num), lbufd_index);
850 for (i = 0; i < numbuffs; i++) {
851 lbuf_addr = (row_addr + lbuf_row_cnt * lbuf_size) / 32;
853 WRITE_RCM4(sc, lbufd_addr, lbuf_addr);
856 WRITE_RCM4(sc, lbufd_addr + 1, lbufd_index);
858 if (++lbuf_row_cnt == lbufs_per_row) {
860 row_addr += row_size;
866 WRITE4(sc, HE_REGO_RLBF_T(num), lbufd_index - 2);
867 WRITE4(sc, HE_REGO_RLBF_C(num), numbuffs);
873 hatm_init_tx_buffer_pool(struct hatm_softc *sc,
874 u_int start, /* start row */
875 u_int numbuffs /* number of entries */
878 u_int row_size; /* bytes per row */
879 uint32_t row_addr; /* start address of this row */
880 u_int lbuf_size; /* bytes per lbuf */
881 u_int lbufs_per_row; /* number of lbufs per memory row */
882 uint32_t lbufd_index; /* index of lbuf descriptor */
883 uint32_t lbufd_addr; /* address of lbuf descriptor */
884 u_int lbuf_row_cnt; /* current lbuf in current row */
885 uint32_t lbuf_addr; /* address of current buffer */
888 row_size = sc->bytes_per_row;;
889 row_addr = start * row_size;
890 lbuf_size = sc->cells_per_lbuf * 48;
891 lbufs_per_row = sc->cells_per_row / sc->cells_per_lbuf;
893 /* descriptor index */
894 lbufd_index = sc->r0_numbuffs + sc->r1_numbuffs;
896 /* 2 words per entry */
897 lbufd_addr = READ4(sc, HE_REGO_RCMLBM_BA) + lbufd_index * 2;
899 /* write head of queue */
900 WRITE4(sc, HE_REGO_TLBF_H, lbufd_index);
903 for (i = 0; i < numbuffs; i++) {
904 lbuf_addr = (row_addr + lbuf_row_cnt * lbuf_size) / 32;
906 WRITE_RCM4(sc, lbufd_addr, lbuf_addr);
908 WRITE_RCM4(sc, lbufd_addr + 1, lbufd_index);
910 if (++lbuf_row_cnt == lbufs_per_row) {
912 row_addr += row_size;
918 WRITE4(sc, HE_REGO_TLBF_T, lbufd_index - 1);
923 * 5.1.5 Initialize Intermediate Receive Queues
926 hatm_init_imed_queues(struct hatm_softc *sc)
931 for (n = 0; n < 8; n++) {
932 WRITE4(sc, HE_REGO_INMQ_S(n), 0x10*n+0x000f);
933 WRITE4(sc, HE_REGO_INMQ_L(n), 0x10*n+0x200f);
936 for (n = 0; n < 8; n++) {
937 WRITE4(sc, HE_REGO_INMQ_S(n), n);
938 WRITE4(sc, HE_REGO_INMQ_L(n), n+0x8);
944 * 5.1.7 Init CS block
947 hatm_init_cs_block(struct hatm_softc *sc)
950 u_int clkfreg, cellrate, decr, tmp;
951 static const uint32_t erthr[2][5][3] = HE_REGT_CS_ERTHR;
952 static const uint32_t erctl[2][3] = HE_REGT_CS_ERCTL;
953 static const uint32_t erstat[2][2] = HE_REGT_CS_ERSTAT;
954 static const uint32_t rtfwr[2] = HE_REGT_CS_RTFWR;
955 static const uint32_t rtatr[2] = HE_REGT_CS_RTATR;
956 static const uint32_t bwalloc[2][6] = HE_REGT_CS_BWALLOC;
957 static const uint32_t orcf[2][2] = HE_REGT_CS_ORCF;
959 /* Clear Rate Controller Start Times and Occupied Flags */
960 for (n = 0; n < 32; n++)
961 WRITE_MBOX4(sc, HE_REGO_CS_STTIM(n), 0);
963 clkfreg = sc->he622 ? HE_622_CLOCK : HE_155_CLOCK;
964 cellrate = sc->he622 ? ATM_RATE_622M : ATM_RATE_155M;
965 decr = cellrate / 32;
967 for (n = 0; n < 16; n++) {
968 tmp = clkfreg / cellrate;
969 WRITE_MBOX4(sc, HE_REGO_CS_TGRLD(n), tmp - 1);
973 i = (sc->cells_per_lbuf == 2) ? 0
974 :(sc->cells_per_lbuf == 4) ? 1
978 WRITE_MBOX4(sc, HE_REGO_CS_ERTHR0, erthr[sc->he622][0][i]);
979 WRITE_MBOX4(sc, HE_REGO_CS_ERTHR1, erthr[sc->he622][1][i]);
980 WRITE_MBOX4(sc, HE_REGO_CS_ERTHR2, erthr[sc->he622][2][i]);
981 WRITE_MBOX4(sc, HE_REGO_CS_ERTHR3, erthr[sc->he622][3][i]);
982 WRITE_MBOX4(sc, HE_REGO_CS_ERTHR4, erthr[sc->he622][4][i]);
984 WRITE_MBOX4(sc, HE_REGO_CS_ERCTL0, erctl[sc->he622][0]);
985 WRITE_MBOX4(sc, HE_REGO_CS_ERCTL1, erctl[sc->he622][1]);
986 WRITE_MBOX4(sc, HE_REGO_CS_ERCTL2, erctl[sc->he622][2]);
988 WRITE_MBOX4(sc, HE_REGO_CS_ERSTAT0, erstat[sc->he622][0]);
989 WRITE_MBOX4(sc, HE_REGO_CS_ERSTAT1, erstat[sc->he622][1]);
991 WRITE_MBOX4(sc, HE_REGO_CS_RTFWR, rtfwr[sc->he622]);
992 WRITE_MBOX4(sc, HE_REGO_CS_RTATR, rtatr[sc->he622]);
994 WRITE_MBOX4(sc, HE_REGO_CS_TFBSET, bwalloc[sc->he622][0]);
995 WRITE_MBOX4(sc, HE_REGO_CS_WCRMAX, bwalloc[sc->he622][1]);
996 WRITE_MBOX4(sc, HE_REGO_CS_WCRMIN, bwalloc[sc->he622][2]);
997 WRITE_MBOX4(sc, HE_REGO_CS_WCRINC, bwalloc[sc->he622][3]);
998 WRITE_MBOX4(sc, HE_REGO_CS_WCRDEC, bwalloc[sc->he622][4]);
999 WRITE_MBOX4(sc, HE_REGO_CS_WCRCEIL, bwalloc[sc->he622][5]);
1001 WRITE_MBOX4(sc, HE_REGO_CS_OTPPER, orcf[sc->he622][0]);
1002 WRITE_MBOX4(sc, HE_REGO_CS_OTWPER, orcf[sc->he622][1]);
1004 WRITE_MBOX4(sc, HE_REGO_CS_OTTLIM, 8);
1006 for (n = 0; n < 8; n++)
1007 WRITE_MBOX4(sc, HE_REGO_CS_HGRRT(n), 0);
1011 * 5.1.8 CS Block Connection Memory Initialisation
1014 hatm_init_cs_block_cm(struct hatm_softc *sc)
1017 u_int expt, mant, etrm, wcr, ttnrm, tnrm;
1019 uint32_t clkfreq, cellrate, decr;
1020 uint32_t *rg, rtg, val = 0;
1022 u_int buf, buf_limit;
1023 uint32_t base = READ4(sc, HE_REGO_RCMABR_BA);
1025 for (n = 0; n < HE_REGL_CM_GQTBL; n++)
1026 WRITE_RCM4(sc, base + HE_REGO_CM_GQTBL + n, 0);
1027 for (n = 0; n < HE_REGL_CM_RGTBL; n++)
1028 WRITE_RCM4(sc, base + HE_REGO_CM_RGTBL + n, 0);
1031 for (n = 0; n < HE_REGL_CM_TNRMTBL * 4; n++) {
1032 expt = (n >> 5) & 0x1f;
1033 mant = ((n & 0x18) << 4) | 0x7f;
1034 wcr = (1 << expt) * (mant + 512) / 512;
1036 ttnrm = wcr / 10 / (1 << etrm);
1041 tnrm = (tnrm << 8) | (ttnrm & 0xff);
1043 WRITE_RCM4(sc, base + HE_REGO_CM_TNRMTBL + (n/4), tnrm);
1046 clkfreq = sc->he622 ? HE_622_CLOCK : HE_155_CLOCK;
1049 cellrate = sc->he622 ? ATM_RATE_622M : ATM_RATE_155M;
1050 decr = cellrate / 32;
1052 /* compute GRID top row in 1000 * cps */
1053 for (n = 0; n < 16; n++) {
1054 u_int interval = clkfreq / cellrate;
1055 sc->rate_grid[0][n] = (u_int64_t)clkfreq * 1000 / interval;
1059 /* compute the other rows according to 2.4 */
1060 for (i = 1; i < 16; i++)
1061 for (n = 0; n < 16; n++)
1062 sc->rate_grid[i][n] = sc->rate_grid[i-1][n] /
1065 /* first entry is line rate */
1066 n = hatm_cps2atmf(sc->he622 ? ATM_RATE_622M : ATM_RATE_155M);
1067 expt = (n >> 9) & 0x1f;
1069 sc->rate_grid[0][0] = (u_int64_t)(1<<expt) * 1000 * (mant+512) / 512;
1071 /* now build the conversion table - each 32 bit word contains
1072 * two entries - this gives a total of 0x400 16 bit entries.
1073 * This table maps the truncated ATMF rate version into a grid index */
1074 cellrate = sc->he622 ? ATM_RATE_622M : ATM_RATE_155M;
1075 rg = &sc->rate_grid[15][15];
1077 for (rate = 0; rate < 2 * HE_REGL_CM_RTGTBL; rate++) {
1078 /* unpack the ATMF rate */
1080 mant = (rate & 0x1f) << 4;
1082 /* get the cell rate - minimum is 10 per second */
1083 drate = (uint64_t)(1 << expt) * 1000 * (mant + 512) / 512;
1084 if (drate < 10 * 1000)
1087 /* now look up the grid index */
1088 while (drate >= *rg && rg-- > &sc->rate_grid[0][0])
1091 rtg = rg - &sc->rate_grid[0][0];
1093 /* now compute the buffer limit */
1094 buf = drate * sc->tx_numbuffs / (cellrate * 2) / 1000;
1097 else if (buf > buf_limit)
1101 val = (val << 16) | (rtg << 8) | buf;
1105 WRITE_RCM4(sc, base + HE_REGO_CM_RTGTBL + rate/2, val);
1110 * Clear an unused receive group buffer pool
1113 hatm_clear_rpool(struct hatm_softc *sc, u_int group, u_int large)
1115 WRITE4(sc, HE_REGO_RBP_S(large, group), 0);
1116 WRITE4(sc, HE_REGO_RBP_T(large, group), 0);
1117 WRITE4(sc, HE_REGO_RBP_QI(large, group), 1);
1118 WRITE4(sc, HE_REGO_RBP_BL(large, group), 0);
1122 * Initialize a receive group buffer pool
1125 hatm_init_rpool(struct hatm_softc *sc, struct herbp *q, u_int group,
1129 hatm_clear_rpool(sc, group, large);
1133 bzero(q->mem.base, q->mem.size);
1134 q->rbp = q->mem.base;
1135 q->head = q->tail = 0;
1137 DBG(sc, ATTACH, ("RBP%u%c=0x%lx", group, "SL"[large],
1138 (u_long)q->mem.paddr));
1140 WRITE4(sc, HE_REGO_RBP_S(large, group), q->mem.paddr);
1141 WRITE4(sc, HE_REGO_RBP_T(large, group), 0);
1142 WRITE4(sc, HE_REGO_RBP_QI(large, group),
1143 ((q->size - 1) << HE_REGS_RBP_SIZE) |
1144 HE_REGM_RBP_INTR_ENB |
1145 (q->thresh << HE_REGS_RBP_THRESH));
1146 WRITE4(sc, HE_REGO_RBP_BL(large, group), (q->bsize >> 2) & ~1);
1150 * Clear an unused receive buffer return queue
1153 hatm_clear_rbrq(struct hatm_softc *sc, u_int group)
1155 WRITE4(sc, HE_REGO_RBRQ_ST(group), 0);
1156 WRITE4(sc, HE_REGO_RBRQ_H(group), 0);
1157 WRITE4(sc, HE_REGO_RBRQ_Q(group), (1 << HE_REGS_RBRQ_THRESH));
1158 WRITE4(sc, HE_REGO_RBRQ_I(group), 0);
1162 * Initialize receive buffer return queue
1165 hatm_init_rbrq(struct hatm_softc *sc, struct herbrq *rq, u_int group)
1167 if (rq->size == 0) {
1168 hatm_clear_rbrq(sc, group);
1172 rq->rbrq = rq->mem.base;
1175 DBG(sc, ATTACH, ("RBRQ%u=0x%lx", group, (u_long)rq->mem.paddr));
1177 WRITE4(sc, HE_REGO_RBRQ_ST(group), rq->mem.paddr);
1178 WRITE4(sc, HE_REGO_RBRQ_H(group), 0);
1179 WRITE4(sc, HE_REGO_RBRQ_Q(group),
1180 (rq->thresh << HE_REGS_RBRQ_THRESH) |
1181 ((rq->size - 1) << HE_REGS_RBRQ_SIZE));
1182 WRITE4(sc, HE_REGO_RBRQ_I(group),
1183 (rq->tout << HE_REGS_RBRQ_TIME) |
1184 (rq->pcnt << HE_REGS_RBRQ_COUNT));
1188 * Clear an unused transmit buffer return queue N
1191 hatm_clear_tbrq(struct hatm_softc *sc, u_int group)
1193 WRITE4(sc, HE_REGO_TBRQ_B_T(group), 0);
1194 WRITE4(sc, HE_REGO_TBRQ_H(group), 0);
1195 WRITE4(sc, HE_REGO_TBRQ_S(group), 0);
1196 WRITE4(sc, HE_REGO_TBRQ_THRESH(group), 1);
1200 * Initialize transmit buffer return queue N
1203 hatm_init_tbrq(struct hatm_softc *sc, struct hetbrq *tq, u_int group)
1205 if (tq->size == 0) {
1206 hatm_clear_tbrq(sc, group);
1210 tq->tbrq = tq->mem.base;
1213 DBG(sc, ATTACH, ("TBRQ%u=0x%lx", group, (u_long)tq->mem.paddr));
1215 WRITE4(sc, HE_REGO_TBRQ_B_T(group), tq->mem.paddr);
1216 WRITE4(sc, HE_REGO_TBRQ_H(group), 0);
1217 WRITE4(sc, HE_REGO_TBRQ_S(group), tq->size - 1);
1218 WRITE4(sc, HE_REGO_TBRQ_THRESH(group), tq->thresh);
1225 hatm_init_tpdrq(struct hatm_softc *sc)
1230 tq->tpdrq = tq->mem.base;
1231 tq->tail = tq->head = 0;
1233 DBG(sc, ATTACH, ("TPDRQ=0x%lx", (u_long)tq->mem.paddr));
1235 WRITE4(sc, HE_REGO_TPDRQ_H, tq->mem.paddr);
1236 WRITE4(sc, HE_REGO_TPDRQ_T, 0);
1237 WRITE4(sc, HE_REGO_TPDRQ_S, tq->size - 1);
1241 * Function can be called by the infrastructure to start the card.
1246 struct hatm_softc *sc = p;
1250 hatm_initialize(sc);
1251 mtx_unlock(&sc->mtx);
1262 hatm_sysctl(SYSCTL_HANDLER_ARGS)
1264 struct hatm_softc *sc = arg1;
1272 len = sizeof(sc->istats);
1276 panic("bad control code");
1279 ret = malloc(len, M_TEMP, M_WAITOK);
1285 sc->istats.mcc += READ4(sc, HE_REGO_MCC);
1286 sc->istats.oec += READ4(sc, HE_REGO_OEC);
1287 sc->istats.dcc += READ4(sc, HE_REGO_DCC);
1288 sc->istats.cec += READ4(sc, HE_REGO_CEC);
1289 bcopy(&sc->istats, ret, sizeof(sc->istats));
1292 mtx_unlock(&sc->mtx);
1294 error = SYSCTL_OUT(req, ret, len);
1301 kenv_getuint(struct hatm_softc *sc, const char *var,
1302 u_int *ptr, u_int def, int rw)
1304 char full[IFNAMSIZ + 3 + 20];
1310 if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
1311 OID_AUTO, var, rw ? CTLFLAG_RW : CTLFLAG_RD, ptr, 0, "") == NULL)
1314 snprintf(full, sizeof(full), "hw.%s.%s",
1315 device_get_nameunit(sc->dev), var);
1317 if ((val = getenv(full)) == NULL)
1319 u = strtoul(val, &end, 0);
1320 if (end == val || *end != '\0') {
1325 if_printf(&sc->ifatm.ifnet, "%s=%u\n", full, u);
1331 * Set configurable parameters. Many of these are configurable via
1335 hatm_configure(struct hatm_softc *sc)
1337 /* Receive buffer pool 0 small */
1338 kenv_getuint(sc, "rbps0_size", &sc->rbp_s0.size,
1339 HE_CONFIG_RBPS0_SIZE, 0);
1340 kenv_getuint(sc, "rbps0_thresh", &sc->rbp_s0.thresh,
1341 HE_CONFIG_RBPS0_THRESH, 0);
1342 sc->rbp_s0.bsize = MBUF0_SIZE;
1344 /* Receive buffer pool 0 large */
1345 kenv_getuint(sc, "rbpl0_size", &sc->rbp_l0.size,
1346 HE_CONFIG_RBPL0_SIZE, 0);
1347 kenv_getuint(sc, "rbpl0_thresh", &sc->rbp_l0.thresh,
1348 HE_CONFIG_RBPL0_THRESH, 0);
1349 sc->rbp_l0.bsize = MCLBYTES - MBUFL_OFFSET;
1351 /* Receive buffer return queue 0 */
1352 kenv_getuint(sc, "rbrq0_size", &sc->rbrq_0.size,
1353 HE_CONFIG_RBRQ0_SIZE, 0);
1354 kenv_getuint(sc, "rbrq0_thresh", &sc->rbrq_0.thresh,
1355 HE_CONFIG_RBRQ0_THRESH, 0);
1356 kenv_getuint(sc, "rbrq0_tout", &sc->rbrq_0.tout,
1357 HE_CONFIG_RBRQ0_TOUT, 0);
1358 kenv_getuint(sc, "rbrq0_pcnt", &sc->rbrq_0.pcnt,
1359 HE_CONFIG_RBRQ0_PCNT, 0);
1361 /* Receive buffer pool 1 small */
1362 kenv_getuint(sc, "rbps1_size", &sc->rbp_s1.size,
1363 HE_CONFIG_RBPS1_SIZE, 0);
1364 kenv_getuint(sc, "rbps1_thresh", &sc->rbp_s1.thresh,
1365 HE_CONFIG_RBPS1_THRESH, 0);
1366 sc->rbp_s1.bsize = MBUF1_SIZE;
1368 /* Receive buffer return queue 1 */
1369 kenv_getuint(sc, "rbrq1_size", &sc->rbrq_1.size,
1370 HE_CONFIG_RBRQ1_SIZE, 0);
1371 kenv_getuint(sc, "rbrq1_thresh", &sc->rbrq_1.thresh,
1372 HE_CONFIG_RBRQ1_THRESH, 0);
1373 kenv_getuint(sc, "rbrq1_tout", &sc->rbrq_1.tout,
1374 HE_CONFIG_RBRQ1_TOUT, 0);
1375 kenv_getuint(sc, "rbrq1_pcnt", &sc->rbrq_1.pcnt,
1376 HE_CONFIG_RBRQ1_PCNT, 0);
1378 /* Interrupt queue 0 */
1379 kenv_getuint(sc, "irq0_size", &sc->irq_0.size,
1380 HE_CONFIG_IRQ0_SIZE, 0);
1381 kenv_getuint(sc, "irq0_thresh", &sc->irq_0.thresh,
1382 HE_CONFIG_IRQ0_THRESH, 0);
1383 sc->irq_0.line = HE_CONFIG_IRQ0_LINE;
1385 /* Transmit buffer return queue 0 */
1386 kenv_getuint(sc, "tbrq0_size", &sc->tbrq.size,
1387 HE_CONFIG_TBRQ_SIZE, 0);
1388 kenv_getuint(sc, "tbrq0_thresh", &sc->tbrq.thresh,
1389 HE_CONFIG_TBRQ_THRESH, 0);
1391 /* Transmit buffer ready queue */
1392 kenv_getuint(sc, "tpdrq_size", &sc->tpdrq.size,
1393 HE_CONFIG_TPDRQ_SIZE, 0);
1394 /* Max TPDs per VCC */
1395 kenv_getuint(sc, "tpdmax", &sc->max_tpd,
1396 HE_CONFIG_TPD_MAXCC, 0);
1398 /* external mbuf pages */
1399 kenv_getuint(sc, "max_mbuf_pages", &sc->mbuf_max_pages,
1400 HE_CONFIG_MAX_MBUF_PAGES, 0);
1403 kenv_getuint(sc, "mpsafe", &sc->mpsafe, 0, 0);
1404 if (sc->mpsafe != 0)
1405 sc->mpsafe = INTR_MPSAFE;
1413 * Get TSRs from connection memory
1416 hatm_sysctl_tsr(SYSCTL_HANDLER_ARGS)
1418 struct hatm_softc *sc = arg1;
1422 val = malloc(sizeof(uint32_t) * HE_MAX_VCCS * 15, M_TEMP, M_WAITOK);
1425 for (i = 0; i < HE_MAX_VCCS; i++)
1426 for (j = 0; j <= 14; j++)
1427 val[15 * i + j] = READ_TSR(sc, i, j);
1428 mtx_unlock(&sc->mtx);
1430 error = SYSCTL_OUT(req, val, sizeof(uint32_t) * HE_MAX_VCCS * 15);
1432 if (error != 0 || req->newptr == NULL)
1439 * Get TPDs from connection memory
1442 hatm_sysctl_tpd(SYSCTL_HANDLER_ARGS)
1444 struct hatm_softc *sc = arg1;
1448 val = malloc(sizeof(uint32_t) * HE_MAX_VCCS * 16, M_TEMP, M_WAITOK);
1451 for (i = 0; i < HE_MAX_VCCS; i++)
1452 for (j = 0; j < 16; j++)
1453 val[16 * i + j] = READ_TCM4(sc, 16 * i + j);
1454 mtx_unlock(&sc->mtx);
1456 error = SYSCTL_OUT(req, val, sizeof(uint32_t) * HE_MAX_VCCS * 16);
1458 if (error != 0 || req->newptr == NULL)
1465 * Get mbox registers
1468 hatm_sysctl_mbox(SYSCTL_HANDLER_ARGS)
1470 struct hatm_softc *sc = arg1;
1474 val = malloc(sizeof(uint32_t) * HE_REGO_CS_END, M_TEMP, M_WAITOK);
1477 for (i = 0; i < HE_REGO_CS_END; i++)
1478 val[i] = READ_MBOX4(sc, i);
1479 mtx_unlock(&sc->mtx);
1481 error = SYSCTL_OUT(req, val, sizeof(uint32_t) * HE_REGO_CS_END);
1483 if (error != 0 || req->newptr == NULL)
1490 * Get connection memory
1493 hatm_sysctl_cm(SYSCTL_HANDLER_ARGS)
1495 struct hatm_softc *sc = arg1;
1499 val = malloc(sizeof(uint32_t) * (HE_CONFIG_RXMEM + 1), M_TEMP, M_WAITOK);
1502 val[0] = READ4(sc, HE_REGO_RCMABR_BA);
1503 for (i = 0; i < HE_CONFIG_RXMEM; i++)
1504 val[i + 1] = READ_RCM4(sc, i);
1505 mtx_unlock(&sc->mtx);
1507 error = SYSCTL_OUT(req, val, sizeof(uint32_t) * (HE_CONFIG_RXMEM + 1));
1509 if (error != 0 || req->newptr == NULL)
1516 * Get local buffer memory
1519 hatm_sysctl_lbmem(SYSCTL_HANDLER_ARGS)
1521 struct hatm_softc *sc = arg1;
1524 u_int bytes = (1 << 21);
1526 val = malloc(bytes, M_TEMP, M_WAITOK);
1529 for (i = 0; i < bytes / 4; i++)
1530 val[i] = READ_LB4(sc, i);
1531 mtx_unlock(&sc->mtx);
1533 error = SYSCTL_OUT(req, val, bytes);
1535 if (error != 0 || req->newptr == NULL)
1542 * Get all card registers
1545 hatm_sysctl_heregs(SYSCTL_HANDLER_ARGS)
1547 struct hatm_softc *sc = arg1;
1551 val = malloc(HE_REGO_END, M_TEMP, M_WAITOK);
1554 for (i = 0; i < HE_REGO_END; i += 4)
1555 val[i / 4] = READ4(sc, i);
1556 mtx_unlock(&sc->mtx);
1558 error = SYSCTL_OUT(req, val, HE_REGO_END);
1560 if (error != 0 || req->newptr == NULL)
1568 * Suni register access
1571 * read at most n SUNI registers starting at reg into val
1574 hatm_utopia_readregs(struct ifatm *ifatm, u_int reg, uint8_t *val, u_int *n)
1577 struct hatm_softc *sc = (struct hatm_softc *)ifatm;
1579 if (reg >= (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4)
1581 if (reg + *n > (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4)
1582 *n = reg - (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4;
1584 mtx_assert(&sc->mtx, MA_OWNED);
1585 for (i = 0; i < *n; i++)
1586 val[i] = READ4(sc, HE_REGO_SUNI + 4 * (reg + i));
1592 * change the bits given by mask to them in val in register reg
1595 hatm_utopia_writereg(struct ifatm *ifatm, u_int reg, u_int mask, u_int val)
1598 struct hatm_softc *sc = (struct hatm_softc *)ifatm;
1600 if (reg >= (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4)
1603 mtx_assert(&sc->mtx, MA_OWNED);
1604 regval = READ4(sc, HE_REGO_SUNI + 4 * reg);
1605 regval = (regval & ~mask) | (val & mask);
1606 WRITE4(sc, HE_REGO_SUNI + 4 * reg, regval);
1611 static struct utopia_methods hatm_utopia_methods = {
1612 hatm_utopia_readregs,
1613 hatm_utopia_writereg,
1617 * Detach - if it is running, stop. Destroy.
1620 hatm_detach(device_t dev)
1622 struct hatm_softc *sc = (struct hatm_softc *)device_get_softc(dev);
1626 if (sc->utopia.state & UTP_ST_ATTACHED) {
1627 utopia_stop(&sc->utopia);
1628 utopia_detach(&sc->utopia);
1630 mtx_unlock(&sc->mtx);
1632 atm_ifdetach(&sc->ifatm.ifnet);
1640 * Attach to the device. Assume that no locking is needed here.
1641 * All resource we allocate here are freed by calling hatm_destroy.
1644 hatm_attach(device_t dev)
1646 struct hatm_softc *sc;
1651 sc = device_get_softc(dev);
1654 sc->ifatm.mib.device = ATM_DEVICE_HE155;
1655 sc->ifatm.mib.serial = 0;
1656 sc->ifatm.mib.hw_version = 0;
1657 sc->ifatm.mib.sw_version = 0;
1658 sc->ifatm.mib.vpi_bits = HE_CONFIG_VPI_BITS;
1659 sc->ifatm.mib.vci_bits = HE_CONFIG_VCI_BITS;
1660 sc->ifatm.mib.max_vpcs = 0;
1661 sc->ifatm.mib.max_vccs = HE_MAX_VCCS;
1662 sc->ifatm.mib.media = IFM_ATM_UNKNOWN;
1664 sc->ifatm.phy = &sc->utopia;
1666 SLIST_INIT(&sc->tpd_free);
1668 mtx_init(&sc->mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF);
1669 cv_init(&sc->vcc_cv, "HEVCCcv");
1670 cv_init(&sc->cv_rcclose, "RCClose");
1672 sysctl_ctx_init(&sc->sysctl_ctx);
1675 * 4.2 BIOS Configuration
1677 v = pci_read_config(dev, PCIR_COMMAND, 2);
1678 v |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
1679 pci_write_config(dev, PCIR_COMMAND, v, 2);
1682 * 4.3 PCI Bus Controller-Specific Initialisation
1684 v = pci_read_config(dev, HE_PCIR_GEN_CNTL_0, 4);
1685 v |= HE_PCIM_CTL0_MRL | HE_PCIM_CTL0_MRM | HE_PCIM_CTL0_IGNORE_TIMEOUT;
1686 #if BYTE_ORDER == BIG_ENDIAN && 0
1687 v |= HE_PCIM_CTL0_BIGENDIAN;
1689 pci_write_config(dev, HE_PCIR_GEN_CNTL_0, v, 4);
1694 v = pci_read_config(dev, PCIR_COMMAND, 2);
1695 if (!(v & PCIM_CMD_MEMEN)) {
1696 device_printf(dev, "failed to enable memory\n");
1700 sc->memid = PCIR_BAR(0);
1701 sc->memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->memid,
1703 if (sc->memres == NULL) {
1704 device_printf(dev, "could not map memory\n");
1708 sc->memh = rman_get_bushandle(sc->memres);
1709 sc->memt = rman_get_bustag(sc->memres);
1712 * ALlocate a DMA tag for subsequent allocations
1714 if (bus_dma_tag_create(NULL, 1, 0,
1715 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
1717 BUS_SPACE_MAXSIZE_32BIT, 1,
1718 BUS_SPACE_MAXSIZE_32BIT, 0,
1719 NULL, NULL, &sc->parent_tag)) {
1720 device_printf(dev, "could not allocate DMA tag\n");
1725 if (bus_dma_tag_create(sc->parent_tag, 1, 0,
1726 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
1730 NULL, NULL, &sc->mbuf_tag)) {
1731 device_printf(dev, "could not allocate mbuf DMA tag\n");
1737 * Allocate a DMA tag for packets to send. Here we have a problem with
1738 * the specification of the maximum number of segments. Theoretically
1739 * this would be the size of the transmit ring - 1 multiplied by 3,
1740 * but this would not work. So make the maximum number of TPDs
1741 * occupied by one packet a configuration parameter.
1743 if (bus_dma_tag_create(NULL, 1, 0,
1744 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1745 HE_MAX_PDU, 3 * HE_CONFIG_MAX_TPD_PER_PACKET, HE_MAX_PDU, 0,
1746 NULL, NULL, &sc->tx_tag)) {
1747 device_printf(dev, "could not allocate TX tag\n");
1753 * Setup the interrupt
1756 sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
1757 RF_SHAREABLE | RF_ACTIVE);
1758 if (sc->irqres == 0) {
1759 device_printf(dev, "could not allocate irq\n");
1764 ifp = &sc->ifatm.ifnet;
1766 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1769 * Make the sysctl tree
1772 if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
1773 SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO,
1774 device_get_nameunit(dev), CTLFLAG_RD, 0, "")) == NULL)
1777 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
1778 OID_AUTO, "istats", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, CTL_ISTATS,
1779 hatm_sysctl, "LU", "internal statistics") == NULL)
1783 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
1784 OID_AUTO, "tsr", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
1785 hatm_sysctl_tsr, "S", "transmission status registers") == NULL)
1788 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
1789 OID_AUTO, "tpd", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
1790 hatm_sysctl_tpd, "S", "transmission packet descriptors") == NULL)
1793 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
1794 OID_AUTO, "mbox", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
1795 hatm_sysctl_mbox, "S", "mbox registers") == NULL)
1798 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
1799 OID_AUTO, "cm", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
1800 hatm_sysctl_cm, "S", "connection memory") == NULL)
1803 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
1804 OID_AUTO, "heregs", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
1805 hatm_sysctl_heregs, "S", "card registers") == NULL)
1808 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
1809 OID_AUTO, "lbmem", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
1810 hatm_sysctl_lbmem, "S", "local memory") == NULL)
1813 kenv_getuint(sc, "debug", &sc->debug, HATM_DEBUG, 1);
1819 if ((error = hatm_configure(sc)) != 0)
1823 * Compute memory parameters
1825 if (sc->rbp_s0.size != 0) {
1826 sc->rbp_s0.mask = (sc->rbp_s0.size - 1) << 3;
1827 sc->rbp_s0.mem.size = sc->rbp_s0.size * 8;
1828 sc->rbp_s0.mem.align = sc->rbp_s0.mem.size;
1830 if (sc->rbp_l0.size != 0) {
1831 sc->rbp_l0.mask = (sc->rbp_l0.size - 1) << 3;
1832 sc->rbp_l0.mem.size = sc->rbp_l0.size * 8;
1833 sc->rbp_l0.mem.align = sc->rbp_l0.mem.size;
1835 if (sc->rbp_s1.size != 0) {
1836 sc->rbp_s1.mask = (sc->rbp_s1.size - 1) << 3;
1837 sc->rbp_s1.mem.size = sc->rbp_s1.size * 8;
1838 sc->rbp_s1.mem.align = sc->rbp_s1.mem.size;
1840 if (sc->rbrq_0.size != 0) {
1841 sc->rbrq_0.mem.size = sc->rbrq_0.size * 8;
1842 sc->rbrq_0.mem.align = sc->rbrq_0.mem.size;
1844 if (sc->rbrq_1.size != 0) {
1845 sc->rbrq_1.mem.size = sc->rbrq_1.size * 8;
1846 sc->rbrq_1.mem.align = sc->rbrq_1.mem.size;
1849 sc->irq_0.mem.size = sc->irq_0.size * sizeof(uint32_t);
1850 sc->irq_0.mem.align = 4 * 1024;
1852 sc->tbrq.mem.size = sc->tbrq.size * 4;
1853 sc->tbrq.mem.align = 2 * sc->tbrq.mem.size; /* ZZZ */
1855 sc->tpdrq.mem.size = sc->tpdrq.size * 8;
1856 sc->tpdrq.mem.align = sc->tpdrq.mem.size;
1858 sc->hsp_mem.size = sizeof(struct he_hsp);
1859 sc->hsp_mem.align = 1024;
1861 sc->lbufs_size = sc->rbp_l0.size + sc->rbrq_0.size;
1862 sc->tpd_total = sc->tbrq.size + sc->tpdrq.size;
1863 sc->tpds.align = 64;
1864 sc->tpds.size = sc->tpd_total * HE_TPD_SIZE;
1866 hatm_init_rmaps(sc);
1867 hatm_init_smbufs(sc);
1868 if ((error = hatm_init_tpds(sc)) != 0)
1874 if ((error = hatm_alloc_dmamem(sc, "IRQ", &sc->irq_0.mem)) != 0 ||
1875 (error = hatm_alloc_dmamem(sc, "TBRQ0", &sc->tbrq.mem)) != 0 ||
1876 (error = hatm_alloc_dmamem(sc, "TPDRQ", &sc->tpdrq.mem)) != 0 ||
1877 (error = hatm_alloc_dmamem(sc, "HSP", &sc->hsp_mem)) != 0)
1880 if (sc->rbp_s0.mem.size != 0 &&
1881 (error = hatm_alloc_dmamem(sc, "RBPS0", &sc->rbp_s0.mem)))
1883 if (sc->rbp_l0.mem.size != 0 &&
1884 (error = hatm_alloc_dmamem(sc, "RBPL0", &sc->rbp_l0.mem)))
1886 if (sc->rbp_s1.mem.size != 0 &&
1887 (error = hatm_alloc_dmamem(sc, "RBPS1", &sc->rbp_s1.mem)))
1890 if (sc->rbrq_0.mem.size != 0 &&
1891 (error = hatm_alloc_dmamem(sc, "RBRQ0", &sc->rbrq_0.mem)))
1893 if (sc->rbrq_1.mem.size != 0 &&
1894 (error = hatm_alloc_dmamem(sc, "RBRQ1", &sc->rbrq_1.mem)))
1897 if ((sc->vcc_zone = uma_zcreate("HE vccs", sizeof(struct hevcc),
1898 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0)) == NULL) {
1899 device_printf(dev, "cannot allocate zone for vccs\n");
1904 * 4.4 Reset the card.
1906 if ((error = hatm_reset(sc)) != 0)
1912 hatm_init_bus_width(sc);
1913 hatm_init_read_eeprom(sc);
1914 hatm_init_endianess(sc);
1917 * Initialize interface
1919 ifp->if_flags = IFF_SIMPLEX;
1920 ifp->if_ioctl = hatm_ioctl;
1921 ifp->if_start = hatm_start;
1922 ifp->if_watchdog = NULL;
1923 ifp->if_init = hatm_init;
1925 utopia_attach(&sc->utopia, &sc->ifatm, &sc->media, &sc->mtx,
1926 &sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
1927 &hatm_utopia_methods);
1928 utopia_init_media(&sc->utopia);
1930 /* these two SUNI routines need the lock */
1932 /* poll while we are not running */
1933 sc->utopia.flags |= UTP_FL_POLL_CARRIER;
1934 utopia_start(&sc->utopia);
1935 utopia_reset(&sc->utopia);
1936 mtx_unlock(&sc->mtx);
1941 bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
1944 error = bus_setup_intr(dev, sc->irqres, sc->mpsafe | INTR_TYPE_NET,
1945 hatm_intr, &sc->irq_0, &sc->ih);
1947 device_printf(dev, "could not setup interrupt\n");
1960 * Start the interface. Assume a state as from attach().
1963 hatm_initialize(struct hatm_softc *sc)
1967 static const u_int layout[2][7] = HE_CONFIG_MEM_LAYOUT;
1969 if (sc->ifatm.ifnet.if_flags & IFF_RUNNING)
1972 hatm_init_bus_width(sc);
1973 hatm_init_endianess(sc);
1975 if_printf(&sc->ifatm.ifnet, "%s, Rev. %s, S/N %u, "
1976 "MAC=%02x:%02x:%02x:%02x:%02x:%02x (%ubit PCI)\n",
1977 sc->prod_id, sc->rev, sc->ifatm.mib.serial,
1978 sc->ifatm.mib.esi[0], sc->ifatm.mib.esi[1], sc->ifatm.mib.esi[2],
1979 sc->ifatm.mib.esi[3], sc->ifatm.mib.esi[4], sc->ifatm.mib.esi[5],
1980 sc->pci64 ? 64 : 32);
1983 * 4.8 SDRAM Controller Initialisation
1984 * 4.9 Initialize RNUM value
1987 WRITE4(sc, HE_REGO_SDRAM_CNTL, HE_REGM_SDRAM_64BIT);
1989 WRITE4(sc, HE_REGO_SDRAM_CNTL, 0);
1992 v = READ4(sc, HE_REGO_LB_SWAP);
1994 v |= 0xf << HE_REGS_LBSWAP_RNUM;
1995 WRITE4(sc, HE_REGO_LB_SWAP, v);
1998 hatm_init_irq(sc, &sc->irq_0, 0);
1999 hatm_clear_irq(sc, 1);
2000 hatm_clear_irq(sc, 2);
2001 hatm_clear_irq(sc, 3);
2003 WRITE4(sc, HE_REGO_GRP_1_0_MAP, 0);
2004 WRITE4(sc, HE_REGO_GRP_3_2_MAP, 0);
2005 WRITE4(sc, HE_REGO_GRP_5_4_MAP, 0);
2006 WRITE4(sc, HE_REGO_GRP_7_6_MAP, 0);
2010 * 4.11 Enable PCI Bus Controller State Machine
2012 v = READ4(sc, HE_REGO_HOST_CNTL);
2014 v |= HE_REGM_HOST_OUTFF_ENB | HE_REGM_HOST_CMDFF_ENB |
2015 HE_REGM_HOST_QUICK_RD | HE_REGM_HOST_QUICK_WR;
2016 WRITE4(sc, HE_REGO_HOST_CNTL, v);
2020 * 5.1.1 Generic configuration state
2022 sc->cells_per_row = layout[sc->he622][0];
2023 sc->bytes_per_row = layout[sc->he622][1];
2024 sc->r0_numrows = layout[sc->he622][2];
2025 sc->tx_numrows = layout[sc->he622][3];
2026 sc->r1_numrows = layout[sc->he622][4];
2027 sc->r0_startrow = layout[sc->he622][5];
2028 sc->tx_startrow = sc->r0_startrow + sc->r0_numrows;
2029 sc->r1_startrow = sc->tx_startrow + sc->tx_numrows;
2030 sc->cells_per_lbuf = layout[sc->he622][6];
2032 sc->r0_numbuffs = sc->r0_numrows * (sc->cells_per_row /
2033 sc->cells_per_lbuf);
2034 sc->r1_numbuffs = sc->r1_numrows * (sc->cells_per_row /
2035 sc->cells_per_lbuf);
2036 sc->tx_numbuffs = sc->tx_numrows * (sc->cells_per_row /
2037 sc->cells_per_lbuf);
2039 if (sc->r0_numbuffs > 2560)
2040 sc->r0_numbuffs = 2560;
2041 if (sc->r1_numbuffs > 2560)
2042 sc->r1_numbuffs = 2560;
2043 if (sc->tx_numbuffs > 5120)
2044 sc->tx_numbuffs = 5120;
2046 DBG(sc, ATTACH, ("cells_per_row=%u bytes_per_row=%u r0_numrows=%u "
2047 "tx_numrows=%u r1_numrows=%u r0_startrow=%u tx_startrow=%u "
2048 "r1_startrow=%u cells_per_lbuf=%u\nr0_numbuffs=%u r1_numbuffs=%u "
2049 "tx_numbuffs=%u\n", sc->cells_per_row, sc->bytes_per_row,
2050 sc->r0_numrows, sc->tx_numrows, sc->r1_numrows, sc->r0_startrow,
2051 sc->tx_startrow, sc->r1_startrow, sc->cells_per_lbuf,
2052 sc->r0_numbuffs, sc->r1_numbuffs, sc->tx_numbuffs));
2055 * 5.1.2 Configure Hardware dependend registers
2058 WRITE4(sc, HE_REGO_LBARB,
2059 (0x2 << HE_REGS_LBARB_SLICE) |
2060 (0xf << HE_REGS_LBARB_RNUM) |
2061 (0x3 << HE_REGS_LBARB_THPRI) |
2062 (0x3 << HE_REGS_LBARB_RHPRI) |
2063 (0x2 << HE_REGS_LBARB_TLPRI) |
2064 (0x1 << HE_REGS_LBARB_RLPRI) |
2065 (0x28 << HE_REGS_LBARB_BUS_MULT) |
2066 (0x50 << HE_REGS_LBARB_NET_PREF));
2068 WRITE4(sc, HE_REGO_SDRAMCON,
2069 /* HW bug: don't use banking */
2070 /* HE_REGM_SDRAMCON_BANK | */
2071 HE_REGM_SDRAMCON_WIDE |
2072 (0x384 << HE_REGS_SDRAMCON_REF));
2074 WRITE4(sc, HE_REGO_RCMCONFIG,
2075 (0x1 << HE_REGS_RCMCONFIG_BANK_WAIT) |
2076 (0x1 << HE_REGS_RCMCONFIG_RW_WAIT) |
2077 (0x0 << HE_REGS_RCMCONFIG_TYPE));
2078 WRITE4(sc, HE_REGO_TCMCONFIG,
2079 (0x2 << HE_REGS_TCMCONFIG_BANK_WAIT) |
2080 (0x1 << HE_REGS_TCMCONFIG_RW_WAIT) |
2081 (0x0 << HE_REGS_TCMCONFIG_TYPE));
2083 WRITE4(sc, HE_REGO_LBARB,
2084 (0x2 << HE_REGS_LBARB_SLICE) |
2085 (0xf << HE_REGS_LBARB_RNUM) |
2086 (0x3 << HE_REGS_LBARB_THPRI) |
2087 (0x3 << HE_REGS_LBARB_RHPRI) |
2088 (0x2 << HE_REGS_LBARB_TLPRI) |
2089 (0x1 << HE_REGS_LBARB_RLPRI) |
2090 (0x46 << HE_REGS_LBARB_BUS_MULT) |
2091 (0x8C << HE_REGS_LBARB_NET_PREF));
2093 WRITE4(sc, HE_REGO_SDRAMCON,
2094 /* HW bug: don't use banking */
2095 /* HE_REGM_SDRAMCON_BANK | */
2096 (0x150 << HE_REGS_SDRAMCON_REF));
2098 WRITE4(sc, HE_REGO_RCMCONFIG,
2099 (0x0 << HE_REGS_RCMCONFIG_BANK_WAIT) |
2100 (0x1 << HE_REGS_RCMCONFIG_RW_WAIT) |
2101 (0x0 << HE_REGS_RCMCONFIG_TYPE));
2102 WRITE4(sc, HE_REGO_TCMCONFIG,
2103 (0x1 << HE_REGS_TCMCONFIG_BANK_WAIT) |
2104 (0x1 << HE_REGS_TCMCONFIG_RW_WAIT) |
2105 (0x0 << HE_REGS_TCMCONFIG_TYPE));
2107 WRITE4(sc, HE_REGO_LBCONFIG, (sc->cells_per_lbuf * 48));
2109 WRITE4(sc, HE_REGO_RLBC_H, 0);
2110 WRITE4(sc, HE_REGO_RLBC_T, 0);
2111 WRITE4(sc, HE_REGO_RLBC_H2, 0);
2113 WRITE4(sc, HE_REGO_RXTHRSH, 512);
2114 WRITE4(sc, HE_REGO_LITHRSH, 256);
2116 WRITE4(sc, HE_REGO_RLBF0_C, sc->r0_numbuffs);
2117 WRITE4(sc, HE_REGO_RLBF1_C, sc->r1_numbuffs);
2120 WRITE4(sc, HE_REGO_RCCONFIG,
2121 (8 << HE_REGS_RCCONFIG_UTDELAY) |
2122 (sc->ifatm.mib.vpi_bits << HE_REGS_RCCONFIG_VP) |
2123 (sc->ifatm.mib.vci_bits << HE_REGS_RCCONFIG_VC));
2124 WRITE4(sc, HE_REGO_TXCONFIG,
2125 (32 << HE_REGS_TXCONFIG_THRESH) |
2126 (sc->ifatm.mib.vci_bits << HE_REGS_TXCONFIG_VCI_MASK) |
2127 (sc->tx_numbuffs << HE_REGS_TXCONFIG_LBFREE));
2129 WRITE4(sc, HE_REGO_RCCONFIG,
2130 (0 << HE_REGS_RCCONFIG_UTDELAY) |
2131 HE_REGM_RCCONFIG_UT_MODE |
2132 (sc->ifatm.mib.vpi_bits << HE_REGS_RCCONFIG_VP) |
2133 (sc->ifatm.mib.vci_bits << HE_REGS_RCCONFIG_VC));
2134 WRITE4(sc, HE_REGO_TXCONFIG,
2135 (32 << HE_REGS_TXCONFIG_THRESH) |
2136 HE_REGM_TXCONFIG_UTMODE |
2137 (sc->ifatm.mib.vci_bits << HE_REGS_TXCONFIG_VCI_MASK) |
2138 (sc->tx_numbuffs << HE_REGS_TXCONFIG_LBFREE));
2141 WRITE4(sc, HE_REGO_TXAAL5_PROTO, 0);
2143 if (sc->rbp_s1.size != 0) {
2144 WRITE4(sc, HE_REGO_RHCONFIG,
2145 HE_REGM_RHCONFIG_PHYENB |
2146 ((sc->he622 ? 0x41 : 0x31) << HE_REGS_RHCONFIG_PTMR_PRE) |
2147 (1 << HE_REGS_RHCONFIG_OAM_GID));
2149 WRITE4(sc, HE_REGO_RHCONFIG,
2150 HE_REGM_RHCONFIG_PHYENB |
2151 ((sc->he622 ? 0x41 : 0x31) << HE_REGS_RHCONFIG_PTMR_PRE) |
2152 (0 << HE_REGS_RHCONFIG_OAM_GID));
2158 hatm_init_rx_buffer_pool(sc, 0, sc->r0_startrow, sc->r0_numbuffs);
2159 hatm_init_rx_buffer_pool(sc, 1, sc->r1_startrow, sc->r1_numbuffs);
2160 hatm_init_tx_buffer_pool(sc, sc->tx_startrow, sc->tx_numbuffs);
2162 hatm_init_imed_queues(sc);
2165 * 5.1.6 Application tunable Parameters
2167 WRITE4(sc, HE_REGO_MCC, 0);
2168 WRITE4(sc, HE_REGO_OEC, 0);
2169 WRITE4(sc, HE_REGO_DCC, 0);
2170 WRITE4(sc, HE_REGO_CEC, 0);
2172 hatm_init_cs_block(sc);
2173 hatm_init_cs_block_cm(sc);
2175 hatm_init_rpool(sc, &sc->rbp_s0, 0, 0);
2176 hatm_init_rpool(sc, &sc->rbp_l0, 0, 1);
2177 hatm_init_rpool(sc, &sc->rbp_s1, 1, 0);
2178 hatm_clear_rpool(sc, 1, 1);
2179 hatm_clear_rpool(sc, 2, 0);
2180 hatm_clear_rpool(sc, 2, 1);
2181 hatm_clear_rpool(sc, 3, 0);
2182 hatm_clear_rpool(sc, 3, 1);
2183 hatm_clear_rpool(sc, 4, 0);
2184 hatm_clear_rpool(sc, 4, 1);
2185 hatm_clear_rpool(sc, 5, 0);
2186 hatm_clear_rpool(sc, 5, 1);
2187 hatm_clear_rpool(sc, 6, 0);
2188 hatm_clear_rpool(sc, 6, 1);
2189 hatm_clear_rpool(sc, 7, 0);
2190 hatm_clear_rpool(sc, 7, 1);
2191 hatm_init_rbrq(sc, &sc->rbrq_0, 0);
2192 hatm_init_rbrq(sc, &sc->rbrq_1, 1);
2193 hatm_clear_rbrq(sc, 2);
2194 hatm_clear_rbrq(sc, 3);
2195 hatm_clear_rbrq(sc, 4);
2196 hatm_clear_rbrq(sc, 5);
2197 hatm_clear_rbrq(sc, 6);
2198 hatm_clear_rbrq(sc, 7);
2201 bzero(sc->lbufs, sizeof(sc->lbufs[0]) * sc->lbufs_size);
2203 hatm_init_tbrq(sc, &sc->tbrq, 0);
2204 hatm_clear_tbrq(sc, 1);
2205 hatm_clear_tbrq(sc, 2);
2206 hatm_clear_tbrq(sc, 3);
2207 hatm_clear_tbrq(sc, 4);
2208 hatm_clear_tbrq(sc, 5);
2209 hatm_clear_tbrq(sc, 6);
2210 hatm_clear_tbrq(sc, 7);
2212 hatm_init_tpdrq(sc);
2214 WRITE4(sc, HE_REGO_UBUFF_BA, (sc->he622 ? 0x104780 : 0x800));
2219 bzero(sc->hsp_mem.base, sc->hsp_mem.size);
2220 sc->hsp = sc->hsp_mem.base;
2221 WRITE4(sc, HE_REGO_HSP_BA, sc->hsp_mem.paddr);
2224 * 5.1.12 Enable transmit and receive
2225 * Enable bus master and interrupts
2227 v = READ_MBOX4(sc, HE_REGO_CS_ERCTL0);
2229 WRITE_MBOX4(sc, HE_REGO_CS_ERCTL0, v);
2231 v = READ4(sc, HE_REGO_RCCONFIG);
2232 v |= HE_REGM_RCCONFIG_RXENB;
2233 WRITE4(sc, HE_REGO_RCCONFIG, v);
2235 v = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4);
2236 v |= HE_PCIM_CTL0_INIT_ENB | HE_PCIM_CTL0_INT_PROC_ENB;
2237 pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v, 4);
2239 sc->ifatm.ifnet.if_flags |= IFF_RUNNING;
2240 sc->ifatm.ifnet.if_baudrate = 53 * 8 * sc->ifatm.mib.pcr;
2242 sc->utopia.flags &= ~UTP_FL_POLL_CARRIER;
2245 for (cid = 0; cid < HE_MAX_VCCS; cid++)
2246 if (sc->vccs[cid] != NULL)
2247 hatm_load_vc(sc, cid, 1);
2249 ATMEV_SEND_IFSTATE_CHANGED(&sc->ifatm,
2250 sc->utopia.carrier == UTP_CARR_OK);
2254 * This functions stops the card and frees all resources allocated after
2255 * the attach. Must have the global lock.
2258 hatm_stop(struct hatm_softc *sc)
2262 struct mbuf_chunk_hdr *ch;
2263 struct mbuf_page *pg;
2265 mtx_assert(&sc->mtx, MA_OWNED);
2267 if (!(sc->ifatm.ifnet.if_flags & IFF_RUNNING))
2269 sc->ifatm.ifnet.if_flags &= ~IFF_RUNNING;
2271 ATMEV_SEND_IFSTATE_CHANGED(&sc->ifatm,
2272 sc->utopia.carrier == UTP_CARR_OK);
2274 sc->utopia.flags |= UTP_FL_POLL_CARRIER;
2277 * Stop and reset the hardware so that everything remains
2280 v = READ_MBOX4(sc, HE_REGO_CS_ERCTL0);
2282 WRITE_MBOX4(sc, HE_REGO_CS_ERCTL0, v);
2284 v = READ4(sc, HE_REGO_RCCONFIG);
2285 v &= ~HE_REGM_RCCONFIG_RXENB;
2286 WRITE4(sc, HE_REGO_RCCONFIG, v);
2288 WRITE4(sc, HE_REGO_RHCONFIG, (0x2 << HE_REGS_RHCONFIG_PTMR_PRE));
2291 v = READ4(sc, HE_REGO_HOST_CNTL);
2293 v &= ~(HE_REGM_HOST_OUTFF_ENB | HE_REGM_HOST_CMDFF_ENB);
2294 WRITE4(sc, HE_REGO_HOST_CNTL, v);
2298 * Disable bust master and interrupts
2300 v = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4);
2301 v &= ~(HE_PCIM_CTL0_INIT_ENB | HE_PCIM_CTL0_INT_PROC_ENB);
2302 pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v, 4);
2304 (void)hatm_reset(sc);
2307 * Card resets the SUNI when resetted, so re-initialize it
2309 utopia_reset(&sc->utopia);
2312 * Give any waiters on closing a VCC a chance. They will stop
2313 * to wait if they see that IFF_RUNNING disappeared.
2315 cv_broadcast(&sc->vcc_cv);
2316 cv_broadcast(&sc->cv_rcclose);
2319 * Now free all resources.
2323 * Free the large mbufs that are given to the card.
2325 for (i = 0 ; i < sc->lbufs_size; i++) {
2326 if (sc->lbufs[i] != NULL) {
2327 bus_dmamap_unload(sc->mbuf_tag, sc->rmaps[i]);
2328 m_freem(sc->lbufs[i]);
2329 sc->lbufs[i] = NULL;
2334 * Free small buffers
2336 for (p = 0; p < sc->mbuf_npages; p++) {
2337 pg = sc->mbuf_pages[p];
2338 for (i = 0; i < pg->hdr.nchunks; i++) {
2339 ch = (struct mbuf_chunk_hdr *) ((char *)pg +
2340 i * pg->hdr.chunksize + pg->hdr.hdroff);
2341 if (ch->flags & MBUF_CARD) {
2342 ch->flags &= ~MBUF_CARD;
2343 ch->flags |= MBUF_USED;
2344 hatm_ext_free(&sc->mbuf_list[pg->hdr.pool],
2345 (struct mbufx_free *)((u_char *)ch -
2354 * Free all partial reassembled PDUs on any VCC.
2356 for (cid = 0; cid < HE_MAX_VCCS; cid++) {
2357 if (sc->vccs[cid] != NULL) {
2358 if (sc->vccs[cid]->chain != NULL) {
2359 m_freem(sc->vccs[cid]->chain);
2360 sc->vccs[cid]->chain = NULL;
2361 sc->vccs[cid]->last = NULL;
2363 if (!(sc->vccs[cid]->vflags & (HE_VCC_RX_OPEN |
2365 hatm_tx_vcc_closed(sc, cid);
2366 uma_zfree(sc->vcc_zone, sc->vccs[cid]);
2367 sc->vccs[cid] = NULL;
2370 sc->vccs[cid]->vflags = 0;
2371 sc->vccs[cid]->ntpds = 0;
2376 if (sc->rbp_s0.size != 0)
2377 bzero(sc->rbp_s0.mem.base, sc->rbp_s0.mem.size);
2378 if (sc->rbp_l0.size != 0)
2379 bzero(sc->rbp_l0.mem.base, sc->rbp_l0.mem.size);
2380 if (sc->rbp_s1.size != 0)
2381 bzero(sc->rbp_s1.mem.base, sc->rbp_s1.mem.size);
2382 if (sc->rbrq_0.size != 0)
2383 bzero(sc->rbrq_0.mem.base, sc->rbrq_0.mem.size);
2384 if (sc->rbrq_1.size != 0)
2385 bzero(sc->rbrq_1.mem.base, sc->rbrq_1.mem.size);
2387 bzero(sc->tbrq.mem.base, sc->tbrq.mem.size);
2388 bzero(sc->tpdrq.mem.base, sc->tpdrq.mem.size);
2389 bzero(sc->hsp_mem.base, sc->hsp_mem.size);
2392 /************************************************************
2394 * Driver infrastructure
2396 devclass_t hatm_devclass;
2398 static device_method_t hatm_methods[] = {
2399 DEVMETHOD(device_probe, hatm_probe),
2400 DEVMETHOD(device_attach, hatm_attach),
2401 DEVMETHOD(device_detach, hatm_detach),
2404 static driver_t hatm_driver = {
2407 sizeof(struct hatm_softc),
2409 DRIVER_MODULE(hatm, pci, hatm_driver, hatm_devclass, NULL, 0);