xref: /csrg-svn/sys/vax/uba/va.c (revision 133)
1*133Sbill /*	va.c	3.2	10/14/12	*/
241Sbill 
341Sbill #ifdef ERNIE
441Sbill #include "../h/param.h"
541Sbill #include "../h/dir.h"
641Sbill #include "../h/user.h"
741Sbill #include "../h/buf.h"
841Sbill #include "../h/systm.h"
941Sbill #include "../h/map.h"
1041Sbill #include "../h/pte.h"
1141Sbill #include "../h/uba.h"
1241Sbill #include "../h/vcmd.h"
1341Sbill 
1441Sbill /*
1541Sbill  * Benson-Varian matrix printer/plotter.  Device "va", for "varian".
1641Sbill  * dma interface driver
1741Sbill  */
1841Sbill int	vabdp = 1;	/* Used with ubasetup. */
1941Sbill 
2041Sbill unsigned minvaph();	/* Maximum amount transferred by physio. */
2141Sbill 
2241Sbill #define	VAPRI	(PZERO-1)
2341Sbill 
2441Sbill struct	varegs {	/* Unibus registers provided by va. */
2541Sbill 	unsigned short vabufaddr;	/* DMA buffer address. */
2641Sbill 	short vawcount;			/* Negative of number of 16-bit
2741Sbill 					   words to transfer by DMA. */
2841Sbill 	union {
2941Sbill 		short vacsrword;	/* csr addressed as a word (for R). */
3041Sbill 		struct {
3141Sbill 			char Vacsrlo;
3241Sbill 			char Vacsrhi;	/* High byte (command bytes go here). */
3341Sbill 		} vacsrbytes;		/* csr addressed as bytes (for W). */
3441Sbill 	} vacsr;			/* Control/Status Register (csr). */
3541Sbill 	short	vadata;
3641Sbill };
3741Sbill 
3841Sbill #define	vacsrhi	vacsr.vacsrbytes.Vacsrhi
3941Sbill #define	vacsrlo	vacsr.vacsrbytes.Vacsrlo
4041Sbill #define	VAADDR	((struct varegs *)(UBA0_DEV + 0164000))
4141Sbill 
4241Sbill /* vacsr.vacsrword bits: */
4341Sbill #define	ERROR		0100000		/* R	Some error has occurred */
4441Sbill #define NPRTIMO		01000		/* R    DMA timeout error */
4541Sbill #define NOTREADY	0400		/* R	Something besides NPRTIMO */
4641Sbill #define DONE		0200		/* R	*/
4741Sbill #define	IENABLE		0100		/* R/W	Interrupt enable */
4841Sbill #define	SUPPLIESLOW	04		/* R	*/
4941Sbill #define BOTOFFORM	02		/* R	*/
5041Sbill #define BYTEREVERSE	01		/* R/W	Reverse byte order in words */
5141Sbill 
5241Sbill /* Command bytes sent to vacsrhi */
5341Sbill #define VAPLOT		0340
5441Sbill #define VAPRINT		0100
5541Sbill #define VAPRINTPLOT	0160
5641Sbill #define VAAUTOSTEP	0244
5741Sbill /* The following commands are not used in this driver: */
5841Sbill #define VANOAUTOSTEP	0045
5941Sbill #define	VAFORMFEED	0263
6041Sbill #define	VASLEW		0265
6141Sbill #define	VASTEP		0064
6241Sbill 
6341Sbill struct {
6441Sbill 	char	va_is_open;
6541Sbill 	char	va_busy;
6641Sbill 	int	va_state;	/* State: bits are commands in vcmd.h. */
6741Sbill 	int	va_wcount;
6841Sbill 	int	va_bufp;
6941Sbill } vainfo;
7041Sbill int	va_ubinfo;
7141Sbill 
7241Sbill struct	buf rvabuf;		/* Used by physio for a buffer. */
7341Sbill 
7441Sbill vaopen()
7541Sbill {
7641Sbill 
7741Sbill 	if (vainfo.va_is_open) {	/* Can't open if it's already open. */
7841Sbill 		u.u_error = ENXIO;
7941Sbill 		return;
8041Sbill 	}
8141Sbill 	vainfo.va_is_open = 1;		/* NOW it's open! */
8241Sbill 	VAADDR->vawcount = 0;		/* Clear residual errors */
8341Sbill 	vainfo.va_wcount = 0;		/* No DMA to do now. */
8441Sbill 	vainfo.va_state = 0;
8541Sbill 	VAADDR->vacsrlo = IENABLE;
8641Sbill 					/* Enable interrupts. */
8741Sbill 	vatimo();
8841Sbill 
8941Sbill 	vacmd(VPRINT);			/* Start in print mode. */
9041Sbill 	if (u.u_error)
9141Sbill 		vaclose();
9241Sbill }
9341Sbill 
9441Sbill vastrategy(bp)
9541Sbill 	register struct buf *bp;
9641Sbill {
9741Sbill 	register int e;
9841Sbill 
99*133Sbill 	(void) spl4();
10041Sbill 	while (vainfo.va_busy)		/* Wait till not busy. */
10141Sbill 		sleep((caddr_t)&vainfo, VAPRI);
10241Sbill 	vainfo.va_busy = 1;		/* Grab it. */
103*133Sbill 	(void) spl0();
10441Sbill 
10541Sbill 	va_ubinfo = ubasetup(bp, vabdp);	/* Set up uba mapper. */
10641Sbill 	vainfo.va_bufp = va_ubinfo & 0x3ffff;
10741Sbill 
108*133Sbill 	(void) spl4();
10941Sbill 	if (e = vaerror(DONE))
11041Sbill 		goto brkout;
11141Sbill 	vainfo.va_wcount = -(bp->b_bcount/2);
11241Sbill 		/* va uses a word count,
11341Sbill 		   so user had better supply an even number of bytes. */
11441Sbill 	vastart();
11541Sbill 	e = vaerror(DONE);	/* Wait for DMA to complete. */
11641Sbill 	vainfo.va_wcount = 0;	/* Reset state info. */
11741Sbill 	vainfo.va_bufp = 0;
11841Sbill 
11941Sbill 	/* After printing a line of characters, VPRINTPLOT mode essentially
12041Sbill 	   reverts to VPLOT mode, plotting things until a new mode is set.
12141Sbill 	   This change is indicated by sending a VAAUTOSTEP command to
12241Sbill 	   the va.  We also change va_state to reflect this effective
12341Sbill 	   mode change.
12441Sbill 	 */
12541Sbill 	if (vainfo.va_state & VPRINTPLOT) {
12641Sbill 		vainfo.va_state = (vainfo.va_state & ~VPRINTPLOT) | VPLOT;
12741Sbill 		VAADDR->vacsrhi = VAAUTOSTEP;
12841Sbill 		e |= vaerror(DONE);
12941Sbill 	}
130*133Sbill 	(void) spl0();
13141Sbill brkout:
13241Sbill 	ubafree(va_ubinfo), va_ubinfo = 0;
13341Sbill 	vainfo.va_busy = 0;
13441Sbill 	iodone(bp);
13541Sbill 	if (e)
13641Sbill 		u.u_error = EIO;
13741Sbill 	wakeup((caddr_t)&vainfo);
13841Sbill }
13941Sbill 
14041Sbill int	vablock = 16384;
14141Sbill 
14241Sbill unsigned
14341Sbill minvaph(bp)
14441Sbill struct buf *bp;
14541Sbill {
14641Sbill 	if (bp->b_bcount > vablock)
14741Sbill 		bp->b_bcount = vablock;
14841Sbill }
14941Sbill 
15041Sbill /*ARGSUSED*/
15141Sbill vawrite(dev)
15241Sbill {
15341Sbill 	physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph);
15441Sbill }
15541Sbill 
15641Sbill /*
15741Sbill  * Vaerror waits until bit or ERROR gets set, then returns non-zero if
15841Sbill  * if it was ERROR that was set.
15941Sbill  */
16041Sbill vaerror(bit)
16141Sbill {
16241Sbill 	register int e;
16341Sbill 
16441Sbill 	while ((e = VAADDR->vacsr.vacsrword & (bit|ERROR)) == 0)
16541Sbill 		sleep((caddr_t)&vainfo, VAPRI);
16641Sbill 	return (e & ERROR);
16741Sbill }
16841Sbill 
16941Sbill /* vastart starts up the DMA by setting the buffer pointer and the word count. */
17041Sbill vastart()
17141Sbill {
17241Sbill 	if (vainfo.va_wcount) {
17341Sbill 		VAADDR->vabufaddr = vainfo.va_bufp;
17441Sbill 		VAADDR->vawcount = vainfo.va_wcount;
17541Sbill 		return;
17641Sbill 	}
17741Sbill }
17841Sbill 
17941Sbill /*ARGSUSED*/
18041Sbill vaioctl(dev, cmd, addr, flag)
18141Sbill 	register caddr_t addr;
18241Sbill {
18341Sbill 	register int vcmd;
18441Sbill 
18541Sbill 	switch (cmd) {
18641Sbill 
18741Sbill 	case VGETSTATE:
188*133Sbill 		(void) suword(addr, vainfo.va_state);
18941Sbill 		return;
19041Sbill 
19141Sbill 	case VSETSTATE:
19241Sbill 		vcmd = fuword(addr);
19341Sbill 		if (vcmd == -1) {
19441Sbill 			u.u_error = EFAULT;
19541Sbill 			return;
19641Sbill 		}
19741Sbill 		vacmd(vcmd);
19841Sbill 		return;
19941Sbill 
20041Sbill 	default:
20141Sbill 		u.u_error = ENOTTY;	/* Not a legal ioctl cmd. */
20241Sbill 		return;
20341Sbill 	}
20441Sbill }
20541Sbill 
20641Sbill /* vacmd sends a command code to the va, and waits for it to complete.
20741Sbill    If an error occurs, u.u_error is set to EIO.
20841Sbill    vacmd also updates vainfo.va_state.
20941Sbill  */
21041Sbill 
21141Sbill vacmd(vcmd)
21241Sbill {
213*133Sbill 	(void) spl4();
214*133Sbill 	(void) vaerror(DONE);	/* Wait for va to be ready. */
21541Sbill 	switch (vcmd) {
21641Sbill 
21741Sbill 	case VPLOT:
21841Sbill 		/* Must turn on plot AND autostep modes. */
21941Sbill 		VAADDR->vacsrhi = VAPLOT;
22041Sbill 		if (vaerror(DONE))
22141Sbill 			u.u_error = EIO;
22241Sbill 		VAADDR->vacsrhi = VAAUTOSTEP;
22341Sbill 		break;
22441Sbill 
22541Sbill 	case VPRINT:
22641Sbill 		VAADDR->vacsrhi = VAPRINT;
22741Sbill 		break;
22841Sbill 
22941Sbill 	case VPRINTPLOT:
23041Sbill 		VAADDR->vacsrhi = VAPRINTPLOT;
23141Sbill 		break;
23241Sbill 	}
23341Sbill 	vainfo.va_state =
23441Sbill 		(vainfo.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd;
23541Sbill 
23641Sbill 	if (vaerror(DONE))	/* Wait for command to complete. */
23741Sbill 		u.u_error = EIO;
238*133Sbill 	(void) spl0();
23941Sbill }
24041Sbill 
24141Sbill vatimo()
24241Sbill {
24341Sbill 	if (vainfo.va_is_open)
24441Sbill 		timeout(vatimo, (caddr_t)0, HZ/10);
24541Sbill 	vaintr(0);
24641Sbill }
24741Sbill 
24841Sbill /*ARGSUSED*/
24941Sbill vaintr(dev)
25041Sbill {
25141Sbill 	wakeup((caddr_t)&vainfo);
25241Sbill }
25341Sbill 
25441Sbill vaclose()
25541Sbill {
25641Sbill 
25741Sbill 	vainfo.va_is_open = 0;
25841Sbill 	vainfo.va_busy = 0;
25941Sbill 	vainfo.va_state = 0;
26041Sbill 	vainfo.va_wcount = 0;
26141Sbill 	vainfo.va_bufp = 0;
26241Sbill 	VAADDR->vacsrlo = 0;
26341Sbill }
26441Sbill #endif
265