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