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