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