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