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

# include "../h/param.h"
# include "../h/dir.h"
# include "../h/user.h"
# include "../h/proc.h"
# include "../h/uba.h"
# include "../h/buf.h"
/*		*/
# define LNKADR (UBA0_DEV+0172410) /* DR11-B devive reg's */
/*
*  UBA0_DEV = 0x80018000
*  LNKADR = 0x80027508
*/
/*  DA11-B  DR-11B Status & Command reg */
# define ERR  0x8000  /*  error bit */
# define NEX  0x4000  /*  non-existent memory */
# define IIR  0x800  /*  Input Interrupt Request */
# define ID  0x400  /*  Input direction */
# define IM  0x200  /*  Input mode */
# define CYCLE  0x100  /* Cycle */
# define RDY  0x80  /* Ready */
# define IE  0x40  /*  Interrupt Enable */
# define OIR  8  /*  Output interrupt request */
# define OD  4  /* Output direction */
# define OM  2  /* output mode */
# define GO  1  /* Go bit */
/*	states	*/
# define CLOSED 0  /*  closed */
# define  OPEN  1  /* open  */
# define  S1  2  /* write state 1 */
# define  S2  4  /* write state 2 */
# define  R1  8  /* read state 1 */
# define  R2  16  /* read state 2 */
# define L_NOT 128  /*  send OIR to other end link */
# define IPEND 256
# define PREread  512  /*  'lnkmon' wait */
# define L_MON 1024  /* 'lnkmon' decr V11opn */
# define L_WAKE  2048
# define BUSY (S1|S2|R1|R2)  /* i-o in progress for driver */
# define S_ERR  0x8000
/*		*/
# define  V11PRI  0
# define BUFSIZ  512
# define VSPEC  0100000
/*		*/
struct lnkreg {
	short drwc , drba , drst , drdb ;
	} ;
struct {
	short state ;
	struct buf *bp ;
	} V11tab ;
char V11opn ;
 
/*		*/
 
V11open(dev,flag)
{
struct buf *geteblk() ;
 
if (V11opn) {
	u.u_error = EBUSY;
	return;
	}
V11opn++;
if (V11tab.bp == 0) /* grab system buffer */
	V11tab.bp = geteblk() ;  /*  VAX call */
((struct lnkreg *)LNKADR)->drst |= IE ;
V11tab.state |= OPEN ;
}
 
/*		*/
 
V11close(dev,flag) /* called on last close only ! ! */
{
V11opn = 0;
V11tab.state = CLOSED ;
((struct lnkreg *)LNKADR)->drst = 0 ; /* IE off */
if (V11tab.bp) brelse(V11tab.bp) ; /* release system buffer */
V11tab.bp = 0 ;
}
 
/*		*/
 
V11write(dev)
{
register int i , j  , k ;
 
/*  INIT clears OUTPUT DIR bit = transmitter */
spl5() ;
V11tab.state |= S1 ;
/* setup for transmit */
((struct lnkreg *)LNKADR)->drst &= ~(OD) ; /* 0 -> transmitter */
spl0() ;
 
i = uballoc(V11tab.bp->b_un.b_addr,BUFSIZ,1) ; /* get UBA map entry for
	system buffer and set valid bit & BDP no. & BO bit & load map */
j = i & 0x3ffff ; /* start map no. & byte offset */
 
/* write loop, until done or error */
while ((u.u_count > 0) && (u.u_error == 0)) {
	iomove(V11tab.bp->b_un.b_addr,min(BUFSIZ,u.u_count),B_WRITE) ; /* move
		data from user space to system buffer */
	((struct lnkreg *)LNKADR)->drwc = (-(BUFSIZ>>1)) ; /* word count */
	((struct lnkreg *)LNKADR)->drba = j ; /* map no. (SBI page) & byte offset */
	spl5() ;
	((struct lnkreg *)LNKADR)->drst |= GO ; /* setup for transfer */
	sleep(LNKADR,V11PRI) ; /* wait for transfer to finish(interrupt) */
	spl0() ;
	if (V11tab.state & S_ERR)
		u.u_error = ENXIO ;
	}
ubafree(i) ;
((struct lnkreg *)LNKADR)->drst &= (~OM);
V11tab.state &= (~BUSY) ;
}
 
/*		*/
 
V11read(dev)
{
register i , j  ;
 
spl5() ;
V11tab.state |= R1 ;
((struct lnkreg *)LNKADR)->drst |= OD ; /* receiver */
spl0() ;
i = uballoc(V11tab.bp->b_un.b_addr,BUFSIZ,1) ;
j = i & 0x3ffff ; /* start map no. & byte offset */
 
while ((u.u_count>0) && (u.u_error == 0)) {
	((struct lnkreg *)LNKADR)->drwc = (-(BUFSIZ>>1)) ;
	((struct lnkreg *)LNKADR)->drba = j ;
	spl5() ;
	((struct lnkreg *)LNKADR)->drst |= GO ;
	/* wait for i-o to finish */
	sleep(LNKADR,V11PRI) ;
	spl0() ;
	if (V11tab.state & S_ERR) {
		u.u_error = ENXIO ;
		continue ;
		}
	iomove(V11tab.bp->b_un.b_addr,min(BUFSIZ,u.u_count),B_READ) ;
	}
 
ubafree(i) ;
V11tab.state &= (~BUSY) ;
}
 
/*		*/
 
V11int(dev)
{
register unsigned short state ;
register int i ;
extern int V11ioctl() ;
 
if ((i = ((struct lnkreg *)LNKADR)->drst) & ERR)
	V11tab.state |= S_ERR ;
state = V11tab.state ;
if (state&BUSY) {
	wakeup(LNKADR) ;
	return ;
	}
if (i&IM) {
	if (state&PREread) {
		wakeup(V11ioctl);
		return;
		}
	if (((state&BUSY) == 0) && (state&OPEN))
		V11tab.state |= IPEND ;
	return;
	}
}
 
/*		*/
 
V11ioctl(dev,cmd,addr,flag)
dev_t dev;
caddr_t addr;
{
if (cmd & VSPEC) {
	switch (cmd & 077777) {
		case L_WAKE : { /* debug wakeup */
			wakeup(LNKADR);
			break;
			}
		case L_NOT : { /* send OIR to other end of link */
			spl5();
			((struct lnkreg *)LNKADR)->drst |= (OIR|OM) ;
			((struct lnkreg *)LNKADR)->drst &= (~OIR);
			spl0();
			break;
			}
		case L_MON : { /* 'lnkmon' decr 'V11opn' */
			V11opn--;
			break;
			}
		case PREread : { /* 'lnkmon' wait */
			spl5();
			if (V11tab.state&IPEND) {
				V11tab.state &= (~IPEND);
				}
			else {
				V11tab.state |= PREread;
				sleep(V11ioctl,PZERO+1);
				V11tab.state &= (~PREread);
				}
			spl0();
			break;
			}
		}
	}
else {
	*((short *)addr) = V11tab.state;
	}
}