32V/usr/src/slowsys/sys/dz.c

Compare this file to the similar file:
Show the results in this format:

/*
*  DZ-11 Driver
*/
# include "../h/param.h"
# include "../h/tty.h"
# include "../h/uba.h"
# include "../h/proc.h"
# include "../h/dir.h"
# include "../h/file.h"
# include "../h/inode.h"
# include "../h/user.h"
# include "../h/conf.h"
 
# define DZADDR  (UBA0_DEV + 0160100)
# define NDZ (1*8)
 
# define  BITS7  020
# define  BITS8  030
# define  TWOSB  040
# define  PENABLE  0100
# define  OPAR  0200
# define  MSE  040  /* Master Scan Enable */
# define  RIE  0100  /* Receiver Interrupt Enable */
# define  TIE  040000  /*  Transmit interrupt enable */
# define  DZ_IEN  (MSE+RIE+TIE)
# define  PERROR  010000
# define  FRERROR  020000
# define SSPEED  7  /* std speed = 300 baud */

 
# define dzlpr  dzrbuf
# define dzmsr  dzbrk
# define  ON  1
# define  OFF  0
 
struct tty dz_tty[NDZ] ;
int dz_cnt = { NDZ }  ;
struct dzregs {
	short dzcsr ;
	short dzrbuf ;
	char  dztcr ;
	char  dzdtr ;
	char  dztbuf ;
	char  dzbrk ;
	} ;
struct dzregs *dz_addr[] = {
	(struct dzregs *)(DZADDR),
	(struct dzregs *)(DZADDR+010),
	(struct dzregs *)(DZADDR+020),
	(struct dzregs *)(DZADDR+030)
	} ;
char dz_timer ;
char dz_speeds[] = {
	0, 020 , 021 , 022 , 023 , 024 , 0, 025,
	026 , 027 , 030 , 032 , 034 , 036 , 0 , 0,
	} ;
 
dzopen(d,flag)
{
	register struct tty *tp ;
	register dev ;
	extern dzstart() , dzscan() ;
 
	dev = minor(d);
	if (dev >= dz_cnt) {
		u.u_error = ENXIO ;
		return ;
		}
	if (dz_timer == 0) {
		dz_timer++ ;
		timeout(dzscan,0,60) ;
		}
	tp = &dz_tty[dev] ;
	tp->t_addr = ((struct dzregs *)DZADDR) + (dev>>3);
	tp->t_oproc = dzstart ;
	tp->t_iproc = NULL;
	tp->t_state |= WOPEN ;
	if ((tp->t_state & ISOPEN) == 0) {
		tp->t_erase = CERASE ;
		tp->t_kill = CKILL ;
		tp->t_ospeed = tp->t_ispeed = SSPEED ;
		tp->t_flags = ODDP|EVENP|ECHO|HUPCLS ;
		dzparam(dev) ;
		}
	else
		if (tp->t_state&XCLUDE && u.u_uid != 0) {
			u.u_error = EBUSY ;
			return ;
			}
	dzmodem(dev,ON) ;
	spl5() ;
	while ((tp->t_state & CARR_ON) == 0) {
		tp->t_state |= WOPEN ;
		sleep(&tp->t_rawq,TTIPRI) ;
		}
	spl0() ;
	(*linesw[tp->t_line].l_open)(d,tp);
}
 
/*		*/
 
dzclose(d)
{
	register struct tty *tp ;
	register dev ;
 
	dev = minor(d);
	tp = &dz_tty[dev] ;
	(*linesw[tp->t_line].l_close)(tp);
	if (tp->t_flags & HUPCLS)
		dzmodem(dev,OFF) ;
	ttyclose(tp);
}
 
/*		*/
 
dzread(d)
{
	register struct tty *tp;
 
	tp = &dz_tty[minor(d)];
	(*linesw[tp->t_line].l_read)(tp);
}
 
/*		*/
 
dzwrite(d)
{
	register struct tty *tp;
 
	tp = &dz_tty[minor(d)];
	(*linesw[tp->t_line].l_write)(tp);
}
 
/*		*/
 
dzrint(dev)
{
	register struct tty *tp ;
	register int c ;
	register struct dzregs *dzaddr ;
 
	dzaddr = dz_addr[dev] ;
	while ((c = dzaddr->dzrbuf) < 0) { /* char present */
		tp = &dz_tty[((c>>8)&07)|(dev<<3)] ;
		if (tp >= &dz_tty[dz_cnt]) continue ;
		if ((tp->t_state & ISOPEN) == 0) {
			wakeup(&tp->t_rawq) ;
			continue ;
			}
		if (c & FRERROR) /* framing error = break */
			if (tp->t_flags & RAW) c = 0 ; /* null for getty */
			else c = 0177 ; /* DEL = interrupt */
		if (c & PERROR) /* parity error */
			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
				continue ;
		(*linesw[tp->t_line].l_rint)(c,tp);
		}
}
 
/*		*/
 
dzioctl(dev,cmd,addr,flag)
caddr_t addr;
dev_t dev;
{
	register struct tty *tp;
 
	tp = &dz_tty[minor(dev)];
	if (ttioccomm(cmd,tp,addr,dev)) {
		if (cmd==TIOCSETP || cmd==TIOCSETN)
			dzparam(minor(dev));
	} else
		u.u_error = ENOTTY;
}
 
/*		*/
 
dzparam(dev)
{
	register struct tty *tp ;
	register struct dzregs *dzaddr ;
	register short lpr ;
 
	tp = &dz_tty[dev] ;
	dzaddr = dz_addr[dev>>3] ;
	dzaddr->dzcsr = DZ_IEN ;
	if (tp->t_ispeed == 0) { /* hang up line */
		dzmodem(dev,OFF) ;
		return ;
		}
	lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07) ;
	if (tp->t_flags & RAW) lpr |= BITS8 ;
	else lpr |= (BITS7|PENABLE) ;
	if ((tp->t_flags & EVENP) == 0) lpr |= OPAR ;
	if (tp->t_ispeed == 3)  /*  110 baud */
		lpr |= TWOSB ; /* 2 stop bits */
	dzaddr->dzlpr = lpr ;
}
 
/*		*/
 
dzxint(dev)
dev_t dev;
{
	register struct tty *tp ;
	register struct dzregs *dzaddr ;
	register unit ;
 
	dzaddr = dz_addr[dev] ;
	while (dzaddr->dzcsr < 0) { /* Transmit Ready is on */
		unit = (dzaddr->dzcsr >> 8) & 07 ;
		tp = &dz_tty[(dev<<3) | unit] ;
		/* the following is an attempt to fix what appears
		   to be a DZ hardware bug which causes the system
		   to loop here.  Transmitting the NUL should not
		   cause too many problems.... */
		if ((dzaddr->dztcr & (1<<unit)) == 0 ) {
			printf("dzxint,line=%d\n", unit);
			dzaddr->dztbuf = 0;
			continue;
		}
		if (tp->t_state & BUSY) {
			dzaddr->dztbuf = tp->t_char ; /* output the char */
			tp->t_state &= ~BUSY ;
			if (tp->t_line)
				(*linesw[tp->t_line].l_start)(tp);
			else
				dzstart(tp);
			continue ;
			}
		unit = (1<<unit) ;
		dzaddr->dztcr &= (~unit) ; /* Transmit enable off */
		}
}
 
/*		*/
 
dzstart(tp)
register struct tty *tp ;
{
	register unit , c ;
	register struct dzregs *dzaddr ;
	extern ttrstrt() ;
	int sps ;
 
	unit = tp - dz_tty ;
	dzaddr = dz_addr[unit>>3] ;
	unit = 1<<(unit&07) ;
	sps = spl5() ;
	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) {
		splx(sps) ;
		return ;
		}
	if ((c = getc(&tp->t_outq)) >= 0) {
		if (c >= 0200 && (tp->t_flags&RAW) == 0) {
			dzaddr->dztcr &= ~unit ;
			tp->t_state |= TIMEOUT ;
			timeout(ttrstrt,tp,(c&0177)+6) ;
			}
		else {
			tp->t_char = c ;
			tp->t_state |= BUSY ;
			dzaddr->dztcr |= unit ;
			}
		if (tp->t_outq.c_cc <= TTLOWAT && tp->t_state&ASLEEP) {
			tp->t_state &= ~ASLEEP ;
			wakeup(&tp->t_outq) ;
			}
		}
		splx(sps) ;
}
 
/*		*/
 
dzmodem(dev,flag)
register int dev;
{
	register struct dzregs *dzaddr ;
	register char bit ;
 
	dzaddr = dz_addr[dev>>3] ;
	bit = 1<<(dev&07) ;
	if (flag == OFF) dzaddr->dzdtr &= ~bit ;
	else dzaddr->dzdtr |= bit ;
}
 
/*		*/
 
dzscan()
{
	register i ;
	register struct dzregs *dzaddr ;
	register bit ;
	register struct tty *tp ;
	extern dzscan() ;
 
	for (i = 0 ; i < dz_cnt ; i++) {
		dzaddr = dz_addr[i>>3] ;
		tp = &dz_tty[i] ;
		bit = 1<<(i&07) ;
		if (dzaddr->dzmsr & bit) { /* carrier present */
			if ((tp->t_state & CARR_ON) == 0) {
				wakeup(&tp->t_rawq) ;
				tp->t_state |= CARR_ON ;
				}
			}
		else {
			if ((tp->t_state & CARR_ON)) { /* carrier lost */
				signal(tp->t_pgrp,SIGHUP) ;
				dzaddr->dzdtr &= ~bit ;
				flushtty(tp) ;
				}
			tp->t_state &= ~CARR_ON ;
			}
		}
		timeout(dzscan,0,2*60) ;
}