Annotation of sys/arch/mac68k/dev/if_ae_nubus.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: if_ae_nubus.c,v 1.17 2007/01/22 13:17:45 martin Exp $ */
! 2: /* $NetBSD: if_ae_nubus.c,v 1.17 1997/05/01 18:17:16 briggs Exp $ */
! 3:
! 4: /*
! 5: * Copyright (C) 1997 Scott Reynolds
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. The name of the author may not be used to endorse or promote products
! 17: * derived from this software without specific prior written permission.
! 18: *
! 19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 20: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 21: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 22: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 24: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 28: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 29: */
! 30: /*
! 31: * Some parts are derived from code adapted for MacBSD by Brad Parker
! 32: * <brad@fcr.com>.
! 33: *
! 34: * Currently supports:
! 35: * Apple NB Ethernet Card
! 36: * Apple NB Ethernet Card II
! 37: * Interlan A310 NuBus Ethernet card
! 38: * Cayman Systems GatorCard
! 39: * Asante MacCon II/E
! 40: * Kinetics EtherPort SE/30
! 41: */
! 42:
! 43: #define AE_OLD_GET_ENADDR
! 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:
! 55: #ifdef INET
! 56: #include <netinet/in.h>
! 57: #include <netinet/if_ether.h>
! 58: #endif
! 59:
! 60: #include <machine/bus.h>
! 61: #include <machine/viareg.h>
! 62:
! 63: #include <net/if_media.h>
! 64:
! 65: #include <dev/ic/dp8390reg.h>
! 66: #include <dev/ic/dp8390var.h>
! 67: #include <mac68k/dev/nubus.h>
! 68: #include <mac68k/dev/if_aevar.h>
! 69: #include <mac68k/dev/if_aereg.h>
! 70:
! 71: static int ae_nubus_match(struct device *, void *, void *);
! 72: static void ae_nubus_attach(struct device *, struct device *, void *);
! 73: static int ae_nb_card_vendor(bus_space_tag_t, bus_space_handle_t,
! 74: struct nubus_attach_args *);
! 75: static int ae_nb_get_enaddr(bus_space_tag_t, bus_space_handle_t,
! 76: struct nubus_attach_args *, u_int8_t *);
! 77: #ifdef DEBUG
! 78: static void ae_nb_watchdog(struct ifnet *);
! 79: #endif
! 80:
! 81: struct cfattach ae_nubus_ca = {
! 82: sizeof(struct dp8390_softc), ae_nubus_match, ae_nubus_attach
! 83: };
! 84:
! 85: static int
! 86: ae_nubus_match(parent, vcf, aux)
! 87: struct device *parent;
! 88: void *vcf;
! 89: void *aux;
! 90: {
! 91: struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
! 92: bus_space_handle_t bsh;
! 93: int rv = 0;
! 94:
! 95: if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
! 96: 0, &bsh))
! 97: return (0);
! 98:
! 99: if (na->category == NUBUS_CATEGORY_NETWORK &&
! 100: na->type == NUBUS_TYPE_ETHERNET) {
! 101: switch (ae_nb_card_vendor(na->na_tag, bsh, na)) {
! 102: case DP8390_VENDOR_APPLE:
! 103: case DP8390_VENDOR_ASANTE:
! 104: case DP8390_VENDOR_FARALLON:
! 105: case DP8390_VENDOR_INTERLAN:
! 106: case DP8390_VENDOR_KINETICS:
! 107: case DP8390_VENDOR_CABLETRON:
! 108: rv = 1;
! 109: break;
! 110: case DP8390_VENDOR_DAYNA:
! 111: case DP8390_VENDOR_FOCUS:
! 112: /* not supported yet */
! 113: /* FALLTHROUGH */
! 114: default:
! 115: rv = 0;
! 116: break;
! 117: }
! 118: }
! 119:
! 120: bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
! 121:
! 122: return (rv);
! 123: }
! 124:
! 125: /*
! 126: * Install interface into kernel networking data structures
! 127: */
! 128: static void
! 129: ae_nubus_attach(parent, self, aux)
! 130: struct device *parent, *self;
! 131: void *aux;
! 132: {
! 133: struct dp8390_softc *sc = (struct dp8390_softc *)self;
! 134: struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
! 135: #ifdef DEBUG
! 136: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 137: #endif
! 138: bus_space_tag_t bst;
! 139: bus_space_handle_t bsh;
! 140: int i, success;
! 141: const char *cardtype;
! 142:
! 143: bst = na->na_tag;
! 144: if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
! 145: 0, &bsh)) {
! 146: printf(": can't map memory space\n");
! 147: return;
! 148: }
! 149:
! 150: sc->sc_regt = sc->sc_buft = bst;
! 151: sc->sc_flags = self->dv_cfdata->cf_flags;
! 152:
! 153: cardtype = nubus_get_card_name(bst, bsh, na->fmt);
! 154:
! 155: sc->is790 = 0;
! 156:
! 157: sc->mem_start = 0;
! 158: sc->mem_size = 0;
! 159:
! 160: success = 0;
! 161:
! 162: switch (ae_nb_card_vendor(bst, bsh, na)) {
! 163: case DP8390_VENDOR_APPLE: /* Apple-compatible cards */
! 164: case DP8390_VENDOR_ASANTE:
! 165: /* Map register offsets */
! 166: for (i = 0; i < 16; i++) /* reverse order, longword aligned */
! 167: sc->sc_reg_map[i] = (15 - i) << 2;
! 168:
! 169: sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
! 170: if (bus_space_subregion(bst, bsh,
! 171: AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
! 172: printf(": failed to map register space\n");
! 173: break;
! 174: }
! 175: if ((sc->mem_size = ae_size_card_memory(bst, bsh,
! 176: AE_DATA_OFFSET)) == 0) {
! 177: printf(": failed to determine size of RAM.\n");
! 178: break;
! 179: }
! 180: if (bus_space_subregion(bst, bsh,
! 181: AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
! 182: printf(": failed to map register space\n");
! 183: break;
! 184: }
! 185: #ifdef AE_OLD_GET_ENADDR
! 186: /* Get station address from on-board ROM */
! 187: for (i = 0; i < ETHER_ADDR_LEN; ++i)
! 188: sc->sc_arpcom.ac_enaddr[i] =
! 189: bus_space_read_1(bst, bsh, (AE_ROM_OFFSET + i * 2));
! 190: #else
! 191: if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_arpcom.ac_enaddr)) {
! 192: printf(": can't find MAC address\n");
! 193: break;
! 194: }
! 195: #endif
! 196:
! 197: success = 1;
! 198: break;
! 199:
! 200: case DP8390_VENDOR_DAYNA:
! 201: /* Map register offsets */
! 202: for (i = 0; i < 16; i++) /* normal order, longword aligned */
! 203: sc->sc_reg_map[i] = i << 2;
! 204:
! 205: sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
! 206: if (bus_space_subregion(bst, bsh,
! 207: DP_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
! 208: printf(": failed to map register space\n");
! 209: break;
! 210: }
! 211: sc->mem_size = 8192;
! 212: if (bus_space_subregion(bst, bsh,
! 213: DP_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
! 214: printf(": failed to map register space\n");
! 215: break;
! 216: }
! 217: #ifdef AE_OLD_GET_ENADDR
! 218: /* Get station address from on-board ROM */
! 219: for (i = 0; i < ETHER_ADDR_LEN; ++i)
! 220: sc->sc_arpcom.ac_enaddr[i] =
! 221: bus_space_read_1(bst, bsh, (DP_ROM_OFFSET + i * 2));
! 222: #else
! 223: if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_arpcom.ac_enaddr)) {
! 224: printf(": can't find MAC address\n");
! 225: break;
! 226: }
! 227: #endif
! 228:
! 229: case DP8390_VENDOR_FARALLON:
! 230: /* Map register offsets */
! 231: for (i = 0; i < 16; i++) /* reverse order, longword aligned */
! 232: sc->sc_reg_map[i] = (15 - i) << 2;
! 233:
! 234: sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
! 235: if (bus_space_subregion(bst, bsh,
! 236: AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
! 237: printf(": failed to map register space\n");
! 238: break;
! 239: }
! 240: if ((sc->mem_size = ae_size_card_memory(bst, bsh,
! 241: AE_DATA_OFFSET)) == 0) {
! 242: printf(": failed to determine size of RAM.\n");
! 243: break;
! 244: }
! 245: if (bus_space_subregion(bst, bsh,
! 246: AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
! 247: printf(": failed to map register space\n");
! 248: break;
! 249: }
! 250: #ifdef AE_OLD_GET_ENADDR
! 251: /* Get station address from on-board ROM */
! 252: for (i = 0; i < ETHER_ADDR_LEN; ++i)
! 253: sc->sc_arpcom.ac_enaddr[i] =
! 254: bus_space_read_1(bst, bsh, (FE_ROM_OFFSET + i));
! 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: printf(": 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: printf(": 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: printf(": 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_arpcom.ac_enaddr)) {
! 286: /* Fall back to snarf directly from ROM. Ick. */
! 287: for (i = 0; i < ETHER_ADDR_LEN; ++i)
! 288: sc->sc_arpcom.ac_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: /* sc->use16bit = 0; */
! 302: if (bus_space_subregion(bst, bsh,
! 303: KE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
! 304: printf(": 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: printf(": 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: printf(": failed to map register space\n");
! 315: break;
! 316: }
! 317: if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_arpcom.ac_enaddr)) {
! 318: printf(": can't find MAC address\n");
! 319: break;
! 320: }
! 321:
! 322: success = 1;
! 323: break;
! 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:
! 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: printf(": 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: printf(": 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: printf(": failed to map register space\n");
! 343: break;
! 344: }
! 345: if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_arpcom.ac_enaddr)) {
! 346: printf(": can't find MAC address\n");
! 347: break;
! 348: }
! 349: success = 1;
! 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: printf(": %s, %dKB memory", 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, dp8390_intr, sc, sc->sc_dev.dv_xname);
! 382: }
! 383:
! 384: static int
! 385: ae_nb_card_vendor(bst, bsh, na)
! 386: bus_space_tag_t bst;
! 387: bus_space_handle_t bsh;
! 388: struct nubus_attach_args *na;
! 389: {
! 390: int vendor;
! 391:
! 392: switch (na->drsw) {
! 393: case NUBUS_DRSW_3COM:
! 394: switch (na->drhw) {
! 395: case NUBUS_DRHW_APPLE_SN:
! 396: case NUBUS_DRHW_APPLE_SNT:
! 397: vendor = DP8390_VENDOR_UNKNOWN;
! 398: break;
! 399: default:
! 400: vendor = DP8390_VENDOR_APPLE;
! 401: break;
! 402: }
! 403: break;
! 404: case NUBUS_DRSW_APPLE:
! 405: if (na->drhw == NUBUS_DRHW_ASANTE_LC) {
! 406: vendor = DP8390_VENDOR_UNKNOWN;
! 407: break;
! 408: }
! 409: /* FALLTHROUGH */
! 410: case NUBUS_DRSW_DAYNA2:
! 411: case NUBUS_DRSW_TECHWORKS:
! 412: case NUBUS_DRSW_TFLLAN:
! 413: if (na->drhw == NUBUS_DRHW_CABLETRON) {
! 414: vendor = DP8390_VENDOR_CABLETRON;
! 415: } else {
! 416: vendor = DP8390_VENDOR_APPLE;
! 417: }
! 418: break;
! 419: case NUBUS_DRSW_ASANTE:
! 420: vendor = DP8390_VENDOR_ASANTE;
! 421: break;
! 422: case NUBUS_DRSW_FARALLON:
! 423: vendor = DP8390_VENDOR_FARALLON;
! 424: break;
! 425: case NUBUS_DRSW_FOCUS:
! 426: vendor = DP8390_VENDOR_FOCUS;
! 427: break;
! 428: case NUBUS_DRSW_GATOR:
! 429: switch (na->drhw) {
! 430: default:
! 431: case NUBUS_DRHW_INTERLAN:
! 432: vendor = DP8390_VENDOR_INTERLAN;
! 433: break;
! 434: case NUBUS_DRHW_KINETICS:
! 435: if (strncmp(nubus_get_card_name(bst, bsh, na->fmt),
! 436: "EtherPort", 9) == 0)
! 437: vendor = DP8390_VENDOR_KINETICS;
! 438: else
! 439: vendor = DP8390_VENDOR_DAYNA;
! 440: break;
! 441: }
! 442: break;
! 443: default:
! 444: vendor = DP8390_VENDOR_UNKNOWN;
! 445: }
! 446: return vendor;
! 447: }
! 448:
! 449: static int
! 450: ae_nb_get_enaddr(bst, bsh, na, ep)
! 451: bus_space_tag_t bst;
! 452: bus_space_handle_t bsh;
! 453: struct nubus_attach_args *na;
! 454: 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 (0x80); these are
! 462: * assumed to be used by all cards, but should be fixed when
! 463: * we find out 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, 0x80, &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(ifp)
! 493: struct ifnet *ifp;
! 494: {
! 495: struct dp8390_softc *sc = ifp->if_softc;
! 496: extern via2hand_t via2intrs[7];
! 497:
! 498: /*
! 499: * This is a kludge! The via code seems to miss slot interrupts
! 500: * sometimes. This kludges around that by calling the handler
! 501: * by hand if the watchdog is activated. -- XXX (akb)
! 502: * XXX note that this assumes the nubus handler is first in the chain.
! 503: */
! 504: if (!SLIST_EMPTY(&via2intrs[1])) {
! 505: struct via2hand *vh = SLIST_FIRST(&via2intrs[1]);
! 506: (void)(*vh->vh_fn)(vh->vh_arg);
! 507: }
! 508:
! 509: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
! 510: ++sc->sc_arpcom.ac_if.if_oerrors;
! 511:
! 512: dp8390_reset(sc);
! 513: }
! 514: #endif
CVSweb