Home | History | Annotate | Line # | Download | only in podulebus
      1  1.20   msaitoh /*	$NetBSD: if_ne_pbus.c,v 1.20 2019/05/29 06:21:56 msaitoh Exp $	*/
      2   1.1   reinoud 
      3   1.1   reinoud /*
      4   1.1   reinoud  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5   1.1   reinoud  * All rights reserved.
      6   1.1   reinoud  *
      7   1.1   reinoud  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1   reinoud  * by Mark Brinicombe of Causality Limited.
      9   1.1   reinoud  *
     10   1.1   reinoud  * EtherH code Copyright (c) 1998 Mike Pumford
     11   1.1   reinoud  * EtherN/EtherI code Copyright (c) 1999 Mike Pumford
     12   1.1   reinoud  *
     13   1.1   reinoud  * Redistribution and use in source and binary forms, with or without
     14   1.1   reinoud  * modification, are permitted provided that the following conditions
     15   1.1   reinoud  * are met:
     16   1.1   reinoud  * 1. Redistributions of source code must retain the above copyright
     17   1.1   reinoud  *    notice, this list of conditions and the following disclaimer.
     18   1.1   reinoud  * 2. Redistributions in binary form must reproduce the above copyright
     19   1.1   reinoud  *    notice, this list of conditions and the following disclaimer in the
     20   1.1   reinoud  *    documentation and/or other materials provided with the distribution.
     21   1.1   reinoud  *
     22   1.1   reinoud  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     23   1.1   reinoud  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     24   1.1   reinoud  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     25   1.1   reinoud  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     26   1.1   reinoud  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27   1.1   reinoud  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28   1.1   reinoud  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29   1.1   reinoud  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30   1.1   reinoud  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31   1.1   reinoud  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     32   1.1   reinoud  * POSSIBILITY OF SUCH DAMAGE.
     33   1.1   reinoud  */
     34   1.1   reinoud 
     35   1.1   reinoud /*
     36   1.1   reinoud  * This driver uses the generic ne2000 & dp8390 IC drivers
     37   1.1   reinoud  *
     38   1.1   reinoud  * Currently supports:
     39   1.1   reinoud  *	ANT EtherM network slot cards
     40   1.1   reinoud  *	ICubed Etherlan 600 (EtherH) network slot cards
     41   1.1   reinoud  *      Irlam EtherN podules
     42   1.1   reinoud  *      Acorn EtherI podules (identical hardware to EtherN)
     43   1.1   reinoud  *
     44   1.1   reinoud  * Thanks go to Stephen Borrill for providing the EtherN card
     45   1.1   reinoud  * and information to program it.
     46   1.1   reinoud  *
     47   1.1   reinoud  * TO DO List for this Driver.
     48   1.1   reinoud  *
     49   1.1   reinoud  * EtherM - Needs proper media support.
     50   1.1   reinoud  */
     51  1.10     lukem 
     52  1.10     lukem #include <sys/cdefs.h>
     53  1.20   msaitoh __KERNEL_RCSID(0, "$NetBSD: if_ne_pbus.c,v 1.20 2019/05/29 06:21:56 msaitoh Exp $");
     54   1.1   reinoud 
     55   1.1   reinoud #include <sys/param.h>
     56   1.1   reinoud #include <sys/device.h>
     57   1.1   reinoud #include <sys/socket.h>
     58   1.1   reinoud #include <sys/systm.h>
     59   1.1   reinoud #include <sys/mbuf.h>
     60  1.16    dyoung #include <sys/bus.h>
     61   1.1   reinoud 
     62   1.1   reinoud #include <net/if.h>
     63   1.1   reinoud #include <net/if_dl.h>
     64   1.1   reinoud #include <net/if_ether.h>
     65   1.1   reinoud #include <net/if_media.h>
     66   1.1   reinoud 
     67   1.2   thorpej #include <machine/intr.h>
     68   1.1   reinoud #include <machine/io.h>
     69   1.1   reinoud #include <dev/ic/dp8390reg.h>
     70   1.1   reinoud #include <dev/ic/dp8390var.h>
     71   1.1   reinoud #include <dev/ic/ne2000reg.h>
     72   1.1   reinoud #include <dev/ic/ne2000var.h>
     73   1.4     bjh21 #include <dev/ic/dp83905reg.h>
     74   1.4     bjh21 #include <dev/ic/dp83905var.h>
     75   1.3     bjh21 #include <dev/ic/mx98905var.h>
     76   1.1   reinoud 
     77   1.1   reinoud #include <arch/acorn32/podulebus/podulebus.h>
     78   1.1   reinoud #include <arch/acorn32/podulebus/if_ne_pbusreg.h>
     79   1.1   reinoud 
     80   1.1   reinoud #include <dev/podulebus/podules.h>
     81   1.1   reinoud 
     82   1.1   reinoud /*
     83   1.1   reinoud  * ne_pbus_softc: ne2000_softc plus podule, interrupt and bs tag info
     84   1.1   reinoud  */
     85   1.1   reinoud struct ne_pbus_softc {
     86   1.1   reinoud 	struct	ne2000_softc	sc_ne2000;		/* ne2000 softc */
     87   1.1   reinoud 	int			sc_podule_number;
     88   1.1   reinoud 	podule_t		*sc_podule;
     89   1.1   reinoud 	struct bus_space	sc_tag;			/* Patched tag */
     90   1.1   reinoud 	irqhandler_t		*sc_ih;			/* Interrupt handler */
     91   1.1   reinoud 	struct evcnt		sc_intrcnt;		/* Interrupt count */
     92   1.1   reinoud 	bus_space_handle_t	sc_extrah;		/* Bus handle for any
     93   1.1   reinoud 							   extra registers */
     94   1.1   reinoud };
     95   1.1   reinoud 
     96   1.1   reinoud /*
     97   1.1   reinoud  * Attach data and prototypes for driver
     98   1.1   reinoud  */
     99  1.14      cube static int  ne_pbus_probe	(device_t, cfdata_t , void *);
    100  1.14      cube static void ne_pbus_attach	(device_t, device_t, void *);
    101   1.1   reinoud 
    102  1.14      cube CFATTACH_DECL_NEW(ne_pbus, sizeof(struct ne_pbus_softc),
    103   1.9   thorpej     ne_pbus_probe, ne_pbus_attach, NULL, NULL);
    104   1.1   reinoud 
    105   1.1   reinoud /*
    106   1.1   reinoud  * Prototypes for interface specific routines
    107   1.1   reinoud  */
    108  1.17     skrll static uint8_t *em_ea		(struct ne_pbus_softc *sc, uint8_t *buffer);
    109  1.14      cube static void em_postattach	(struct ne_pbus_softc *sc);
    110  1.14      cube static void eh600_postattach	(struct ne_pbus_softc *sc);
    111  1.14      cube static void eh600_preattach	(struct ne_pbus_softc *sc);
    112  1.17     skrll static uint8_t *eh600_ea	(struct ne_pbus_softc *sc, uint8_t *buffer);
    113   1.1   reinoud 
    114  1.14      cube void	eh600_init_media        (struct dp8390_softc *);
    115   1.1   reinoud 
    116  1.14      cube void	en_postattach		(struct ne_pbus_softc *);
    117  1.14      cube void	en_init_media           (struct dp8390_softc *);
    118   1.1   reinoud 
    119   1.1   reinoud /*
    120   1.1   reinoud  * Define a structure to hold all the information required on an NE2000
    121   1.1   reinoud  * clone interface.
    122   1.1   reinoud  * We create an array of these structures to describe all the interfaces
    123   1.1   reinoud  * that we can handle via the MI NE2000 driver.
    124   1.1   reinoud  */
    125   1.1   reinoud struct ne_clone {
    126   1.1   reinoud 	int		product;	/* podule product id */
    127   1.1   reinoud 	unsigned int	cookie;		/* podulebus space cookie */
    128   1.1   reinoud 	unsigned int	nicbase;	/* byte offset of NIC */
    129   1.1   reinoud 	unsigned int	nicsize;	/* size of NIC (regs) */
    130   1.1   reinoud 	unsigned int	asicbase;	/* byte offset of ASIC */
    131   1.1   reinoud 	unsigned int	asicsize;	/* size of ASIC (regs) */
    132   1.1   reinoud 	unsigned int    extrabase;      /* extra registers byte offset */
    133   1.1   reinoud 	unsigned int    extrasize;      /* size of extra registers(regs) */
    134   1.1   reinoud 	unsigned char	nicspace;	/* easi,fast or mod space ? */
    135   1.1   reinoud 	unsigned char	asicspace;	/* easi,fast or mod space ? */
    136   1.1   reinoud 	unsigned char   extraspace;     /* easi,fast or mod space ? */
    137   1.1   reinoud #define NE_SPACE_FAST		0
    138   1.1   reinoud #define NE_SPACE_MOD		1
    139   1.1   reinoud #define NE_SPACE_EASI           2
    140   1.1   reinoud 	unsigned char	reserved0;	/* not used (padding) */
    141   1.1   reinoud 	const char	*name;		/* name */
    142  1.17     skrll 	uint8_t *	(*getea)	/* do this to get the MAC */
    143  1.17     skrll 			    (struct ne_pbus_softc *sc, uint8_t *buffer);
    144   1.1   reinoud 	void		(*preattach)	/* do this before attach */
    145  1.14      cube 			    (struct ne_pbus_softc *sc);
    146   1.1   reinoud 	void		(*postattach)	/* do this after attach */
    147  1.14      cube 			    (struct ne_pbus_softc *sc);
    148   1.1   reinoud         int          	(*mediachange)  /* media change */
    149  1.14      cube                             (struct dp8390_softc *);
    150   1.1   reinoud         void          	(*mediastatus)  /* media status */
    151  1.14      cube                             (struct dp8390_softc *, struct ifmediareq *);
    152   1.1   reinoud         void          	(*init_card)    /* media init card */
    153  1.14      cube                             (struct dp8390_softc *);
    154   1.1   reinoud         void          	(*init_media)   /* media init */
    155  1.14      cube                             (struct dp8390_softc *);
    156   1.1   reinoud } ne_clones[] = {
    157   1.1   reinoud 	/* ANT EtherM netslot interface */
    158   1.1   reinoud 	{
    159   1.5     bjh21 	  PODULE_ETHERM, EM_REGSHIFT,
    160   1.1   reinoud 	  EM_NIC_OFFSET, EM_NIC_SIZE, EM_ASIC_OFFSET, EM_ASIC_SIZE,
    161   1.1   reinoud 	  0,0, NE_SPACE_FAST,
    162   1.1   reinoud 	  NE_SPACE_FAST, NE_SPACE_FAST, 0,
    163   1.1   reinoud 	  "EtherM", em_ea, NULL, em_postattach,
    164   1.1   reinoud 	  NULL,NULL,NULL,NULL
    165   1.1   reinoud 	},
    166   1.1   reinoud 	/* ICubed EtherLan EtherH netslot interface */
    167   1.1   reinoud 	{
    168   1.5     bjh21 	  PODULE_ETHERLAN600, EH600_REGSHIFT,
    169   1.1   reinoud 	  EH600_NIC_OFFSET, EH600_NIC_SIZE, EH600_ASIC_OFFSET, EH600_ASIC_SIZE,
    170   1.1   reinoud 	  EH600_CONTROL_OFFSET, EH600_CONTROL_SIZE, NE_SPACE_FAST,
    171   1.1   reinoud 	  NE_SPACE_FAST, NE_SPACE_FAST, 0,
    172   1.1   reinoud 	  "EtherLan 600", eh600_ea, eh600_preattach, eh600_postattach,
    173   1.4     bjh21 	  dp83905_mediachange, dp83905_mediastatus, dp83905_init_card,
    174   1.1   reinoud 	  eh600_init_media
    175   1.1   reinoud 	},
    176   1.1   reinoud 	/* Acorn EtherLan EtherH netslot interface */
    177   1.1   reinoud 	{
    178   1.5     bjh21 	  PODULE_ETHERLAN600AEH, EH600_REGSHIFT,
    179   1.1   reinoud 	  EH600_NIC_OFFSET, EH600_NIC_SIZE, EH600_ASIC_OFFSET, EH600_ASIC_SIZE,
    180   1.1   reinoud 	  EH600_CONTROL_OFFSET, EH600_CONTROL_SIZE, NE_SPACE_FAST,
    181   1.1   reinoud 	  NE_SPACE_FAST, NE_SPACE_FAST, 0,
    182   1.1   reinoud 	  "EtherLan 600A", eh600_ea , eh600_preattach, eh600_postattach,
    183   1.4     bjh21 	  dp83905_mediachange, dp83905_mediastatus, dp83905_init_card,
    184   1.1   reinoud 	  eh600_init_media
    185   1.1   reinoud 	},
    186   1.1   reinoud 	/* Irlam EtherN podule. (supplied with NC) */
    187   1.1   reinoud 	{
    188  1.11     bjh21 	  PODULE_ETHERN, EN_REGSHIFT,
    189   1.1   reinoud 	  EN_NIC_OFFSET, EN_NIC_SIZE, EN_ASIC_OFFSET, EN_ASIC_SIZE,
    190   1.1   reinoud 	  0,0, NE_SPACE_EASI,
    191   1.1   reinoud 	  NE_SPACE_EASI, NE_SPACE_EASI, 0,
    192   1.3     bjh21 	  "EtherN", em_ea, NULL, en_postattach,
    193   1.4     bjh21 	  dp83905_mediachange, dp83905_mediastatus, dp83905_init_card,
    194   1.1   reinoud 	  en_init_media
    195   1.1   reinoud 	},
    196   1.1   reinoud 	/* Acorn EtherI podule. (supplied with NC) */
    197   1.1   reinoud 	{
    198  1.12     bjh21 	  PODULE_ETHERI, EN_REGSHIFT,
    199   1.1   reinoud 	  EN_NIC_OFFSET, EN_NIC_SIZE, EN_ASIC_OFFSET, EN_ASIC_SIZE,
    200   1.1   reinoud 	  0,0, NE_SPACE_EASI,
    201   1.1   reinoud 	  NE_SPACE_EASI, NE_SPACE_EASI, 0,
    202   1.3     bjh21 	  "EtherI", em_ea, NULL, en_postattach,
    203   1.4     bjh21 	  dp83905_mediachange, dp83905_mediastatus, dp83905_init_card,
    204   1.1   reinoud 	  en_init_media
    205   1.1   reinoud 	},
    206   1.1   reinoud };
    207   1.1   reinoud 
    208   1.1   reinoud /*
    209   1.1   reinoud  * Determine if the device is present.
    210   1.1   reinoud  */
    211   1.1   reinoud static int
    212  1.14      cube ne_pbus_probe(device_t parent, cfdata_t cf, void *aux)
    213   1.1   reinoud {
    214  1.19   msaitoh 	struct podule_attach_args *pa = (void *)aux;
    215   1.1   reinoud 	int loop;
    216   1.1   reinoud 
    217   1.1   reinoud 	/* Scan the list of known interfaces looking for a match */
    218   1.1   reinoud 	for (loop = 0; loop < sizeof(ne_clones) / sizeof(struct ne_clone);
    219   1.1   reinoud 	    ++loop) {
    220   1.5     bjh21 		if (pa->pa_product == ne_clones[loop].product)
    221  1.19   msaitoh 			return 1;
    222   1.1   reinoud 	}
    223  1.19   msaitoh 	return 0;
    224   1.1   reinoud }
    225   1.1   reinoud 
    226   1.1   reinoud /*
    227   1.1   reinoud  * Install interface into kernel networking data structures.
    228   1.1   reinoud  */
    229   1.1   reinoud static void
    230  1.14      cube ne_pbus_attach(device_t parent, device_t self, void *aux)
    231   1.1   reinoud {
    232   1.1   reinoud 	struct podule_attach_args *pa = (void *)aux;
    233  1.14      cube 	struct ne_pbus_softc *npsc = device_private(self);
    234   1.1   reinoud 	struct ne2000_softc *nsc = &npsc->sc_ne2000;
    235   1.1   reinoud 	struct dp8390_softc *dsc = &nsc->sc_dp8390;
    236   1.1   reinoud 	struct ne_clone *ne = NULL;
    237  1.17     skrll 	uint8_t buffer[6];
    238  1.17     skrll 	uint8_t *myea;
    239   1.1   reinoud 	int loop;
    240   1.1   reinoud 
    241  1.14      cube 	dsc->sc_dev = self;
    242   1.1   reinoud 	/* Check a few things about the attach args */
    243   1.1   reinoud 
    244   1.1   reinoud 	if (pa->pa_podule_number == -1)
    245   1.1   reinoud 		panic("Podule has disappeared !");
    246   1.1   reinoud 
    247   1.1   reinoud 	npsc->sc_podule_number = pa->pa_podule_number;
    248   1.1   reinoud 	npsc->sc_podule = pa->pa_podule;
    249   1.1   reinoud 	podules[npsc->sc_podule_number].attached = 1;		/* XXX */
    250   1.1   reinoud 
    251   1.1   reinoud 	/* Scan the list of known interfaces for a match */
    252   1.1   reinoud 	for (loop = 0; loop < sizeof(ne_clones) / sizeof(struct ne_clone);
    253   1.1   reinoud 	    ++loop) {
    254   1.5     bjh21 		if (pa->pa_product == ne_clones[loop].product) {
    255   1.1   reinoud 			ne = &ne_clones[loop];
    256   1.1   reinoud 			break;
    257   1.1   reinoud 		}
    258   1.1   reinoud 	}
    259   1.1   reinoud 
    260   1.1   reinoud #ifdef	DIAGNOSTIC
    261   1.1   reinoud 	/* This should never fail as we must have matched at probe time */
    262   1.1   reinoud 	if (ne == NULL)
    263   1.6    provos 		panic("Podule has vanished");
    264   1.1   reinoud #endif
    265   1.1   reinoud 
    266   1.1   reinoud 	/* Update the nic and asic base addresses appropriately */
    267   1.1   reinoud 	switch (ne->nicspace) {
    268   1.1   reinoud 	case NE_SPACE_EASI:
    269   1.1   reinoud 		ne->nicbase += npsc->sc_podule->easi_base;
    270   1.1   reinoud 		break;
    271   1.1   reinoud 	case NE_SPACE_MOD:
    272   1.1   reinoud 		ne->nicbase += npsc->sc_podule->mod_base;
    273   1.1   reinoud 		break;
    274   1.1   reinoud 	case NE_SPACE_FAST:
    275   1.1   reinoud 	default:
    276   1.1   reinoud 		ne->nicbase += npsc->sc_podule->fast_base;
    277   1.1   reinoud 		break;
    278   1.1   reinoud 	}
    279   1.1   reinoud 	switch (ne->asicspace) {
    280   1.1   reinoud 	case NE_SPACE_EASI:
    281   1.1   reinoud 		ne->asicbase += npsc->sc_podule->easi_base;
    282   1.1   reinoud 		break;
    283   1.1   reinoud 	case NE_SPACE_MOD:
    284   1.1   reinoud 		ne->asicbase += npsc->sc_podule->mod_base;
    285   1.1   reinoud 		break;
    286   1.1   reinoud 	case NE_SPACE_FAST:
    287   1.1   reinoud 	default:
    288   1.1   reinoud 		ne->asicbase += npsc->sc_podule->fast_base;
    289   1.1   reinoud 		break;
    290   1.1   reinoud 	}
    291   1.1   reinoud 
    292   1.1   reinoud 	switch (ne->extraspace) {
    293   1.1   reinoud 	case NE_SPACE_EASI:
    294   1.1   reinoud 		ne->extrabase += npsc->sc_podule->easi_base;
    295   1.1   reinoud 		break;
    296   1.1   reinoud 	case NE_SPACE_MOD:
    297   1.1   reinoud 		ne->extrabase += npsc->sc_podule->mod_base;
    298   1.1   reinoud 		break;
    299   1.1   reinoud 	case NE_SPACE_FAST:
    300   1.1   reinoud 	default:
    301   1.1   reinoud 		ne->extrabase += npsc->sc_podule->fast_base;
    302   1.1   reinoud 		break;
    303   1.1   reinoud 	}
    304   1.1   reinoud 
    305   1.1   reinoud 	/* Report the interface name */
    306  1.14      cube 	aprint_normal(": %s ethernet\n", ne->name);
    307   1.1   reinoud 
    308   1.1   reinoud 	/*
    309   1.1   reinoud 	 * Ok we need our own bus tag as the register spacing
    310   1.1   reinoud 	 * may not the default.
    311   1.1   reinoud 	 *
    312   1.1   reinoud 	 * For the podulebus, the bus tag cookie is the shift
    313   1.1   reinoud 	 * to apply to registers
    314   1.1   reinoud 	 * So duplicate the bus space tag and change the
    315   1.1   reinoud 	 * cookie.
    316   1.1   reinoud 	 */
    317   1.1   reinoud 
    318   1.1   reinoud 	npsc->sc_tag = *pa->pa_iot;
    319   1.1   reinoud 	npsc->sc_tag.bs_cookie = (void *) ne->cookie;
    320   1.1   reinoud 
    321   1.1   reinoud 	dsc->sc_regt = &npsc->sc_tag;
    322   1.1   reinoud 	nsc->sc_asict = dsc->sc_regt;
    323   1.1   reinoud 
    324   1.1   reinoud 	/* Map all the I/O space for the NIC */
    325   1.1   reinoud 	if (bus_space_map(dsc->sc_regt, ne->nicbase, ne->nicsize,
    326   1.1   reinoud 	    0, &dsc->sc_regh)) {
    327  1.14      cube 		aprint_error_dev(self, "cannot map i/o space\n");
    328   1.1   reinoud 		return;
    329   1.1   reinoud 	}
    330   1.1   reinoud 	/* Map the I/O space for the ASIC */
    331   1.1   reinoud 	if (bus_space_map(nsc->sc_asict, ne->asicbase, ne->asicsize,
    332   1.1   reinoud 	    0, &nsc->sc_asich)) {
    333  1.14      cube 		aprint_error_dev(self, "cannot map i/o space\n");
    334   1.1   reinoud 		return;
    335   1.1   reinoud 	}
    336   1.1   reinoud 	/* Map any extra register space required by the card */
    337   1.1   reinoud 	if (ne->extrasize > 0) {
    338   1.1   reinoud 		if (bus_space_map(&npsc->sc_tag, ne->extrabase, ne->extrasize,
    339   1.1   reinoud 				  0, &npsc->sc_extrah)) {
    340  1.14      cube 			aprint_error_dev(self, "cannot map extra space\n");
    341   1.1   reinoud 			return;
    342   1.1   reinoud 		}
    343   1.1   reinoud 	}
    344   1.1   reinoud 
    345   1.1   reinoud 	/* This interface is always enabled. */
    346   1.1   reinoud 	dsc->sc_enabled = 1;
    347   1.1   reinoud 
    348   1.1   reinoud 	/*
    349   1.1   reinoud 	 * Now get the ethernet address in an interface specific manner if
    350   1.1   reinoud 	 * specified
    351   1.1   reinoud 	 */
    352   1.1   reinoud 	if (ne->getea)
    353   1.1   reinoud 		myea = ne->getea(npsc, buffer);
    354   1.1   reinoud 	else
    355   1.1   reinoud 		myea = NULL;
    356   1.1   reinoud 
    357   1.1   reinoud 	/* Does the interface need a preattach call ? */
    358   1.1   reinoud 	if (ne->preattach)
    359   1.1   reinoud 		ne->preattach(npsc);
    360   1.1   reinoud 
    361  1.19   msaitoh 	/* If the interface has media support initialise it */
    362   1.1   reinoud 	if (ne->init_media) {
    363   1.1   reinoud 		dsc->sc_mediachange = ne->mediachange;
    364   1.1   reinoud 		dsc->sc_mediastatus = ne->mediastatus;
    365   1.1   reinoud 		dsc->init_card = ne->init_card;
    366   1.1   reinoud 		dsc->sc_media_init = ne->init_media;
    367  1.18  christos #if 0
    368  1.18  christos 		int *media = NULL, nmedia = 0, defmedia = 0;
    369  1.18  christos 		ne->init_media(dsc, &media, &nmedia, &defmedia);
    370  1.18  christos #endif
    371   1.1   reinoud 	}
    372   1.1   reinoud 
    373   1.1   reinoud 	/*
    374   1.1   reinoud 	 * Do generic NE2000 attach.  This will read the station address
    375   1.1   reinoud 	 * from the EEPROM.
    376   1.1   reinoud 	 */
    377   1.1   reinoud 	ne2000_attach(nsc, myea);
    378  1.14      cube 	aprint_normal_dev(self, "");
    379   1.1   reinoud 	switch (nsc->sc_type) {
    380   1.1   reinoud 	case NE2000_TYPE_NE1000:
    381  1.14      cube 		aprint_normal("NE1000");
    382   1.1   reinoud 		break;
    383   1.1   reinoud 	case NE2000_TYPE_NE2000:
    384  1.14      cube 		aprint_normal("NE2000");
    385   1.1   reinoud 		break;
    386   1.1   reinoud 	case NE2000_TYPE_AX88190:
    387  1.14      cube 		aprint_normal("AX88190");
    388   1.1   reinoud 		break;
    389   1.1   reinoud 	case NE2000_TYPE_DL10019:
    390  1.14      cube 		aprint_normal("DL10019");
    391   1.1   reinoud 		break;
    392  1.19   msaitoh 	case NE2000_TYPE_DL10022:
    393  1.14      cube 		aprint_normal("DL10022");
    394   1.1   reinoud 		break;
    395   1.1   reinoud 	default:
    396   1.1   reinoud 		printf("??");
    397   1.1   reinoud 	};
    398  1.14      cube 	aprint_normal(" chipset, %d Kb memory\n", dsc->mem_start/1024);
    399   1.1   reinoud 
    400   1.1   reinoud 	/* Does the interface need a postattach call ? */
    401   1.1   reinoud 	if (ne->postattach)
    402   1.1   reinoud 		ne->postattach(npsc);
    403   1.1   reinoud 
    404   1.1   reinoud 	/* Install an interrupt handler */
    405   1.1   reinoud 	evcnt_attach_dynamic(&npsc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
    406  1.14      cube 	    device_xname(self), "intr");
    407   1.1   reinoud 	npsc->sc_ih = podulebus_irq_establish(pa->pa_ih, IPL_NET, dp8390_intr,
    408   1.1   reinoud 	    dsc, &npsc->sc_intrcnt);
    409   1.1   reinoud 	if (npsc->sc_ih == NULL)
    410   1.1   reinoud 		panic("%s: Cannot install interrupt handler",
    411  1.14      cube 		   device_xname(self));
    412  1.19   msaitoh 	/* This feels wrong to do this here */
    413   1.1   reinoud 	npsc->sc_ih->ih_maskaddr = npsc->sc_podule->irq_addr;
    414   1.1   reinoud 	npsc->sc_ih->ih_maskbits = npsc->sc_podule->irq_mask;
    415   1.1   reinoud }
    416   1.1   reinoud 
    417   1.1   reinoud /*
    418   1.1   reinoud  * em_ea()
    419   1.1   reinoud  *
    420   1.1   reinoud  * return the ethernet address for an EtherM netslot interface.
    421   1.1   reinoud  * The EtherM interface uses the machines ethernet address so just
    422   1.1   reinoud  * fill it out
    423   1.1   reinoud  */
    424  1.14      cube static uint8_t *
    425  1.14      cube em_ea(struct ne_pbus_softc *sc, uint8_t *buffer)
    426   1.1   reinoud {
    427   1.1   reinoud 	/*
    428   1.1   reinoud 	 * Use the podulebus netslot_ea() function to get the netslot
    429   1.1   reinoud 	 * ethernet address. This is generated from the machine ID.
    430   1.1   reinoud 	 */
    431   1.1   reinoud 
    432   1.1   reinoud 	netslot_ea(buffer);
    433  1.19   msaitoh 	return buffer;
    434   1.1   reinoud }
    435   1.1   reinoud 
    436   1.1   reinoud /*
    437   1.1   reinoud  * em_postattach()
    438   1.1   reinoud  *
    439   1.1   reinoud  * The EtherM interface has a Diagnostic Status register. After attaching
    440   1.1   reinoud  * the driver, print out some more information using this register.
    441   1.1   reinoud  */
    442   1.1   reinoud static void
    443  1.14      cube em_postattach(struct ne_pbus_softc *sc)
    444   1.1   reinoud {
    445   1.1   reinoud 	int dsr;
    446   1.1   reinoud 
    447   1.1   reinoud 	/*
    448   1.1   reinoud 	 * Report information from the Diagnostic Status Register for
    449   1.1   reinoud 	 * the EtherM card
    450   1.1   reinoud 	 */
    451  1.14      cube 	aprint_normal_dev(sc->sc_ne2000.sc_dp8390.sc_dev,
    452  1.14      cube 	    "16KB buffer memory");
    453   1.1   reinoud 
    454   1.1   reinoud 	/* Get the Diagnostic Status Register */
    455   1.1   reinoud 	dsr = bus_space_read_1(sc->sc_ne2000.sc_asict,
    456   1.1   reinoud 	    sc->sc_ne2000.sc_asich, EM_DSR_REG);
    457   1.1   reinoud 
    458   1.1   reinoud 	/* Check for bits that indicate a fault */
    459   1.1   reinoud 	if (!(dsr & EM_DSR_20M))
    460  1.14      cube 		aprint_normal(", VCO faulty");
    461   1.1   reinoud 	if (!(dsr & EM_DSR_TCOK))
    462  1.14      cube 		aprint_normal(", TxClk faulty");
    463   1.1   reinoud 
    464   1.1   reinoud 	/* Report status of card */
    465   1.1   reinoud 	if (dsr & EM_DSR_POL)
    466  1.14      cube 		aprint_normal(", UTP reverse polarity");
    467   1.1   reinoud 	if (dsr & EM_DSR_JAB)
    468  1.14      cube 		aprint_normal(", jabber");
    469   1.1   reinoud 	if (dsr & EM_DSR_LNK)
    470  1.14      cube 		aprint_normal(", link OK");
    471   1.1   reinoud 	if (dsr & EM_DSR_LBK)
    472  1.14      cube 		aprint_normal(", loopback");
    473   1.1   reinoud 	if (dsr & EM_DSR_UTP)
    474  1.14      cube 		aprint_normal(", UTP");
    475  1.14      cube 	aprint_normal("\n");
    476   1.1   reinoud }
    477   1.1   reinoud 
    478   1.1   reinoud 
    479   1.1   reinoud /*
    480   1.1   reinoud  * eh600_preattach()
    481   1.1   reinoud  *
    482  1.19   msaitoh  * pre-initialise the AT/Lantic chipset so that the card probes and
    483  1.19   msaitoh  * detects properly.
    484   1.1   reinoud  */
    485   1.1   reinoud static void
    486  1.14      cube eh600_preattach(struct ne_pbus_softc *sc)
    487   1.1   reinoud {
    488   1.1   reinoud 	u_char tmp;
    489   1.1   reinoud 	struct ne2000_softc *nsc = &sc->sc_ne2000;
    490   1.1   reinoud 	struct dp8390_softc *dsc = &nsc->sc_dp8390;
    491   1.1   reinoud 	bus_space_tag_t nict = dsc->sc_regt;
    492   1.1   reinoud 	bus_space_handle_t nich = dsc->sc_regh;
    493  1.19   msaitoh 
    494  1.19   msaitoh 	/* Initialise EH600 config register */
    495   1.4     bjh21 	bus_space_read_1(nict, nich, DP83905_MCRA);
    496   1.4     bjh21 	bus_space_write_1(nict, nich, DP83905_MCRA, DP83905_MCRA_INT3);
    497   1.1   reinoud 
    498  1.19   msaitoh 	/* Enable interrupts for the card */
    499  1.20   msaitoh 	tmp = bus_space_read_1(&sc->sc_tag, sc->sc_extrah, 0);
    500   1.1   reinoud 	tmp |= EH_INTR_MASK;
    501  1.20   msaitoh 	bus_space_write_1(&sc->sc_tag, sc->sc_extrah, 0, tmp);
    502   1.1   reinoud }
    503   1.1   reinoud 
    504   1.1   reinoud /*
    505   1.1   reinoud  * eh600_postattach()
    506   1.1   reinoud  *
    507  1.19   msaitoh  * Etherlan 600 has 32k of buffer memory as it runs the AT/Lantic
    508  1.19   msaitoh  * DP8390 clone in IO non-compatible mode. We need to adjust the memory
    509   1.1   reinoud  * description set up by dp8390.c and ne2000.c to reflect this.
    510   1.1   reinoud  */
    511   1.1   reinoud static void
    512  1.14      cube eh600_postattach(struct ne_pbus_softc *sc)
    513   1.1   reinoud {
    514   1.1   reinoud 	struct ne2000_softc *nsc = &sc->sc_ne2000;
    515   1.1   reinoud 	struct dp8390_softc *dsc = &nsc->sc_dp8390;
    516  1.19   msaitoh 
    517  1.19   msaitoh 	/* First page is mapped to the PROM. so start at 2nd page */
    518   1.1   reinoud 	dsc->mem_start = EH600_MEM_START;
    519   1.1   reinoud 	dsc->mem_size = EH600_MEM_END - EH600_MEM_START;
    520   1.1   reinoud 	dsc->mem_end = EH600_MEM_END;
    521   1.1   reinoud 	dsc->txb_cnt = 3; /* >16k of ram setup 3 tx buffers */
    522  1.19   msaitoh 	/* Recompute the mem ring (taken straight from the ne2000 init code) */
    523  1.19   msaitoh 	dsc->mem_ring =
    524  1.19   msaitoh 		dsc->mem_start +
    525   1.1   reinoud 		(((dsc->txb_cnt + 1) * ED_TXBUF_SIZE ) <<
    526   1.1   reinoud 		 ED_PAGE_SHIFT);
    527   1.1   reinoud 
    528  1.19   msaitoh 	/* Recompute the dp8390 register values. (from dp8390 init code) */
    529   1.1   reinoud 	dsc->tx_page_start = dsc->mem_start >> ED_PAGE_SHIFT;
    530   1.1   reinoud 
    531  1.19   msaitoh 	dsc->rec_page_start = dsc->tx_page_start +
    532   1.1   reinoud 		(dsc->txb_cnt + 1) * ED_TXBUF_SIZE;
    533   1.1   reinoud 
    534  1.19   msaitoh 	dsc->rec_page_stop = dsc->tx_page_start +
    535   1.1   reinoud 		(dsc->mem_size >> ED_PAGE_SHIFT);
    536  1.14      cube 	aprint_normal_dev(dsc->sc_dev, "32KB buffer memory\n");
    537   1.1   reinoud }
    538   1.1   reinoud /*
    539   1.1   reinoud  * EtherLan 600 media.
    540   1.1   reinoud  */
    541  1.14      cube void eh600_init_media(struct dp8390_softc *sc)
    542   1.1   reinoud {
    543   1.1   reinoud 	static int eh600_media[] = {
    544  1.19   msaitoh 		IFM_ETHER | IFM_AUTO,
    545  1.19   msaitoh 		IFM_ETHER | IFM_10_T,
    546  1.19   msaitoh 		IFM_ETHER | IFM_10_2,
    547   1.1   reinoud 	};
    548  1.19   msaitoh 	int i, defmedia = IFM_ETHER | IFM_AUTO;
    549  1.19   msaitoh 	static const int eh600_nmedia = __arraycount(eh600_media);
    550   1.1   reinoud 
    551  1.14      cube 	aprint_normal_dev(sc->sc_dev,
    552  1.14      cube 	    "10base2, 10baseT, auto, default auto\n");
    553   1.1   reinoud 
    554   1.1   reinoud 	ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus);
    555   1.1   reinoud 	for (i = 0; i < eh600_nmedia; i++)
    556   1.1   reinoud 		ifmedia_add(&sc->sc_media, eh600_media[i], 0, NULL);
    557   1.1   reinoud 	ifmedia_set(&sc->sc_media, defmedia);
    558   1.1   reinoud }
    559   1.1   reinoud 
    560   1.1   reinoud 
    561   1.3     bjh21 void
    562  1.14      cube en_postattach(struct ne_pbus_softc *sc)
    563   1.3     bjh21 {
    564   1.3     bjh21 
    565   1.3     bjh21 	mx98905_attach(&sc->sc_ne2000.sc_dp8390);
    566   1.3     bjh21 }
    567   1.1   reinoud 
    568   1.1   reinoud /*
    569   1.1   reinoud  * EtherN media.
    570   1.1   reinoud  */
    571   1.1   reinoud void
    572  1.14      cube en_init_media(struct dp8390_softc *sc)
    573   1.1   reinoud {
    574   1.1   reinoud 	static int en_media[] = {
    575  1.20   msaitoh 		IFM_ETHER | IFM_10_T
    576   1.1   reinoud 	};
    577  1.19   msaitoh 
    578  1.14      cube 	aprint_normal_dev(sc->sc_dev, "10baseT, default 10baseT\n");
    579   1.1   reinoud 
    580   1.1   reinoud 	ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus);
    581   1.1   reinoud 	ifmedia_add(&sc->sc_media, en_media[0], 0, NULL);
    582   1.1   reinoud 	ifmedia_set(&sc->sc_media, en_media[0]);
    583   1.1   reinoud }
    584   1.1   reinoud 
    585   1.1   reinoud 
    586  1.19   msaitoh /*
    587   1.1   reinoud  * extracts the station address from the Podule description string.
    588  1.19   msaitoh  * The description has to be re-read here since the podule description
    589   1.1   reinoud  * string is not always long enough to contain the full address.
    590   1.1   reinoud  *
    591  1.19   msaitoh  * If for any reason we cannot extract the address this routine will
    592   1.1   reinoud  * use netslot_ea() to return the generic address for the network slot.
    593   1.1   reinoud  */
    594   1.1   reinoud 
    595   1.1   reinoud #define POD_READ(addr) \
    596   1.1   reinoud 	podule->read_rom(podule->sync_base, addr)
    597   1.1   reinoud 
    598  1.14      cube static uint8_t *
    599  1.14      cube eh600_ea(struct ne_pbus_softc *sc, uint8_t *buffer)
    600   1.1   reinoud {
    601   1.1   reinoud 	podule_t *podule = sc->sc_podule;
    602   1.1   reinoud 	u_int address;
    603   1.1   reinoud 	u_int id;
    604   1.1   reinoud 
    605   1.1   reinoud 	address = 0x40;
    606   1.1   reinoud 	memset(buffer, 0, 6);
    607   1.1   reinoud 
    608  1.19   msaitoh 	/* Read chunks from the podule	*/
    609   1.1   reinoud 	do {
    610   1.1   reinoud 		id = POD_READ(address);
    611  1.19   msaitoh 		/* Check for description chunk. */
    612   1.1   reinoud 		if (id == 0xf5) {
    613   1.1   reinoud 			u_int size;
    614   1.1   reinoud 			u_int pod_addr;
    615   1.1   reinoud 			int loop;
    616   1.1   reinoud 
    617  1.19   msaitoh 			/* Read the size */
    618   1.1   reinoud 			size = POD_READ(address + 4);
    619   1.1   reinoud 			size |= (POD_READ(address + 8) << 8);
    620   1.1   reinoud 			size |= (POD_READ(address + 12) << 16);
    621   1.1   reinoud 
    622  1.19   msaitoh 			/* Read address of description */
    623   1.1   reinoud 			pod_addr = POD_READ(address + 16);
    624   1.1   reinoud 			pod_addr |= (POD_READ(address + 20) << 8);
    625   1.1   reinoud 			pod_addr |= (POD_READ(address + 24) << 16);
    626   1.1   reinoud 			pod_addr |= (POD_READ(address + 28) << 24);
    627   1.1   reinoud 
    628   1.1   reinoud 			if (pod_addr < 0x800) {
    629  1.17     skrll 				uint8_t tmp;
    630   1.1   reinoud 				int addr_index = 0;
    631   1.1   reinoud 				int found_ether = 0;
    632   1.1   reinoud 
    633   1.1   reinoud 				/*
    634  1.19   msaitoh 				 * Start scanning for ethernet address
    635   1.1   reinoud 				 * which starts with a '('
    636   1.1   reinoud 				 */
    637   1.1   reinoud 				for (loop = 0; loop < size; ++loop) {
    638   1.1   reinoud 					if (found_ether) {
    639  1.19   msaitoh 						/* We have found a '(' so start decoding the address */
    640   1.1   reinoud 						tmp = POD_READ((pod_addr + loop) * 4);
    641   1.1   reinoud 						if (tmp >= '0' &&  tmp <= '9') {
    642   1.1   reinoud 							buffer[addr_index >> 1] |= (tmp - '0') << ((addr_index & 1) ? 0 : 4);
    643   1.1   reinoud 							++addr_index;
    644   1.1   reinoud 						}
    645  1.19   msaitoh 						else if (tmp >= 'a' &&	tmp <= 'f'){
    646   1.1   reinoud 							buffer[addr_index >> 1] |= (10 + (tmp - 'a')) << ((addr_index & 1) ? 0 : 4);
    647   1.1   reinoud 							++addr_index;
    648   1.1   reinoud 						}
    649  1.19   msaitoh 						else if (tmp >= 'A' &&	tmp <= 'F'){
    650   1.1   reinoud 							buffer[addr_index >> 1] |= (10 + (tmp - 'A')) << ((addr_index & 1) ? 0 : 4);
    651   1.1   reinoud 							++addr_index;
    652   1.1   reinoud 						}
    653   1.1   reinoud 						else if (tmp == ')') {
    654  1.19   msaitoh 							/* We have read the whole address so we can stop scanning
    655   1.1   reinoud 							 * the podule description */
    656   1.1   reinoud 							break;
    657   1.1   reinoud 						}
    658   1.1   reinoud 					}
    659   1.1   reinoud 					/*
    660  1.19   msaitoh 					 * We have found the start of the ethernet address (decode begins
    661   1.1   reinoud 					 * on the next run round the loop. */
    662   1.1   reinoud 					if (POD_READ((pod_addr + loop) * 4) == '(') {
    663   1.1   reinoud 						found_ether = 1;
    664   1.1   reinoud 					}
    665   1.1   reinoud 				}
    666   1.1   reinoud 				/*
    667   1.1   reinoud 				 * Failed to find the address so fall back
    668   1.1   reinoud 				 * on the netslot address
    669   1.1   reinoud 				 */
    670   1.1   reinoud 				if (!found_ether)
    671   1.1   reinoud 					netslot_ea(buffer);
    672  1.19   msaitoh 				return buffer;
    673   1.1   reinoud 			}
    674   1.1   reinoud 		}
    675   1.1   reinoud 		address += 32;
    676   1.1   reinoud 	} while (id != 0 && address < 0x8000);
    677   1.1   reinoud 
    678   1.1   reinoud 	/*
    679   1.1   reinoud 	 * If we get here we failed to find the address
    680   1.1   reinoud 	 * In this case the best solution is to go with the netslot addrness
    681   1.1   reinoud 	 */
    682   1.1   reinoud 	netslot_ea(buffer);
    683  1.19   msaitoh 	return buffer;
    684   1.1   reinoud }
    685