Home | History | Annotate | Line # | Download | only in nubus
if_ae_nubus.c revision 1.3
      1 /*	$NetBSD: if_ae_nubus.c,v 1.3 1997/02/25 06:36:06 scottr Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 1997 Scott Reynolds
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *      This product includes software developed by Scott Reynolds for
     18  *      the NetBSD Project.
     19  * 4. The name of the author may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 #include <sys/param.h>
     35 #include <sys/device.h>
     36 #include <sys/errno.h>
     37 #include <sys/ioctl.h>
     38 #include <sys/socket.h>
     39 #include <sys/systm.h>
     40 
     41 #include <net/if.h>
     42 
     43 #ifdef INET
     44 #include <netinet/in.h>
     45 #include <netinet/if_ether.h>
     46 #endif
     47 
     48 #include <machine/bus.h>
     49 #include <machine/viareg.h>
     50 
     51 #include "nubus.h"
     52 #include <dev/ic/dp8390reg.h>
     53 #include "if_aereg.h"
     54 #include "if_aevar.h"
     55 
     56 static int	ae_nubus_match __P((struct device *, struct cfdata *, void *));
     57 static void	ae_nubus_attach __P((struct device *, struct device *, void *));
     58 static int	ae_card_vendor __P((struct nubus_attach_args *na));
     59 static int	ae_get_enaddr __P((struct nubus_attach_args *na, u_int8_t *ep));
     60 
     61 struct cfattach ae_nubus_ca = {
     62 	sizeof(struct ae_softc), ae_nubus_match, ae_nubus_attach
     63 };
     64 
     65 static int
     66 ae_nubus_match(parent, cf, aux)
     67 	struct device *parent;
     68 	struct cfdata *cf;
     69 	void *aux;
     70 {
     71 	struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
     72 	bus_space_handle_t bsh;
     73 	int rv;
     74 
     75 	if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
     76 	    0, &bsh))
     77 		return (0);
     78 
     79 	rv = 0;
     80 
     81 	if (na->category == NUBUS_CATEGORY_NETWORK &&
     82 	    na->type == NUBUS_TYPE_ETHERNET) {
     83 		switch (ae_card_vendor(na)) {
     84 		case AE_VENDOR_APPLE:
     85 		case AE_VENDOR_ASANTE:
     86 		case AE_VENDOR_FARALLON:
     87 		case AE_VENDOR_INTERLAN:
     88 		case AE_VENDOR_KINETICS:
     89 			rv = 1;
     90 			break;
     91 		case AE_VENDOR_DAYNA:
     92 		case AE_VENDOR_FOCUS:
     93 			rv = UNSUPP;
     94 			break;
     95 		default:
     96 			break;
     97 		}
     98 	}
     99 
    100 	bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
    101 
    102 	return rv;
    103 }
    104 
    105 /*
    106  * Install interface into kernel networking data structures
    107  */
    108 static void
    109 ae_nubus_attach(parent, self, aux)
    110 	struct device *parent, *self;
    111 	void   *aux;
    112 {
    113 	struct ae_softc *sc = (struct ae_softc *) self;
    114 	struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
    115 	bus_space_tag_t bst;
    116 	bus_space_handle_t bsh;
    117 	int success;
    118 #ifdef AE_OLD_GET_ENADDR
    119 	int i;
    120 #endif
    121 
    122 	bst = na->na_tag;
    123 	if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
    124 	    0, &bsh)) {
    125 		printf(": can't map memory space\n");
    126 		return;
    127 	}
    128 
    129 	sc->sc_reg_tag = sc->sc_buf_tag = bst;
    130 	sc->sc_flags = self->dv_cfdata->cf_flags;
    131 	sc->regs_rev = 0;
    132 	sc->use16bit = 1;
    133 	sc->vendor = ae_card_vendor(na);
    134 	strncpy(sc->type_str, nubus_get_card_name(na->fmt),
    135 	    INTERFACE_NAME_LEN);
    136 	sc->type_str[INTERFACE_NAME_LEN-1] = '\0';
    137 	sc->mem_size = 0;
    138 
    139 	success = 0;
    140 
    141 	switch (sc->vendor) {
    142 	case AE_VENDOR_APPLE:	/* Apple-compatible cards */
    143 	case AE_VENDOR_ASANTE:
    144 		sc->regs_rev = 1;
    145 		if (bus_space_subregion(bst, bsh,
    146 		    AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
    147 			printf(": failed to map register space\n");
    148 			break;
    149 		}
    150 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
    151 		    AE_DATA_OFFSET)) == 0) {
    152 			printf(": failed to determine size of RAM.\n");
    153 			break;
    154 		}
    155 		if (bus_space_subregion(bst, bsh,
    156 		    AE_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
    157 			printf(": failed to map register space\n");
    158 			break;
    159 		}
    160 #ifdef AE_OLD_GET_ENADDR
    161 		/* Get station address from on-board ROM */
    162 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
    163 			sc->sc_arpcom.ac_enaddr[i] =
    164 			    bus_space_read_1(bst, bsh, (AE_ROM_OFFSET + i * 2));
    165 #else
    166 		if (ae_get_enaddr(na, sc->sc_arpcom.ac_enaddr)) {
    167 			printf(": can't find MAC address\n");
    168 			break;
    169 		}
    170 #endif
    171 
    172 		success = 1;
    173 		break;
    174 
    175 	case AE_VENDOR_DAYNA:
    176 		if (bus_space_subregion(bst, bsh,
    177 		    DP_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
    178 			printf(": failed to map register space\n");
    179 			break;
    180 		}
    181 		sc->mem_size = 8192;
    182 		if (bus_space_subregion(bst, bsh,
    183 		    DP_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
    184 			printf(": failed to map register space\n");
    185 			break;
    186 		}
    187 #ifdef AE_OLD_GET_ENADDR
    188 		/* Get station address from on-board ROM */
    189 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
    190 			sc->sc_arpcom.ac_enaddr[i] =
    191 			    bus_space_read_1(bst, bsh, (DP_ROM_OFFSET + i * 2));
    192 #else
    193 		if (ae_get_enaddr(na, sc->sc_arpcom.ac_enaddr)) {
    194 			printf(": can't find MAC address\n");
    195 			break;
    196 		}
    197 #endif
    198 
    199 		printf(": unsupported Dayna hardware\n");
    200 		break;
    201 
    202 	case AE_VENDOR_FARALLON:
    203 		sc->regs_rev = 1;
    204 		if (bus_space_subregion(bst, bsh,
    205 		    AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
    206 			printf(": failed to map register space\n");
    207 			break;
    208 		}
    209 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
    210 		    AE_DATA_OFFSET)) == 0) {
    211 			printf(": failed to determine size of RAM.\n");
    212 			break;
    213 		}
    214 		if (bus_space_subregion(bst, bsh,
    215 		    AE_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
    216 			printf(": failed to map register space\n");
    217 			break;
    218 		}
    219 #ifdef AE_OLD_GET_ENADDR
    220 		/* Get station address from on-board ROM */
    221 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
    222 			sc->sc_arpcom.ac_enaddr[i] =
    223 			    bus_space_read_1(bst, bsh, (FE_ROM_OFFSET + i));
    224 #endif
    225 
    226 		success = 1;
    227 		break;
    228 
    229 	case AE_VENDOR_FOCUS:
    230 		printf(": unsupported Focus hardware\n");
    231 		break;
    232 
    233 	case AE_VENDOR_INTERLAN:
    234 		if (bus_space_subregion(bst, bsh,
    235 		    GC_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
    236 			printf(": failed to map register space\n");
    237 			break;
    238 		}
    239 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
    240 		    GC_DATA_OFFSET)) == 0) {
    241 			printf(": failed to determine size of RAM.\n");
    242 			break;
    243 		}
    244 		if (bus_space_subregion(bst, bsh,
    245 		    GC_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
    246 			printf(": failed to map register space\n");
    247 			break;
    248 		}
    249 
    250 		/* reset the NIC chip */
    251 		bus_space_write_1(bst, bsh, GC_RESET_OFFSET, 0);
    252 
    253 #ifdef AE_OLD_GET_ENADDR
    254 		/* Get station address from on-board ROM */
    255 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
    256 			sc->sc_arpcom.ac_enaddr[i] =
    257 			    bus_space_read_1(bst, bsh, (GC_ROM_OFFSET + i * 4));
    258 #else
    259 		if (ae_get_enaddr(na, sc->sc_arpcom.ac_enaddr)) {
    260 			printf(": can't find MAC address\n");
    261 			break;
    262 		}
    263 #endif
    264 
    265 		success = 1;
    266 		break;
    267 
    268 	case AE_VENDOR_KINETICS:
    269 		sc->use16bit = 0;
    270 		if (bus_space_subregion(bst, bsh,
    271 		    KE_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
    272 			printf(": failed to map register space\n");
    273 			break;
    274 		}
    275 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
    276 		    KE_DATA_OFFSET)) == 0) {
    277 			printf(": failed to determine size of RAM.\n");
    278 			break;
    279 		}
    280 		if (bus_space_subregion(bst, bsh,
    281 		    KE_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
    282 			printf(": failed to map register space\n");
    283 			break;
    284 		}
    285 		if (ae_get_enaddr(na, sc->sc_arpcom.ac_enaddr)) {
    286 			printf(": can't find MAC address\n");
    287 			break;
    288 		}
    289 
    290 		success = 1;
    291 		break;
    292 
    293 	default:
    294 		break;
    295 	}
    296 
    297 	if (!success) {
    298 		bus_space_unmap(bst, bsh, NBMEMSIZE);
    299 		return;
    300 	}
    301 
    302 	aesetup(sc);
    303 
    304 	/* make sure interrupts are vectored to us */
    305 	add_nubus_intr(na->slot, aeintr, sc);
    306 
    307 	/*
    308 	 * XXX -- enable nubus interrupts here.  Should be done elsewhere,
    309 	 *        but that currently breaks with some nubus video cards'
    310 	 *	  interrupts.  So we only enable nubus interrupts if we
    311 	 *	  have an ethernet card...  i.e., we do it here.
    312 	 */
    313 	enable_nubus_intr();
    314 }
    315 
    316 static int
    317 ae_card_vendor(na)
    318 	struct nubus_attach_args *na;
    319 {
    320 	int vendor;
    321 
    322 	switch (na->drsw) {
    323 	case NUBUS_DRSW_3COM:
    324 	case NUBUS_DRSW_APPLE:
    325 	case NUBUS_DRSW_TECHWORKS:
    326 		vendor = AE_VENDOR_APPLE;
    327 		break;
    328 	case NUBUS_DRSW_ASANTE:
    329 		vendor = AE_VENDOR_ASANTE;
    330 		break;
    331 	case NUBUS_DRSW_FARALLON:
    332 		vendor = AE_VENDOR_FARALLON;
    333 		break;
    334 	case NUBUS_DRSW_FOCUS:
    335 		vendor = AE_VENDOR_FOCUS;
    336 		break;
    337 	case NUBUS_DRSW_GATOR:
    338 		switch (na->drhw) {
    339 		default:
    340 		case NUBUS_DRHW_INTERLAN:
    341 			vendor = AE_VENDOR_INTERLAN;
    342 			break;
    343 		case NUBUS_DRHW_KINETICS:
    344 			if (strncmp(
    345 			    nubus_get_card_name(na->fmt), "EtherPort", 9) == 0)
    346 				vendor = AE_VENDOR_KINETICS;
    347 			else
    348 				vendor = AE_VENDOR_DAYNA;
    349 			break;
    350 		}
    351 		break;
    352 	default:
    353 #ifdef AE_DEBUG
    354 		printf("Unknown ethernet drsw: %x\n", na->drsw);
    355 #endif
    356 		vendor = AE_VENDOR_UNKNOWN;
    357 	}
    358 	return vendor;
    359 }
    360 
    361 static int
    362 ae_get_enaddr(na, ep)
    363 	struct nubus_attach_args *na;
    364 	u_int8_t *ep;
    365 {
    366 	nubus_dir dir;
    367 	nubus_dirent dirent;
    368 
    369 	/*
    370 	 * XXX - note hardwired resource IDs here (0x80); these are
    371 	 * assumed to be used by all cards, but should be fixed when
    372 	 * we find out more about Ethernet card resources.
    373 	 */
    374 	nubus_get_main_dir(na->fmt, &dir);
    375 	if (nubus_find_rsrc(na->fmt, &dir, 0x80, &dirent) <= 0)
    376 		return 1;
    377 	nubus_get_dir_from_rsrc(na->fmt, &dirent, &dir);
    378 	if (nubus_find_rsrc(na->fmt, &dir, 0x80, &dirent) <= 0)
    379 		return 1;
    380 	if (nubus_get_ind_data(na->fmt, &dirent, ep, ETHER_ADDR_LEN) <= 0)
    381 		return 1;
    382 
    383 	return 0;
    384 }
    385