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.10 (Berkeley) 05/04/92
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 "../include/pte.h"
28
29 #include "sys/param.h"
30 #include "sys/systm.h"
31 #include "sys/mbuf.h"
32 #include "sys/buf.h"
33 #include "sys/ioctl.h" /* must precede tty.h */
34 #include "sys/protosw.h"
35 #include "sys/socket.h"
36 #include "sys/socketvar.h"
37 #include "sys/syslog.h"
38 #include "sys/vmmac.h"
39 #include "sys/errno.h"
40 #include "sys/time.h"
41 #include "sys/kernel.h"
42
43 #include "net/if.h"
44 #include "net/if_types.h"
45 #include "net/netisr.h"
46 #include "net/route.h"
47
48 #include "../include/cpu.h"
49 #include "../include/mtpr.h"
50
51 #define dzdevice dpdevice
52 #include "../uba/pdma.h"
53 #include "../uba/ubavar.h"
54
55 #include "netccitt/x25.h"
56 #include "netccitt/pk.h"
57 #include "netccitt/pk_var.h"
58
59 #include "if_dpreg.h"
60
61 /*
62 * Driver information for auto-configuration stuff.
63 */
64 int dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint();
65 int dpoutput(), dpreset(), dptimeout(), dpstart(), dptestoutput();
66 int x25_ifoutput(), x25_rtrequest();
67
68 struct uba_device *dpinfo[NDP];
69
70 u_short dpstd[] = { 0 };
71 struct uba_driver dpdriver =
72 { dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo };
73
74 /*
75 * Pdma structures for fast interrupts.
76 */
77 struct pdma dppdma[2*NDP];
78
79 /*
80 * DP software status per interface.
81 *
82 * Each interface is referenced by a network interface structure,
83 * dp_if, which the routing code uses to locate the interface.
84 * This structure contains the output queue for the interface, its address, ...
85 */
86 struct dp_softc {
87 struct ifnet dp_if; /* network-visible interface */
88 int dp_ipl;
89 struct dpdevice *dp_addr; /* dpcsr address */
90 short dp_iused; /* input buffers given to DP */
91 short dp_flags; /* flags */
92 #define DPF_RUNNING 0x01 /* device initialized */
93 #define DPF_ONLINE 0x02 /* device running (had a RDYO) */
94 #define DPF_RESTART 0x04 /* software restart in progress */
95 #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */
96 #define DPF_X25UP 0x10 /* XXX -- someday we'll do PPP also */
97 short dp_ostate; /* restarting, etc. */
98 short dp_istate; /* not sure this is necessary */
99 #define DPS_IDLE 0
100 #define DPS_RESTART 1
101 #define DPS_ACTIVE 2
102 #define DPS_XEM 3 /* transmitting CRC, etc. */
103 short dp_olen; /* length of last packet sent */
104 short dp_ilen; /* length of last packet recvd */
105 char dp_obuf[DP_MTU+8];
106 char dp_ibuf[DP_MTU+8];
107 } dp_softc[NDP];
108
109 /*
110 * Debug info
111 */
112 struct dpstat {
113 long start;
114 long nohdr;
115 long init;
116 long rint;
117 long xint;
118 long reset;
119 long ioctl;
120 long down;
121 long mchange;
122 long timeout;
123 long rsm;
124 long rem;
125 long remchr;
126 long rga;
127 long xem;
128 long rovr;
129 } dpstat;
130
131 short dp_ilb = 0;
132 short dp_log = 0;
133
134 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
135 int dp_sizes[] = {
136 sizeof(dp_softc[0]), sizeof(struct ifnet),
137 _offsetof(struct dp_softc, dp_obuf[0]),
138 _offsetof(struct dp_softc, dp_ibuf[0]),
139 };
140
dpprobe(reg,ui)141 dpprobe(reg, ui)
142 caddr_t reg;
143 struct uba_device *ui;
144 {
145 register int br, cvec;
146 register struct dpdevice *addr = (struct dpdevice *)reg;
147 register int unit = ui->ui_unit;
148
149 #ifdef lint
150 br = 0; cvec = br; br = cvec;
151 dprint(0); dpxint(0);
152 #endif
153 (void) spl6();
154 addr->dpclr = DP_CLR;
155 addr->dpclr = DP_XIE|DP_XE;
156 DELAY(100000);
157 dp_softc[unit].dp_ipl = br = qbgetpri();
158 dp_softc[unit].dp_addr = addr;
159 addr->dpclr = 0;
160 if (cvec && cvec != 0x200){
161 cvec -= 4;
162 }
163 return (1);
164 }
165
166 /*
167 * Interface exists: make available by filling in network interface
168 * record. System will initialize the interface when it is ready
169 * to accept packets.
170 */
dpattach(ui)171 dpattach(ui)
172 register struct uba_device *ui;
173 {
174 register struct dp_softc *dp = &dp_softc[ui->ui_unit];
175
176 dp->dp_if.if_unit = ui->ui_unit;
177 dp->dp_if.if_name = "dp";
178 dp->dp_if.if_mtu = DP_MTU;
179 dp->dp_if.if_init = dpinit;
180 dp->dp_if.if_output = x25_ifoutput;
181 dp->dp_if.if_type = IFT_X25;
182 dp->dp_if.if_hdrlen = 5;
183 dp->dp_if.if_addrlen = 8;
184 dp->dp_if.if_start = dpstart;
185 dp->dp_if.if_ioctl = dpioctl;
186 dp->dp_if.if_reset = dpreset;
187 dp->dp_if.if_watchdog = dptimeout;
188 dp->dp_if.if_flags = 0;
189 if_attach(&dp->dp_if);
190 }
191
192 /*
193 * Reset of interface after UNIBUS reset.
194 * If interface is on specified UBA, reset its state.
195 */
dpreset(unit,uban)196 dpreset(unit, uban)
197 int unit, uban;
198 {
199 register struct uba_device *ui;
200 register struct dp_softc *dp = &dp_softc[unit];
201 register struct dpdevice *addr;
202
203 dpstat.reset++;
204 if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 ||
205 ui->ui_ubanum != uban)
206 return;
207 dpdown(unit);
208 dpinit(unit);
209 printf(" dp%d", unit);
210 }
211
212 /*
213 * Initialization of interface.
214 */
dpinit(unit)215 dpinit(unit)
216 int unit;
217 {
218 register struct dp_softc *dp = &dp_softc[unit];
219 register struct dpdevice *addr;
220 register struct ifaddr *ifa;
221 register struct pdma *pdp = &dppdma[unit*2];
222 int base, s;
223
224 dpstat.init++;
225 /*
226 * Check to see that an address has been set.
227 */
228 for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next)
229 if (ifa->ifa_addr->sa_family != AF_LINK)
230 break;
231 if (ifa == (struct ifaddr *) 0)
232 return;
233
234 addr = dp->dp_addr;
235 s = splimp();
236 dp->dp_iused = 0;
237 dp->dp_istate = dp->dp_ostate = DPS_IDLE;
238 dp->dp_if.if_flags |= IFF_RUNNING;
239 dp->dp_if.if_flags &= ~IFF_OACTIVE;
240
241 pdp->p_addr = addr;
242 pdp->p_fcn = dpxint;
243 pdp->p_mem = pdp->p_end = dp->dp_obuf;
244 pdp++;
245 pdp->p_addr = addr;
246 pdp->p_fcn = dprint;
247 /* force initial interrupt to come to dprint */
248 pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8;
249
250 addr->dpclr = DP_CLR;
251 DELAY(5000);
252 /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts),
253 CRC = CCIIT, initially all ones, 2nd addr = 0 */
254 addr->dpsar = DP_SSLM | DP_IDLE;
255 addr->dpclr = DP_XE | dp_ilb;
256 addr->dptdsr = DP_XSM;
257 /* enable receiver, receive interrupt, DTR, RTS */
258 addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
259 dpstart(&dp->dp_if);
260 splx(s);
261 }
262
263 /*
264 * Start output on interface. Get another datagram
265 * to send from the interface queue and map it to
266 * the interface before starting output.
267 *
268 */
269 dpstart(ifp)
270 struct ifnet *ifp;
271 {
272 int s, unit = ifp->if_unit, error = 0, len;
273 register struct dp_softc *dp = &dp_softc[unit];
274 register struct dpdevice *addr = dp->dp_addr;
275 register struct mbuf *m;
276 register char *cp;
277 char *cplim;
278
279 /*
280 * If already doing output, go away and depend on transmit
281 * complete or error.
282 */
283 dpstat.start++;
284 if ((dp->dp_if.if_flags & IFF_OACTIVE) ||
285 (dp->dp_if.if_flags & IFF_RUNNING) == 0)
286 goto out;
287 IF_DEQUEUE(&dp->dp_if.if_snd, m);
288 if (m == 0)
289 goto out;
290 dp->dp_if.if_collisions++;
291 if (m->m_flags & M_PKTHDR)
292 len = m->m_pkthdr.len;
293 else {
294 struct mbuf *m0 = m;
295 for (len = 0; m; m = m->m_next)
296 len += m->m_len;
297 m = m0;
298 dpstat.nohdr++;
299 }
300 if (len < 2)
301 goto out;
302 if (len > DP_MTU) {
303 error = EINVAL;
304 goto out;
305 }
306 dppdma[2*unit].p_mem = cp = dp->dp_obuf;
307 while (m) {
308 struct mbuf *n;
309 bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len);
310 cp += m->m_len;
311 MFREE(m, n); m = n;
312 }
313 dppdma[2*unit].p_end = cp - 1;
314 dp->dp_if.if_flags |= IFF_OACTIVE;
315 dp->dp_ostate = DPS_ACTIVE;
316 dp->dp_if.if_collisions--;
317 dp->dp_olen = len;
318 if (dp_log) {
319 register u_char *p = (u_char *)dp->dp_obuf;
320 log(LOG_DEBUG, "dpoutput(%d):%x %x %x %x %x\n",
321 len, p[0], p[1], p[2], p[3], p[4]);
322 }
323 addr->dpsar = DP_SSLM | DP_IDLE;
324 addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
325 addr->dpclr = DP_XIE | DP_XE | dp_ilb;
326 addr->dptdsr = DP_XSM;
327 out:
328 return (error);
329 }
330 /*
331 * Receive done or error interrupt
332 */
dprint(unit,pdma,addr)333 dprint(unit, pdma, addr)
334 register struct pdma *pdma;
335 register struct dpdevice *addr;
336 {
337 register struct dp_softc *dp = &dp_softc[unit];
338 short rdsr = addr->dprdsr, rcsr = pdma->p_arg;
339
340 dpstat.rint++;
341 splx(dp->dp_ipl);
342 if (rdsr & DP_RGA) {
343 /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts),
344 CRC = CCIIT, initially all ones, 2nd addr = 0 */
345 addr->dpsar = DP_SSLM | DP_IDLE;
346 addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
347 dpstat.rga++;
348 return;
349 }
350 if (rdsr & DP_RSM) { /* Received Start of Message */
351 dpstat.rsm++;
352 pdma->p_mem = dp->dp_ibuf;
353 if (rcsr & DP_RDR) {
354 dp->dp_ibuf[0] = rdsr & DP_RBUF;
355 pdma->p_mem++;
356 }
357 dp->dp_flags &= ~DPF_FLUSH;
358 return;
359 }
360 if (rdsr & DP_REM) { /* Received End of Message */
361 dpstat.rem++;
362 if (rcsr & DP_RDR) {
363 *(pdma->p_mem++) = rdsr;
364 dpstat.remchr++;
365 }
366 dp->dp_ilen = pdma->p_mem - dp->dp_ibuf;
367 if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) {
368 dp->dp_if.if_ierrors++;
369 } else
370 dpinput(&dp->dp_if, dp->dp_ilen, dp->dp_ibuf);
371 pdma->p_mem = pdma->p_end;
372 dp->dp_flags &= ~ DPF_FLUSH;
373 return;
374 }
375 if (rdsr & DP_ROVR) {
376 dpstat.rovr++;
377 dp->dp_flags |= DPF_FLUSH;
378 return;
379 }
380 if (rcsr & DP_MSC) {
381 dpstat.mchange++;
382 if (0 == (rcsr & DP_DSR)) {
383 log(LOG_DEBUG, "dp%d: lost modem\n", unit);
384 /*dpdown(unit);*/
385 }
386 return;
387 }
388 dp->dp_flags |= DPF_FLUSH;
389 if (pdma->p_mem != pdma->p_end)
390 log(LOG_DEBUG, "dp%d: unexplained receiver interrupt\n", unit);
391 }
392 /*
393 * Transmit complete or error interrupt
394 */
dpxint(unit,pdma,addr)395 dpxint(unit, pdma, addr)
396 register struct pdma *pdma;
397 register struct dpdevice *addr;
398 {
399 register struct dp_softc *dp = &dp_softc[unit];
400 int s;
401
402 splx(dp->dp_ipl);
403 dpstat.xint++;
404 if (addr->dptdsr & DP_XERR) {
405 log(LOG_DEBUG, "if_dp%d: data late\n", unit);
406 restart:
407 pdma->p_mem = dp->dp_obuf;
408 addr->dptdsr = DP_XSM;
409 dp->dp_if.if_oerrors++;
410 return;
411 }
412 switch (dp->dp_ostate) {
413
414 case DPS_ACTIVE:
415 if (pdma->p_mem != pdma->p_end) {
416 log(LOG_DEBUG, "if_dp%d: misc error in dpxint\n", unit);
417 goto restart;
418 }
419 addr->dpsar = DP_IDLE|DP_SSLM;
420 addr->dpclr = DP_XE | DP_XIE | dp_ilb;
421 addr->dptdsr = DP_XEM | (0xff & pdma->p_mem[0]);
422 addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
423 dp->dp_ostate = DPS_XEM;
424 break;
425
426 case DPS_XEM:
427 dpstat.xem++;
428 dp->dp_if.if_opackets++;
429 dp->dp_ostate = DPS_IDLE;
430 dp->dp_if.if_flags &= ~IFF_OACTIVE;
431 if (dp->dp_if.if_snd.ifq_len)
432 dpstart(&dp->dp_if);
433 else {
434 addr->dpsar = DP_IDLE|DP_SSLM;
435 addr->dpclr = DP_XE | dp_ilb;
436 addr->dptdsr = DP_XSM;
437 addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR|DP_RTS;
438 }
439 break;
440
441 default:
442 log(LOG_DEBUG, "if_dp%d: impossible state in dpxint\n");
443 }
444 }
445
dpinput(ifp,len,buffer)446 dpinput(ifp, len, buffer)
447 register struct ifnet *ifp;
448 caddr_t buffer;
449 {
450 register struct ifqueue *inq;
451 register struct mbuf *m;
452 extern struct ifqueue hdintrq, ipintrq;
453 int isr;
454 extern struct mbuf *m_devget();
455
456 ifp->if_ipackets++;
457 if (dp_log) {
458 register u_char *p = (u_char *)buffer;
459 log(LOG_DEBUG, "dpinput(%d):%x %x %x %x %x\n",
460 len, p[0], p[1], p[2], p[3], p[4]);
461 }
462
463 {
464 register struct ifaddr *ifa = ifp->if_addrlist;
465 register u_char *cp = (u_char *)buffer;
466
467 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
468 if (ifa->ifa_addr->sa_family != AF_LINK)
469 break;
470 if (cp[0] == 0xff && cp[1] == 0x3) {
471 /* This is a UI HDLC Packet, so we'll assume PPP
472 protocol. for now, IP only. */
473 buffer += 4;
474 len -= 4;
475 inq = &ipintrq;
476 isr = NETISR_IP;
477 } else {
478 inq = &hdintrq;
479 isr = NETISR_CCITT;
480 }
481 }
482 if (len <= 0)
483 return;
484
485 m = m_devget(buffer, len , 0, ifp, 0);
486 if (m == 0)
487 return;
488
489 if(IF_QFULL(inq)) {
490 IF_DROP(inq);
491 m_freem(m);
492 } else {
493 IF_ENQUEUE(inq, m);
494 schednetisr(isr);
495 }
496 }
497
498 /*
499 * Process an ioctl request.
500 */
dpioctl(ifp,cmd,data)501 dpioctl(ifp, cmd, data)
502 register struct ifnet *ifp;
503 int cmd;
504 caddr_t data;
505 {
506 register struct ifaddr *ifa = (struct ifaddr *)data;
507 int s = splimp(), error = 0;
508 struct dp_softc *dp = &dp_softc[ifp->if_unit];
509
510 dpstat.ioctl++;
511 switch (cmd) {
512 case SIOCSIFCONF_X25:
513 ifp->if_flags |= IFF_UP;
514 error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr);
515 if (error == 0)
516 dpinit(ifp->if_unit);
517 break;
518
519 case SIOCSIFADDR:
520 ifa->ifa_rtrequest = x25_rtrequest;
521 break;
522
523 case SIOCSIFFLAGS:
524 if ((ifp->if_flags & IFF_UP) == 0 &&
525 (ifp->if_flags & IFF_RUNNING))
526 dpdown(ifp->if_unit);
527 else if (ifp->if_flags & IFF_UP &&
528 (ifp->if_flags & IFF_RUNNING) == 0)
529 dpinit(ifp->if_unit);
530 break;
531
532
533 default:
534 error = EINVAL;
535 }
536 splx(s);
537 return (error);
538 }
539 /*
540 * Reset a device and mark down.
541 * Flush output queue and drop queue limit.
542 */
dpdown(unit)543 dpdown(unit)
544 int unit;
545 {
546
547 register struct dp_softc *dp = &dp_softc[unit];
548 register struct dpdevice *addr = dp->dp_addr;
549
550 dpstat.down++;
551 if_qflush(&dp->dp_if.if_snd);
552 dp->dp_flags = 0;
553 dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
554
555 addr->dpclr = DP_CLR;
556 DELAY(1000);
557 addr->dpsar = 0;
558 addr->dprcsr = 0;
559 }
560
561 /*
562 * Watchdog timeout to see that transmitted packets don't
563 * lose interrupts. The device has to be online (the first
564 * transmission may block until the other side comes up).
565 */
dptimeout(unit)566 dptimeout(unit)
567 int unit;
568 {
569 register struct dp_softc *dp;
570
571 /* currently not armed */
572 dpstat.timeout++;
573 dp = &dp_softc[unit];
574 if (dp->dp_if.if_flags & IFF_OACTIVE) {
575 dpstart(&dp->dp_if);
576 }
577 }
578 /*
579 * For debugging loopback activity.
580 */
581 static char pppheader[4] = { -1, 3, 0, 0x21 };
582 int dp_louts;
583
dptestoutput(ifp,m,dst,rt)584 dptestoutput(ifp, m, dst, rt)
585 register struct ifnet *ifp;
586 register struct mbuf *m;
587 struct sockaddr *dst;
588 struct rtentry *rt;
589 {
590 /*
591 * Queue message on interface, and start output if interface
592 * not yet active.
593 */
594 int s = splimp(), error = 0;
595 dp_louts++;
596 M_PREPEND(m, sizeof pppheader, M_DONTWAIT);
597 if (m == 0) {
598 splx(s);
599 return ENOBUFS;
600 }
601 bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader);
602 if (IF_QFULL(&ifp->if_snd)) {
603 IF_DROP(&ifp->if_snd);
604 /* printf("%s%d: HDLC says OK to send but queue full, may hang\n",
605 ifp->if_name, ifp->if_unit);*/
606 m_freem(m);
607 error = ENOBUFS;
608 } else {
609 IF_ENQUEUE(&ifp->if_snd, m);
610 if ((ifp->if_flags & IFF_OACTIVE) == 0)
611 (*ifp->if_start)(ifp);
612 }
613 splx(s);
614 return (error);
615 }
616
617 #endif
618