1/* $NetBSD: if_ae_nubus.c,v 1.40 2008/04/04 09:49:33 hauke 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. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29/* 30 * Some parts are derived from code adapted for MacBSD by Brad Parker 31 * <brad@fcr.com>. 32 * 33 * Currently supports: 34 * Apple NB Ethernet Card 35 * Apple NB Ethernet Card II 36 * Interlan A310 NuBus Ethernet card 37 * Cayman Systems GatorCard 38 * Asante MacCon II/E 39 * Kinetics EtherPort SE/30 40 */ 41 42#include <sys/cdefs.h> 43__KERNEL_RCSID(0, "$NetBSD: if_ae_nubus.c,v 1.40 2008/04/04 09:49:33 hauke Exp $"); 44 45#include <sys/param.h> 46#include <sys/device.h> 47#include <sys/errno.h> 48#include <sys/ioctl.h> 49#include <sys/malloc.h> 50#include <sys/socket.h> 51#include <sys/syslog.h> 52#include <sys/systm.h> 53 54#include <net/if.h> 55#include <net/if_media.h> 56#include <net/if_ether.h> 57 58#include <machine/bus.h> 59#include <machine/viareg.h> 60 61#include <dev/ic/dp8390reg.h> 62#include <dev/ic/dp8390var.h> 63#include <mac68k/nubus/nubus.h> 64#include <mac68k/dev/if_aevar.h> 65#include <mac68k/dev/if_aereg.h> 66 67static int ae_nubus_match(device_t, cfdata_t, void *); 68static void ae_nubus_attach(device_t, device_t, void *); 69static int ae_nb_card_vendor(bus_space_tag_t, bus_space_handle_t, 70 struct nubus_attach_args *); 71static int ae_nb_get_enaddr(bus_space_tag_t, bus_space_handle_t, 72 struct nubus_attach_args *, u_int8_t *); 73#ifdef DEBUG 74static void ae_nb_watchdog(struct ifnet *); 75#endif 76 77void ae_nubus_intr(void *); 78 79CFATTACH_DECL_NEW(ae_nubus, sizeof(struct dp8390_softc), 80 ae_nubus_match, ae_nubus_attach, NULL, NULL); 81 82static int 83ae_nubus_match(device_t parent, cfdata_t cf, void *aux) 84{ 85 struct nubus_attach_args *na = aux; 86 bus_space_handle_t bsh; 87 int rv; 88 89 if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot), NBMEMSIZE, 90 0, &bsh)) 91 return (0); 92 93 rv = 0; 94 95 if (na->category == NUBUS_CATEGORY_NETWORK && 96 na->type == NUBUS_TYPE_ETHERNET) { 97 switch (ae_nb_card_vendor(na->na_tag, bsh, na)) { 98 case DP8390_VENDOR_APPLE: 99 case DP8390_VENDOR_ASANTE: 100 case DP8390_VENDOR_FARALLON: 101 case DP8390_VENDOR_INTERLAN: 102 case DP8390_VENDOR_KINETICS: 103 case DP8390_VENDOR_CABLETRON: 104 rv = 1; 105 break; 106 case DP8390_VENDOR_DAYNA: 107 rv = UNSUPP; 108 break; 109 default: 110 break; 111 } 112 } 113 114 bus_space_unmap(na->na_tag, bsh, NBMEMSIZE); 115 116 return rv; 117} 118 119/* 120 * Install interface into kernel networking data structures 121 */ 122static void 123ae_nubus_attach(device_t parent, device_t self, void *aux) 124{ 125 struct dp8390_softc *sc = device_private(self); 126 struct nubus_attach_args *na = aux; 127#ifdef DEBUG 128 struct ifnet *ifp = &sc->sc_ec.ec_if; 129#endif 130 bus_space_tag_t bst; 131 bus_space_handle_t bsh; 132 int i, success; 133 const char *cardtype; 134 135 sc->sc_dev = self; 136 bst = na->na_tag; 137 if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE, 138 0, &bsh)) { 139 aprint_error(": can't map memory space\n"); 140 return; 141 } 142 143 sc->sc_regt = sc->sc_buft = bst; 144 sc->sc_flags = device_cfdata(self)->cf_flags; 145 146 cardtype = nubus_get_card_name(bst, bsh, na->fmt); 147 148 sc->is790 = 0; 149 150 sc->mem_start = 0; 151 sc->mem_size = 0; 152 153 success = 0; 154 155 switch (ae_nb_card_vendor(bst, bsh, na)) { 156 case DP8390_VENDOR_APPLE: /* Apple-compatible cards */ 157 case DP8390_VENDOR_ASANTE: 158 /* Map register offsets */ 159 for (i = 0; i < 16; i++) /* reverse order, longword aligned */ 160 sc->sc_reg_map[i] = (15 - i) << 2; 161 162 sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS); 163 if (bus_space_subregion(bst, bsh, 164 AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) { 165 aprint_error(": failed to map register space\n"); 166 break; 167 } 168 if ((sc->mem_size = ae_size_card_memory(bst, bsh, 169 AE_DATA_OFFSET)) == 0) { 170 aprint_error(": failed to determine size of RAM.\n"); 171 break; 172 } 173 if (bus_space_subregion(bst, bsh, 174 AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) { 175 aprint_error(": failed to map register space\n"); 176 break; 177 } 178#ifdef AE_OLD_GET_ENADDR 179 /* Get station address from on-board ROM */ 180 for (i = 0; i < ETHER_ADDR_LEN; ++i) 181 sc->sc_enaddr[i] = 182 bus_space_read_1(bst, bsh, (AE_ROM_OFFSET + i * 2)); 183#else 184 if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) { 185 aprint_error(": can't find MAC address\n"); 186 break; 187 } 188#endif 189 190 success = 1; 191 break; 192 193 case DP8390_VENDOR_DAYNA: 194 /* Map register offsets */ 195 for (i = 0; i < 16; i++) /* normal order, longword aligned */ 196 sc->sc_reg_map[i] = i << 2; 197 198 sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS); 199 if (bus_space_subregion(bst, bsh, 200 DP_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) { 201 aprint_error(": failed to map register space\n"); 202 break; 203 } 204 sc->mem_size = 8192; 205 if (bus_space_subregion(bst, bsh, 206 DP_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) { 207 aprint_error(": failed to map register space\n"); 208 break; 209 } 210#ifdef AE_OLD_GET_ENADDR 211 /* Get station address from on-board ROM */ 212 for (i = 0; i < ETHER_ADDR_LEN; ++i) 213 sc->sc_enaddr[i] = 214 bus_space_read_1(bst, bsh, (DP_ROM_OFFSET + i * 2)); 215#else 216 if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) { 217 aprint_error(": can't find MAC address\n"); 218 break; 219 } 220#endif 221 222 aprint_error(": unsupported Dayna hardware\n"); 223 break; 224 225 case DP8390_VENDOR_FARALLON: 226 /* Map register offsets */ 227 for (i = 0; i < 16; i++) /* reverse order, longword aligned */ 228 sc->sc_reg_map[i] = (15 - i) << 2; 229 230 sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS); 231 if (bus_space_subregion(bst, bsh, 232 AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) { 233 aprint_error(": failed to map register space\n"); 234 break; 235 } 236 if ((sc->mem_size = ae_size_card_memory(bst, bsh, 237 AE_DATA_OFFSET)) == 0) { 238 aprint_error(": failed to determine size of RAM.\n"); 239 break; 240 } 241 if (bus_space_subregion(bst, bsh, 242 AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) { 243 aprint_error(": failed to map register space\n"); 244 break; 245 } 246#ifdef AE_OLD_GET_ENADDR 247 /* Get station address from on-board ROM */ 248 for (i = 0; i < ETHER_ADDR_LEN; ++i) 249 sc->sc_enaddr[i] = 250 bus_space_read_1(bst, bsh, (FE_ROM_OFFSET + i)); 251#else 252 if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) { 253 aprint_error(": can't find MAC address\n"); 254 break; 255 } 256#endif 257 258 success = 1; 259 break; 260 261 case DP8390_VENDOR_INTERLAN: 262 /* Map register offsets */ 263 for (i = 0; i < 16; i++) /* normal order, longword aligned */ 264 sc->sc_reg_map[i] = i << 2; 265 266 sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS); 267 if (bus_space_subregion(bst, bsh, 268 GC_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) { 269 aprint_error(": failed to map register space\n"); 270 break; 271 } 272 if ((sc->mem_size = ae_size_card_memory(bst, bsh, 273 GC_DATA_OFFSET)) == 0) { 274 aprint_error(": failed to determine size of RAM.\n"); 275 break; 276 } 277 if (bus_space_subregion(bst, bsh, 278 GC_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) { 279 aprint_error(": failed to map register space\n"); 280 break; 281 } 282 283 /* reset the NIC chip */ 284 bus_space_write_1(bst, bsh, GC_RESET_OFFSET, 0); 285 286 if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) { 287 /* Fall back to snarf directly from ROM. Ick. */ 288 for (i = 0; i < ETHER_ADDR_LEN; ++i) 289 sc->sc_enaddr[i] = 290 bus_space_read_1(bst, bsh, 291 (GC_ROM_OFFSET + i * 4)); 292 } 293 294 success = 1; 295 break; 296 297 case DP8390_VENDOR_KINETICS: 298 /* Map register offsets */ 299 for (i = 0; i < 16; i++) /* normal order, longword aligned */ 300 sc->sc_reg_map[i] = i << 2; 301 302 if (bus_space_subregion(bst, bsh, 303 KE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) { 304 aprint_error(": failed to map register space\n"); 305 break; 306 } 307 if ((sc->mem_size = ae_size_card_memory(bst, bsh, 308 KE_DATA_OFFSET)) == 0) { 309 aprint_error(": failed to determine size of RAM.\n"); 310 break; 311 } 312 if (bus_space_subregion(bst, bsh, 313 KE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) { 314 aprint_error(": failed to map register space\n"); 315 break; 316 } 317 if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) { 318 aprint_error(": can't find MAC address\n"); 319 break; 320 } 321 322 success = 1; 323 break; 324 325 case DP8390_VENDOR_CABLETRON: 326 /* Map register offsets */ 327 for (i = 0; i < 16; i++) 328 sc->sc_reg_map[i] = i << 1 ; /* normal order, word aligned */ 329 sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS); 330 if (bus_space_subregion(bst, bsh, 331 CT_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) { 332 aprint_error(": failed to map register space\n"); 333 break; 334 } 335 if ((sc->mem_size = ae_size_card_memory(bst, bsh, 336 CT_DATA_OFFSET)) == 0) { 337 aprint_error(": failed to determine size of RAM.\n"); 338 break; 339 } 340 if (bus_space_subregion(bst, bsh, 341 CT_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) { 342 aprint_error(": failed to map register space\n"); 343 break; 344 } 345 if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) { 346 aprint_error(": can't find MAC address\n"); 347 break; 348 } 349 success = 1; 350 break; 351 default: 352 break; 353 } 354 355 if (!success) { 356 bus_space_unmap(bst, bsh, NBMEMSIZE); 357 return; 358 } 359 360 /* 361 * Override test_mem and write_mbuf functions; other defaults 362 * already work properly. 363 */ 364 sc->test_mem = ae_test_mem; 365 sc->write_mbuf = ae_write_mbuf; 366#ifdef DEBUG 367 ifp->if_watchdog = ae_nb_watchdog; /* Override watchdog */ 368#endif 369 sc->sc_media_init = dp8390_media_init; 370 371 /* Interface is always enabled. */ 372 sc->sc_enabled = 1; 373 374 aprint_normal(": %s, %dKB memory\n", cardtype, sc->mem_size / 1024); 375 376 if (dp8390_config(sc)) { 377 bus_space_unmap(bst, bsh, NBMEMSIZE); 378 return; 379 } 380 381 /* make sure interrupts are vectored to us */ 382 add_nubus_intr(na->slot, ae_nubus_intr, sc); 383} 384 385void 386ae_nubus_intr(void *arg) 387{ 388 struct dp8390_softc *sc = arg; 389 390 (void)dp8390_intr(sc); 391} 392 393static int 394ae_nb_card_vendor(bus_space_tag_t bst, bus_space_handle_t bsh, 395 struct nubus_attach_args *na) 396{ 397 int vendor; 398 399 switch (na->drsw) { 400 case NUBUS_DRSW_3COM: 401 switch (na->drhw) { 402 case NUBUS_DRHW_APPLE_SN: 403 case NUBUS_DRHW_APPLE_SNT: 404 vendor = DP8390_VENDOR_UNKNOWN; 405 break; 406 default: 407 vendor = DP8390_VENDOR_APPLE; 408 break; 409 } 410 break; 411 case NUBUS_DRSW_APPLE: 412 if (na->drhw == NUBUS_DRHW_ASANTE_LC) { 413 vendor = DP8390_VENDOR_UNKNOWN; 414 break; 415 } 416 /* FALLTHROUGH */ 417 case NUBUS_DRSW_DAYNA2: 418 case NUBUS_DRSW_TECHWORKS: 419 case NUBUS_DRSW_TFLLAN: 420 if (na->drhw == NUBUS_DRHW_CABLETRON) { 421 vendor = DP8390_VENDOR_CABLETRON; 422 } else { 423 vendor = DP8390_VENDOR_APPLE; 424 } 425 break; 426 case NUBUS_DRSW_ASANTE: 427 vendor = DP8390_VENDOR_ASANTE; 428 break; 429 case NUBUS_DRSW_FARALLON: 430 vendor = DP8390_VENDOR_FARALLON; 431 break; 432 case NUBUS_DRSW_GATOR: 433 switch (na->drhw) { 434 default: 435 case NUBUS_DRHW_INTERLAN: 436 vendor = DP8390_VENDOR_INTERLAN; 437 break; 438 case NUBUS_DRHW_KINETICS: 439 if (strncmp(nubus_get_card_name(bst, bsh, na->fmt), 440 "EtherPort", 9) == 0) 441 vendor = DP8390_VENDOR_KINETICS; 442 else 443 vendor = DP8390_VENDOR_DAYNA; 444 break; 445 } 446 break; 447 default: 448 vendor = DP8390_VENDOR_UNKNOWN; 449 } 450 return vendor; 451} 452 453static int 454ae_nb_get_enaddr(bus_space_tag_t bst, bus_space_handle_t bsh, 455 struct nubus_attach_args *na, u_int8_t *ep) 456{ 457 nubus_dir dir; 458 nubus_dirent dirent; 459 int rv; 460 461 /* 462 * XXX - note hardwired resource IDs here; these are assumed to 463 * be used by all cards, but should be fixed when we find out 464 * more about Ethernet card resources. 465 */ 466 nubus_get_main_dir(na->fmt, &dir); 467 switch (ae_nb_card_vendor(bst, bsh, na)) { 468 case DP8390_VENDOR_APPLE: 469 if (na->drsw == NUBUS_DRSW_TFLLAN) { /* TFL LAN E410/E420 */ 470 rv = nubus_find_rsrc(bst, bsh, na->fmt, 471 &dir, 0x08, &dirent); 472 break; 473 } 474 /*FALLTHROUGH*/ 475 default: 476 rv = nubus_find_rsrc(bst, bsh, na->fmt, &dir, 0x80, &dirent); 477 break; 478 } 479 if (rv <= 0) 480 return 1; 481 nubus_get_dir_from_rsrc(na->fmt, &dirent, &dir); 482 if (nubus_find_rsrc(bst, bsh, na->fmt, &dir, 0x80, &dirent) <= 0) 483 return 1; 484 if (nubus_get_ind_data(bst, bsh, 485 na->fmt, &dirent, ep, ETHER_ADDR_LEN) <= 0) 486 return 1; 487 488 return 0; 489} 490 491#ifdef DEBUG 492static void 493ae_nb_watchdog(struct ifnet *ifp) 494{ 495 struct dp8390_softc *sc = ifp->if_softc; 496 497/* 498 * This is a kludge! The via code seems to miss slot interrupts 499 * sometimes. This kludges around that by calling the handler 500 * by hand if the watchdog is activated. -- XXX (akb) 501 */ 502 (*via2itab[1])((void *)1); 503 504 log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); 505 ++ifp->if_oerrors; 506 507 dp8390_reset(sc); 508} 509#endif 510