Annotation of sys/arch/mvme68k/dev/if_le.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: if_le.c,v 1.31 2006/01/11 07:21:58 miod Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 1982, 1992, 1993
! 5: * The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors
! 16: * may be used to endorse or promote products derived from this software
! 17: * without specific prior written permission.
! 18: *
! 19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 29: * SUCH DAMAGE.
! 30: *
! 31: * @(#)if_le.c 8.2 (Berkeley) 10/30/93
! 32: */
! 33:
! 34: #include "bpfilter.h"
! 35:
! 36: #include <sys/param.h>
! 37: #include <sys/systm.h>
! 38: #include <sys/mbuf.h>
! 39: #include <sys/syslog.h>
! 40: #include <sys/socket.h>
! 41: #include <sys/device.h>
! 42: #include <sys/malloc.h>
! 43:
! 44: #include <net/if.h>
! 45:
! 46: #ifdef INET
! 47: #include <netinet/in.h>
! 48: #include <netinet/if_ether.h>
! 49: #endif
! 50:
! 51: #include <net/if_media.h>
! 52:
! 53: #include <machine/autoconf.h>
! 54: #include <machine/cpu.h>
! 55:
! 56: #include <dev/ic/am7990reg.h>
! 57: #include <dev/ic/am7990var.h>
! 58:
! 59: #include <mvme68k/dev/if_lereg.h>
! 60: #include <mvme68k/dev/if_levar.h>
! 61: #include <mvme68k/dev/vme.h>
! 62:
! 63: #include "pcc.h"
! 64: #if NPCC > 0
! 65: #include <mvme68k/dev/pccreg.h>
! 66: #endif
! 67:
! 68: /* autoconfiguration driver */
! 69: void leattach(struct device *, struct device *, void *);
! 70: int lematch(struct device *, void *, void *);
! 71:
! 72: struct cfattach le_ca = {
! 73: sizeof(struct le_softc), lematch, leattach
! 74: };
! 75:
! 76: static int lebustype;
! 77:
! 78: void lewrcsr(struct am7990_softc *, u_int16_t, u_int16_t);
! 79: u_int16_t lerdcsr(struct am7990_softc *, u_int16_t);
! 80: void vlewrcsr(struct am7990_softc *, u_int16_t, u_int16_t);
! 81: u_int16_t vlerdcsr(struct am7990_softc *, u_int16_t);
! 82: void nvram_cmd(struct am7990_softc *, u_char, u_short);
! 83: u_int16_t nvram_read(struct am7990_softc *, u_char);
! 84: void vleetheraddr(struct am7990_softc *);
! 85: void vleinit(struct am7990_softc *);
! 86: void vlereset(struct am7990_softc *);
! 87: int vle_intr(void *);
! 88: void vle_copytobuf_contig(struct am7990_softc *, void *, int, int);
! 89: void vle_zerobuf_contig(struct am7990_softc *, int, int);
! 90:
! 91: /* send command to the nvram controller */
! 92: void
! 93: nvram_cmd(sc, cmd, addr)
! 94: struct am7990_softc *sc;
! 95: u_char cmd;
! 96: u_short addr;
! 97: {
! 98: int i;
! 99: struct vlereg1 *reg1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
! 100:
! 101: for (i=0;i<8;i++) {
! 102: reg1->ler1_ear=((cmd|(addr<<1))>>i);
! 103: CDELAY;
! 104: }
! 105: }
! 106:
! 107: /* read nvram one bit at a time */
! 108: u_int16_t
! 109: nvram_read(sc, nvram_addr)
! 110: struct am7990_softc *sc;
! 111: u_char nvram_addr;
! 112: {
! 113: u_short val = 0, mask = 0x04000;
! 114: u_int16_t wbit;
! 115: /* these used by macros DO NOT CHANGE!*/
! 116: struct vlereg1 *reg1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
! 117: ((struct le_softc *)sc)->csr = 0x4f;
! 118: ENABLE_NVRAM;
! 119: nvram_cmd(sc, NVRAM_RCL, 0);
! 120: DISABLE_NVRAM;
! 121: CDELAY;
! 122: ENABLE_NVRAM;
! 123: nvram_cmd(sc, NVRAM_READ, nvram_addr);
! 124: for (wbit=0; wbit<15; wbit++) {
! 125: (reg1->ler1_ear & 0x01) ? (val = (val | mask)) : (val = (val & (~mask)));
! 126: mask = mask>>1;
! 127: CDELAY;
! 128: }
! 129: (reg1->ler1_ear & 0x01) ? (val = (val | 0x8000)) : (val = (val & 0x7FFF));
! 130: CDELAY;
! 131: DISABLE_NVRAM;
! 132: return (val);
! 133: }
! 134:
! 135: void
! 136: vleetheraddr(sc)
! 137: struct am7990_softc *sc;
! 138: {
! 139: u_char * cp = sc->sc_arpcom.ac_enaddr;
! 140: u_int16_t ival[3];
! 141: u_char i;
! 142:
! 143: for (i=0; i<3; i++) {
! 144: ival[i] = nvram_read(sc, i);
! 145: }
! 146: memcpy(cp, &ival[0], 6);
! 147: }
! 148:
! 149: void
! 150: lewrcsr(sc, port, val)
! 151: struct am7990_softc *sc;
! 152: u_int16_t port, val;
! 153: {
! 154: register struct lereg1 *ler1 = (struct lereg1 *)((struct le_softc *)sc)->sc_r1;
! 155:
! 156: ler1->ler1_rap = port;
! 157: ler1->ler1_rdp = val;
! 158: }
! 159:
! 160: void
! 161: vlewrcsr(sc, port, val)
! 162: struct am7990_softc *sc;
! 163: u_int16_t port, val;
! 164: {
! 165: register struct vlereg1 *ler1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
! 166:
! 167: ler1->ler1_rap = port;
! 168: ler1->ler1_rdp = val;
! 169: }
! 170:
! 171: u_int16_t
! 172: lerdcsr(sc, port)
! 173: struct am7990_softc *sc;
! 174: u_int16_t port;
! 175: {
! 176: register struct lereg1 *ler1 = (struct lereg1 *)((struct le_softc *)sc)->sc_r1;
! 177: u_int16_t val;
! 178:
! 179: ler1->ler1_rap = port;
! 180: val = ler1->ler1_rdp;
! 181: return (val);
! 182: }
! 183:
! 184: u_int16_t
! 185: vlerdcsr(sc, port)
! 186: struct am7990_softc *sc;
! 187: u_int16_t port;
! 188: {
! 189: register struct vlereg1 *ler1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
! 190: u_int16_t val;
! 191:
! 192: ler1->ler1_rap = port;
! 193: val = ler1->ler1_rdp;
! 194: return (val);
! 195: }
! 196:
! 197: /* init MVME376, set ipl and vec */
! 198: void
! 199: vleinit(sc)
! 200: struct am7990_softc *sc;
! 201: {
! 202: register struct vlereg1 *reg1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
! 203: u_char vec = ((struct le_softc *)sc)->sc_vec;
! 204: u_char ipl = ((struct le_softc *)sc)->sc_ipl;
! 205: ((struct le_softc *)sc)->csr = 0x4f;
! 206: WRITE_CSR_AND( ~ipl );
! 207: SET_VEC(vec);
! 208: return;
! 209: }
! 210:
! 211: /* MVME376 hardware reset */
! 212: void
! 213: vlereset(sc)
! 214: struct am7990_softc *sc;
! 215: {
! 216: register struct vlereg1 *reg1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
! 217: RESET_HW;
! 218: #ifdef LEDEBUG
! 219: if (sc->sc_debug) {
! 220: printf("\nle: hardware reset\n");
! 221: }
! 222: #endif
! 223: SYSFAIL_CL;
! 224: return;
! 225: }
! 226:
! 227: int
! 228: vle_intr(sc)
! 229: void *sc;
! 230: {
! 231: register struct vlereg1 *reg1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
! 232: int rc;
! 233: rc = am7990_intr(sc);
! 234: ENABLE_INTR;
! 235: return (rc);
! 236: }
! 237:
! 238: void
! 239: vle_copytobuf_contig(sc, from, boff, len)
! 240: struct am7990_softc *sc;
! 241: void *from;
! 242: int boff, len;
! 243: {
! 244: volatile caddr_t buf = sc->sc_mem;
! 245:
! 246: /*
! 247: * Do the cache stuff
! 248: */
! 249: dma_cachectl(buf + boff, len);
! 250: /*
! 251: * Just call bcopy() to do the work.
! 252: */
! 253: bcopy(from, buf + boff, len);
! 254: }
! 255:
! 256: void
! 257: vle_zerobuf_contig(sc, boff, len)
! 258: struct am7990_softc *sc;
! 259: int boff, len;
! 260: {
! 261: volatile caddr_t buf = sc->sc_mem;
! 262: /*
! 263: * Do the cache stuff
! 264: */
! 265: dma_cachectl(buf + boff, len);
! 266: /*
! 267: * Just let bzero() do the work
! 268: */
! 269: bzero(buf + boff, len);
! 270: }
! 271:
! 272: int
! 273: lematch(parent, vcf, args)
! 274: struct device *parent;
! 275: void *vcf, *args;
! 276: {
! 277: struct confargs *ca = args;
! 278: /* check physical addr for bogus MVME162 addr @0xffffd200. weird XXX - smurph */
! 279: if (cputyp == CPU_162 && ca->ca_paddr == 0xffffd200)
! 280: return (0);
! 281:
! 282: return (!badvaddr((vaddr_t)ca->ca_vaddr, 2));
! 283: }
! 284:
! 285: /*
! 286: * Interface exists: make available by filling in network interface
! 287: * record. System will initialize the interface when it is ready
! 288: * to accept packets.
! 289: */
! 290: void
! 291: leattach(parent, self, aux)
! 292: struct device *parent;
! 293: struct device *self;
! 294: void *aux;
! 295: {
! 296: register struct le_softc *lesc = (struct le_softc *)self;
! 297: struct am7990_softc *sc = &lesc->sc_am7990;
! 298: struct confargs *ca = aux;
! 299: int pri = ca->ca_ipl;
! 300: extern void *etherbuf;
! 301: paddr_t addr;
! 302: int card;
! 303:
! 304: /* XXX the following declarations should be elsewhere */
! 305: extern void myetheraddr(u_char *);
! 306:
! 307: lebustype = ca->ca_bustype;
! 308:
! 309: switch (lebustype) {
! 310: case BUS_VMES:
! 311: /*
! 312: * get the first available etherbuf. MVME376 uses its own
! 313: * dual-ported RAM for etherbuf. It is set by dip switches
! 314: * on board. We support the six Motorola address locations,
! 315: * however, the board can be set up at any other address.
! 316: * XXX These physical addresses should be mapped in extio!!!
! 317: */
! 318: switch (ca->ca_paddr) {
! 319: case 0xffff1200:
! 320: card = 0;
! 321: break;
! 322: case 0xffff1400:
! 323: card = 1;
! 324: break;
! 325: case 0xffff1600:
! 326: card = 2;
! 327: break;
! 328: case 0xffff5400:
! 329: card = 3;
! 330: break;
! 331: case 0xffff5600:
! 332: card = 4;
! 333: break;
! 334: case 0xffffa400:
! 335: card = 5;
! 336: break;
! 337: default:
! 338: printf(": unsupported address\n");
! 339: return;
! 340: }
! 341:
! 342: addr = VLEMEMBASE - (card * VLEMEMSIZE);
! 343:
! 344: sc->sc_mem = (void *)mapiodev(addr, VLEMEMSIZE);
! 345: if (sc->sc_mem == NULL) {
! 346: printf("\n%s: no more memory in external I/O map\n",
! 347: sc->sc_dev.dv_xname);
! 348: return;
! 349: }
! 350: sc->sc_addr = addr & 0x00ffffff;
! 351:
! 352: lesc->sc_r1 = (void *)ca->ca_vaddr;
! 353: lesc->sc_ipl = ca->ca_ipl;
! 354: lesc->sc_vec = ca->ca_vec;
! 355: sc->sc_memsize = VLEMEMSIZE;
! 356: sc->sc_conf3 = LE_C3_BSWP;
! 357: sc->sc_hwreset = vlereset;
! 358: sc->sc_rdcsr = vlerdcsr;
! 359: sc->sc_wrcsr = vlewrcsr;
! 360: sc->sc_hwinit = vleinit;
! 361: sc->sc_copytodesc = vle_copytobuf_contig;
! 362: sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
! 363: sc->sc_copytobuf = vle_copytobuf_contig;
! 364: sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
! 365: sc->sc_zerobuf = am7990_zerobuf_contig;
! 366: /* get ether address */
! 367: vleetheraddr(sc);
! 368: break;
! 369: case BUS_PCC:
! 370: sc->sc_mem = etherbuf;
! 371: lesc->sc_r1 = (void *)ca->ca_vaddr;
! 372: sc->sc_conf3 = LE_C3_BSWP /*| LE_C3_ACON | LE_C3_BCON*/;
! 373: sc->sc_addr = kvtop((vaddr_t)sc->sc_mem);
! 374: sc->sc_memsize = LEMEMSIZE;
! 375: sc->sc_rdcsr = lerdcsr;
! 376: sc->sc_wrcsr = lewrcsr;
! 377: sc->sc_hwreset = NULL;
! 378: sc->sc_hwinit = NULL;
! 379: sc->sc_copytodesc = am7990_copytobuf_contig;
! 380: sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
! 381: sc->sc_copytobuf = am7990_copytobuf_contig;
! 382: sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
! 383: sc->sc_zerobuf = am7990_zerobuf_contig;
! 384: /* get ether address */
! 385: myetheraddr(sc->sc_arpcom.ac_enaddr);
! 386: break;
! 387: default:
! 388: printf(": unknown bus type\n");
! 389: return;
! 390: }
! 391:
! 392: am7990_config(sc);
! 393:
! 394: /* connect the interrupt */
! 395: switch (lebustype) {
! 396: case BUS_VMES:
! 397: lesc->sc_ih.ih_fn = vle_intr;
! 398: lesc->sc_ih.ih_arg = sc;
! 399: lesc->sc_ih.ih_ipl = pri;
! 400: vmeintr_establish(ca->ca_vec + 0, &lesc->sc_ih, self->dv_xname);
! 401: break;
! 402: #if NPCC > 0
! 403: case BUS_PCC:
! 404: lesc->sc_ih.ih_fn = am7990_intr;
! 405: lesc->sc_ih.ih_arg = sc;
! 406: lesc->sc_ih.ih_ipl = pri;
! 407: pccintr_establish(PCCV_LE, &lesc->sc_ih, self->dv_xname);
! 408: sys_pcc->pcc_leirq = pri | PCC_IRQ_IEN;
! 409: break;
! 410: #endif
! 411: }
! 412: }
CVSweb