1 /* $OpenBSD: if_ie_gsc.c,v 1.29 2015/11/24 17:11:38 mpi Exp $ */ 2 3 /* 4 * Copyright (c) 1998-2004 Michael Shalayeff 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * References: 31 * 1. 82596DX and 82596SX High-Performance 32-bit Local Area Network Coprocessor 32 * Intel Corporation, November 1996, Order Number: 290219-006 33 * 34 * 2. 712 I/O Subsystem ERS Rev 1.0 35 * Hewlett-Packard, June 17 1992, Dwg No. A-A2263-66510-31 36 */ 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 #include <sys/socket.h> 41 #include <sys/sockio.h> 42 43 #include <net/if.h> 44 #include <net/if_media.h> 45 46 #include <netinet/in.h> 47 #include <netinet/if_ether.h> 48 49 #include <machine/bus.h> 50 #include <machine/intr.h> 51 #include <machine/iomod.h> 52 #include <machine/autoconf.h> 53 54 #include <hppa/dev/cpudevs.h> 55 #include <hppa/gsc/gscbusvar.h> 56 57 #include <dev/ic/i82596reg.h> 58 #include <dev/ic/i82596var.h> 59 60 #define IEGSC_GECKO IEMD_FLAG0 61 62 struct ie_gsc_regs { 63 u_int32_t ie_reset; 64 u_int32_t ie_port; 65 u_int32_t ie_attn; 66 }; 67 68 #define IE_SIZE 0x8000 69 70 int ie_gsc_probe(struct device *, void *, void *); 71 void ie_gsc_attach(struct device *, struct device *, void *); 72 73 struct cfattach ie_gsc_ca = { 74 sizeof(struct ie_softc), ie_gsc_probe, ie_gsc_attach 75 }; 76 77 static uint64_t ie_gsc_media[] = { 78 IFM_ETHER | IFM_10_2, 79 }; 80 #define IE_NMEDIA (sizeof(ie_gsc_media) / sizeof(ie_gsc_media[0])) 81 82 char *ie_mem; 83 84 void ie_gsc_reset(struct ie_softc *sc, int what); 85 void ie_gsc_attend(struct ie_softc *sc); 86 void ie_gsc_run(struct ie_softc *sc); 87 void ie_gsc_port(struct ie_softc *sc, u_int); 88 #ifdef USELEDS 89 int ie_gsc_intrhook(struct ie_softc *sc, int what); 90 #endif 91 u_int16_t ie_gsc_read16(struct ie_softc *sc, int offset); 92 void ie_gsc_write16(struct ie_softc *sc, int offset, u_int16_t v); 93 void ie_gsc_write24(struct ie_softc *sc, int offset, int addr); 94 void ie_gsc_memcopyin(struct ie_softc *sc, void *p, int offset, size_t); 95 void ie_gsc_memcopyout(struct ie_softc *sc, const void *p, int, size_t); 96 97 98 void 99 ie_gsc_reset(sc, what) 100 struct ie_softc *sc; 101 int what; 102 { 103 volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh; 104 int i; 105 106 r->ie_reset = 0; 107 /* 108 * per [2] 4.6.2.1 109 * delay for 10 system clocks + 5 transmit clocks, 110 * NB: works for system clocks over 10MHz 111 */ 112 DELAY(1000); 113 114 switch (what) { 115 case IE_CHIP_PROBE: 116 break; 117 118 case IE_CARD_RESET: 119 /* 120 * after the hardware reset: 121 * inform i825[89]6 about new SCP address, 122 * maddr must be at least 16-byte aligned 123 */ 124 ie_gsc_port(sc, IE_PORT_SCP); 125 ie_gsc_attend(sc); 126 127 for (i = 9000; i-- && ie_gsc_read16(sc, IE_ISCP_BUSY(sc->iscp)); 128 DELAY(100)) 129 pdcache(0, sc->sc_maddr + sc->iscp, IE_ISCP_SZ); 130 131 #ifdef I82596_DEBUG 132 if (i < 0) { 133 printf("timeout for PORT command (%x)%s\n", 134 ie_gsc_read16(sc, IE_ISCP_BUSY(sc->iscp)), 135 (sc->sc_flags & IEGSC_GECKO)? " on gecko":""); 136 return; 137 } 138 #endif 139 break; 140 } 141 } 142 143 void 144 ie_gsc_attend(sc) 145 struct ie_softc *sc; 146 { 147 volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh; 148 149 fdcache(0, (vaddr_t)ie_mem, IE_SIZE); 150 DELAY(1); 151 r->ie_attn = 0; 152 DELAY(1); 153 } 154 155 void 156 ie_gsc_run(sc) 157 struct ie_softc *sc; 158 { 159 } 160 161 void 162 ie_gsc_port(sc, cmd) 163 struct ie_softc *sc; 164 u_int cmd; 165 { 166 switch (cmd) { 167 case IE_PORT_RESET: 168 cmd = 0; 169 break; 170 case IE_PORT_TEST: 171 cmd = ((u_int)sc->sc_maddr + sc->scp) | 1; 172 break; 173 case IE_PORT_SCP: 174 cmd = ((u_int)sc->sc_maddr + sc->scp) | 2; 175 break; 176 case IE_PORT_DUMP: 177 cmd = 3; 178 break; 179 } 180 181 if (sc->sc_flags & IEGSC_GECKO) { 182 volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh; 183 r->ie_port = cmd & 0xffff; 184 DELAY(1000); 185 r->ie_port = cmd >> 16; 186 DELAY(1000); 187 } else { 188 volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh; 189 r->ie_port = cmd >> 16; 190 DELAY(1000); 191 r->ie_port = cmd & 0xffff; 192 DELAY(1000); 193 } 194 } 195 196 #ifdef USELEDS 197 int 198 ie_gsc_intrhook(sc, where) 199 struct ie_softc *sc; 200 int where; 201 { 202 switch (where) { 203 case IE_INTR_ENRCV: 204 ledctl(PALED_NETRCV, 0, 0); 205 break; 206 case IE_INTR_ENSND: 207 ledctl(PALED_NETSND, 0, 0); 208 break; 209 case IE_INTR_EXIT: 210 case IE_INTR_LOOP: 211 fdcache(0, (vaddr_t)ie_mem, IE_SIZE); 212 break; 213 } 214 return 0; 215 } 216 #endif 217 218 u_int16_t 219 ie_gsc_read16(sc, offset) 220 struct ie_softc *sc; 221 int offset; 222 { 223 volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset); 224 225 asm volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr)); 226 return *addr; 227 } 228 229 void 230 ie_gsc_write16(sc, offset, v) 231 struct ie_softc *sc; 232 int offset; 233 u_int16_t v; 234 { 235 volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset); 236 237 *addr = v; 238 asm volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr)); 239 } 240 241 void 242 ie_gsc_write24(sc, offset, v) 243 struct ie_softc *sc; 244 int offset; 245 int v; 246 { 247 volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset); 248 249 addr[0] = (v ) & 0xffff; 250 addr[1] = (v >> 16) & 0xffff; 251 asm volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr+0)); 252 asm volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr+1)); 253 } 254 255 void 256 ie_gsc_memcopyin(sc, p, offset, size) 257 struct ie_softc *sc; 258 void *p; 259 int offset; 260 size_t size; 261 { 262 pdcache(0, sc->bh + offset, size); 263 bcopy ((void *)((u_long)sc->bh + offset), p, size); 264 } 265 266 void 267 ie_gsc_memcopyout(sc, p, offset, size) 268 struct ie_softc *sc; 269 const void *p; 270 int offset; 271 size_t size; 272 { 273 bcopy (p, (void *)((u_long)sc->bh + offset), size); 274 fdcache(0, sc->bh + offset, size); 275 } 276 277 int 278 ie_gsc_probe(parent, match, aux) 279 struct device *parent; 280 void *match, *aux; 281 { 282 struct gsc_attach_args *ga = aux; 283 284 if (ga->ga_type.iodc_type != HPPA_TYPE_FIO || 285 (ga->ga_type.iodc_sv_model != HPPA_FIO_LAN && 286 ga->ga_type.iodc_sv_model != HPPA_FIO_GLAN)) 287 return 0; 288 289 return 1; 290 } 291 292 void 293 ie_gsc_attach(parent, self, aux) 294 struct device *parent, *self; 295 void *aux; 296 { 297 struct pdc_lan_station_id pdc_mac PDC_ALIGNMENT; 298 struct ie_softc *sc = (struct ie_softc *)self; 299 struct gsc_attach_args *ga = aux; 300 /*bus_dma_segment_t seg; 301 int rseg;*/ 302 int rv; 303 #ifdef PMAPDEBUG 304 extern int pmapdebug; 305 int opmapdebug = pmapdebug; 306 pmapdebug = 0; 307 #endif 308 309 sc->iot = sc->bt = ga->ga_iot; 310 if (bus_space_map(sc->iot, ga->ga_hpa, IOMOD_HPASIZE, 0, &sc->ioh)) { 311 printf(": can't map IO space\n"); 312 return; 313 } 314 315 if (ga->ga_type.iodc_sv_model == HPPA_FIO_GLAN) 316 sc->sc_flags |= IEGSC_GECKO; 317 318 sc->sc_msize = IE_SIZE; 319 /* XXX memory must be under 16M until the mi part is fixed */ 320 #if 0 321 if (bus_dmamem_alloc(ga->ga_dmatag, sc->sc_msize, NBPG, 0, 322 &seg, 1, &rseg, BUS_DMA_NOWAIT)) { 323 printf (": cannot allocate %d bytes of DMA memory\n", 324 sc->sc_msize); 325 return; 326 } 327 if (bus_dmamem_map(ga->ga_dmatag, &seg, rseg, sc->sc_msize, 328 (caddr_t *)&sc->bh, BUS_DMA_NOWAIT)) { 329 printf (": cannot map DMA memory\n"); 330 bus_dmamem_free(ga->ga_dmatag, &seg, rseg); 331 return; 332 } 333 334 bzero((void *)sc->bh, sc->sc_msize); 335 sc->sc_maddr = kvtop((caddr_t)sc->bh); 336 337 #else 338 sc->bh = (u_int)ie_mem; 339 sc->sc_maddr = sc->bh; 340 #endif 341 sc->sysbus = 0x40 | IE_SYSBUS_82586 | IE_SYSBUS_INTLOW | IE_SYSBUS_TRG | IE_SYSBUS_BE; 342 343 sc->do_xmitnopchain = 0; 344 sc->hwreset = ie_gsc_reset; 345 sc->chan_attn = ie_gsc_attend; 346 sc->port = ie_gsc_port; 347 sc->hwinit = ie_gsc_run; 348 sc->memcopyout = ie_gsc_memcopyout; 349 sc->memcopyin = ie_gsc_memcopyin; 350 sc->ie_bus_read16 = ie_gsc_read16; 351 sc->ie_bus_write16 = ie_gsc_write16; 352 sc->ie_bus_write24 = ie_gsc_write24; 353 #ifdef USELEDS 354 sc->intrhook = ie_gsc_intrhook; 355 #else 356 sc->intrhook = NULL; 357 #endif 358 359 #ifdef I82596_DEBUG 360 printf(" mem %x[%p]/%x", sc->bh, sc->sc_maddr, sc->sc_msize); 361 sc->sc_debug = IED_ALL; 362 #endif 363 rv = i82596_probe(sc); 364 if (!rv) { 365 /*bus_dmamem_free(ga->ga_dmatag, &seg, sc->sc_msize);*/ 366 } 367 #ifdef PMAPDEBUG 368 pmapdebug = opmapdebug; 369 #endif 370 if (!rv) { 371 printf("\n"); 372 return; 373 } 374 375 if (pdc_call((iodcio_t)pdc, 0, PDC_LAN_STATION_ID, 376 PDC_LAN_STATION_ID_READ, &pdc_mac, ga->ga_hpa) < 0) 377 bcopy((void *)ASP_PROM, sc->sc_arpcom.ac_enaddr, 378 ETHER_ADDR_LEN); 379 else 380 bcopy(pdc_mac.addr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); 381 382 printf(":"); 383 384 sc->iscp = 0; 385 sc->scp = 32; 386 sc->scb = 94; 387 sc->buf_area = 256; 388 sc->buf_area_sz = sc->sc_msize - sc->buf_area; 389 sc->sc_type = sc->sc_flags & IEGSC_GECKO? "LASI/i82596CA" : "i82596DX"; 390 sc->sc_vers = ga->ga_type.iodc_model * 10 + ga->ga_type.iodc_sv_rev; 391 i82596_attach(sc, sc->sc_type, (char *)sc->sc_arpcom.ac_enaddr, 392 ie_gsc_media, IE_NMEDIA, ie_gsc_media[0]); 393 394 sc->sc_ih = gsc_intr_establish((struct gsc_softc *)parent, 395 ga->ga_irq, IPL_NET, i82596_intr, sc, sc->sc_dev.dv_xname); 396 } 397