1*06998a74Sthorpej /* $NetBSD: depca_eisa.c,v 1.17 2021/07/24 19:14:35 thorpej Exp $ */
28cb7deb8Sthorpej
38cb7deb8Sthorpej /*-
48cb7deb8Sthorpej * Copyright (c) 2000 The NetBSD Foundation, Inc.
58cb7deb8Sthorpej * All rights reserved.
68cb7deb8Sthorpej *
78cb7deb8Sthorpej * This code is derived from software contributed to The NetBSD Foundation
88cb7deb8Sthorpej * by Jason R. Thorpe.
98cb7deb8Sthorpej *
108cb7deb8Sthorpej * Redistribution and use in source and binary forms, with or without
118cb7deb8Sthorpej * modification, are permitted provided that the following conditions
128cb7deb8Sthorpej * are met:
138cb7deb8Sthorpej * 1. Redistributions of source code must retain the above copyright
148cb7deb8Sthorpej * notice, this list of conditions and the following disclaimer.
158cb7deb8Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
168cb7deb8Sthorpej * notice, this list of conditions and the following disclaimer in the
178cb7deb8Sthorpej * documentation and/or other materials provided with the distribution.
188cb7deb8Sthorpej *
198cb7deb8Sthorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
208cb7deb8Sthorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
218cb7deb8Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
228cb7deb8Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
238cb7deb8Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
248cb7deb8Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
258cb7deb8Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
268cb7deb8Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
278cb7deb8Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
288cb7deb8Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
298cb7deb8Sthorpej * POSSIBILITY OF SUCH DAMAGE.
308cb7deb8Sthorpej */
318cb7deb8Sthorpej
328cb7deb8Sthorpej /*
338cb7deb8Sthorpej * EISA bus front-end for the Digital DEPCA Ethernet controller.
348cb7deb8Sthorpej */
358cb7deb8Sthorpej
36b84f53efSlukem #include <sys/cdefs.h>
37*06998a74Sthorpej __KERNEL_RCSID(0, "$NetBSD: depca_eisa.c,v 1.17 2021/07/24 19:14:35 thorpej Exp $");
38b84f53efSlukem
398cb7deb8Sthorpej #include "opt_inet.h"
408cb7deb8Sthorpej
418cb7deb8Sthorpej #include <sys/param.h>
428cb7deb8Sthorpej #include <sys/systm.h>
438cb7deb8Sthorpej #include <sys/mbuf.h>
448cb7deb8Sthorpej #include <sys/syslog.h>
458cb7deb8Sthorpej #include <sys/socket.h>
468cb7deb8Sthorpej #include <sys/device.h>
478cb7deb8Sthorpej
488cb7deb8Sthorpej #include <net/if.h>
498cb7deb8Sthorpej #include <net/if_media.h>
508cb7deb8Sthorpej #include <net/if_ether.h>
518cb7deb8Sthorpej
528cb7deb8Sthorpej #ifdef INET
538cb7deb8Sthorpej #include <netinet/in.h>
548cb7deb8Sthorpej #include <netinet/if_inarp.h>
558cb7deb8Sthorpej #endif
568cb7deb8Sthorpej
57a2a38285Sad #include <sys/bus.h>
58a2a38285Sad #include <sys/intr.h>
598cb7deb8Sthorpej
608cb7deb8Sthorpej #include <dev/eisa/eisareg.h>
618cb7deb8Sthorpej #include <dev/eisa/eisavar.h>
628cb7deb8Sthorpej #include <dev/eisa/eisadevs.h>
638cb7deb8Sthorpej
648cb7deb8Sthorpej #include <dev/ic/lancereg.h>
658cb7deb8Sthorpej #include <dev/ic/lancevar.h>
668cb7deb8Sthorpej #include <dev/ic/am7990reg.h>
678cb7deb8Sthorpej #include <dev/ic/am7990var.h>
688cb7deb8Sthorpej #include <dev/ic/depcareg.h>
698cb7deb8Sthorpej #include <dev/ic/depcavar.h>
708cb7deb8Sthorpej
71d9941582Stsutsui static int depca_eisa_match(device_t, cfdata_t, void *);
72d9941582Stsutsui static void depca_eisa_attach(device_t, device_t, void *);
738cb7deb8Sthorpej
748cb7deb8Sthorpej struct depca_eisa_softc {
758cb7deb8Sthorpej struct depca_softc sc_depca;
768cb7deb8Sthorpej
778cb7deb8Sthorpej eisa_chipset_tag_t sc_ec;
788cb7deb8Sthorpej int sc_irq;
798cb7deb8Sthorpej int sc_ist;
808cb7deb8Sthorpej };
818cb7deb8Sthorpej
82d9941582Stsutsui CFATTACH_DECL_NEW(depca_eisa, sizeof(struct depca_eisa_softc),
83c9b3657cSthorpej depca_eisa_match, depca_eisa_attach, NULL, NULL);
848cb7deb8Sthorpej
853e1286d6Sthorpej static void *depca_eisa_intr_establish(struct depca_softc *,
863e1286d6Sthorpej struct lance_softc *);
878cb7deb8Sthorpej
883e1286d6Sthorpej static int
depca_eisa_match(device_t parent,cfdata_t cf,void * aux)89d9941582Stsutsui depca_eisa_match(device_t parent, cfdata_t cf, void *aux)
908cb7deb8Sthorpej {
918cb7deb8Sthorpej struct eisa_attach_args *ea = aux;
928cb7deb8Sthorpej
938cb7deb8Sthorpej return (strcmp(ea->ea_idstring, "DEC4220") == 0);
948cb7deb8Sthorpej }
958cb7deb8Sthorpej
968cb7deb8Sthorpej #define DEPCA_ECU_FUNC_NETINTR 0
978cb7deb8Sthorpej #define DEPCA_ECU_FUNC_NETBUF 1
988cb7deb8Sthorpej
993e1286d6Sthorpej static void
depca_eisa_attach(device_t parent,device_t self,void * aux)100d9941582Stsutsui depca_eisa_attach(device_t parent, device_t self, void *aux)
1018cb7deb8Sthorpej {
10292c7bba3Sthorpej struct depca_eisa_softc *esc = device_private(self);
103d9941582Stsutsui struct depca_softc *sc = &esc->sc_depca;
1048cb7deb8Sthorpej struct eisa_attach_args *ea = aux;
1058cb7deb8Sthorpej struct eisa_cfg_mem ecm;
1068cb7deb8Sthorpej struct eisa_cfg_irq eci;
1078cb7deb8Sthorpej
108d9941582Stsutsui sc->sc_dev = self;
109d7026ba0Sthorpej aprint_naive("\n");
110d7026ba0Sthorpej aprint_normal(": DEC DE422 Ethernet\n");
1118cb7deb8Sthorpej
1128cb7deb8Sthorpej sc->sc_iot = ea->ea_iot;
1138cb7deb8Sthorpej sc->sc_memt = ea->ea_memt;
1148cb7deb8Sthorpej
1158cb7deb8Sthorpej esc->sc_ec = ea->ea_ec;
1168cb7deb8Sthorpej
1178cb7deb8Sthorpej sc->sc_intr_establish = depca_eisa_intr_establish;
1188cb7deb8Sthorpej
1198cb7deb8Sthorpej if (eisa_conf_read_mem(ea->ea_ec, ea->ea_slot,
1208cb7deb8Sthorpej DEPCA_ECU_FUNC_NETBUF, 0, &ecm) != 0) {
121d9941582Stsutsui aprint_error_dev(self, "unable to find network buffer\n");
1228cb7deb8Sthorpej return;
1238cb7deb8Sthorpej }
1248cb7deb8Sthorpej
125d9941582Stsutsui aprint_normal_dev(self, "shared memory at 0x%lx-0x%lx\n",
1268cb7deb8Sthorpej ecm.ecm_addr, ecm.ecm_addr + ecm.ecm_size - 1);
1278cb7deb8Sthorpej
1288cb7deb8Sthorpej sc->sc_memsize = ecm.ecm_size;
1298cb7deb8Sthorpej
1308cb7deb8Sthorpej if (bus_space_map(sc->sc_iot, EISA_SLOT_ADDR(ea->ea_slot) + 0xc00, 16,
1318cb7deb8Sthorpej 0, &sc->sc_ioh) != 0) {
132d9941582Stsutsui aprint_error_dev(self, "unable to map i/o space\n");
1338cb7deb8Sthorpej return;
1348cb7deb8Sthorpej }
1358cb7deb8Sthorpej if (bus_space_map(sc->sc_memt, ecm.ecm_addr, sc->sc_memsize,
1368cb7deb8Sthorpej 0, &sc->sc_memh) != 0) {
137d9941582Stsutsui aprint_error_dev(self, "unable to map memory space\n");
1388cb7deb8Sthorpej return;
1398cb7deb8Sthorpej }
1408cb7deb8Sthorpej
1418cb7deb8Sthorpej if (eisa_conf_read_irq(ea->ea_ec, ea->ea_slot,
1428cb7deb8Sthorpej DEPCA_ECU_FUNC_NETINTR, 0, &eci) != 0) {
143d9941582Stsutsui aprint_error_dev(self, "unable to determine IRQ\n");
1448cb7deb8Sthorpej return;
1458cb7deb8Sthorpej }
1468cb7deb8Sthorpej
1478cb7deb8Sthorpej esc->sc_irq = eci.eci_irq;
1488cb7deb8Sthorpej esc->sc_ist = eci.eci_ist;
1498cb7deb8Sthorpej
1508cb7deb8Sthorpej depca_attach(sc);
1518cb7deb8Sthorpej }
1528cb7deb8Sthorpej
1533e1286d6Sthorpej static void *
depca_eisa_intr_establish(struct depca_softc * sc,struct lance_softc * child)154cbab9cadSchs depca_eisa_intr_establish(struct depca_softc *sc, struct lance_softc *child)
1558cb7deb8Sthorpej {
156cbab9cadSchs struct depca_eisa_softc *esc = (struct depca_eisa_softc *)sc;
1578cb7deb8Sthorpej eisa_intr_handle_t ih;
1588cb7deb8Sthorpej const char *intrstr;
1598cb7deb8Sthorpej void *rv;
160e58a356cSchristos char intrbuf[EISA_INTRSTR_LEN];
1618cb7deb8Sthorpej
1628cb7deb8Sthorpej if (eisa_intr_map(esc->sc_ec, esc->sc_irq, &ih)) {
163cbab9cadSchs aprint_error_dev(sc->sc_dev,
164d9941582Stsutsui "unable to map interrupt (%d)\n", esc->sc_irq);
1658cb7deb8Sthorpej return (NULL);
1668cb7deb8Sthorpej }
167e58a356cSchristos intrstr = eisa_intr_string(esc->sc_ec, ih, intrbuf, sizeof(intrbuf));
1688cb7deb8Sthorpej rv = eisa_intr_establish(esc->sc_ec, ih, esc->sc_ist, IPL_NET,
1698cb7deb8Sthorpej (esc->sc_ist == IST_LEVEL) ? am7990_intr : depca_intredge, child);
1708cb7deb8Sthorpej if (rv == NULL) {
171cbab9cadSchs aprint_error_dev(sc->sc_dev,
172d9941582Stsutsui "unable to establish interrupt");
1738cb7deb8Sthorpej if (intrstr != NULL)
174d9941582Stsutsui aprint_error(" at %s", intrstr);
175d9941582Stsutsui aprint_error("\n");
1768cb7deb8Sthorpej return (NULL);
1778cb7deb8Sthorpej }
178*06998a74Sthorpej if (intrstr != NULL) {
179*06998a74Sthorpej aprint_normal_dev(sc->sc_dev,
180*06998a74Sthorpej "interrupting at %s (%s trigger)\n",
181*06998a74Sthorpej (esc->sc_ist == IST_LEVEL) ? "level" : "edge", intrstr);
182*06998a74Sthorpej }
1838cb7deb8Sthorpej
1848cb7deb8Sthorpej return (rv);
1858cb7deb8Sthorpej }
186