1 /* $NetBSD: if_sn_obio.c,v 1.28 2008/04/23 13:29:45 tsutsui Exp $ */ 2 3 /* 4 * Copyright (C) 1997 Allen Briggs 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Allen Briggs 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: if_sn_obio.c,v 1.28 2008/04/23 13:29:45 tsutsui Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/device.h> 38 #include <sys/systm.h> 39 #include <sys/ioctl.h> 40 41 #include <net/if.h> 42 #include <net/if_ether.h> 43 44 #include <machine/bus.h> 45 #include <machine/cpu.h> 46 #include <machine/viareg.h> 47 48 #include <dev/ic/dp83932reg.h> 49 #include <dev/ic/dp83932var.h> 50 51 #include <mac68k/obio/obiovar.h> 52 #include <mac68k/dev/if_snvar.h> 53 54 #define SONIC_REG_BASE 0x50F0A000 55 #define SONIC_PROM_BASE 0x50F08000 56 #define SONIC_SLOTNO 9 57 58 static int sn_obio_match(device_t, cfdata_t, void *); 59 static void sn_obio_attach(device_t, device_t, void *); 60 static int sn_obio_getaddr(struct sonic_softc *, uint8_t *); 61 static int sn_obio_getaddr_kludge(struct sonic_softc *, uint8_t *); 62 63 CFATTACH_DECL_NEW(sn_obio, sizeof(struct sonic_softc), 64 sn_obio_match, sn_obio_attach, NULL, NULL); 65 66 static int 67 sn_obio_match(device_t parent, cfdata_t cf, void *aux) 68 { 69 struct obio_attach_args *oa = aux; 70 bus_space_handle_t bsh; 71 int found = 0; 72 73 if (!mac68k_machine.sonic) 74 return 0; 75 76 if (bus_space_map(oa->oa_tag, 77 SONIC_REG_BASE, SONIC_NREGS * 4, 0, &bsh)) 78 return 0; 79 80 if (mac68k_bus_space_probe(oa->oa_tag, bsh, 0, 4)) 81 found = 1; 82 83 bus_space_unmap(oa->oa_tag, bsh, SONIC_NREGS * 4); 84 85 return found; 86 } 87 88 /* 89 * Install interface into kernel networking data structures 90 */ 91 static void 92 sn_obio_attach(device_t parent, device_t self, void *aux) 93 { 94 struct sonic_softc *sc = device_private(self); 95 struct obio_attach_args *oa = aux; 96 uint8_t myaddr[ETHER_ADDR_LEN]; 97 int i; 98 99 sc->sc_dev = self; 100 sc->sc_st = oa->oa_tag; 101 sc->sc_dmat = oa->oa_dmat; 102 103 if (bus_space_map(sc->sc_st, 104 SONIC_REG_BASE, SONIC_NREGS * 4, 0, &sc->sc_sh)) { 105 aprint_error(": failed to map space for SONIC regs.\n"); 106 return; 107 } 108 109 /* regs are addressed as words, big-endian. */ 110 for (i = 0; i < SONIC_NREGS; i++) { 111 sc->sc_regmap[i] = (bus_size_t)((i * 4) + 2); 112 } 113 114 sc->sc_bigendian = 1; 115 116 sc->sc_dcr = DCR_BMS | DCR_RFT1 | DCR_TFT0; 117 sc->sc_dcr2 = 0; 118 119 switch (current_mac_model->machineid) { 120 case MACH_MACC610: 121 case MACH_MACC650: 122 case MACH_MACQ610: 123 case MACH_MACQ650: 124 case MACH_MACQ700: 125 case MACH_MACQ800: 126 case MACH_MACQ900: 127 case MACH_MACQ950: 128 sc->sc_dcr |= DCR_EXBUS; 129 sc->sc_32bit = 1; 130 break; 131 132 case MACH_MACLC575: 133 case MACH_MACP580: 134 case MACH_MACQ630: 135 /* Apple Comm Slot cards; assume they are 32 bit */ 136 sc->sc_dcr |= DCR_EXBUS | DCR_USR1 | DCR_USR0; 137 sc->sc_32bit = 1; 138 break; 139 140 case MACH_MACPB500: 141 sc->sc_dcr |= DCR_SBUS | DCR_LBR; 142 sc->sc_32bit = 0; /* 16 bit interface */ 143 break; 144 145 default: 146 aprint_error(": unsupported machine type\n"); 147 return; 148 } 149 150 if (sn_obio_getaddr(sc, myaddr) && 151 sn_obio_getaddr_kludge(sc, myaddr)) { /* XXX kludge for PB */ 152 aprint_error(": failed to get MAC address.\n"); 153 bus_space_unmap(sc->sc_st, sc->sc_sh, SONIC_NREGS * 4); 154 return; 155 } 156 157 aprint_normal(": integrated SONIC Ethernet adapter\n"); 158 159 if (mac68k_machine.aux_interrupts) { 160 intr_establish(sonic_intr, (void *)sc, 3); 161 } else { 162 add_nubus_intr(SONIC_SLOTNO, (void (*)(void *))sonic_intr, 163 (void *)sc); 164 } 165 166 sonic_attach(sc, myaddr); 167 } 168 169 static int 170 sn_obio_getaddr(struct sonic_softc *sc, uint8_t *lladdr) 171 { 172 bus_space_handle_t bsh; 173 174 if (bus_space_map(sc->sc_st, SONIC_PROM_BASE, PAGE_SIZE, 0, &bsh)) { 175 aprint_error(": failed to map space to read SONIC address.\n"); 176 aprint_normal("%s:", device_xname(sc->sc_dev)); 177 return -1; 178 } 179 180 if (!mac68k_bus_space_probe(sc->sc_st, bsh, 0, 1)) { 181 bus_space_unmap(sc->sc_st, bsh, PAGE_SIZE); 182 return -1; 183 } 184 185 sn_get_enaddr(sc->sc_st, bsh, 0, lladdr); 186 187 bus_space_unmap(sc->sc_st, bsh, PAGE_SIZE); 188 189 return 0; 190 } 191 192 /* 193 * Assume that the SONIC was initialized in MacOS. This should go away 194 * when we can properly get the MAC address on the PBs. 195 */ 196 static int 197 sn_obio_getaddr_kludge(struct sonic_softc *sc, u_int8_t *lladdr) 198 { 199 int i, ors = 0; 200 201 /* Shut down NIC */ 202 CSR_WRITE(sc, SONIC_CR, CR_RST); 203 204 /* For some reason, Apple fills top first. */ 205 CSR_WRITE(sc, SONIC_CEP, 15); 206 207 i = CSR_READ(sc, SONIC_CAP2); 208 209 ors |= i; 210 lladdr[5] = i >> 8; 211 lladdr[4] = i; 212 213 i = CSR_READ(sc, SONIC_CAP1); 214 215 ors |= i; 216 lladdr[3] = i >> 8; 217 lladdr[2] = i; 218 219 i = CSR_READ(sc, SONIC_CAP0); 220 221 ors |= i; 222 lladdr[1] = i >> 8; 223 lladdr[0] = i; 224 225 CSR_WRITE(sc, SONIC_CR, 0); 226 227 if (ors == 0) 228 return -1; 229 230 return 0; 231 } 232