Annotation of sys/arch/hppa/gsc/if_ie_gsc.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: if_ie_gsc.c,v 1.25 2004/10/28 19:13:30 mickey 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: }
CVSweb