1 /* 2 * Copyright (c) 1990 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)if_dp.c 7.1 (Berkeley) 08/30/90 8 */ 9 10 #include "dp.h" 11 #if NDP > 0 12 13 /* 14 * DPV-11 device driver, X.25 version 15 * 16 * Derived from dmc-11 driver: 17 * 18 * Bill Nesheim 19 * Cornell University 20 * 21 * Lou Salkind 22 * New York University 23 */ 24 25 /* #define DEBUG /* for base table dump on fatal error */ 26 27 #include "machine/pte.h" 28 29 #include "param.h" 30 #include "systm.h" 31 #include "mbuf.h" 32 #include "buf.h" 33 #include "ioctl.h" /* must precede tty.h */ 34 #include "protosw.h" 35 #include "socket.h" 36 #include "syslog.h" 37 #include "vmmac.h" 38 #include "errno.h" 39 #include "time.h" 40 #include "kernel.h" 41 42 #include "../net/if.h" 43 #include "../net/netisr.h" 44 #include "../net/route.h" 45 46 #include "../vax/cpu.h" 47 #include "../vax/mtpr.h" 48 #include "../vaxuba/pdma.h" 49 50 #include "if_dpreg.h" 51 52 /* 53 * Driver information for auto-configuration stuff. 54 */ 55 int dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint(); 56 int dpoutput(), dpreset(), dptimeout(), x25_ifoutput(); 57 58 struct uba_device *dpinfo[NDP]; 59 60 u_short dpstd[] = { 0 }; 61 struct uba_driver dpdriver = 62 { dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo }; 63 64 /* 65 * Pdma structures for fast interrupts. 66 */ 67 struct pdma dppdma[2*NDP]; 68 69 /* error reporting intervals */ 70 #define DPI_RPNBFS 50 71 #define DPI_RPDSC 1 72 #define DPI_RPTMO 10 73 #define DPI_RPDCK 10 74 75 76 /* 77 * DP software status per interface. 78 * 79 * Each interface is referenced by a network interface structure, 80 * dp_if, which the routing code uses to locate the interface. 81 * This structure contains the output queue for the interface, its address, ... 82 */ 83 struct dp_softc { 84 struct ifnet dp_if; /* network-visible interface */ 85 short dp_iused; /* input buffers given to DP */ 86 short dp_flags; /* flags */ 87 short dp_ostate; /* restarting, etc. */ 88 short dp_istate; /* not sure this is necessary */ 89 #define DPS_IDLE 0 90 #define DPS_RESTART 1 91 #define DPS_ACTIVE 2 92 #define DPS_XEM 3 /* transmitting CRC, etc. */ 93 /* flags */ 94 #define DPF_RUNNING 0x01 /* device initialized */ 95 #define DPF_ONLINE 0x02 /* device running (had a RDYO) */ 96 #define DPF_RESTART 0x04 /* software restart in progress */ 97 #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */ 98 int dp_errors[4]; /* non-fatal error counters */ 99 #define dp_datck dp_errors[0] 100 #define dp_timeo dp_errors[1] 101 #define dp_nobuf dp_errors[2] 102 #define dp_disc dp_errors[3] 103 char dp_obuf[DP_MTU+8]; 104 char dp_rbuf[DP_MTU+8]; 105 } dp_softc[NDP]; 106 107 dpprobe(reg, ui) 108 caddr_t reg; 109 struct uba_device *ui; 110 { 111 register int br, cvec; 112 register struct dpdevice *addr = (struct dpdevice *)reg; 113 register int i; 114 115 #ifdef lint 116 br = 0; cvec = br; br = cvec; 117 dprint(0); dpxint(0); 118 #endif 119 addr->dpclr = DP_CLR; 120 addr->dpclr = DP_XIE|DP_XE; 121 DELAY(100000); 122 addr->dpclr = 0; 123 return (1); 124 } 125 126 /* 127 * Interface exists: make available by filling in network interface 128 * record. System will initialize the interface when it is ready 129 * to accept packets. 130 */ 131 dpattach(ui) 132 register struct uba_device *ui; 133 { 134 register struct dp_softc *dp = &dp_softc[ui->ui_unit]; 135 register struct pdma *pdp = &dppdma[ui->ui_unit*2]; 136 137 dp->dp_if.if_unit = ui->ui_unit; 138 dp->dp_if.if_name = "dp"; 139 dp->dp_if.if_mtu = DP_MTU; 140 dp->dp_if.if_init = dpinit; 141 dp->dp_if.if_output = x25_ifoutput; 142 dp->dp_if.if_start = dpstart; 143 dp->dp_if.if_ioctl = dpioctl; 144 dp->dp_if.if_reset = dpreset; 145 dp->dp_if.if_watchdog = dptimeout; 146 dp->dp_if.if_flags = IFF_POINTOPOINT; 147 148 149 pdp->p_addr = (struct dzdevice *)ui->ui_addr; 150 pdp->p_arg = (int)dp; 151 pdp->p_fcn = dpxint; 152 pdp->p_mem = pdp->p_end = dp->dp_obuf; 153 pdp++; 154 pdp->p_addr = (struct dzdevice *)ui->ui_addr; 155 pdp->p_arg = (int)dp; 156 pdp->p_fcn = dprint; 157 pdp->p_mem = pdp->p_end = dp->dp_rbuf; 158 159 if_attach(&dp->dp_if); 160 } 161 162 /* 163 * Reset of interface after UNIBUS reset. 164 * If interface is on specified UBA, reset its state. 165 */ 166 dpreset(unit, uban) 167 int unit, uban; 168 { 169 register struct uba_device *ui; 170 register struct dp_softc *dp = &dp_softc[unit]; 171 register struct dpdevice *addr; 172 173 if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 || 174 ui->ui_ubanum != uban) 175 return; 176 printf(" dp%d", unit); 177 dp->dp_flag = 0; 178 dp->dp_if.if_flags &= ~IFF_RUNNING; 179 addr = ui->ui_addr; 180 addr->dpclr = DP_CLR; 181 addr->dpsar = 0; 182 addr->dprcsr = 0; 183 dpinit(unit); 184 } 185 186 /* 187 * Initialization of interface. 188 */ 189 dpinit(unit) 190 int unit; 191 { 192 register struct dp_softc *dp = &dp_softc[unit]; 193 register struct uba_device *ui = dpinfo[unit]; 194 register struct dpdevice *addr; 195 register struct ifnet *ifp = &dp->dp_if; 196 struct ifaddr *ifa; 197 int base; 198 int s; 199 200 addr = (struct dpdevice *)ui->ui_addr; 201 202 /* 203 * Check to see that an address has been set. 204 */ 205 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 206 if (ifa->ifa_addr->sa_family != AF_LINK) 207 break; 208 if (ifa == (struct ifaddr *) 0) 209 return; 210 211 s = spl5(); 212 dp->dp_iused = 0; 213 dp->dp_istate = dp->dp_ostate = DPS_IDLE; 214 dppdma[2*unit+1].p_end = 215 dppdma[2*unit+1].p_mem = = dp->dp_rbuf; 216 /* enable receive interrupt; CTS comming up will trigger it also */ 217 addr->dpsar = DP_CHRM | 0x7E; /* 7E is the flag character */ 218 addr->dpclr = 0; 219 addr->dprcsr = DP_RIE | DP_DTR | DP_RE; 220 splx(s); 221 } 222 223 /* 224 * Start output on interface. Get another datagram 225 * to send from the interface queue and map it to 226 * the interface before starting output. 227 * 228 */ 229 dpstart(ifp) 230 struct ifnet *ifp; 231 { 232 int s, unit = ifp->if_unit; 233 register struct dp_softc *dp = &dp_softc[unit]; 234 register struct dpdevice *addr = dpinfo[unit].ui_addr; 235 register struct mbuf *m; 236 register char *cp; 237 char *cplim; 238 239 /* 240 * If already doing output, go away and depend on transmit 241 * complete or error. 242 */ 243 s = splimp(); 244 if (dp->dp_if.if_flags & IFF_OACTIVE) { 245 splx(s); 246 return (0); 247 } 248 IF_DEQUEUE(&dp->dp_if.if_snd, m); 249 if (m == 0) 250 return (0); 251 if ((m->m_flags | M_PKTHDR) == 0 || m->m_pkthdr.len > DP_MTU) 252 return (EINVAL); 253 s = spl5(); 254 dppdma[2*unit].p_mem = cp = dp->dp_obuf; 255 while (m) { 256 struct mbuf *n; 257 bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len); 258 cp += m->m_len; 259 MFREE(m, n); m = n; 260 } 261 if (cp == dp->dp_obuf) 262 return (0); 263 dppdma[2*unit].p_end = cp; 264 addr->dpclr = DP_XE | DP_XIE; 265 addr->dptdsr = DP_XSM; 266 dp->dp_if.if_flags |= IFF_OACTIVE; 267 dp->dp_ostate = DPS_ACTIVE; 268 splx(s); 269 return (0); 270 } 271 /* 272 * Receive done or error interrupt 273 */ 274 dprint(unit, pdma, addr) 275 register struct pdma *pdma; 276 register struct dpdevice *addr; 277 { 278 register struct dpsoftc *dp = &dpsoftc[unit]; 279 unsigned short dprdsr = addr->dprdsr; 280 281 if (dprdsr & DP_ROVR) { 282 dp->dp_flags |= DPF_FLUSH; 283 return; 284 } 285 if (dprdsr & DP_RSM) { /* Received Start of Message */ 286 dp->dp_ibuf[0] = dprdsr & DP_RBUF; 287 pdma->p_mem = dp->dp_ibuf + 1; 288 dpflags &= ~DPF_FLUSH; 289 return; 290 } 291 if (dprdsr & DP_REM) { /* Received End of Message */ 292 if (dprdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { 293 dp->dp_if.if_errors++; 294 pdma->p_mem = dp->dp_ibuf; 295 dp->dp_flags &= ~ DPF_FLUSH; 296 return; 297 } 298 dpinput(dp, pdma->p_mem - dp->dp_ibuf, dp->dp_ibuf); 299 return; 300 } 301 dp->dp_flags |= DPF_FLUSH; 302 if (pdma->p_mem != pdma->p_end) 303 log(dp%d: unexplained receiver interrupt\n"); 304 } 305 306 /* 307 * Transmit complete or error interrupt 308 */ 309 dpxint(unit, pdma, addr) 310 register struct pdma *pdma; 311 register struct dpdevice *addr; 312 { 313 register struct dpsoftc *dp = &dpsoftc[unit]; 314 315 if (addr->dptdsr & DP_XERR) { 316 log("if_dp%d: data late\n", unit); 317 restart: 318 pdma->p_mem = dp->dp_obuf; 319 addr->dptdsr = DP_XSM; 320 return; 321 } 322 switch (dp->dp_ostate) { 323 324 case DPS_ACTIVE: 325 if (pdma->p_mem != pdma->p_end) { 326 log("if_dp%d: misc error in dpxint\n"); 327 goto restart; 328 } 329 addr->dptdsr = DP_XEM; 330 dp->dp_ostate = DPS_XEM; 331 break; 332 333 case DPS_XEM: 334 dp->dp_if.if_flags &= ~IFF_OACTIVE; 335 if (dp->dp_if.if_snd.ifq_len) 336 dpstart(&dp->dp_if); 337 else { 338 addr->dpclr = 0; 339 dp->dp_ostate = DPS_IDLE; 340 } 341 break; 342 343 default: 344 log("if_dp%d: impossible state in dpxint\n"); 345 } 346 } 347 /* 348 * Routine to copy from device buffer into mbufs. 349 * 350 * Warning: This makes the fairly safe assumption that 351 * mbufs have even lengths. 352 */ 353 struct mbuf * 354 dpget(rxbuf, totlen, off, ifp) 355 caddr_t rxbuf; 356 int totlen, off; 357 struct ifnet *ifp; 358 { 359 register caddr_t cp; 360 register struct mbuf *m; 361 struct mbuf *top = 0, **mp = ⊤ 362 int len; 363 caddr_t packet_end; 364 365 cp = rxbuf; 366 packet_end = cp + totlen; 367 if (off) { 368 off += 2 * sizeof(u_short); 369 totlen -= 2 *sizeof(u_short); 370 cp = rxbuf + off; 371 } 372 373 MGETHDR(m, M_DONTWAIT, MT_DATA); 374 if (m == 0) 375 return (0); 376 m->m_pkthdr.rcvif = ifp; 377 m->m_pkthdr.len = totlen; 378 m->m_len = MHLEN; 379 380 while (totlen > 0) { 381 if (top) { 382 MGET(m, M_DONTWAIT, MT_DATA); 383 if (m == 0) { 384 m_freem(top); 385 return (0); 386 } 387 m->m_len = MLEN; 388 } 389 len = min(totlen, (packet_end - cp)); 390 if (len >= MINCLSIZE) { 391 MCLGET(m, M_DONTWAIT); 392 if (m->m_flags & M_EXT) 393 m->m_len = len = min(len, MCLBYTES); 394 else 395 len = m->m_len; 396 } else { 397 /* 398 * Place initial small packet/header at end of mbuf. 399 */ 400 if (len < m->m_len) { 401 if (top == 0 && len + max_linkhdr <= m->m_len) 402 m->m_data += max_linkhdr; 403 m->m_len = len; 404 } else 405 len = m->m_len; 406 } 407 bcopy(cp, mtod(m, caddr_t), (u_int)len); 408 *mp = m; 409 mp = &m->m_next; 410 totlen -= len; 411 cp += len; 412 if (cp == packet_end) 413 cp = rxbuf; 414 } 415 return (top); 416 } 417 418 dpinput(dp, len, buffer) 419 register struct dpsoftc *dp; 420 caddr_t buffer; 421 { 422 register struct ifnet *ifp = &dp->dp_if; 423 register struct ifqueue *inq; 424 register struct mbuf *m; 425 extern struct ifqueue hdintrq; 426 427 if(len <= 0 || ifp->if_addrlist == 0) 428 return; 429 430 m = dpget(buffer, len , 0, ifp); 431 if (m == 0) 432 return; 433 ifp->if_ipackets++; 434 435 /* Only AF_CCITT makes sense at this point */ 436 inq = &hdintrq; 437 438 if(IF_QFULL(inq)) { 439 IF_DROP(inq); 440 m_freem(m); 441 } else { 442 IF_ENQUEUE(inq, m); 443 schednetisr(NETISR_HD); 444 } 445 } 446 447 /* 448 * Process an ioctl request. 449 */ 450 dpioctl(ifp, cmd, data) 451 register struct ifnet *ifp; 452 int cmd; 453 caddr_t data; 454 { 455 register struct ifaddr *ifa = (struct ifaddr *)data; 456 int s = splimp(), error = 0; 457 458 switch (cmd) { 459 460 case SIOCSIFADDR: 461 ifp->if_flags |= IFF_UP; 462 switch (ifa->ifa_addr->sa_family) { 463 #ifdef CCITT 464 case AF_CCITT: 465 error = hd_ctlinput (PRC_IFUP, (caddr_t)&ifa->ifa_addr); 466 if (error == 0) 467 dpinit(ifp->if_unit); 468 break; 469 #endif 470 case SIOCSIFFLAGS: 471 if ((ifp->if_flags & IFF_UP) == 0 && 472 (dp->dp_flags & DPF_RUNNING)) 473 dpdown(ifp->if_unit); 474 else if (ifp->if_flags & IFF_UP && 475 (dp->dp_flags & DPF_RUNNING) == 0) 476 dpinit(ifp->if_unit); 477 break; 478 479 default: 480 dpinit(ifp->if_unit); 481 break; 482 } 483 break; 484 485 /* case SIOCSIFFLAGS: ... */ 486 487 default: 488 error = EINVAL; 489 } 490 splx(s); 491 return (error); 492 } 493 /* 494 * Reset a device and mark down. 495 * Flush output queue and drop queue limit. 496 */ 497 dpdown(unit) 498 int unit; 499 { 500 register struct dp_softc *dp = &dp_softc[unit]; 501 register struct ifxmt *ifxp; 502 503 dp->dp_flags &= ~(DP_RUNNING | DP_ONLINE); 504 addr->dpclr = DP_CLR; 505 addr->dpclr = 0; 506 507 if_qflush(&dp->dp_if.if_snd); 508 } 509 510 /* 511 * Watchdog timeout to see that transmitted packets don't 512 * lose interrupts. The device has to be online (the first 513 * transmission may block until the other side comes up). 514 */ 515 dptimeout(unit) 516 int unit; 517 { 518 register struct dp_softc *dp; 519 struct dpdevice *addr; 520 521 dp = &dp_softc[unit]; 522 if (dp->dp_flags & DP_ONLINE) { 523 addr = (struct dpdevice *)(dpinfo[unit]->ui_addr); 524 dpstart(unit); 525 } 526 } 527 #endif 528