xref: /netbsd-src/sys/dev/eisa/depca_eisa.c (revision 06998a742e1e259be93175222463dd539cce253e)
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