Home | History | Annotate | Line # | Download | only in nubus
if_ae_nubus.c revision 1.1
      1 /*	$NetBSD: if_ae_nubus.c,v 1.1 1997/02/24 06:03:58 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 "bpfilter.h"
     35 
     36 #include <sys/param.h>
     37 #include <sys/device.h>
     38 #include <sys/errno.h>
     39 #include <sys/ioctl.h>
     40 #include <sys/socket.h>
     41 #include <sys/systm.h>
     42 
     43 #include <net/if.h>
     44 #include <net/if_dl.h>
     45 #include <net/if_types.h>
     46 #include <net/netisr.h>
     47 
     48 #ifdef INET
     49 #include <netinet/in.h>
     50 #include <netinet/in_systm.h>
     51 #include <netinet/in_var.h>
     52 #include <netinet/ip.h>
     53 #include <netinet/if_ether.h>
     54 #endif
     55 
     56 #ifdef NS
     57 #include <netns/ns.h>
     58 #include <netns/ns_if.h>
     59 #endif
     60 
     61 #if NBPFILTER > 0
     62 #include <net/bpf.h>
     63 #include <net/bpfdesc.h>
     64 #endif
     65 
     66 #include <machine/bus.h>
     67 #include <machine/viareg.h>
     68 
     69 #include "nubus.h"
     70 #include <dev/ic/dp8390reg.h>
     71 #include "if_aereg.h"
     72 #include "if_aevar.h"
     73 
     74 static int	ae_nubus_match __P((struct device *, struct cfdata *, void *));
     75 static void	ae_nubus_attach __P((struct device *, struct device *, void *));
     76 static int	ae_card_vendor __P((struct nubus_attach_args *na));
     77 
     78 struct cfattach ae_nubus_ca = {
     79 	sizeof(struct ae_softc), ae_nubus_match, ae_nubus_attach
     80 };
     81 
     82 static int
     83 ae_nubus_match(parent, cf, aux)
     84 	struct device *parent;
     85 	struct cfdata *cf;
     86 	void *aux;
     87 {
     88 	struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
     89 	bus_space_handle_t bsh;
     90 	int rv;
     91 
     92 	if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
     93 	    0, &bsh))
     94 		return (0);
     95 
     96 	rv = 0;
     97 
     98 	if (na->category == NUBUS_CATEGORY_NETWORK &&
     99 	    na->type == NUBUS_TYPE_ETHERNET) {
    100 		switch (ae_card_vendor(na)) {
    101 		case AE_VENDOR_APPLE:
    102 		case AE_VENDOR_ASANTE:
    103 		case AE_VENDOR_FARALLON:
    104 		case AE_VENDOR_INTERLAN:
    105 			rv = 1;
    106 			break;
    107 		case AE_VENDOR_DAYNA:
    108 		case AE_VENDOR_FOCUS:
    109 			rv = UNSUPP;
    110 			break;
    111 		default:
    112 			break;
    113 		}
    114 	}
    115 
    116 	bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
    117 
    118 	return rv;
    119 }
    120 
    121 /*
    122  * Install interface into kernel networking data structures
    123  */
    124 static void
    125 ae_nubus_attach(parent, self, aux)
    126 	struct device *parent, *self;
    127 	void   *aux;
    128 {
    129 	struct ae_softc *sc = (struct ae_softc *) self;
    130 	struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
    131 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    132 	bus_space_tag_t bst;
    133 	bus_space_handle_t bsh;
    134 	int i, success;
    135 	int flags = 0;
    136 
    137 	bst = na->na_tag;
    138 	if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
    139 	    0, &bsh)) {
    140 		printf(": can't map memory space\n");
    141 		return;
    142 	}
    143 
    144 	sc->regs_rev = 0;
    145 	sc->vendor = ae_card_vendor(na);
    146 	strncpy(sc->type_str, nubus_get_card_name(na->fmt),
    147 	    INTERFACE_NAME_LEN);
    148 	sc->type_str[INTERFACE_NAME_LEN-1] = '\0';
    149 	sc->mem_size = 0;
    150 
    151 	success = 0;
    152 
    153 	switch (sc->vendor) {
    154 	case AE_VENDOR_INTERLAN:
    155 		if (bus_space_subregion(bst, bsh,
    156 		    GC_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
    157 			printf(": failed to map register space\n");
    158 			break;
    159 		}
    160 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
    161 		    GC_DATA_OFFSET)) == 0) {
    162 			printf(": failed to determine size of RAM.\n");
    163 			break;
    164 		}
    165 		if (bus_space_subregion(bst, bsh,
    166 		    GC_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
    167 			printf(": failed to map register space\n");
    168 			break;
    169 		}
    170 
    171 		/* reset the NIC chip */
    172 		bus_space_write_1(bst, bsh, GC_RESET_OFFSET, 0);
    173 
    174 		/* Get station address from on-board ROM */
    175 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
    176 			sc->sc_arpcom.ac_enaddr[i] =
    177 			    bus_space_read_1(bst, bsh, (GC_ROM_OFFSET + i * 4));
    178 
    179 		success = 1;
    180 		break;
    181 
    182 		/* Apple-compatible cards */
    183 	case AE_VENDOR_ASANTE:
    184 	case AE_VENDOR_APPLE:
    185 		sc->regs_rev = 1;
    186 		if (bus_space_subregion(bst, bsh,
    187 		    AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
    188 			printf(": failed to map register space\n");
    189 			break;
    190 		}
    191 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
    192 		    AE_DATA_OFFSET)) == 0) {
    193 			printf(": failed to determine size of RAM.\n");
    194 			break;
    195 		}
    196 		if (bus_space_subregion(bst, bsh,
    197 		    AE_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
    198 			printf(": failed to map register space\n");
    199 			break;
    200 		}
    201 
    202 		/* Get station address from on-board ROM */
    203 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
    204 			sc->sc_arpcom.ac_enaddr[i] =
    205 			    bus_space_read_1(bst, bsh, (AE_ROM_OFFSET + i * 2));
    206 
    207 		success = 1;
    208 		break;
    209 
    210 	case AE_VENDOR_DAYNA:
    211 		if (bus_space_subregion(bst, bsh,
    212 		    DP_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
    213 			printf(": failed to map register space\n");
    214 			break;
    215 		}
    216 		sc->mem_size = 8192;
    217 		if (bus_space_subregion(bst, bsh,
    218 		    DP_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
    219 			printf(": failed to map register space\n");
    220 			break;
    221 		}
    222 
    223 		/* Get station address from on-board ROM */
    224 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
    225 			sc->sc_arpcom.ac_enaddr[i] =
    226 			    bus_space_read_1(bst, bsh, (DP_ROM_OFFSET + i * 2));
    227 
    228 		printf(": unsupported Dayna hardware\n");
    229 		break;
    230 
    231 	case AE_VENDOR_FARALLON:
    232 		sc->regs_rev = 1;
    233 		if (bus_space_subregion(bst, bsh,
    234 		    AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
    235 			printf(": failed to map register space\n");
    236 			break;
    237 		}
    238 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
    239 		    AE_DATA_OFFSET)) == 0) {
    240 			printf(": failed to determine size of RAM.\n");
    241 			break;
    242 		}
    243 		if (bus_space_subregion(bst, bsh,
    244 		    AE_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
    245 			printf(": failed to map register space\n");
    246 			break;
    247 		}
    248 
    249 		/* Get station address from on-board ROM */
    250 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
    251 			sc->sc_arpcom.ac_enaddr[i] =
    252 			    bus_space_read_1(bst, bsh, (FE_ROM_OFFSET + i));
    253 
    254 		success = 1;
    255 		break;
    256 
    257 	case AE_VENDOR_FOCUS:
    258 		printf(": unsupported Focus hardware\n");
    259 		break;
    260 
    261 	default:
    262 		break;
    263 	}
    264 
    265 	if (!success) {
    266 		bus_space_unmap(bst, bsh, NBMEMSIZE);
    267 		return;
    268 	}
    269 
    270 	sc->sc_reg_tag = sc->sc_buf_tag = bst;
    271 
    272 	sc->cr_proto = ED_CR_RD2;
    273 
    274 	/* Allocate one xmit buffer if < 16k, two buffers otherwise. */
    275 	if ((sc->mem_size < 16384) || (flags & AE_FLAGS_NO_DOUBLE_BUFFERING))
    276 		sc->txb_cnt = 1;
    277 	else
    278 		sc->txb_cnt = 2;
    279 
    280 	sc->tx_page_start = 0;
    281 	sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
    282 	sc->rec_page_stop = sc->tx_page_start + (sc->mem_size >> ED_PAGE_SHIFT);
    283 	sc->mem_ring = sc->rec_page_start << ED_PAGE_SHIFT;
    284 
    285 	/* Now zero memory and verify that it is clear. */
    286 	bus_space_set_region_2(sc->sc_buf_tag, sc->sc_buf_handle, 0,
    287 	    0, sc->mem_size / 2);
    288 
    289 	for (i = 0; i < sc->mem_size; ++i)
    290 		if (bus_space_read_1(sc->sc_buf_tag, sc->sc_buf_handle, i))
    291 printf("%s: failed to clear shared memory - check configuration\n",
    292 			    sc->sc_dev.dv_xname);
    293 
    294 	/* Set interface to stopped condition (reset). */
    295 	aestop(sc);
    296 
    297 	/* Initialize ifnet structure. */
    298 	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
    299 	ifp->if_softc = sc;
    300 	ifp->if_start = aestart;
    301 	ifp->if_ioctl = aeioctl;
    302 	ifp->if_watchdog = aewatchdog;
    303 	ifp->if_flags =
    304 	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
    305 
    306 	/* Attach the interface. */
    307 	if_attach(ifp);
    308 	ether_ifattach(ifp);
    309 
    310 	/* Print additional info when attached. */
    311 	printf(": address %s, ", ether_sprintf(sc->sc_arpcom.ac_enaddr));
    312 
    313 	printf("type %s, %dKB memory\n", sc->type_str, sc->mem_size / 1024);
    314 
    315 #if NBPFILTER > 0
    316 	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
    317 #endif
    318 
    319 	/* make sure interrupts are vectored to us */
    320 	add_nubus_intr(na->slot, aeintr, sc);
    321 
    322 	/*
    323 	 * XXX -- enable nubus interrupts here.  Should be done elsewhere,
    324 	 *        but that currently breaks with some nubus video cards'
    325 	 *	  interrupts.  So we only enable nubus interrupts if we
    326 	 *	  have an ethernet card...  i.e., we do it here.
    327 	 */
    328 	enable_nubus_intr();
    329 }
    330 
    331 static int
    332 ae_card_vendor(na)
    333 	struct nubus_attach_args *na;
    334 {
    335 	int vendor;
    336 
    337 	switch (na->drsw) {
    338 	case NUBUS_DRSW_3COM:
    339 	case NUBUS_DRSW_APPLE:
    340 	case NUBUS_DRSW_TECHWORKS:
    341 		vendor = AE_VENDOR_APPLE;
    342 		break;
    343 	case NUBUS_DRSW_ASANTE:
    344 		vendor = AE_VENDOR_ASANTE;
    345 		break;
    346 	case NUBUS_DRSW_FARALLON:
    347 		vendor = AE_VENDOR_FARALLON;
    348 		break;
    349 	case NUBUS_DRSW_FOCUS:
    350 		vendor = AE_VENDOR_FOCUS;
    351 		break;
    352 	case NUBUS_DRSW_GATOR:
    353 		switch (na->drhw) {
    354 		default:
    355 		case NUBUS_DRHW_INTERLAN:
    356 			vendor = AE_VENDOR_INTERLAN;
    357 			break;
    358 		case NUBUS_DRHW_KINETICS:
    359 			vendor = AE_VENDOR_DAYNA;
    360 			break;
    361 		}
    362 		break;
    363 	default:
    364 #ifdef AE_DEBUG
    365 		printf("Unknown ethernet drsw: %x\n", na->drsw);
    366 #endif
    367 		vendor = AE_VENDOR_UNKNOWN;
    368 	}
    369 	return vendor;
    370 }
    371