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