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