#define KERNEL 1 #include #ifdef UCB_SCCSID static char sccs_id[] = "@(#)pk1.c 3.1"; #endif /* * kernel support routines. */ struct pack *pklines[NPLINES]; int maxwindow =2; /* * start initial synchronization. * allocate space. */ pkopen(dev, tp, addr) register struct tty *tp; caddr_t addr; { register struct pack *pk; register i; int pktimeout(); char **bp; static timer_on; int s; struct piocb piocb; if (tp->t_line) return; /* * copy user parameters */ if (copyin(addr, (caddr_t)&piocb, sizeof (piocb))) { u.u_error = EFAULT; return; } npbits = dtom(sizeof(struct pack)); pk = (struct pack *)getepack(npbits); if (pk==NULL) goto notsobad; pkzero((caddr_t)pk,sizeof (struct pack)); pk->p_rwindow = piocb.window; if (pk->p_rwindow > maxwindow) pk->p_rwindow = maxwindow; pk->p_rsize = piocb.psize; if (pk->p_rsize > 512 || pk->p_rsize & 037) goto notsobad; pk->p_mode = piocb.mode; if (pk->p_mode & 01) pkdebug++; /* * try to allocate input window */ pk->p_bits = dtom(pk->p_rsize); for(i=0; ip_rwindow; i++) { bp = (char **)getepack(pk->p_bits); if (bp==NULL) break; *bp = (char *)pk->p_ipool; pk->p_ipool = bp; } if (i==0 && bp==NULL) goto notsobad; pk->p_rwindow = i; /* * start timer process, * wait for synchronization. */ flushtty(tp); s = spl6(); pkdisc = tp->t_line = piocb.t; pk->p_ttyp = tp; tp->t_linep = (caddr_t)pk; q2.c_cf = q2.c_cl = NULL; q1.c_cf = q1.c_cl = (caddr_t)&pk->p_ihbuf; q1.c_cc = -HDRSIZ; if (tp->t_iproc != NULL) (*tp->t_iproc)(tp); pk->p_rmsg = M_INITA; for(i=0; ip_timer++; if (timer_on==0) { timer_on++; pktimeout(); } splx(s); SLEEP(&pk->p_state, PKOPRI); pkreset(pk); if ((pk->p_state&LIVE)==0) { pk->p_state = DOWN; pk->p_rmsg = 0; notsobad: u.u_error = ENXIO; return; } pksetgrp(tp); pkioctl(DIOCGETP, tp, addr); } /* * unix ioctl interface */ pkioctl(com,tp,addr) register struct tty *tp; caddr_t addr; { struct piocb piocb; register struct pack *pk; pk = (struct pack *)tp->t_linep; if (com == DIOCGETP) { piocb.window = pk->p_swindow; piocb.psize = pk->p_xsize; piocb.state = pk->p_state; if (copyout((caddr_t)&piocb, addr, sizeof(piocb))) { u.u_error = EFAULT; } if (u.u_error==0) u.u_r.r_val1 = piocb.psize; } } /* * Arrange for the device (i.e. tp) * to be able to generate signals if need be. */ pksetgrp(tp) register struct tty *tp; { register struct proc *pp; pp = u.u_procp; if (pp->p_pgrp == 0) pp->p_pgrp = pp->p_pid; if (tp->t_pgrp == 0) tp->t_pgrp = pp->p_pgrp; } /* * Shut down io. * The problem is mainly input since the * device driver may have a buffer. */ pkturnoff(tp) register struct tty *tp; { register char **bp; register struct pack *pk; register s; pk = PADDR; LOCK; bp = pk->p_io; tp->t_line = 0; q1.c_cf = NULL; flushtty(tp); if (bp!=NULL) { *bp = (char *)pk->p_ipool; pk->p_ipool = bp; } UNLOCK; } /* * link dead? */ pklive(pk) register struct pack *pk; { register struct tty *tp; tp = pk->p_ttyp; if (tp->t_line!=pkdisc || tp->t_linep!=(caddr_t)pk) { return(0); } return(tp->t_state&CARR_ON); } /* * timeout process: * wakes up periodically to check status * of active lines. */ pktimeout() { register struct pack *pk; extern time_t time; register i; for(i=0;ip_nout == pk->p_tout) { if (pk->p_xcount && pk->p_timer==0) { pk->p_timer = 3; pk->p_state |= WAITO; } } else pk->p_tout = pk->p_nout; if (pk->p_timer==0) { if (pk->p_state & BADFRAME) { pk->p_msg |= M_RJ; pk->p_state &= ~BADFRAME; goto startup; } if (pk->p_rmsg) goto startup; WAKEUP(&pk->p_ps); continue; } if (--pk->p_timer == 0) { if ((pk->p_state&LIVE)==0) { startup: pk->p_timer = 1; } else if (pk->p_state & WAITO) { if (pk->p_state&DRAINO) { pk->p_state |= DOWN; } else { pk->p_state |= RXMIT; } pkoutput(pk); pk->p_timer = 5+2*pkzot; } WAKEUP(&pk->p_ps); pk->p_msg |= pk->p_rmsg; if (pk->p_msg) pkoutput(pk); } } timeout(pktimeout, (caddr_t)pk, 60); /* * randomize timeouts. */ pkzot = 2 + time&07; }