1: /* 2: * Copyright (c) 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)if_dmc.c 1.1 (2.10BSD Berkeley) 12/1/86 7: */ 8: 9: #include "dmc.h" 10: #if NDMC > 0 11: 12: #define printd if(dmcdebug)printf 13: int dmcdebug = 1; 14: /* 15: * DMC11 device driver, internet version 16: * 17: * TODO 18: * allow more than one outstanding read or write. 19: */ 20: 21: #include "param.h" 22: #include "systm.h" 23: #include "mbuf.h" 24: #include "buf.h" 25: #include "ioctl.h" 26: #include "tty.h" 27: #include "domain.h" 28: #include "protosw.h" 29: #include "socket.h" 30: #include "pdpuba/ubavar.h" 31: #include "netinet/in.h" 32: #include "netinet/in_systm.h" 33: #include "net/if.h" 34: #include "pdpif/if_uba.h" 35: #include "pdpif/if_dmc.h" 36: #include "netinet/ip.h" 37: #include "netinet/in_var.h" 38: #include "netinet/ip_var.h" 39: #include "net/route.h" 40: #include "net/netisr.h" 41: #include "errno.h" 42: 43: /* 44: * Driver information for auto-configuration stuff. 45: */ 46: int dmcprobe(), dmcattach(), dmcinit(), dmcoutput(); 47: struct uba_device *dmcinfo[NDMC]; 48: u_short dmcstd[] = { 0 }; 49: struct uba_driver dmcdriver = 50: { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo }; 51: 52: #define DMC_AF 0xff /* 8 bits of address type in ui_flags */ 53: #define DMC_NET 0xffffff00 /* 24 bits of net number in ui_flags */ 54: 55: /* 56: * DMC software status per interface. 57: * 58: * Each interface is referenced by a network interface structure, 59: * sc_if, which the routing code uses to locate the interface. 60: * This structure contains the output queue for the interface, its address, ... 61: * We also have, for each interface, a UBA interface structure, which 62: * contains information about the UNIBUS resources held by the interface: 63: * map registers, buffered data paths, etc. Information is cached in this 64: * structure for use by the if_uba.c routines in running the interface 65: * efficiently. 66: */ 67: struct dmc_softc { 68: struct ifnet sc_if; /* network-visible interface */ 69: struct ifuba sc_ifuba; /* UNIBUS resources */ 70: short sc_flag; /* flags */ 71: short sc_oactive; /* output active */ 72: int sc_ubinfo; /* UBA mapping info for base table */ 73: struct clist sc_que; /* command queue */ 74: } dmc_softc[NDMC]; 75: 76: /* flags */ 77: #define DMCRUN 01 78: #define DMCBMAPPED 02 /* base table mapped */ 79: 80: struct dmc_base { 81: short d_base[128]; /* DMC base table */ 82: } dmc_base[NDMC]; 83: 84: #define loword(x) ((short *)&x)[0] 85: #define hiword(x) ((short *)&x)[1] 86: 87: dmcprobe(reg) 88: caddr_t reg; 89: { 90: register int br, cvec; 91: register struct dmcdevice *addr = (struct dmcdevice *)reg; 92: register int i; 93: 94: #ifdef lint 95: br = 0; cvec = br; br = cvec; 96: dmcrint(0); dmcxint(0); 97: #endif 98: addr->bsel1 = DMC_MCLR; 99: for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) 100: ; 101: if ((addr->bsel1 & DMC_RUN) == 0) 102: return (0); 103: addr->bsel1 &= ~DMC_MCLR; 104: addr->bsel0 = DMC_RQI|DMC_IEI; 105: DELAY(100000L); 106: addr->bsel1 = DMC_MCLR; 107: for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) 108: ; 109: #ifdef ECHACK 110: br = 0x16; 111: #endif 112: return (1); 113: } 114: 115: /* 116: * Interface exists: make available by filling in network interface 117: * record. System will initialize the interface when it is ready 118: * to accept packets. 119: */ 120: dmcattach(ui) 121: register struct uba_device *ui; 122: { 123: register struct dmc_softc *sc = &dmc_softc[ui->ui_unit]; 124: register struct sockaddr_in *sin; 125: 126: sc->sc_if.if_unit = ui->ui_unit; 127: sc->sc_if.if_name = "dmc"; 128: sc->sc_if.if_mtu = DMCMTU; 129: sc->sc_if.if_init = dmcinit; 130: sc->sc_if.if_output = dmcoutput; 131: sc->sc_if.if_reset = 0; 132: sc->sc_if.if_flags = IFF_POINTOPOINT; 133: /* DON'T KNOW IF THIS WILL WORK WITH A BDP AT HIGH SPEEDS */ 134: sc->sc_ifuba.ifu_flags = UBA_NEEDBDP | UBA_CANTWAIT; 135: if_attach(&sc->sc_if); 136: } 137: 138: /* 139: * Initialization of interface; reinitialize UNIBUS usage. 140: */ 141: dmcinit(unit) 142: int unit; 143: { 144: register struct dmc_softc *sc = &dmc_softc[unit]; 145: register struct uba_device *ui = dmcinfo[unit]; 146: register struct dmcdevice *addr; 147: int base; 148: 149: printd("dmcinit\n"); 150: if ((sc->sc_flag&DMCBMAPPED) == 0) { 151: sc->sc_ubinfo = uballoc((caddr_t)&dmc_base[unit], 152: sizeof (struct dmc_base)); 153: sc->sc_flag |= DMCBMAPPED; 154: } 155: if (if_ubainit(&sc->sc_ifuba, ui->ui_ubanum, 0, 156: (int)btoc(DMCMTU)) == 0) { 157: printf("dmc%d: can't initialize\n", unit); 158: sc->sc_if.if_flags &= ~IFF_UP; 159: return; 160: } 161: addr = (struct dmcdevice *)ui->ui_addr; 162: addr->bsel2 |= DMC_IEO; 163: base = sc->sc_ubinfo & 0x3ffff; 164: printd(" base 0x%x\n", base); 165: dmcload(sc, DMC_BASEI, base, (base>>2)&DMC_XMEM); 166: dmcload(sc, DMC_CNTLI, 0, 0); 167: base = sc->sc_ifuba.ifu_r.ifrw_info & 0x3ffff; 168: dmcload(sc, DMC_READ, base, ((base>>2)&DMC_XMEM)|DMCMTU); 169: printd(" first read queued, addr 0x%x\n", base); 170: sc->sc_if.if_flags |= IFF_UP; 171: } 172: 173: /* 174: * Start output on interface. Get another datagram 175: * to send from the interface queue and map it to 176: * the interface before starting output. 177: */ 178: dmcstart(dev) 179: dev_t dev; 180: { 181: int unit = minor(dev); 182: struct uba_device *ui = dmcinfo[unit]; 183: register struct dmc_softc *sc = &dmc_softc[unit]; 184: int addr, len; 185: struct mbuf *m; 186: 187: printd("dmcstart\n"); 188: /* 189: * Dequeue a request and map it to the UNIBUS. 190: * If no more requests, just return. 191: */ 192: IF_DEQUEUE(&sc->sc_if.if_snd, m); 193: if (m == 0) 194: return; 195: len = if_wubaput(&sc->sc_ifuba, m); 196: 197: addr = sc->sc_ifuba.ifu_w.ifrw_info & 0x3ffff; 198: printd(" len %d, addr 0x%x, ", len, addr); 199: printd("mr 0x%lx\n", sc->sc_ifuba.ifu_w.ifrw_info); 200: dmcload(sc, DMC_WRITE, addr, (len&DMC_CCOUNT)|((addr>>2)&DMC_XMEM)); 201: sc->sc_oactive = 1; 202: } 203: 204: /* 205: * Utility routine to load the DMC device registers. 206: */ 207: dmcload(sc, type, w0, w1) 208: register struct dmc_softc *sc; 209: int type, w0, w1; 210: { 211: register struct dmcdevice *addr; 212: register int unit, sps, n; 213: 214: printd("dmcload: 0x%x 0x%x 0x%x\n", type, w0, w1); 215: unit = sc - dmc_softc; 216: addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr; 217: sps = splimp(); 218: if ((n = sc->sc_que.c_cc) == 0) 219: addr->bsel0 = type | DMC_RQI; 220: else 221: (void) putc(type | DMC_RQI, &sc->sc_que); 222: (void) putw(w0, &sc->sc_que); 223: (void) putw(w1, &sc->sc_que); 224: if (n == 0) 225: dmcrint(unit); 226: splx(sps); 227: } 228: 229: /* 230: * DMC interface receiver interrupt. 231: * Ready to accept another command, 232: * pull one off the command queue. 233: */ 234: dmcrint(unit) 235: int unit; 236: { 237: register struct dmc_softc *sc; 238: register struct dmcdevice *addr; 239: register int n; 240: 241: addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr; 242: sc = &dmc_softc[unit]; 243: while (addr->bsel0&DMC_RDYI) { 244: addr->sel4 = getw(&sc->sc_que); 245: addr->sel6 = getw(&sc->sc_que); 246: addr->bsel0 &= ~(DMC_IEI|DMC_RQI); 247: while (addr->bsel0&DMC_RDYI) 248: ; 249: if (sc->sc_que.c_cc == 0) 250: return; 251: addr->bsel0 = getc(&sc->sc_que); 252: n = RDYSCAN; 253: while (n-- && (addr->bsel0&DMC_RDYI) == 0) 254: ; 255: } 256: if (sc->sc_que.c_cc) 257: addr->bsel0 |= DMC_IEI; 258: } 259: 260: /* 261: * DMC interface transmitter interrupt. 262: * A transfer has completed, check for errors. 263: * If it was a read, notify appropriate protocol. 264: * If it was a write, pull the next one off the queue. 265: */ 266: dmcxint(unit) 267: int unit; 268: { 269: register struct dmc_softc *sc; 270: struct uba_device *ui = dmcinfo[unit]; 271: struct dmcdevice *addr; 272: struct mbuf *m; 273: register struct ifqueue *inq; 274: int arg, cmd, len; 275: 276: addr = (struct dmcdevice *)ui->ui_addr; 277: arg = addr->sel6; 278: cmd = addr->bsel2&7; 279: addr->bsel2 &= ~DMC_RDYO; 280: sc = &dmc_softc[unit]; 281: printd("dmcxint\n"); 282: switch (cmd) { 283: 284: case DMC_OUR: 285: /* 286: * A read has completed. Purge input buffered 287: * data path. Pass packet to type specific 288: * higher-level input routine. 289: */ 290: sc->sc_if.if_ipackets++; 291: len = arg & DMC_CCOUNT; 292: printd(" read done, len %d\n", len); 293: switch (sc->sc_flag & DMC_AF) { 294: #ifdef INET 295: case AF_INET: 296: schednetisr(NETISR_IP); 297: inq = &ipintrq; 298: break; 299: #endif 300: 301: default: 302: printf("dmc%d: unknown address type %d\n", unit, 303: sc->sc_flag & DMC_AF); 304: goto setup; 305: } 306: m = if_rubaget(&sc->sc_ifuba, len, 0, &sc->sc_if); 307: if (m == 0) 308: goto setup; 309: if (IF_QFULL(inq)) { 310: IF_DROP(inq); 311: (void) m_freem(m); 312: } else 313: IF_ENQUEUE(inq, m); 314: 315: setup: 316: arg = sc->sc_ifuba.ifu_r.ifrw_info & 0x3ffff; 317: dmcload(sc, DMC_READ, arg, ((arg >> 2) & DMC_XMEM) | DMCMTU); 318: return; 319: 320: case DMC_OUX: 321: /* 322: * A write has completed, start another 323: * transfer if there is more data to send. 324: */ 325: if (sc->sc_oactive == 0) 326: return; /* SHOULD IT BE A FATAL ERROR? */ 327: printd(" write done\n"); 328: sc->sc_if.if_opackets++; 329: sc->sc_oactive = 0; 330: if (sc->sc_ifuba.ifu_xtofree) { 331: (void) m_freem(sc->sc_ifuba.ifu_xtofree); 332: sc->sc_ifuba.ifu_xtofree = 0; 333: } 334: if (sc->sc_if.if_snd.ifq_head == 0) 335: return; 336: dmcstart(unit); 337: return; 338: 339: case DMC_CNTLO: 340: arg &= DMC_CNTMASK; 341: if (arg&DMC_FATAL) { 342: addr->bsel1 = DMC_MCLR; 343: sc->sc_flag &= ~DMCRUN; 344: /*** DO SOMETHING TO RESTART DEVICE ***/ 345: printf("DMC FATAL ERROR 0%o\n", arg); 346: } else { 347: /* ACCUMULATE STATISTICS */ 348: printf("DMC SOFT ERROR 0%o\n", arg); 349: } 350: return; 351: 352: default: 353: printf("dmc%d: bad control %o\n", unit, cmd); 354: } 355: } 356: 357: /* 358: * DMC output routine. 359: * Just send the data, header was supplied by 360: * upper level protocol routines. 361: */ 362: dmcoutput(ifp, m, dst) 363: register struct ifnet *ifp; 364: register struct mbuf *m; 365: struct sockaddr *dst; 366: { 367: struct uba_device *ui = dmcinfo[ifp->if_unit]; 368: int s; 369: 370: printd("dmcoutput\n"); 371: if (dst->sa_family != AF_INET) { 372: printf("dmc%d: af%d not supported\n", ifp->if_unit, AF_INET); 373: m_freem(m); 374: return (EAFNOSUPPORT); 375: } 376: s = splimp(); 377: if (IF_QFULL(&ifp->if_snd)) { 378: IF_DROP(&ifp->if_snd); 379: m_freem(m); 380: splx(s); 381: return (ENOBUFS); 382: } 383: IF_ENQUEUE(&ifp->if_snd, m); 384: if (dmc_softc[ifp->if_unit].sc_oactive == 0) 385: dmcstart(ifp->if_unit); 386: splx(s); 387: return (0); 388: } 389: #endif NDMC